arduino-libraries / MKRWAN

An Arduino library for sending and receiving data using LoRaWAN protocol and LoRa® radios.
https://www.arduino.cc
GNU Lesser General Public License v3.0
86 stars 60 forks source link

Not receiving downlink during SAMD21 sleep #36

Open sslupsky opened 5 years ago

sslupsky commented 5 years ago

I have noticed an anomaly with the MKRWAN library that prevents the application from receiving a downlink payload.

When sending a downlink to a MKR WAN device, I can see the downlink queued by the server. I configured the device to confirm the downlink and I see the ACK in the server log. This occurs when the SAMD21 is sleeping or awake which makes sense since the LoRa stack is running on the Murata module.

When the SAMD21 wakes from sleep and checks the receive buffer using available(), there is nothing in the receive buffer. That is, a call to available() returns 0. If I replace the call to deepsleep() with a delay() to prevent the application from sleeping, the call to available() indicates there is something in the buffer and I can read it out.

Which device coordinates the data transfer between the SAMD21 and the Murata module?

sslupsky commented 5 years ago

The schematic suggests that the SAMD21 is the master SPI device. That suggests the SAMD21 polls the Murata module for status and data.

sslupsky commented 5 years ago

Looking further into MKRWAN.h, I think this problem has something to do with the stream. Perhaps the default timeout which I think is 1000ms? I reduced the time in deepsleep to 500ms but this did not make a difference in whether or not the payload was received by the application.

Does the mkrwan murata module firmware buffer the receive data?

sslupsky commented 5 years ago

I looked into the module firmware and the receive data in the murata module is buffered. Moreover, the receive data buffer is returned in response to a poll with the at_Receive command.

I think I see the source of the problem. The murata module firmware calls at_receive asynchronously when it receives a LoRa downlink:

static void LoraRxData(lora_AppData_t *AppData) { set_at_receive(AppData->Port, AppData->Buff, AppData->BuffSize); at_Receive(NULL); }

To fix this, we need an option that allows us to turn off the call to at_Receive() in the murata module and add a function to the MKRWAN API that allow us to call this function from our application. That way, when we sleep, we will not miss the asynchronous transmission of data from the module.

remuslazar commented 4 years ago

@facchinm Is there any update on this issue? I run into the same issue, I workaround it by not using the LowPower.deepSleep() for the "receive window" time period, which I configured to be 2 seconds after every tx attempt.

sslupsky commented 4 years ago

@remuslazar to my knowledge there is no fix for this at the moment. The work described above was a method to defer the delivery of a downlink message from the module to the MCU until the MCU wakes up and polls the module. The workaround you described sounds reasonable but requires the MCU to stay awake longer.

I recently developed a zephyr driver that addresses this issue. It is likely possible to use the ideas from that driver to fix this issue. Note, the fix would require changes to the Sercom drivers. I am not sure if Arduino would allow changes to these drivers as well.

I have found since using my zephyr driver that there are several other downlink messages (ADR related) that are being dropped by the existing driver.

remuslazar commented 4 years ago

@sslupsky thank you for your feedback!

I don't quite understand why there is a problem with the current implementation; when the Murata Module buffers the data until the MCU polls it, why is there a problem when the MCU sleeps? The received data should stay there until the MCU wakes up and fetches it. Could you please elaborate a little bit more on that?

Fixing the firmware and also the MKRWAN library is definitely an option but there are upcoming efforts to rework both, see https://github.com/arduino-libraries/MKRWAN/issues/64. @facchinm is there a roadmap if/when this will be available?

sslupsky commented 4 years ago

@remuslazar The current module firmware does not buffer the data. When the module receives a downlink, it sends a downlink message data immediately to the attached mcu. If the mcu is sleeping, the message is lost. My proposed changes above implement a method to prevent the sending of the message until the module is polled.

Another way to do this is to implement a data ready interrupt.

However, I have found that because the module uses a slow serial baud rate (19.2kbps), it is possible to wake the mcu from sleep. I have successfully implemented such a method using my zephyr driver. So, when the module sends a UART message, the message causes the SERCOM interface to trigger the SAMD21 to wake up. Such a method would require changes to the Arduino SERCOM driver to work within the Arduino development environment.

remuslazar commented 4 years ago

@sslupsky gotcha, thanks!

remuslazar commented 4 years ago

@sslupsky I just stumbled over https://github.com/arduino-libraries/ArduinoLowPower/pull/20, which additionally adds the nice feature to wakeup the SAMD21 on sercon traffic. So I'm wondering if this can be used to also fix this issue in a more elegant way, not having to fiddle with the current MKRWAN implementation. What do you think?

I will definitely try out your PR, which will also remove the annoying 10ms delay.. currently reading the pio documentation to find out how to use a custom Arduino framework from git.

sslupsky commented 4 years ago

@remuslazar Yeah, that PR needs to be accepted into the LowPower library. I have no idea why it hasn't been discussed or accepted yet.

You should have a close look at the Zephyr Project. The environment is as easy to use as the Arduino environment if you use your own IDE (I use vscode). Zephyr is an open source operating system and falls under the umbrella of the Linux Foundation. The capabilities of the operating system are incredible by comparison to the Arduino IDE and it is evolving rapidly now. The development environment is cross platform as well as the application targets. That is, you can create an application and then build it for different / multiple targets such as SAMDx, SAMEx, Nordic NRF52x, STM32x, Kinetis, x86, etc. IMHO, it is the best thing to happen for embedded development since the beginning of embedded development.

I have put together a zephyr board package for the Arduino MKR WAN 1310. I can share that with you if you are interested. As mentioned earlier, I have also put together a driver for the MKR WAN. If we can get a few more people interested in working on it, we could probably get FUOTA and a few other LoRaWAN features integrated.

I have also put together a zephyr driver for the BQ24195 pmic. That has uncovered another design problem with the MKR series that use this pmic. The interrupt pin of the BQ24195 is not attached to the samd. Unfortunately, this has additional power consumption implications because you have to poll the device.

remuslazar commented 4 years ago

@sslupsky I do agree.. open source development is not as agile as it could be :(

About the Zephyr Project: it sounds really interesting and I will definitely try it out. Currently I'm using PlatformIO with CLion (me being a big fan of all JetBrains IDEs) and PIO supports Zephyr out of the box, so it should work just fine with my current setup. Some time ago I thought about getting my hands on FreeRTOS, but Zephyr looks really nice, also having POSIX Support, cool!

I will come back to you for the MKR WAN 1310 board package but prior I want to gain some basic knowledge about Zephyr, to play around with end evaluate it.

Thanks!

StefanFirefly commented 3 years ago

@facchinm are there any further considerations re. this issue. (I seem to have a similar issue, but when running a Class C device, with MCU in deep-sleep)

reyes73a commented 2 years ago

any news on this? seeing this very same issue on the MKR1310 operating in Class A. Gateway confirms the downlink, which is also removed from the queue, but I see nothing on the MKR1310...