Feather 32u4 with TinyLoRa for weeks-long balloon contest

ok so you don’t have (your own) a gateway therefore you can only ‘see’ in the console your application data coming in… or not.

then its difficult to ‘bughunt’ your new node… is it joining … or not, is the distance to big?, are the keys wrong? ect.

found this labstory to

https://blog.werktag.io/posts/adafruit-feather-m0-lora-on-ttn/

The tutorial you sent is for the M0, but I suppose that the process with the 32u4 is similar aside from the different board selection and different wiring.

Hmm, with the TinyLoRa library I get just “Sending LoRa Data…” and “Frame Counter: x” but that is expected because it’s supposed to be a small library so it doesn’t have many debugging options.

But even using the LMIC library, I never got nothing which said that it’s joining. I did get only “EV_TXCOMPLETE (includes waiting for RX windows)” and “Packet queued” on the serial monitor. Weird.

How should the output look like when it’s working correctly?

first thing is that your device is registered with the network.
you do that through the console… add application ’ test ’ with device ’ ada1 ’ for example.
(how exactly you can see in that link)

then the credentials you get from the console, you enter in the program that you upload to the 32U4.
you can choose OTAA and ABP… because you experiment a lot its better not to use the frame counter.

now open your browser window (and leave it open) and power on the node.
if the node is in range (and A gateway within range is ON) you should see a yellow thunder

I have that. I have the aplication. I have the device EUI consisting of the MAC adress which came in the box with the 32u4. I have the activation method set to ABP. I have the frame counter width set to 16 bits. I have disabled the frame counter checks. I have copy-pasted the credentials into my code. I have it set up.

Hmm, I thought I would see a blue triangle and some data on the console if it’s working.
balonik

My idea would be to try and contact someone from the local community, maybe even the gateway owner close to you.
All TTN’ers are nice guys ( :wink: ) So maybe a community member could help you test your node.
Just send them a PM… its worth a try

Thanks. Will do.

1 Like

Did you enable the correct region in the TinyLoRa library? See:


So, did you follow that tutorial? That seems quite solid to me, except for not mentioning the region settings…?

Maybe show us the code that you used, so we can compare that to the screenshots you posted. (See How do I format my forum post? [HowTo])

As for the jumper, it seems that it’s needed for LMIC, but not for TinyLoRa, regardless whether you’re using the M0 or 32u4.

The jumper is documented for the M0 as:

Pin 3 is internally connected to pin io0, but we’ll need to add a jumper wire between the Feather Digital Pin 6 and Feather Pin io1.

Looking at the pin layout of the M0, you’ll read:

Since not all pins can be brought out to breakouts, due to the small size of the Feather, we use these to control the radio module

  • #8 - used as the radio CS (chip select) pin
  • #3 - used as the radio GPIO0 / IRQ (interrupt request) pin.
  • #4 - used as the radio Reset pin

There are also breakouts for 3 of the RFM’s GPIO pins (IO1, IO2, IO3 and IO5).

So, the IOx pins are connected to the little green RFM LoRa board, but on the M0 no pin from the MCU is connected to the RFM’s GPIO1.

Now, things are not much different for the 32u4, though now pin 7 is internally connected to pin IO0, instead of pin 3:

  • #8 - used as the radio CS (chip select) pin
  • #7 - used as the radio GPIO0 / IRQ (interrupt request) pin.
  • #4 - used as the radio Reset pin

There are also breakouts for 3 of the RFM’s GPIO pins (IO1, IO2 and IO3).

Indeed, when using the TinyLoRa library, you’ll see a small difference in the code:

// Pinout for Adafruit Feather 32u4 LoRa
TinyLoRa lora = TinyLoRa(7, 8);

// Pinout for Adafruit Feather M0 LoRa
TinyLoRa lora = TinyLoRa(3, 8);

But no mention of pin 6 anywhere, in TinyLoRa. However, the M0 tutorial uses LMIC, and things are different in Arduino-LMIC:

// Pin mapping for Adafruit Feather M0 LoRa
const lmic_pinmap lmic_pins = {
    .nss = 8,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 4,
    .dio = {3, 6, LMIC_UNUSED_PIN},
    .rxtx_rx_active = 0,
    .rssi_cal = 8, // LBT cal for the Adafruit Feather M0 LoRa, in dB
    .spi_freq = 8000000,
};

For Arduino-LMIC, the DIO pins are documented as:

In LoRa mode the DIO pins are used as follows:

  • DIO0: TxDone and RxDone
  • DIO1: RxTimeout

So, for LMIC the wire to pin 6 (or another pin of your choice) is needed to detect a RxTimeout; without it, LMIC will probably hang after an uplink, when it’s trying to determine if there’s any downlink in RX1 or RX2.

I’d guess TinyLoRa does not support downlinks at all?

So, (very) long story short: when using LMIC on the 32u4 I’d say you’ll need the jumper wire as well. (But I’ve not used the Adafruit boards, nor TinyLoRa.)


