I've been going through the examples and I decided to try to create a debounced button using an interrupt. This leaves the loop() function free to do complex tasks without having to monitor the state of the button.
Here is the code:
const int buttonInterrupt = 0; // Button interrupt
const int buttonLedPin = 13; // LED indicating the button state
const int switchLedPin = 12; // LED indicating the switch state
volatile int buttonState = LOW; //initial button state
volatile boolean switchState = false;
volatile long lastDebounceTime = 0; // the last time the interrupt was triggered
long debounceDelay = 10; // the debounce time; decrease if quick button presses are ignored
void setup() {
pinMode(buttonLedPin, OUTPUT);
pinMode(switchLedPin, OUTPUT);
digitalWrite(buttonLedPin, LOW);
attachInterrupt(buttonInterrupt, Rise, RISING);
}
void loop()
{
}
void Rise()
{
long currentTime = millis();
if ((currentTime - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = currentTime;
if (buttonState == LOW)
{
buttonState = HIGH;
attachInterrupt(buttonInterrupt, Fall, FALLING);
}
digitalWrite(buttonLedPin, buttonState);
Switch(buttonState);
}
}
void Fall()
{
long currentTime = millis();
if ((currentTime - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = currentTime;
if (buttonState == HIGH)
{
buttonState = LOW;
attachInterrupt(buttonInterrupt, Rise, RISING);
}
digitalWrite(buttonLedPin, buttonState);
Switch(buttonState);
}
}
void Switch(int state)
{
if (state == HIGH)
{
switchState = !switchState;
}
if (switchState)
{
digitalWrite(switchLedPin, HIGH);
}
else
{
digitalWrite(switchLedPin, LOW);
}
}
Since the millis() function does not update in an interrupt service routine and since calling the interrupt on CHANGE does not indicate the rising or falling state, the logic for debouncing a button is a little different here.
A button is attached to the interrupt 0 pin 2. A LED indicating the state of the button is attached to pin 13 and a LED indicating the state of an on-off condition (such as causing something happen or not happen in the loop() function) is attached to pin 12.
At the start of the sketch, the interrupt is attached to a routine called Rise that is fired when the button state goes from low to high. When this routing is called, we compare the value of millis() to the stored value of the last interrupt time. If the difference is less then debounceDelay, we change the state of the button and attach the interrupt to a service routine called Fall which is fired when the button goes from high to low.
Since the millis() function does not update during the interrupt service routine, the debounceDelay value can be very small since the noise created by the button will cause millis() to return values that are very close or exactly the same regardless of how long we spend in the service routine.
Here is how it looks:
Let me know what you think!