Go Down

Topic: Arduino to sleep: wakeup on external interrupt OR timer > 8s (Read 5 times) previous topic - next topic

strus_fr

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):
Code: [Select]

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.


RIDDICK

#6
Dec 17, 2012, 11:32 am Last Edit: Dec 17, 2012, 11:34 am by RIDDICK Reason: 1
1.
isnt the power consumption the only reason for all this? :-)

2.
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?

3.
what about this structure (in PSEUDOCODE):
Code: [Select]

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...)...
}
-Arne

strus_fr

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

strus_fr

Hi,

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

Code: [Select]
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?


RIDDICK

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

Go Up