“Privilege” doesn’t seem to be the correct translation for what you’re trying to say, but when far away from the gateway, indeed use SF12, which is the slowest transmission speed with the best range. Using SF12 the transmission will take a lot longer (so you can send far fewer packets per hour) but chances that a gateway receives the transmission are better. When SF12 works, go down to SF11 and so on.

Also, as long as you’ve not received anything: put the device as high as possible, outside, to improve the chances of a gateway receiving the transmission. And check the length of your antenna wire.

So: do you know how to set the device to use SF12 for your first tests?


Reading that, I was expecting that LMIC would simply not work at all. But the MCCI Arduino-LMIC documentation explicitly mentions it is supported. Maybe using LMIC leaves not enough flash memory for other code and libraries, like to read some sensors.

Still then: if possible, then LMIC is better, as OTAA is better than ABP, and LMIC supports ADR. But as OTAA needs a downlink for the Join Accept and as you don’t have access to any gateway logs, starting with ABP is better now. And the Adafruit tutorial looks great, so I’d say that starting with TinyLora (which only supports ABP) seems fine too.


That’s correct when using ABP.


Also correct for ABP; blue upward icons denote uplinks. (For OTAA, you’d first see orange and green icons for the Join Request and Join Accept, if all is well, where the green icon is only shown in the gateway’s Traffic page, which you cannot see.)

As an aside: Adafruit’s Decoder for a TTN Payload Format does not support negative values. If you ever get to that point, then see Negative Temperature - #3 by arjanvanb.

4 Likes

I am sure I am not alone. I live in EU, I successfully use a couple of Feather clones (the BSFrance version). However, I am using LMIC, not TinyLora that apparently does not allow downlinks. LMIC is large but it leaves sufficient room for a temperature sensor library, or GPS, and is used by a lot of people, so it is easier to find help. And jumper is needed.

1 Like

Wow, thanks very much for the reply.

Did you enable the correct region in the TinyLoRa library?

Yeah, I have that.

Thanks for clarifying the pinouts.

I’d guess TinyLoRa does not support downlinks at all?

That’s fine for me.

When SF12 works, go down to SF11 and so on.

I want to use the 32u4 inside of a high altitude balloon to send data. Therefore I suppose that I should keep the SF value as high as possible at all times.

So: do you know how to set the device to use SF12 for your first tests?

Like this? lora.setDatarate(SF12BW125);

Maybe using LMIC leaves not enough flash memory for other code and libraries, like to read some sensors.

That’s exactly what Adafruit says.

After reading this I think I’m going to stay with the TinyLoRa library.

Also, my code here:

#include <TinyLoRa.h>
#include <SPI.h>
// Network Session Key (MSB)
uint8_t NwkSkey[16] = { 0xC1, 0x74, 0xBB, 0xFE, 0xE4, 0xA0, 0xCB, 0xA1, 0x12, 0x5E, 0xD7, 0x1D, 0xA1, 0x33, 0xBE, 0xB4 };
// Application Session Key (MSB)
uint8_t AppSkey[16] = { 0xD8, 0xDD, 0xA7, 0xCA, 0x56, 0xAE, 0x0D, 0x45, 0xD0, 0x36, 0xD3, 0x97, 0x67, 0xDF, 0x20, 0x8B };
// Device Address (MSB)
uint8_t DevAddr[4] = { 0x26, 0x01, 0x14, 0x24 };
// Data Packet to Send to TTN
unsigned char loraData[1] = {“f”};
// How many times data transfer should occur, in seconds
const unsigned int sendInterval = 5;
// Pinout for Feather 32u4 LoRa
TinyLoRa lora = TinyLoRa(7, 8);
void setup()
{
delay(2000);
Serial.begin(9600);
while (! Serial);
// Initialize pin LED_BUILTIN as an output
pinMode(LED_BUILTIN, OUTPUT);
// Initialize LoRa
Serial.print(“Starting LoRa…”);
// define channel to send data on
lora.setChannel(MULTI);
// set datarate
lora.setDatarate(SF12BW125);
if(!lora.begin())
{
Serial.println(“Failed”);
Serial.println(“Check your radio”);
while(true);
}
Serial.println(“OK”);
}
void loop()
{
Serial.println(“Sending LoRa Data…”);
lora.sendData(loraData, sizeof(loraData), lora.frameCounter);
Serial.print("Frame Counter: ");
Serial.println(lora.frameCounter);
lora.frameCounter++;
// blink LED to indicate packet sent
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
Serial.println(“delaying…”);
delay(sendInterval * 1000);
}

Just to be sure, so you changed it, right? So it’s:

//#define US902 ///< Used in USA, Canada and South America
#define EU863 ///< Used in Europe

Also, I don’t know how easily the Arduino IDE detects changes in libraries; you may want to do some full compilation.

Not related to your problems:

