arduino-lmic
arduino-lmic copied to clipboard
Adding Method to Adjust hal_ticks Upon Waking Up from Sleep
A simple method of sleeping would be placing the sleep code in the EV_TXCOMPLETE event. But, upon waking up from sleep for a period of SLEEP_PERIOD, the hal_ticks will be off by that amount. Having a method to adjust this hal_ticks will prevent the transmission being rejected due to duty cycle violation as the OS might think transmission is back-to-back as micros() and millis() doesn't run during sleep.
See also https://github.com/arduino/Arduino/issues/5087 for a more thorough way to solve this (but, until that happens, fixing this in LMIC is a sound idea).
I think passing a value in unit of seconds is better suited for LMIC as transmission interval can varies from a minute (for lower SF) to even few hours once (or even a day once!). The LMIC would then convert this seconds to the correct value in ms and us. This would avoid confusion for end user to deal with ms and us. By adding this important adjustment, I believe it would iron out possible bug (people that incorrectly think why the duty cycle check is incorrect). On older branch of the library, there is a variable called addTicks
which I think would help to make the implementation easier but it is no longer present in the current version. Thanks for the great work on the library!
Hello. What is the proposal to implement this? Did it get resolved?
This indeed a problem when I put my rocketscream board into sleep mode with SF12. A solutions would be nice.
:+1: Would be great to have some kind of a solution or workaround.
Found it: You can reset the duty cycle limits after sleep by calling:
LMIC.bands[BAND_MILLI].avail = os_getTime();
LMIC.bands[BAND_CENTI].avail = os_getTime();
LMIC.bands[BAND_DECI].avail = os_getTime();
Ensure to still meet all LoRa regulations!
A while ago, I implemented a workaround by updating the Arduino timer value. This uses internal Arduino variables, so is likely to break at some point if Arduino changes its implementation. It is also specific to the AVR Arduino core, other architectures likely need something else. Still, here it is (from here):
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
extern volatile unsigned long timer0_millis;
extern volatile unsigned long timer0_overflow_count;
timer0_millis += slept;
// timer0 uses a /64 prescaler and overflows every 256 timer ticks
timer0_overflow_count += microsecondsToClockCycles((uint32_t)slept * 1000) / (64 * 256);
}
Here, slept
is the number of millseconds spent in sleep.