Code Monkey home page Code Monkey logo

lora_device_lib's Introduction

LDL: A LoRaWAN Device Library

Build Status

LDL is a LoRaWAN implementation for devices.

Use one of the releases for best results and read history.md if updating from an old version.

Examples

Features

  • Small memory footprint
  • L2 Support
    • 1.0.3 (recommended)
    • 1.0.4 (recommended)
    • 1.1
  • Class A
  • OTAA
  • ADR
  • Region Support (RP002-1.0.1)
    • EU_868_870
    • EU_433
    • US_902_928
    • AU_915_928
  • Radio Drivers
    • SX1272
    • SX1276
    • SX1261
    • SX1262
    • STM32WL55
  • Linted to MISRA 2012

Limitations

  • Class B and C not supported
  • FSK modulation not supported
  • ABP not supported
  • 1.1 Rejoin not supported
  • Experimental

Documentation

See Also

License

MIT

lora_device_lib's People

Contributors

cjhdev avatar dzurikmiroslav avatar jbinko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lora_device_lib's Issues

Incorrect MIC generated LoRaWAN 1.1 retransmissions and command responses

Affects 0.3.0 and earlier but only for 1.1 servers.

The problem occurs in LoRaWAN 1.1 where the channel index as a parameter for generating MIC. LoRaWAN 1.0 doesn't do this.

LDL currently works by sending the exact same frame as before for re-transmission, but usually on a different channel to the original. This also affects "dedicated mac command responses" because the MIC is generated before the channel is selected.

This will be fixed in the next release.

Proposal to remove diagnostic events from ldl_mac_response_type

I want to remove the diagnostic events because this information isn't useful to applications and yet takes code space and increases the line count. Previously these events could be enabled/disabled at compile time but I removed the option as it made the configuration documentation more complicated.

Since the information is sometimes useful to eyeball during development, I propose that the information should be printed via LDL_DEBUG. This is typically what these events get used for anyway, at least in the ports I've written.

Diagnostic events include:

  • LDL_MAC_RX1_SLOT
  • LDL_MAC_RX2_SLOT
  • LDL_MAC_DOWNSTREAM
  • LDL_MAC_TX_COMPLETE
  • LDL_MAC_TX_BEGIN

OTAA join-accept not being received

Hello. First of all I would like to thank you for the amazing library you wrote. I'm using it instead of loramac-node because your library is so much smaller. Also is not Arduino dependant like lmic (mcci port).

Anyway, I ported your code to a STM32 with a RFM95. The frequency plan I'm using is AU915 and for the development I use TTN. I was able to make the library transmit perfectly, but for some reason I'm not receiving correctly the OTAA response. This is the debug output from your library (plus some added by me).

tx begin
ticks=8630550 freq=917600000 power=0  bw=125000 sf=10 size=23
DIO0 Interrupt 8667667
offtime=100
tx complete
ticks=8668127
rx1 slot
ticks=9167831 timeout=8 lag=0 freq=925700000 bw=500000 sf=10
DIO1 Interrupt 9169402
rx2 slot
ticks=9266908 timeout=8 lag=1 freq=923300000 bw=500000 sf=12
DIO1 Interrupt 9273411
LDL_MAC_DEV_NONCE_UPDATED: 4
waiting to retry OTAA

I can see on the TTN console that the gateway is sending the downlink with the network join accept. But nevertheless, LDL is not receiving it. Not sure what to try. Could you give me a hint on what to test to find the problem?

image

UplinkDwellTime not correctly applied on AU915

When the node receives the command TXParamSetupReq the network defines if the node has to limit the uplink and downlink time to 400ms (a.k.a. dwell time)

What you actually do in the current version of this library, is limit the datarate to 2 (0 and 1 do not comply with the dwell time limitation). But the function LDL_Region_convertRate does not take the dwell time into account when it should. The maximum payload allowable is dependent on the dwell time too.

image

Not receiving Join Accept

Hello,