I’ve no idea. For outdoor gateways you’ll always have line of sight from the sky. (Though the antenna orientation might not be optimal?) Beware that the range might be quite far then, and that you’re using a radio spectrum shared with others. Many others when transmitting from a high location.

Also, with SF12 you cannot send every 5 seconds (or every 6 seconds, given the 1 second delay for the LED): even when doing the experiment for only an hour, a 2 bytes application payload only allows for 25 messages on SF12 on the TTN Fair Access Policy, and only one message every 2 minutes for the maximum duty cycle regulations. LMIC will enforce the latter but not the former. TinyLoRa does not enforce anything. Finally, a hardcoded SF11 or SF12 is not allowed. (But I assume it’s just an experiment, not something you’d be using on a regular basis?)

For the very same reasons: while testing your code from home, if SF12 works, I’d surely go down to try better data rates if possible.

Also, TinyLoRa always transmits at maximum power; I don’t know what that maximum is, and if it’s within EU limits. All said, when using TinyLoRa then one’s own code needs to ensure one plays nice in the shared radio network.

//#define US902 ///< Used in USA, Canada and South America
#define EU863 ///< Used in Europe

Yeah, I have it like that.

Also, I don’t know how easily the Arduino IDE detects changes in libraries; you may want to do some full compilation.

I’m not sure what is full compilation. I just hit the compile button. I have the .h and .cpp files in the same folder as the sketch.

Beware that the range might be quite far then, and that you’re using a radio spectrum shared with others. Many others when transmitting from a high location.

Yeah, someone said that he got 450km range with LoRa from 31km height.

Finally, a hardcoded SF11 or SF12 is not allowed.

But what if SF10 won’t be enough? Is there a way to change the SF value automatically? The thing has to work because once in the air, I can not reupload the code.

But I assume it’s just an experiment, not something you’d be using on a regular basis?

Well, I’m launching the balloon just once, but that can stay in the air and try to send the data for up to a couple of weeks so it will be sending many packets.

All said, when using TinyLoRa then one’s own code needs to ensure one plays nice in the shared radio network.

I’m fine with it sending data every hour or even once in a day. The tracker is for a contest, winner is the one which lasts longest. I really don’t care about the data, we just need to know if the tracker is still alive.

Hi everyone,
Thanks to your support, I got it working. Now I have it working using the “MCCl LoRaWAN LMIC” library and with a jumper.

Now I’m rushing to complete the tracker because the contest is in four days.

I’ve got a problem. I’m trying to encode a float into the message. I’m using the “ttn-abp-feather-us915-dht22”. There is a unknown command on the line 195. It’s “LMIC_f2sflt16(input);”. The compiler complains about it. When I googled it, it gave me like 7 results. Everything else about the code is fine. Any ideas?

Check library version, or just convert it by yourself, after considering the range and precision truly needd.

I followed the tutorial, I implemented the example code from the How to send multiple numbers? part. My code looks like this:

byte payloadA = { 0xF0 };
byte payloadB = { 0x0F };
int sizeofPayloadA = sizeof(payloadA);
int sizeofPayloadB = sizeof(payloadB);
byte payload[sizeofPayloadA + sizeofPayloadB];
memcpy(payload, payloadA, sizeofPayloadA);
memcpy(payload + sizeofPayloadA, payloadB, sizeofPayloadB);
LMIC_setTxData2(1, payload, sizeof(payload)-1, 0);

It sends only the first byte. Why is that?

The -1 in the last line is for sending null-terminated string values. (Which is very much discouraged.) For that, the terminating null-character does not need to be sent. In your case, remove the -1, so:

LMIC_setTxData2(1, payload, sizeof(payload), 0);
1 Like

Thanks, it worked.

Also, I have a problem. The code needs to be very energy-effecient. I need to replace “delay(x);” with “Watchdog.enable(x)” so the processor will be dissabled. But when I look at the lmic code, there is no delay there. Just: “const unsigned TX_INTERVAL = 30”. I know that the delay function is located somewhere deep in the library. I couldn’t find it. I just need help locating it so I can replace it with the Watchdog function. That should work, right?

Unlikely you will find a single delay corresponding to TX_INTERVAL. LMIC schedules processes at specific times, and your transmission is only one of them (disclaimer: I have a vague knowledge of its internals).

One way to introduce sleep/delays is to escape from the main execution model. There is some example where delays and sleep are put just after the TX_COMPLETE event, but during sleep also internal time is not updated so some workaround is needed to avoid that transmission is further delayed to satisfy duty cycle limitations (though if you send every hour it might not be problematic).
You may also use an external RTC to switch on/off the board when needed…

Hi @Maker_Bois,
I got the Adafruit feathers to work with both LMIC and TinyLora. Let me know if you still need help.
This tutorial covers it well, with the only exception that it doesn’t mention that you have to change region (default is US, I am EU).
Best

No thanks.

Thanks to your support we managed to get it working in time. We were second in the picoballoon contest. We published a YouTube video and an Instructable regarding this, and we won the runner up prize with it. Thank you!

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.