How does waking up by external interrupt from SLEEP_MODE_PWR_DOWN work?

Status
Not open for further replies.

liuhuan

Member
Dear Paul and friends,

I am able to put Teensy++ 2.0 into SLEEP_MODE_PWR_DOWN and wake it up using an external interrupt. However, I do not fully understand the wake up process. I wonder if you could help me with the following questions. Thanks!

1. From my testing, it seems to me that (1) the attached interrupt function gets executed, then (2) the loop() function gets executed. Is this order correct?
2. The attached interrupt function seems to have bad timing. I have set a LED to be on for 5 seconds, but it stays on for only 1 second. Why is this?
3. Both the attached interrupt function and the loop() can finish execution successfully, if I only include digitalWrite to LED. If I include a digitalWrite to a PIN with load, then the execution stops there. What might have caused this? Is there a way to know the error message?

Finally, I'm running Teensy++ 2.0 at 2MHz with Sd card. I use Teensyduino 1.0.3. Please let me know if you need any more info.

Thanks!

Huan
 
Last edited:
Hi Pete,

Thanks for the reminder! The code below shows the timing problem in the attached interrupt function.

Questions:
1. From my testing, it seems to me that (1) the attached interrupt function gets executed, then (2) the loop() function gets executed. Is this order correct?
2. The attached interrupt function seems to have bad timing. I have set a LED to be on for 5 seconds, but it stays on for only 1 second. Why is this?

Code:
const int ledPin = 6;
const int wakeupPin = 2;
volatile int wakeState=1;

void wakeUp()
{
  Serial.println("in wakeUp()");
  if (wakeState==0)
  {
    wakeState=1;
    digitalWrite(ledPin,HIGH);
    delay(5000);
    digitalWrite(ledPin,LOW);
    delay(5000);
    Serial.println("done wakeUp()");
  }
}

void setup()
{
  Serial.begin(38400);
  
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  pinMode(wakeupPin, INPUT_PULLUP);

  attachInterrupt(wakeupPin, wakeUp, FALLING); //LOW,RISING, FALLING,CHANGE
  
  powerdown();
  Serial.println("done init");
}

#include <avr/sleep.h>

void powerdown() {
  wakeState=0;

  Serial.println("bye world!");
  delay(1000);
  Serial.end(); // shut off USB
  ADCSRA = 0;   // shut off ADC
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  noInterrupts();
  sleep_enable();
  interrupts();
  sleep_cpu();
  sleep_disable();
}

void loop() 
{
  if (wakeState==1) {
    digitalWrite(ledPin,HIGH);
    delay(1000);
    digitalWrite(ledPin,LOW);
    delay(1000);
    digitalWrite(ledPin,HIGH);
    delay(1000);
    digitalWrite(ledPin,LOW);
    delay(1000);
    digitalWrite(ledPin,HIGH);
    delay(1000);
    digitalWrite(ledPin,LOW);
    delay(1000);
    powerdown();
  }
}

I'll post the code for question 3 soon. Thanks for your help!
 
Everything in the setup functions is executed first. Then the loop function is executed repeatedly.
It is not a good idea to call powerdown() in setup. You should do that in loop().
You must not call delay() in an interrupt routine because it puts the processor to sleep.

Pete
 
No, it's not in the manual. I've used Teensy and Arduino long enough, and a lot of other computers before that, to know that the interrupt routine must execute as quickly as possible, otherwise you will lose any other interrupts that occur. For example, in your original code you were delaying for 10 seconds in wakeUp during which time a lot of other interrupts can occur.
Also, as a general rule, you should not use anything in the interrupt routine that requires another interrupt.

Pete
 
Status
Not open for further replies.
Back
Top