Arduino to sleep: wakeup on external interrupt OR timer > 8s

Hi,
I have an issue while trying to save energy with my Arduino.
So, putting the arduino to sleep using the LowPower library is an easy task.
Waking up the arduino every 8s or 4s is also easy with this library.
Waking up the arduino using an external interrupt coming from a PIR is also easy.
But ... I would like to wake up the Arduino every 5mn (looping the 8s or 4s sleep could do the job but this is definitively not working for interrupt) OR before 5mn if a PIR interruption rises.

I have been browsing internet without any success, so I am hopping someone has an answer since this seems something a lot of peapole want to do.

Thanks in advance!

strus_fr:
I would like to wake up the Arduino every 5mn (looping the 8s or 4s sleep could do the job but this is definitively not working for interrupt)

What do you mean by "this is definitively not working for interrupt"?

Which "LowPower" library are you using? The one by rocketscream?

Hi

Yes, the LowPower library from Rockscream.
Also, the library seems to work with the interrupt when I only do one 8s sleep, but as soon as i put a "for" loop to sleep longer (38 times to be extact) the interrupt happens ... randomly and not as soon as I dance in front of the pir :slight_smile:

Also, on the Uno, if I take the current between the 5v and gnd of the arduino during the sleep mode, i have something lile 300mA ... far away from the microA ... any idea ?

Any idea?
Thanks!

Yes, the LowPower library from Rockscream.

Do you have a link?

ur

"for" loop to sleep longer (38 times to be extact)

needs to check for a pending interrupt... :slight_smile:
in case of a pending interrupt it should break, so that interrupt handling can take place...

why do u want to sleep more than 8sec?

how much current does it draw when it is not sleeping?
what sleep mode does that library use?
there r different sleep modes: idle (mA), adc (mA, but less noise than idle) and deep (uA)...

Thanks for the answers, here are the requested details:

  1. The LowPower arduino library is the following:
    http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/

  2. I want to sleep more than 8s since I need to read the sensors once every 5mn (but during this sleep time, the PIR should be able to interrupt the sleep and put the arduino back to sleep)

  3. I think the library is using: SLEEP_MODE_PWR_DOWN

From what I have read, is it possible that I am in the following situation:

Warning Code like this, which is a typical example of sleep code, can cause a problem if you are relying on the interrupt to wake you from sleep: (this is typically what is done when yopu are using the LowPower library since I call the attachInterrupt function, the call LowPower.powerDown(...) function):

attachInterrupt(0, pin2_isr, LOW);
/* 0, 1, or many lines of code here */
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_enable();
sleep_bod_disable();
sei();
sleep_cpu();
/* wake up here */
sleep_disable();

"The problem is if the interrupt occurs after attachInterrupt but before sleep_cpu(). The ISR will run, the interrupt will be detached, and then the CPU will enter sleep mode with no interrupt enabled. The MCU will never wake up this way. Fortunately there is a solution. The sleep enable bit can be cleared during the ISR and thus the MCU will not go to sleep. "

And that means the library should be modified to take into account this kind of situation, or that I should write directly the piece of code without relaying on this library, no?

Even if I could fall in this situation sometimes ... I cannot get why the behavior I have happens all the time.

So, what do you think I should do? (the power consumption I have noticed is not the main issue, so let's focus on the interrupt and sleep for 5mn issue first). Thanks.

isnt the power consumption the only reason for all this? :slight_smile:

would it b ok, if it just sleeps 16msec and then looks, if the PIR acts up?
i mean: no other interrupts but the watchdog interrupt?
ur timing would b more accurate then even if the PIR is upset...
or is the PIR signal too short?

what about this structure (in PSEUDOCODE):

void setup() {
attachInterrupt to function handler()
configure watchdog to 8SEC interrupt mode (no reset)
}

uint8_t workpending=0;
void handler() { workpending=1U; }

void loop() {
  for (uint8_t i=0U; i<(5U*60U)/8U; i++) {
    cli(); // no interrupt can b missed now
    if (workpending) { workpending=0; and do the PIR work now }
    power save (ADCSRA=0, ACSR=1<<ACD; PRR)
    // PIR interrupt is already enabled in setup();
    sei(); // pending interrupts will b processed after next instruction, so we dont sleep forever 
    asm("sleep\n"); // wakeup after 8SEC or after PIR interrupt
  }
  read the sensors after about 5 minutes (there is not way to say, how many seconds of sleep we skipped due to the PIR interrupt - or u check the WDIF after sleep...)...
}

ok, I will try that and another solution I found. I will keep you in touch asap.
Thanks

Hi,

Ok I have updated my code to do something like (pseudo-code):

volatile int isInterrupted = 0;
int i = 0;
loop() {
    readSensors():
    sleep();
}

wake() {
    detachInterrupt(0);
    isInterrupted = 1;
}

sleep() {
    isInterrupted = 0;
    attachInterrupt;
    LowPower.powerDown(SLEEP_8S); // sleep for 8s
    delay(75); // allows the arduino to fully wake up.
}

void readSensors() {
    if (interrupted) {
       buzzer();
   } else {
       if (i<30) { // means 8s of sleep 30 times ... 
         i++;
       } else {
          //read the sensors
         ...
      }
   }
}

This seems to work, even if I am not sure that I get the most efficiency from this sleep method. I do not miss PIR interruptions anymore.
Any suggestion?

why do u detach and attach the interrupt handler?
cant u just attach the interrupt handler once in setup()?

Hi
Simply because I do not want to be interrupted by the PIR when I send a message using RF for the moment, and that is what I do during wake-up time.

ok... :slight_smile:
r u sure that ur RF routine is not interrupt proof?
but it looks like u cant really miss a PIR interrupt very often...

Hi,
can anyone send me code to keep the arduino in wake up mode for jus 3 seconds and then after 3 seconds it should enter sleep mode.
my code is as follows
#include<avr/sleep.h>

void setup()
{
Serial.begin(9600);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
pinMode(2,INPUT);
digitalWrite(2,HIGH);
}

void loop()
{
delay(3000);
sleepSetup();
}
void sleepSetup()
{
sleep_enable();
attachInterrupt(0,pinInterrupt,LOW);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
digitalWrite(13,LOW);
sleep_cpu();
Serial.println("WOKE UP");
digitalWrite(13,HIGH);

}
void pinInterrupt()
{
sleep_disable();
detachInterrupt(0);
}