Project

General

Profile

Problem with Sleepy::loseSomeTime using ATtiny85

Added by RobJW about 4 years ago

I am running some low power nodes who's sleep should be interrupted if a signal is detected from a PIR. The PIR is wired to generate an external interrupt (INT0). Interrupts are handled correctly when the code is compiled for a ATmega328p, but not when compiled for an ATtiny85.

loseSomeTime should return a 1 if the processor has had a full sleep and 0 if interrupted in the middle of its snooze. With the ATtiny, loseSomeTime only returns 1. Otherwise loseSomeTime is functioning as expected: the sleep is the correct duration, i.e. timer0_millis is incremented by the msec spent asleep. Fascinating! I'd really appreciate any thoughts on what might help my sleep problem!

Here's the code:

// boilerplate for low-power waiting
ISR(WDT_vect)
{
Sleepy::watchdogEvent();
}

void wakeUp()
{
// Just a handler for the pin interrupt.
}

main loop:

// Allow wake up pin to trigger interrupt on low to high transition.
// Enter power down state with ADC and BOD module disabled.
// loseSomeTime returns a 0 if an interrupt occurred
// a packet is sent every sleep_time * no_sleeps
int sleep_count = 0;
while (!movement && (sleep_count < no_sleeps))
{
attachInterrupt(digitalPinToInterrupt(wakeup_pin), wakeUp, CHANGE); // with 328P can use RISING but not ATtiny85
movement = !Sleepy::loseSomeTime(sleep_time); // time to sleep in msec - up to 65536
// Disable external pin interrupt on wake up pin.
detachInterrupt(digitalPinToInterrupt(wakeup_pin));
sleep_count = ++sleep_count;
}
// assemble packet

If I change the code to set a flag in wakeUp(), the ISR for INT0, then the while loop terminates early. This suggests that external interrupts are indeed processed, but not until after the watchdog has timed down

Changed code

volatile bool movement;
movement = false;

// boilerplate for low-power waiting
ISR(WDT_vect)
{
Sleepy::watchdogEvent();
}

void wakeUp()
{
movement = true;
}

main loop:

// Allow wake up pin to trigger interrupt on low to high transition.
// Enter power down state with ADC and BOD module disabled.
// loseSomeTime returns a 0 if an interrupt occurred
// a packet is sent every sleep_time * no_sleeps
int sleep_count = 0;
while (!movement && (sleep_count < no_sleeps))
{
attachInterrupt(digitalPinToInterrupt(wakeup_pin), wakeUp, CHANGE); // with 328P can use RISING but not ATtiny85
ignorethisflag = !Sleepy::loseSomeTime(sleep_time); // time to sleep in msec - up to 65536
// Disable external pin interrupt on wake up pin.
detachInterrupt(digitalPinToInterrupt(wakeup_pin));
sleep_count = ++sleep_count;
}
// assemble packet