Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Teensy++ 2.0 low power wake up on external interrupt

  1. #1
    Junior Member
    Join Date
    Feb 2013
    Posts
    14

    Teensy++ 2.0 low power wake up on external interrupt

    The problem is solved
    I simply need to uncomment the attachInterrupt line in setup(). The interrupt can wake up teensy.
    Also, documentation on sleep modes can be found on page 51 of http://www.pjrc.com/teensy/at90usb1286.pdf


    Dear Paul and friends,

    I am trying to run Teensy on battery and I hope to make the battery last as long as possible.

    My plan is to have Teensy wake up on an external interrupt signal. I can reliably detect the external interrupt signal (please see more info at the end of the post), but I don't know how to write the code to properly put Teensy into and out of sleep mode.

    More specifically, I don't know how to set up Teensy with the interrupt port I wish to wake it up with.

    Below is the code I got from http://www.pjrc.com/teensy/low_power.html . Maybe I'm just missing a line? I have also put some questions inline.

    As you can see, I am a little clueless about how sleep mode works. I would love to be pointed to an external reference where I can learn more about it.

    Thanks for your help!

    Huan

    Code:
    const int ledPin = 6;
    const int wakeupPin = 2;
    volatile int ledState = LOW;
    volatile int ledVal;
    
    void wakeUp()
    {
      Serial.println("in wakeUp()");
      ledState = HIGH;
      Serial.println(ledState);
      Serial.println("Turn on");
      digitalWrite(ledPin, HIGH);
      delay(5000);
      Serial.println("Turn off");
      digitalWrite(ledPin, LOW);
    }
    
    void setup()
    {
      Serial.begin(38400);
      pinMode(ledPin, OUTPUT);
      pinMode(wakeupPin, INPUT);
      //attachInterrupt(wakeupPin, wakeUp, FALLING); //LOW,RISING, FALLING,CHANGE
      ledVal=0;
      digitalWrite(ledPin, ledVal);
      Serial.println("done init");
    }
    
    #include <avr/sleep.h>
    
    void powerdown() {
      digitalWrite(ledPin, HIGH);
      delay(1000);
      digitalWrite(ledPin, LOW);
      Serial.println("bye world!");
      delay(1000);
      Serial.end(); // shut off USB
      ADCSRA = 0;   // shut off ADC
      set_sleep_mode(SLEEP_MODE_PWR_DOWN); // QUESTION: what about PWR_SAVE mode?
      noInterrupts(); // QUESTION: are we disabling the interrupts so that the powerdown procedure can finish?
      sleep_enable();
      interrupts(); // QUESTION: how do I specify which port? can I specify multiple ports?
      sleep_cpu(); // QUESTION: does teensy go to sleep here?
      sleep_disable(); // QUESTION: why do we clear the sleep bit here?
      // QUESTION: will the code below ever get executed?
      Serial.begin(38400);
      delay(1000);
      Serial.println("hello world!");
      delay(1000);
      digitalWrite(ledPin, HIGH);
      delay(1000);
    }
    
    void loop() 
    {
      powerdown();
    }

    I am using Teensy++ 2.0. I have tested the external interrupt with the following code:

    Code:
    const int ledPin = 6;
    const int wakeupPin = 2;
    volatile int ledState = LOW;
    
    void wakeUp()
    {
      Serial.println("in wakeUp()");
      Serial.println("Turn on");
      digitalWrite(ledPin, HIGH);
      delay(5000);
      Serial.println("Turn off");
      digitalWrite(ledPin, LOW);
    }
    
    volatile int ledVal;
    void setup()
    {
      Serial.begin(38400);
      pinMode(ledPin, OUTPUT);
      pinMode(wakeupPin, INPUT);
      attachInterrupt(wakeupPin, wakeUp, FALLING); //LOW,RISING, FALLING,CHANGE
      ledVal=0;
      digitalWrite(ledPin, ledVal);
      Serial.println("done init");
    }
    The external interrupt is set up with a pull up resistor, and I am detecting the falling signal. INPUT in the diagram is connected to INT2 (D2) on Teensy++ 2.0 .
    Click image for larger version. 

Name:	pullup.png 
Views:	367 
Size:	13.2 KB 
ID:	343
    Last edited by liuhuan; 03-25-2013 at 11:20 AM. Reason: solved!

  2. #2
    Member
    Join Date
    Jan 2013
    Location
    Zürich, Switzerland
    Posts
    86

    wakeUp()-function is not called when waking up from sleep (teensy++ 2.0)

    I tried to adapt your code, lihuan, thanks for it. I use a teensy++ 2.0 with an attached button to put it to sleep and an LDR to wake it back up. The µP goes to sleep very nicely when the button (pin 41) is pulled low. It wakes up when the LDR detects turned on light. But I don't understand, why my wakeUp()-function is never called. Instead, the code right below sleep_disable() is called when waking up.

    Does anyone have an idea, why the wakeUp-function is not called?

    Thanks a bunch for any hints!

    Dani

    Code:
    #include <avr/sleep.h>
    
    const int ledPin = 6;
    const int wakeupPin = 0;
    const int buttonPin = 41;
    
    
    void setup()
    {
      pinMode(ledPin, OUTPUT);
      pinMode(buttonPin, INPUT);
      digitalWrite(buttonPin, HIGH); //Pullup
      pinMode(wakeupPin, INPUT);
      attachInterrupt(wakeupPin, wakeUp, FALLING); //LOW,RISING, FALLING,CHANGE
      digitalWrite(ledPin, HIGH);
    }
    
    void wakeUp() // This routine is never called - not even after a successful wake up - Why?
    {
        for (int i = 0; i < 10; i++){
        digitalWrite(ledPin, HIGH);
        delay(500);
        digitalWrite(ledPin, LOW);
        delay(500);
      }
      digitalWrite(ledPin, HIGH);
    }
    
    
    void powerdown() {
      for (int i = 0; i < 10; i++){
        digitalWrite(ledPin, HIGH);
        delay(100);
        digitalWrite(ledPin, LOW);
        delay(100);
      }
      //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(); 
      
      // QUESTION: Why is the code below executed after the wakeup?
    
        for (int i = 0; i < 10; i++){
          digitalWrite(ledPin, HIGH);
          delay(100);
          digitalWrite(ledPin, LOW);
          delay(100);
        }
        digitalWrite(ledPin, HIGH);
    }
    
    void loop() 
    {
      if(digitalRead(buttonPin) == LOW) {powerdown();}
    }
    Edit:
    I think I figured out how it works:
    The µP goes to sleep right after the call of sleep_cpu(); (see code above).
    When the interrupt-trigger has happened, wakeUp() is called but - within the interrupt-function, delay does not work properly. Therefore the LED just flickers strangely.
    After wakeUp(), the function sleep_disable() is called and the board is working as before.

    I hope I'm right with my guesses - any corrections are very welcome!
    /Edit
    Last edited by local_dani_21; 07-02-2013 at 10:44 PM. Reason: I figured out answers to my questions.

  3. #3
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,876
    You can't use delay in an interrupt routine. Your wakeUp function should just set a flag which loop() watches for.

    Code:
    volatile wakeup_flag = 0;
    void wakeUp()
    {
      wakeup_flag = 1;
    }
    
    void loop() 
    {
      if(digitalRead(buttonPin) == LOW) {
        powerdown();
      }
      if(wakeup_flag) {
        wakeup_flag = 0;
        for (int i = 0; i < 10; i++){
          digitalWrite(ledPin, HIGH);
          delay(500);
          digitalWrite(ledPin, LOW);
          delay(500);
        }
        digitalWrite(ledPin, HIGH);
      }
    }
    You must also ensure that the action in loop() doesn't take longer than the time between two interrupts - in this case the interrupts must not occur any closer than ten seconds.


    Pete

  4. #4
    Member
    Join Date
    Jan 2013
    Location
    Zürich, Switzerland
    Posts
    86
    Cool, thanks!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •