-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LMIC and sleeping MCUs #380
Comments
Hi @Mark-Wills, when I use this library while sleeping, there are two things I worry about. I am careful not to sleep with the LMIC is active. This can be done in a number of ways, because on a Class A device, after joining, the LMIC only becomes active when the application transmits a message, and it will become inactive after a fairly predictable delay (worst case). The delay can vary based on network behavior, etc. However, as we add the rest of the obscure features of the spec, this becomes less predictable, because the network can do things like sending a chain of confirmed downlinks. This will keep the LMIC active indefinitely. Because of this concern, there's a newish API, The second critical issue with the current LMIC HAL is the value of millis() -- this must advance in sync with real time. You must arrange to update this after you wake up, or you must modify the code that implements os_getTime() to allow it to return a value that is otherwise locked to real time. On the Adafruit / M0 BSP, I had to modify the BSP to add an API, |
Thanks very much for the heads up regarding Your comments regarding changing I came up with the following code (which is specific to the AVR, I'm afraid):
I put the ATMEGA to sleep in blocks of 8 seconds, which the largest amount of time it can sleep for. So it could be used like this:
I have tested the above code in isolation and it appears to work perfectly: extern volatile unsigned long timer0_millis;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(millis());
delay(2000);
advanceMillis(10000);
}
void advanceMillis(unsigned long offset) {
uint8_t oldSREG = SREG;
cli();
timer0_millis += offset;
SREG = oldSREG;
} Next step will be to integrate this into my application and see if I can pull it all together. Adding this functionality to the library might be tricky as there is no gurantee that Regards Mark |
@Mark-Wills, would be happy to include such an example. |
What I did when I was still using LMiC was to sleep in the OS scheduler itself, until just before the next scheduled event, in effect by replacing the delay function that was being used with a state-preserving sleep (my sleep code busy waits instead if given a short interval). For a while I had odd code to patchup the running ticks counter from the RTC on wake, eventually I just used a fresh RTC reading anywhere the time was needed (and because the RTC on my chip wants to do leap years and other nastiness that would make converting back to monotonic time painful, I only let it run from midnight 1/1/1970 for about ten minutes, then accumulate that to an offset maintained by the reading code and reset the RTC) I'd avoid not sleeping when unjoined, as that means that a node that powers up out of range of a gateway with working backhaul will set about quite enthusiastically draining its battery. |
@cstratton That will work. There is a known bug (#2) with join implementation that causes battery drainage as well as network issues if you have a dense deployment of thousands of devices; I’ve just identified the root cause so perhaps I’ll have a fix for that someday soon. This bug is (like many LMIC things) much worse for US-like bandplans. For EU, it honors the duty cycle. |
Oh was just simple.
the wake_count I'll reload in setup. |
@OstertagM yes, as long as you save |
Hi Guys, I ask you for help on a firmware problem. void loop(void) { |
What does not work? The sleep period the downlink / uplink? |
LMIC.opmode |
switch on the debug of lmic and post it here. What activation method do you use? Are you joined? |
You can use os_queryTimeCriticalJobs to determine if the unit can sleep or not. if(!os_queryTimeCriticalJobs(ms2osticksRound(9000)))
Serial.println("Can sleep");
else Serial.println("Cannot sleep"); The code above determines if there are any scheduled jobs within the next 9 seconds. Regards Mark |
@Mark-Wills OK thanks also I will try. Could be better for me. |
One thing is setting to deep sleep to very long time you if you Arduino youd should do:
Because all examples shows it without ULL and I wondered why it didn't worked even it should.
But without testing this query. I saw that I am here always in the case to can a sleep. |
What would be a best practice to do this? Saving and reloading (which?) parts of LMIC struct? |
As you can see I just save |
Hello Mark, Do you know how could this be done on ESP32? |
I think there are many different ways to do it with an Esp32. Essentially is to store the state know how many time is gone and restore the state. Perhaps somebody can tell here which variables or functions returns the state in joined case. |
Regarding that, #460 (comment) |
As mentioned in #460, see https://github.com/mcci-catena/arduino-lorawan for a (c++) example of saving and restoring session information, and https://githhub.com/mcci-catena/Catena-Arduino-Platform for a (very elaborate) library that actually uses the apis to save and restore info as needed. |
thanks for your reply @terrillmoore, I've already looked at https://github.com/mcci-catena/arduino-lorawan but only at the examples level and well let's say my code was already at an advanced state when I found this wrapper library so I didn't want to redo all my work and go to a C++ styled coding; but know looking at the structure inside the classes I can see this: struct SessionInfoV2 I guess I have to save all this variables from the LMIC, on bold is what I'm at the moment saving before going into deepsleep, I guess I can add the other variables as well and save them on RTC memory space of ESP32. Regarding https://githhub.com/mcci-catena/Catena-Arduino-Platform, could you be a little more specific, it's a huge library and I'm a little bit lost on what should I be looking. Thanks again and regards from Paris |
Question: what is the suggested method/technique to use this library with an MCU that sleeps? I'm using it with AVR, and I sleep the MCU for blocks of 8 seconds. I've used this technique successfully before, however, while attempting to use this technique with the LMIC library the system crashes and resets.
Are there any special considerations / rules that I need to follow to allow the MCU to sleep? Do I need to adjust the LMIC clock in some way?
Thanks
Mark
The text was updated successfully, but these errors were encountered: