Ok, so I've never worked with interrupts before, but this project requires long battery life, so I'm trying to learn. I have got the code working properly for putting the Arduino to sleep after holding the button for a few seconds, and it even wakes up with the interrupt, if I release the button before sleep starts. The problem occurs if the button is still held after the Arduino goes to sleep, then it will wake upon release, even though the line is going LOW or FALLING. As you can see in my code below, I am using a HIGH interrupt. I have also tried it with a RISING interrupt, but I get the same behavior. I can only think that maybe I need to debounce the interrupt in some way, but I'm not sure how to do that. Also, in case anyone is wondering, the button is connected on one side to 5v, on the other side to Pin 2 and a 10k resistor to ground. Code is below, any help is greatly appreciated.
#include <avr/sleep.h>
// set pin numbers:
const int led0Pin = 8; // the number of the 1st LED pin
const int led1Pin = 9; // the number of the 2nd LED pin
const int buttonPin = 2; // the number of the button pin
// Set up initial Variables
long lastDebounceTime = 0; // the last time the output pin was toggled
long sleepButtonDelay = 3000; // How long the button needs to be pressed to turn off
int lastButtonState = LOW; // the previous reading from the input pin
int buttonState = LOW; // Current reading of button state
void setup() {
// initialize the LED pin as an output:
pinMode(led0Pin, OUTPUT);
pinMode(led1Pin, OUTPUT);
pinMode(buttonPin, INPUT);
buttonState = digitalRead(buttonPin);
if (buttonState)
lastButtonState = LOW;
else
lastButtonState = HIGH;
}
void loop() {
// Long Button hold will put arduino to sleep
// if (buttonPressed)
// {
// buttonLongPressSleep();
// goToSleepNow();
// } else {
// Insert code for lighting loops here.
digitalWrite(led0Pin, HIGH);
digitalWrite(led1Pin, HIGH);
delay(500);
digitalWrite(led0Pin, LOW);
digitalWrite(led1Pin, LOW);
delay(500);
buttonLongPressSleep();
// }
}
// check for a long button press and put uc to sleep if one is detected
// short press will wake it back up through interrupt
int buttonLongPressSleep()
{
// Read current state of the button
int reading = digitalRead(buttonPin);
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
lastButtonState = reading;
// reset the debouncing timer
lastDebounceTime = millis();
}
if (((millis() - lastDebounceTime) > sleepButtonDelay) && lastButtonState == HIGH)
{
// The pin has been HIGH longer
// than the delay, so we should go to sleep here:
goToSleepNow();
}
}
// Interupt service routine for a button press, Nothing needed but to wake up.
void isrWakeUp()
{
// No action required, wake up only.
}
void goToSleepNow()
{
// Flash twice quickly to notify that sleep is starting.
notificationFlash();
// Enable Interrupts
interrupts();
// Set up sleep mode
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Enable Sleep Mode
sleep_enable();
// Attach an interrupt to the button pin to bring us out of sleep
attachInterrupt(0, isrWakeUp, HIGH);
// attachInterrupt(0, isrWakeUp, RISING);
// Sleep
sleep_mode();
//
// Right here we are sleeping until the button is pressed
//
sleep_disable(); // Disable Sleep Mode
detachInterrupt(0);
noInterrupts();
// Reset the sketch to the beginning after resuming from sleep
softReset();
}
// Sketch starts over, but, not a full hardware reset.
void softReset()
{
// Reset sketch. Code pulled from arduino forums.
asm volatile (" jmp 0");
}
// Flash twice to indicate sleep
void notificationFlash()
{
digitalWrite(led0Pin, HIGH);
digitalWrite(led1Pin, HIGH);
delay(250);
digitalWrite(led0Pin, LOW);
digitalWrite(led1Pin, LOW);
delay(250);
digitalWrite(led0Pin, HIGH);
digitalWrite(led1Pin, HIGH);
delay(250);
digitalWrite(led0Pin, LOW);
digitalWrite(led1Pin, LOW);
}