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
84 stars 60 forks source link

modem.endpacket() fails #39

Open sslupsky opened 5 years ago

sslupsky commented 5 years ago

This is probably more a question than a problem.

I have on several occasions noticed that when I attempt to sent a packet, I receive an error with the call to modem.endpacket(). I prepare and send the packet as follows:

modem.beginPacket(); modem.write( (uint8_t *) &sensorPayload, sizeof(sensorPayload)); err = modem.endPacket(false); if (err > 0) { ...

I have noticed that sometimes endPacket() returns an error. Often the next time (about 10 seconds later) the loop tries to send a packet it goes through. On several occasions though, I have noticed that I get into a loop where the endPacket() always returns an error and the packet is never sent. I have noticed this behaviour occasionally when the device has not joined the network. At other times, it appears that the device joined the network but still will not send a packet.

I am struggling to understand why that would happen.

Would is be appropriate that beginPacket() be preceded first by a check to connected() to confirm that the device is still connected? Can the module "loose" its' join status from time to time?

sslupsky commented 5 years ago

I have been considering edge cases and have identified an issue where after a device joins a network and is then moved out of range of the gateway, the device continues to send packets and is not aware the packets have not reached the gateway.

I expected that somewhere along the way, the gateway would request a status (once per hour or once per day?). Perhaps this did occur but the device was out of range and did not receive the downlink. Does the murata module firmware have a timer that tracks the last time the gateway talked to the device? I am not even sure if this is something built into the LoRaWAN specification. It seems to me that if the device hasn't heard from the gateway in a while, there should be a way to identify that condition.

At the moment, the only way I can think to do so is to queue a confirmed packet every once in a while. I'm not sure thought that will work with the current firmware because of the blocking timeouts, the period between transmissions (in my case 2 mins), sleeping and watchdog. That is, it is undesirable to stay awake several seconds (or up to 16 minutes if the packet is retried up to 8 times) waiting for a confirmed packet.

We should give some consideration to providing a state machine and asynchronous function(s) that allows the device to determine the state of the network and the last time there was communication with the gateway. connected() returns the join state but doesn't really tell you if the device has stopped communicating with the gateway for some reason. Moreover, an asynchronous function to check the confirmed packet status would be helpful so that when you wake from sleep, you can check if the sent packet was confirmed.

I think a state machine could also help with checking the receive status as well when you wake from sleep.

sslupsky commented 5 years ago

Regarding the endpacket() issue, there are some hints in lora_send() here: https://github.com/arduino/mkrwan1300-fw/blob/63787fe5ed8bd07119caba20d2065a26004b2261/Projects/Multi/Applications/LoRa/AT_Slave/src/lora.c#L734

However, the return value is a generic "busy". I think it would it be helpful if the return value was the actual busy condition?

facchinm commented 5 years ago

AFAIK, the rejection policies (which concur to define the maximum message rate) are internally handled by the LoRa standard (duty cycle, transmission windows and so on). As you correctly found, the only way to know if you are still "connected" (not the right word) is to send a confirmed packed once in a while. To reduce the blocking timeouts I suggest to use one of the spare GPIOs as IRQ to signal that a message is available. This would require some addition to both the FW and the library.

sslupsky commented 5 years ago

Thank you for the feedback.

I like the idea of the GPIO connection. Sort of like a flow control line. Is there any chance you could add a GPIO connection from the Murata module to the SAMD in the board rev you guys are working on?

facchinm commented 5 years ago

There are already a few unused gpios, no need to wait for the new revision. It's "only" a matter of finding the time to implement it (or accepting the right pull request :wink: )

sslupsky commented 5 years ago

Apologies, I am missing something here? I had a look at the MKRWAN schematic and, other than the existing SPI connections, there are no other no electrical connections from the module to the samd21? So, to use a hardware handshake would require a physical connection?

Is there some way to agree on what pins will be reserved for this purpose so when you guys update the board, the modification will be implemented?

I can in the mean time likely hack the existing board as you suggest.

BTW, any word on when the new board will become available?

sslupsky commented 5 years ago

PA28 on the samd21 looks like a nice potential candidate.

facchinm commented 5 years ago

PA13_SCK and PA14_RF_SSN are also unused on the actual library but are routed (we use them in "dumb" mode). In normal operation mode thay could be used for this kind of "ring" indication.