0
votes

I am trying to switch on and off the Arduino via a button. I used tutorial https://www.instructables.com/id/A-Guide-to-Putting-Your-Arduino-to-Sleep/ in order to get an idea how to do so. But unfortunately, the scenario does not fit 100%. I want both, on and off via the same switch (not by timer). So I have implemented it the way shown below, just re-assigning different functions to the event via attachInterrupt(). Its like you cannot re-assign the function once assigned to an event. Is that the case? Does someone have a solution for that problem?

I already added detachInterrupt before using attachInterrupt again. Also I have already added a delay in between. Tried interrupt event HIGH, LOW and CHANGE, always same result, goes to sleep but never wakes up again.

#include <avr/sleep.h>
#define INTERRUPT_PWR_BUTTON_PIN 2 // pin for power button (Power button)

void setup() {                
    Serial.println("I'm up...");
    attachInterrupt (digitalPinToInterrupt(INTERRUPT_PWR_BUTTON_PIN), goToSleep, HIGH); //attaching wakeup to interrup 0 on pin 2
    delay(1000);
}

void loop() {
    Serial.println("Ping");
    delay(1000);              // wait 1 sec
}

void goToSleep() {
    Serial.println("Power Button pressed...");
    Serial.flush();
    sleep_enable(); // only enabling sleep mode, nothing more
    detachInterrupt(digitalPinToInterrupt(INTERRUPT_PWR_BUTTON_PIN)); //remove interrupt 0 from pin 2
    attachInterrupt (digitalPinToInterrupt(INTERRUPT_PWR_BUTTON_PIN), wakeUp, HIGH);
    /* 2019-05-02 NN: Does not work, device will not wake up at all, unless pressing reset -> 2 buttons for now */
    set_sleep_mode(SLEEP_MODE_PWR_DOWN); // setting sleep mode to max pwr saving
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
    sleep_cpu();
    Serial.println("Just woke up!"); // gets executed after interrupt
    digitalWrite(LED_BUILTIN, HIGH);  
}

void wakeUp () {
    Serial.println("Wakeup Interrupt Fired");
    sleep_disable();
    detachInterrupt(digitalPinToInterrupt(INTERRUPT_PWR_BUTTON_PIN)); //remove interrupt 0 from pin 2
    attachInterrupt (digitalPinToInterrupt(INTERRUPT_PWR_BUTTON_PIN), goToSleep, HIGH);
}
1

1 Answers

0
votes

As you want to use only one button, you can trigger toggle function via interrupt and from that function make Arduino sleep or wake. You have to use one boolean flag to achieve this.

...
// use flag to control state of sleep
bool isSleeping = false;

void setup() {
    ...
    attachInterrupt (digitalPinToInterrupt(INTERRUPT_PWR_BUTTON_PIN), toggleSleepState, HIGH); //attaching wakeup to interrup 0 on pin 2
    ...
}

void loop() {
    ...
}

void toggleSleepState() {

    static unsigned long last_interrupt_time = 0;
    unsigned long interrupt_time = millis();
    // If interrupts come faster than 200ms, assume it's a bounce and ignore
    if (interrupt_time - last_interrupt_time > 200) 
    {
        // toggle state of sleep
        isSleeping = !isSleeping;

        if (isSleeping == true) {
            goToSleep();
        }
        else {
            wakeUp()
        }
    }
    last_interrupt_time = interrupt_time;
}

void goToSleep() {
    // sleep logic
}

void wakeUp () {
    // wake up logic
}