Arduino LMIC library updated

(Addy de Jongh) #4

Thanks for making this available. Unfortunately I get a compiling error like this:

In function ‘u4_t hal_ticks()’:
D:\Addy\Documenten\Arduino\libraries\arduino-lmic-master\src\hal\hal.cpp:154:115: error: ‘static_assert’ was not declared in this scope

What is wrong here?

Thanks is advance for your answer.

(Matthijs Kooijman) #5

As mentioned by e-mail as well, you’ll need to use Arduino 1.6.6 or above, which enables C++11 and C99 support (at least for the regular Arduino cores, third-party cores might be different).


@matthijs : compiling with Arduino-1.6.7 / Teensyduino for Teensy-3.2 not successful
compiling output as PM
for an UNO : OK

(Matthijs Kooijman) #7

Right, it seems that Teensyduino does not have C99 mode enabled, like the regular Arduino core has since 1.6.6. I’ve contacted Paul (Teensy maintainer) about this, I’ll keep you posted. For now, you can probably fix this by finding the Teensy platform.txt, looking for a line starting with compiler.c.flags and adding the -std=gnu11 op;tion (this enables C11 mode with GNU extensions, which includes C99).

A second problem is that the printf support I used turns out to be AVR-specific. You can either disable it in config.h, or try this branch (I’ll merge this to master once someone confirms printf works on Teensy or some other non-avr platform with it).


@matthijs I used also the branch non-avr-print. no luck

(Matthijs Kooijman) #9

I’ve just pushed and tagged an update that has the printf support disabled by default (but still has assertion failure enabled, which no longer coupled to the printf support). This fixes half of the problem for Teensy, for the C99 thing I’ve contacted Paul to see if he can change that.

(Arjan) #10

@matthijs, did you ever try to understand the DO_DEVDB macro?

I wondered if frame counters survive Arduino restarts, but they don’t. This might soon become troublesome, as per Security in LoRaWAN and TTN in the staging wiki:

[…] you should realize that these frame counters reset to 0 every time the device restarts (when you flash the firmware or when you unplug it). As a result, The Things Network will block all messages from the device until the FCntUp becomes higher than the previous FCntUp. Therefore, you should re-register your device in the backend every time you reset it.

When a counter increments, it seems LMiC allows for storing it in some “device database” (beware: my own terminology). Like for LoRaWAN’s FCntUp:

LMIC.seqnoUp += 1;

The same macro is used after Over-the-Air Activation, or for adaptive date rate. However, DO_DEVDB is a no-operation in oslmic.h:

#define DO_DEVDB(field1,field2) /**/

(Which, I think, is also why this code even compiles, as the bare seqnoUp is not even defined?)

But maybe my guess about the meaning of the DO_DEVDB macro is wrong. First, for a database, I’d have expected LMiC to define that in the HAL, not in oslmic.h. Also, I don’t see how the values are ever read back from such database, in the IBM code. And the LMiC documentation states:

2.5.4 void LMIC_setSession (u4_t netid, devaddr_t devaddr, u1_t* nwkKey, u1_t* artKey)

Set static session parameters. Instead of dynamically establishing a session by joining the network, precomputed session parameters can be provided. To resume a session with precomputed parameters, the frame sequence counters (LMIC.seqnoUp and LMIC.seqnoDn) must be restored to their latest values.

I guess that implies one should store the counters in the EV_TXCOMPLETE event. And when doing so, the following might be relevant too:


Session reset due to rollover of sequence counters. Network will be rejoined automatically to acquire new session.

Reading the LMiC documentation makes me think this is only a problem for Activation by Personalization (as used in the example code). But I’ve not checked if Over-the-Air Activation automatically resets the counters in the TTN backend.

New backend. How to connect?
What LMIC state must be preserved during sleep mode?
(Matthijs Kooijman) #11

I haven’t actually noticed it before, to be honest :slight_smile:

I agree with your analysis, though - the macro seems to be intended for storing the frame counter, but I suspect it is used for internal debugging purposes or something, since it is not exposed as a proper API currently. Storing the counter in TX_COMPLETE seems sensible to me, though that’s not currently implemented in the library or examples.

AFAIU the spec, it should reset the counters, since that’s pretty much the only way to handle rollover currently. Note that it should not just reset the counters, but also allocate a new key (which is why resetting the counters does not hurt security). For personalized devices, I guess the same could happen by re-registering a device in the TTN backend, but then the burden of actually changing the key is on whoever does the registration.


I have checked your question/assumption about the counters and OTAA. If I restart the LMIC code (a port to RaspberryPi) while using OTAA, the device gets new keys (as can be seen in the ttnctl devices info DEVEUI output) and the counters are reset to 0.
So no need to store the counters with OTAA.

