How long have I been asleep? System.sleep(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long seconds)

I am using the function in the topic to sleep until the pin wiggles or the sleep times out with the given duration. What I want to know when the system awakes is how much time has elapsed in sleep mode?

I discovered several interesting things while experimenting with this to see if I can figure this question out.

  1. You can immediately on waking query the state of the wakeUpPin to determine if it, or the timeout was the cause of your waking. It seems to work very fast, and even just a millisecond or two pulse is correctly queried.
  2. If you have attached your own interrupt to the pin that is used as wakeUpPin , not only does it wake you up, but your ISR is called too.
  3. It appears that “millis()” gets frozen in time during the sleep period, and that when you awaken it is as if 0 time has elapsed on that timer. I haven’t tried “micros()”

I know that I could connect to the network, wait for the network time to synchronize and then use the real-world time to get a good guess. However, there must be a timer that is counting down for the timeout feature of this to work, so I was hoping there is some way to read out the current value of that timer when you awaken.

A suggestion would be that this system call just return the value of the timer when you awaken … this could simultaneously tell you how much time is left, and if 0 that you were awaken by the timer, not the pin.

Thanks for any help.

The timed wake is not done via a countdown but by an interrupt triggered by the RTC and hence taking that time will give you the best results.
Just store the time before your device went to sleep and compare with the time of wake, which doesn’t have to be synced first, as the RTC keeps the time anyway.

The pin read does not work reliably for deep sleep or non-mechanic triggers which could be just a few µs.

micros() will be frozen too.

2 Likes

Perfect! Thank you very much. I can’t wait to get home and try it.

@ScruffR worked perfectly, thank you. I now have this code which works well:

void goIntoLowPowerMode()
{
    int sleepLeft = SLEEP_PERIOD;
    int startSleep = Time.now();
    while (sleepLeft > 0) {
        int rainCounterBeforeSleep = rainCounter;
        System.sleep(RAIN_PIN, FALLING, sleepLeft );
        sleepLeft = SLEEP_PERIOD - (Time.now() - startSleep);
        if (sleepLeft > 0) {
            // RAIN_PIN was tripped because there is time left on the timer
            // Wake just long enough to count the pulse, then go back to sleep for remaining time
            unsigned long timeout = millis();
            while (rainCounterBeforeSleep == rainCounter && millis() - timeout < 10) delay(1); 
        }
    }
}

If the pin falls and causes System.sleep to return, do you know if the ISR also attached to the falling edge of that pin will get called immediately so I can count the pulse, before I get around the loop and back into the sleep? Or is that indeterminate? I’m just wondering if that code I have above waiting for the count to increment is necessary.

I’d wouldn’t rely on the interrupt to be counted, but I’d also have a test setup to check.

My immediate feeling would be a secondary ISR would not be triggered, but as you pointed out, you saw it happen.
Having another controller producing wake pulses of different durations might be a possible setup to get empiric data.

1 Like

The line is pulled low by a mechanical switch actuated by a magnet passing. I’ve tried it dozens of times physically moving the magnet, generating pulses of a few milliseconds in length, and the secondary ISR gets called every time (with the code above). I guess it doesn’t matter to leave that code in, so long as it is reliable. I was just wondering if there was some guaranteed contract on the secondary ISR getting called. I guess not that you know of. Thanks again.