I can't receive the join accepts. The ldl doesn't even get to the RX mode and instantly goes for a RESET.
I'm getting radio faults and interrupt faults. Maybe it has to do with the ticks configuration ?

The debug messages look like this :

chIndex=0 freq=868100000 minRate=0 maxRate=5
chIndex=1 freq=868300000 minRate=0 maxRate=5
chIndex=2 freq=868500000 minRate=0 maxRate=5
set radio reset: ticks=39
clear radio reset: ticks=46
chIndex=0 freq=868100000 minRate=0 maxRate=5
chIndex=1 freq=868300000 minRate=0 maxRate=5
chIndex=2 freq=868500000 minRate=0 maxRate=5
OTAA is pending
add dither to otaa: ticks=111 delay=0
tx begin
ticks=162 freq=868500000 power=0 bw=125000 sf=7 size=23
offtime=100
interrupt fault
ticks=281
waiting to retry OTAA
radio fault detected, initiating radio reset
clear radio reset: ticks=318
channel is ready
add dither to otaa: ticks=6133 delay=0
tx begin
ticks=6187 freq=868300000 power=0 bw=125000 sf=8 size=23
offtime=100
interrupt fault
ticks=6397
waiting to retry OTAA
radio fault detected, initiating radio reset
clear radio reset: ticks=6434
channel is ready
add dither to otaa: ticks=16938 delay=0
tx begin
ticks=16990 freq=868100000 power=0 bw=125000 sf=9 size=23
offtime=100
interrupt fault
ticks=17367
waiting to retry OTAA
radio fault detected, initiating radio reset
clear radio reset: ticks=17405

Also I'm using the main loop given as an example

I'm using a STM32L412 on a custom PCB board with a SX1261

any help would be very appreciated.
thank you

Proposal to refactor LDL_DEBUG, LDL_ERROR, and LDL_INFO

These macros currently look like this:

LDL_DEBUG(APP, ...)

The APP argument is a hangover from some time ago when I thought it was useful to be able to link a message back to some instance. In practice a suitable pointer isn't always available, and even if one is, there is usually only on instance producing messages and so its redundant.

The ... usually expands to something like:

LDL_DEBUG(NULL, "a format string with some number %d", 42)

This is a problem for anyone using AVR since you have no option of putting the format string into progmem.

I propose changing the pattern to:

LDL_DEBUG(FMT, ...)

This could then be redefined on your port as:

LDL_DEBUG(FMT, ...) printf(FMT, __VA_ARGS__);

Or if you are on AVR and want the string in flash:

LDL_DEBUG(FMT, ...) printf(PSTR(FMT), __VA_ARGS__);

etc.

OTAA not recieving JoinAccept

Hello ,
i m having some troubles connecting my node to TTN as the node is stuck in the join procedure.
i thought it was a timer issue ,i was using stm32 1ms systick timer as a counter then i switched to lptim which is ticking at a rate of 16384 tick per second but the problem still persist i m still not recieving the joinaccept packets.
I've set a breakpoint in LDL_MAC_process() where LDL_Radio_collect() is called but its not reaching that point.

I'm using STM32L073RZ microcontroller with the semtech sx1272 transceiver , laird RX186 gateway and the TTN server stack
my node is about five meters away from the gateway
the joinrequest messages are received by TTN and its sending the join accept messages back.

also i tried to enlarge RX1/RX2 windows but wont work either
https://github.com/cjhdev/lora_device_lib/blob/94c64ba1cae06d81ee4d3b80d4895b543284ec27/src/ldl_mac.c#L570

https://github.com/cjhdev/lora_device_lib/blob/94c64ba1cae06d81ee4d3b80d4895b543284ec27/src/ldl_mac.c#L616

here is the link to my test repo
https://github.com/abdouTCH13/LDL_STM32L073RZ_test

any help would be very appreciated.
thank you

Lora modules driver

hi ! this is a great package ! but it lack of add driver for different Lora module ! could anyone help to add or adding instruction how to add extra drivers for different modules ? thank you !

Maximum sleep time due to LDL_MAC_ticksUntilNextEvent() values