(Arjan) #13

You mean the counters in the TTN backend? (I knew they are reset in the node; I just didn’t check if they are reset in the TTN backend too. But indeed, I agree with matthijs that they should be reset in the backend as well; if not then that would be a bug.)


They are reset correctly in the TTN backend.


@matthijs: I just joined a Ideetron Nexus with OTAA using your library without much trouble (once I figured out which bits go where, reversed or not), so that seems to be working (in case you didn’t know yet).

Had to DISABLE_PING and/or DISABLE_BEACONS to fit it in the Nexus.

And getting non-zero FCntUp in ttnctl devices info :grinning:

Edit: downlink works, too!

Edit2: after a while I get EV_LINK_DEAD, followed by EV_REJOIN_FAILED (SF increments each time this happens), but everything keeps working, FCntUp increments, EV_TXCOMPLETEs, and uplink messages keep showing up in mqtt.

(Matthijs Kooijman) #16

@melvin, cool, I hadn’t actually tested OTAA so far.

I also have a Nexus lying around here, waiting for a testrun. Could you share the the pin map from your sketch so I can include it as an example for the Nexus?

I suspect that using OTAA pulls in additional code from the LMIC library, pushing the flash size over the limit. If we replace the AES implementation (which is waiting for a license change), then more space should become available (see LMIC-1.51 fitting in Arduino Atmega 328)

Not sure what happens there, perhaps ACKs aren’t being sent by TTN, which makes LMIC think the link is dead? I can’t remember if the staging backend already supports ACKs.

(Hylke Visser) #17

Yes, the backend supports ACKs, but apparently we’re sending them on the wrong port, see this issue on github.



const lmic_pinmap lmic_pins = {
    .nss = 10,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = LMIC_UNUSED_PIN, // hardwired to AtMega RESET
    .dio = {4, 5, 7},

Want to get started with NEXUS, don't know were to begin

Has anyone been able to get this running using It works for me in the Arduino IDE, but not as soon as I use the arduino-mk - I added the CFLAGS_STD = -std=c99 setting, but no difference.


@joscha : if I remember correctly, I had to add in boards.txt to each type of teensy; because it was empty.
probably that helps


I changed some code to store the counter values in EEPROM memory so it will survive resets. In the Arduino sketch, I added (sorry, I don’t know how to format it properly):

// Source:
// MACRO : Combines FROM_BYTES into TO_OBJECT of datatype “DATATYPE”

// MACRO : Splits FROM_DATA of DATATYPE into equivalent byte array TO_BYTES

// Writes Integer’s equivalent bytes to Address and Address + 1
void EEPROM_Write_Int(unsigned int Address, int Data)
// Get the size of datatype to write number of bytes
const byte SizeOf_DataType = sizeof(int);

// Create tem buffer to get Bytes of Datatype
byte Temp_Buffer[SizeOf_DataType];

// Call macro to store byte array into Temp_Buffer from Data
GetBytes(Data, int, Temp_Buffer);

// Write number of bytes to memory location specified in Address and so on
for(byte Index = 0; Index < SizeOf_DataType; Index++)
EEPROM.write(Address + Index, Temp_Buffer[Index]);

// Reads two bytes from Address and Address + 1 and returns equivalent int
int EEPROM_Read_Int(unsigned int Address)
// Get the size of datatype to write number of bytes
const byte SizeOf_DataType = sizeof(int);

// Create tem buffer to get Bytes of Datatype
byte Temp_Buffer[SizeOf_DataType];

int Result;

// Read number of bytes from memory location
for(byte Index = 0; Index < SizeOf_DataType; Index++)
Temp_Buffer[Index] = + Index);

// Call macro to combine bytes into equivalent to int
CombineBytes(Temp_Buffer, int, Result);

return Result;

int counter = EEPROM_Read_Int(0);

Then in the do_send() function add:

and in setup() at the end add:
//Set the counter from memory

Maybe someone could improve on the code, it’s my first quick and dirty programming steps for Arduino.

Where in LMiC is the "fCnt" parameter stored?
Big ESP32 + SX127x topic part 2

maybe you can use an EEPROM I2C memory module

or a combined I2C RTC/memory module

or even a single chip

(ANders) #23

I’m running the ttn example from the LMIC library on a arduino UNO. I am using a Semtech SX1276mb1mas board and a level converter between the arudino and the semtech board. But when trying uploading the ttn example to the arduino i get the following in the serial monitor:

FAILURE C:\Users***\Documents\Arduino\libraries\IBM_LMIC_framework\src\lmic\radio.c:657

I have the right pin mapping, and have set the library to SX1276 in the config.h file. What can be the problem? Thank you in regards!