Remainder sleep time upon an interrupt

  • Contest Winner

    I think this is not possible but better to ask...I have a few situations in which I put the board to sleep and it has to wake up based on an interrupt and then has to go to sleep again. The problem is I don't know for how long the board slept til the interrupt because ideally I want it to sleep next only for the remainder time (e.g. if supposed to sleep for 10 minutes and woke up after 2 minutes, I want it to sleep for 8 minutes at the next round).
    Assuming I cannot get the timestamp from the controller or from an attached RTC, is there a way to determine the time elapsed while sleeping since millis() is not reliable?

  • Mod

    @user2684 earlier discussions on this topic:

    The second thread has a way for a solution that I would love to se support for in the MySensors library.

  • Contest Winner

    @mfalkvidd thanks and shame on me for missing these old threads 🙂 Looks like that "ms" is still not globally available and I'd rather not to create my own custom version of the official library 😕 I guess RTC would fit best here, keep asking the time to the controller would have an impact if interrupts happen frequently.
    Thanks again!

  • Mod

    @user2684 you're welcome. For any use case that needs precise timing, RTC is probably the way to go.

    I think there can be use cases where approximate sleeping time (from the ms variable) is sufficient. I don't know a good way to expose the variable though. The sleep function already returns a value, and I don't think c++ can return more than two values unless you wrap them in a struct which might be unnecessarily complex. A global variable is simple but ugly. Adding a pointer as parameter to the sleep function might be a solution, and seems to be the preferred way to do it in C.

  • A coarser but library-compatible way of doing it is to keep a variable with your desired sleep time in it. Each time you wake up from sleep you test if the wake up was caused by interrupt or by the sleep time completing. If it was an interrupt, halve the value of your sleep time variable and call sleep again with the new value. If it was by sleep time expiring, reset your sleep time variable to your desired interval.

    Here's a snippet from a recent sketch where I faced this issue:

    if(sleep(1, CHANGE, (uint32_t)cycleTimer) == MY_WAKE_UP_BY_TIMER) { // Put the CPU to sleep, wake on interrupts
          #ifdef MY_DEBUG
            Serial.println("- Wake From Full Sleep Cycle -");
          cycleComplete = true; // Flag that a full sleep cycle was completed
        } else {
          cycleTimer /= 2; // If we get woken from normal sleep by interrupt, halve the remaining cycle time

    Up in my main loop I use "cycleComplete" to flag that the sleep interval is over and it's time to send some messages, and in that routine "cycleTimer" gets reset to the full interval.

  • Contest Winner

    @Carywin interesting thanks. If I have understood correctly it basically wraps around the sleep function like if I have to sleep 10 minutes I can e.g. sleep at chunks of 1 minute each so to have a better estimation of the remainder time. I'd try to implement this concept as well in NodeManager so to provide multiple alternatives (together with RTC, time from the controller, etc.) in global a "time-aware" enhancement. Thanks again!

Log in to reply

Suggested Topics