Hello,
I updated successfully to the latest version 0.4.5 (597630c).

I see a different behaviour, compared to previous versions. The function LDL_MAC_ticksUntilNextEvent() returns always values less than 60 seconds, due to a armed LDL_TIMER_BAND timer. I use the value to calculate possible power down times for my application and that value is rather short.

Is it really necessary to have a timer for band events? The processing function is in any case called from LDL_MAC_process and at first glance I see no problems if more ticks elapse before the next call. I would like to get UINT32_MAX from LDL_MAC_ticksUntilNextEvent() when the last receive window is closed and no (MAC) messages are queued.

Kind regards,
Frank

SX1262 support

You mentioned in another issue you'd like some kind of coordination before others submitted PRs. I have some SX1262 modules arriving soon, and I'd like to add support to this library (I can see where, and how). Just wanted to hear your thoughts on contributing this upstream before I start.

I share your frustration with the (over)complexity of the other implementations, after looking at either using semtech's reference which has SX1262 support already, or adapting arduino-lmic.

Discussion: Better control of confirmed uplink messages from application

IMHO the handling of confirmed uplink messages can be improved. The number of retransmissions can be controlled by nbTrans, but control of further timing and data rate changes are not possible. The default ADR algorithm will eventually lower the rate on bad conditions, but that takes a lot of time. My first idea was, that LDL could get additional parameters for further repetitions and data rate changes. But that is not an ideal solution, when we encounter long delays for retransmissions the possibility is high, that updated measurements exists, that should be sent instead.

So I came to a solution, where I refactored some library code, so that two new callable functions exist:

  1. to retransmit a confirmed message with same frame counter.
  2. to lower the data rate and increase the transmit power.

With both functions the application can control the data rate very easily and retry a transmission on demand. It works well together with ADR, the network increases the data rate on demand and the application can decrease the data rate and repeat the transmission on packet loss.

I'm not sure, if that is the right solution and the code is of sufficient quality, so I did not create a pull request yet, but implemented that on a private branch only. The commit is https://github.com/frbehrens/lora_device_lib/commit/16fdba6dd2281611ecb0b13db2f2317cbc51be2f

What do you think?

Kind regards,
Frank

LPTIM 16 bit ticker

Hello, I'm using using an STM32L4 and thus I'm using LPTimer. The timer has a 16 bit resolution but the system ticks used in LDL assume the timer has a 32 bit resolution.
I read in another issue that you also use LPTIM so how do you solve this problem ?

regards

preferred way to use DeviceTimeSync

Hi,

How do you use the DeviceTimeSync options with the current implementation?

I've added a new app callback function to the end of the processTX function, where I only record the current msec/tick counter, and calculate the time diff at the LDL_MAC_DEVICE_TIME callback, but I'm not sure this is the best way.

Increment devNonce on every join request

I observed sometimes problems with joins, where a reduced rate is required due to a longer distance. I debugged this further and could see, that the TTN ignores repeated join frames with the same devNonce. That happens, when a join-accept downlink is lost, but not when the join-request uplink is lost.

The LoRaWAN standard (1.0.4) seems to require a different devNonce as well: "For each transmission of a Join-Request, the end-device SHALL increment the DevNonce value."

So I propose to increment the devNonce in LDL for every join request frame.

