void hwInternalSleep(unsigned long ms) { // Let serial prints finish (debug, log etc) #ifndef MY_DISABLED_SERIAL MY_SERIALDEVICE.flush(); #endif while (!interruptWakeUp() && ms >= 8000) { hwPowerDown(SLEEP_8S); ms -= 8000; } if (!interruptWakeUp() && ms >= 4000) { hwPowerDown(SLEEP_4S); ms -= 4000; } if (!interruptWakeUp() && ms >= 2000) { hwPowerDown(SLEEP_2S); ms -= 2000; } if (!interruptWakeUp() && ms >= 1000) { hwPowerDown(SLEEP_1S); ms -= 1000; } if (!interruptWakeUp() && ms >= 500) { hwPowerDown(SLEEP_500MS); ms -= 500; } if (!interruptWakeUp() && ms >= 250) { hwPowerDown(SLEEP_250MS); ms -= 250; } if (!interruptWakeUp() && ms >= 125) { hwPowerDown(SLEEP_120MS); ms -= 120; } if (!interruptWakeUp() && ms >= 64) { hwPowerDown(SLEEP_60MS); ms -= 60; } if (!interruptWakeUp() && ms >= 32) { hwPowerDown(SLEEP_30MS); ms -= 30; } if (!interruptWakeUp() && ms >= 16) { hwPowerDown(SLEEP_15MS); ms -= 15; } }
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! cli(); // attach interrupts _wakeUp1Interrupt = interrupt1; _wakeUp2Interrupt = interrupt2; if (interrupt1 != INVALID_INTERRUPT_NUM) attachInterrupt(interrupt1, wakeUp1, mode1); if (interrupt2 != INVALID_INTERRUPT_NUM) attachInterrupt(interrupt2, wakeUp2, mode2); if (ms>0) { // sleep for defined time hwInternalSleep(ms); } else { // sleep until ext interrupt triggered hwPowerDown(SLEEP_FOREVER); } // Assure any interrupts attached, will get detached when they did not occur. if (interrupt1 != INVALID_INTERRUPT_NUM) detachInterrupt(interrupt1); if (interrupt2 != INVALID_INTERRUPT_NUM) detachInterrupt(interrupt2); // Return what woke the mcu. int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up if (interruptWakeUp()) ret = static_cast<int8_t>(_wokeUpByInterrupt); // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; return ret; }
int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, uint32_t ms) { // ATMega328P supports following modes to wake from sleep: LOW, CHANGE, RISING, FALLING // Datasheet states only LOW can be used with INT0/1 to wake from sleep, which is incorrect. // Ref: http://gammon.com.au/interrupts // Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt() // and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled! cli(); // attach interrupts _wakeUp1Interrupt = interrupt1; _wakeUp2Interrupt = interrupt2; // Attach external interrupt handlers, and clear any pending interrupt flag // to prevent waking immediately again. // Ref: https://forum.arduino.cc/index.php?topic=59217.0 if (interrupt1 != INVALID_INTERRUPT_NUM) { clearPendingInterrupt(interrupt1); attachInterrupt(interrupt1, wakeUp1, mode1); } if (interrupt2 != INVALID_INTERRUPT_NUM) { clearPendingInterrupt(interrupt2); attachInterrupt(interrupt2, wakeUp2, mode2); } if (ms > 0u) { // sleep for defined time hwInternalSleep(ms); } else { // sleep until ext interrupt triggered hwPowerDown(WDTO_SLEEP_FOREVER); } // Assure any interrupts attached, will get detached when they did not occur. if (interrupt1 != INVALID_INTERRUPT_NUM) { detachInterrupt(interrupt1); } if (interrupt2 != INVALID_INTERRUPT_NUM) { detachInterrupt(interrupt2); } // Return what woke the mcu. // Default: no interrupt triggered, timer wake up int8_t ret = MY_WAKE_UP_BY_TIMER; if (interruptWakeUp()) { ret = static_cast<int8_t>(_wokeUpByInterrupt); } // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; return ret; }
void hwInternalSleep(uint32_t ms) { // Sleeping with watchdog only supports multiples of 16ms. // Round up to next multiple of 16ms, to assure we sleep at least the // requested amount of time. Sleep of 0ms will not sleep at all! ms += 15u; while (!interruptWakeUp() && ms >= 16) { for (uint8_t period = 9u; ; --period) { const uint16_t comparatorMS = 1 << (period + 4); if ( ms >= comparatorMS) { hwPowerDown(period); // 8192ms => 9, 16ms => 0 ms -= comparatorMS; break; } } } }
int8_t hwSleep(uint32_t ms) { // Return what woke the mcu. // Default: no interrupt triggered, timer wake up int8_t ret = MY_WAKE_UP_BY_TIMER; if (ms > 0u) { // sleep for defined time hwInternalSleep(ms); } else { // sleep until ext interrupt triggered hwPowerDown(WDTO_SLEEP_FOREVER); } if (interruptWakeUp()) { ret = static_cast<int8_t>(_wokeUpByInterrupt); } // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; return ret; }