arduino-lmic icon indicating copy to clipboard operation
arduino-lmic copied to clipboard

Adding Method to Adjust hal_ticks Upon Waking Up from Sleep

Open rocketscream opened this issue 7 years ago • 7 comments

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.

rocketscream avatar Aug 01 '17 11:08 rocketscream

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).

matthijskooijman avatar Aug 01 '17 11:08 matthijskooijman

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!

rocketscream avatar Aug 01 '17 15:08 rocketscream

Hello. What is the proposal to implement this? Did it get resolved?

tierralibre avatar Oct 16 '17 09:10 tierralibre

This indeed a problem when I put my rocketscream board into sleep mode with SF12. A solutions would be nice.

braadworst avatar Feb 05 '18 05:02 braadworst

:+1: Would be great to have some kind of a solution or workaround.

T94T avatar Apr 25 '18 10:04 T94T

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!

T94T avatar Apr 25 '18 11:04 T94T

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.

matthijskooijman avatar Nov 14 '18 16:11 matthijskooijman