I created a PoC (https://github.com/frbehrens/lora_device_lib/commit/8e7c8acd76036a16cd3c07b6faa060e44930b24a), that solved the problem and allows a stable device join procedure.

What do you think about the issue?

Radio interrupt not raised when message received in SF11 and SF12

This bug is in 0.4.0 but it's possibly been around longer.

Normally, a radio waiting to receive a packet will raise one of two interrupt lines to signal:

  1. RX complete: a message was received
  2. RX timeout: no preamble was detected

LDL uses a guard timer to reset the chip if no interrupt is raised within an extended period of time. If this timer expires, LDL produces a chip error event and performs a chip reset.

I've been reproducing this bug by waiting for OTAA to increase the spreading factor to 11 (or 12) before starting the network server to answer the join request at that spreading factor. If there is no message sent, the timeout interrupt is raised. If there is a message sent, then no interrupt is raised.

I'm going to start the investigation by adding trace level messages to the radio driver to compare register access between modes that work and modes that don't.

Join timeout

Hi,

I am build my own single channel gateway using ESP-1ch-Gateway and connect it to TTN. In TTN console I see received join query and joint accept response. My device always give me LDL_MAC_JOIN_TIMEOUT.

This problem may be caused by wrong LDL_System_advance value? In what way I should calculate it?

Simplify function timerDelta()

I believe - because we use for all operands and the result the same integer type - we can simplify the function in ldl_mac.c

static uint32_t timerDelta(uint32_t timeout, uint32_t time)
{
    return (timeout <= time) ? (time - timeout) : (UINT32_MAX - timeout + time);
}

to

static uint32_t timerDelta(uint32_t timeout, uint32_t time)
{
    return (time - timeout);
}

Add a check for maximum message size on send

There is no explizit check for maximum message size. If the size is too big, it leads to the (wrong) error message LDL_STATUS_MACPRIORITY / "mac data has been prioritised".

I propose an explicit check like mentioned in the patch. I know, that the style does not match the library, therefore I did not create a pull request.

--- "a/src/ldl_mac.c"
+++ "b/src/ldl_mac.c"
@@ -1656,40 +1665,45 @@ static enum ldl_mac_status externalDataCommand(struct ldl_mac *self, bool confir
     if(self->ctx.joined){
 
         if(self->op == LDL_OP_NONE){
 
             if((port > 0U) && (port <= 223U)){
 
                 if(self->band[LDL_BAND_GLOBAL] == 0U){
 
                     /* set desired power and rate */
                     self->tx.power = self->ctx.power;
 #ifdef LDL_DISABLE_TX_PARAM_SETUP
                     self->tx.rate = self->ctx.rate;
 #else
                     self->tx.rate = LDL_Region_applyUplinkDwell(self->ctx.region, uplinkDwell(self->ctx.tx_param_setup), self->ctx.rate);
 #endif
 
                     if(selectChannel(self, self->ctx.rate, 0U, &self->tx)){
 
                         LDL_Region_convertRate(self->ctx.region, self->ctx.rate, &sf, &bw, &maxPayload);
 
+                        if (len + LDL_Frame_dataOverhead() > maxPayload) {
+                            LDL_INFO("message is too large");
+                            return LDL_STATUS_SIZE;
+                        }
+
                         (void)memset(&self->opts, 0, sizeof(self->opts));
 
                         if(opts != NULL){
 
                             (void)memcpy(&self->opts, opts, sizeof(self->opts));
                         }
 
                         self->opts.nbTrans = self->opts.nbTrans & 0xfU;
 
                         {
                             self->trials = 0U;
 
                             (void)memset(&f, 0, sizeof(f));
 
                             self->op = confirmed ? LDL_OP_DATA_CONFIRMED : LDL_OP_DATA_UNCONFIRMED;
 
                             f.type = confirmed ? FRAME_TYPE_DATA_CONFIRMED_UP : FRAME_TYPE_DATA_UNCONFIRMED_UP;
                             f.devAddr = self->ctx.devAddr;
                             f.counter = U16(self->ctx.up);
                             f.adr = self->ctx.adr;

State of the library and future plans

Hi,

I came across your library after asking about open source LoRaWan stack implementartions here.

We want to develop sensor nodes in a factory environment, we're planning to use STM32Lx devices, communicating over LoRaWan with a gateway. We're using Atollic TrueStudio (configuration code generated with STM32CubeMX) and I would like to include your library to the project, I tried to do so with lorawan-mac I i wasn't able to do so.

After searching LoRaWan stacks I think yours is the most sane one, but i would like to know what is your roadmap, maybe if you accept contributions, plans to implement Class B and C, etc.

possible deprecated #define LDL_LITTLE_ENDIAN

Hi,

I'd ported this nice little library to my custom cortex m0+ microcontroller, but with the LDL_LITTLE_ENDIAN define the OTAA authentication fails, with "joinAccept MIC failed" error.

After removing the define it successfully join and packets are ok, so this option is possibly deprecated or buggy.

OTAA join

Hi, I am glad to see there is new alternative to LMIC or LoRaMac-Node for no-arduino developers.
I am using ESP32, in my code https://github.com/dzurikmiroslav/esp32-ldl-example I have issue with OTAA joining request. In log I see many attempts to join, but in TTN console I see only first attempt. After restart is the situation same, in TTN console will be added one join request.

Application log:

1229: LDL_MAC_addChannel: debug: adding chIndex=0 freq=868100000 minRate=0 maxRate=5
1229: LDL_MAC_addChannel: debug: adding chIndex=1 freq=868300000 minRate=0 maxRate=5
1229: LDL_MAC_addChannel: debug: adding chIndex=2 freq=868500000 minRate=0 maxRate=5
I (318) main: LDL_MAC_RESET
I (318) main: LDL_MAC_STARTUP
216: LDL_MAC_otaa: debug: sending join in 16359821 ticks
I (76518) main: LDL_MAC_TX_BEGIN
I (76618) main: LDL_MAC_TX_COMPLETE
I (81618) main: LDL_MAC_RX1_SLOT
I (82518) main: LDL_MAC_RX2_SLOT
I (83318) main: LDL_MAC_JOIN_TIMEOUT
950: LDL_MAC_process: debug: dither retry by 18069775 ticks
I (107518) main: LDL_MAC_TX_BEGIN
I (107718) main: LDL_MAC_TX_COMPLETE
I (112618) main: LDL_MAC_RX1_SLOT
I (113618) main: LDL_MAC_RX2_SLOT
I (114618) main: LDL_MAC_JOIN_TIMEOUT
950: LDL_MAC_process: debug: dither retry by 4623390 ticks
I (130018) main: LDL_MAC_TX_BEGIN
I (130318) main: LDL_MAC_TX_COMPLETE
I (135218) main: LDL_MAC_RX1_SLOT
I (136218) main: LDL_MAC_RX2_SLOT
I (137218) main: LDL_MAC_JOIN_TIMEOUT
950: LDL_MAC_process: debug: dither retry by 18470742 ticks
I (174118) main: LDL_MAC_TX_BEGIN
I (174618) main: LDL_MAC_TX_COMPLETE
I (179518) main: LDL_MAC_RX1_SLOT
I (180518) main: LDL_MAC_RX2_SLOT
I (181518) main: LDL_MAC_JOIN_TIMEOUT
950: LDL_MAC_process: debug: dither retry by 17685113 ticks
I (236118) main: LDL_MAC_TX_BEGIN
I (237118) main: LDL_MAC_TX_COMPLETE
I (242018) main: LDL_MAC_RX1_SLOT
I (243018) main: LDL_MAC_RX2_SLOT
I (244718) main: LDL_MAC_JOIN_TIMEOUT

TTN console:
TTN console

ticksUntilNextEvent keeps returning UINT32_MAX

Hello,
I've been trying to use the library with my STM32L4 in Stop2 mode.
I'm using a software 32bit timer with my LPTimer to make it work all together as you told me to in my last issue.
The problem is happening at 2 different points in my program :

  • right after the boot state : any subsequent run in LDL_mac_process after some time resolves the issue
  • in the joining process, during the wait_RX window : the debug messages say the channel is ready then I get UINT32_MAX and any subsequent run in LDL_mac_process doesn't help.

I'm using a SX1261 with the STM32L412KB, the timer used is LPTIM1 clocked at 1000KHz. The interrupt on pin DIO1 is getting handled and I'm calling LDL_Radio_handleInterrupt inside the callback.

I actually had no issue when not going into stop mode and simply looping with the LDL_mac_process.

I've tried forcing the loop through LDL_mac_process using LDL_MAC_priority but then it means the mcu is looping during a whole TX-RX sequence.

Thank you for your help

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.