// Switch usage tutorial with debounce and interrupt by DiskDoctor
// credit to Michael Margolis 'Arduino Cookbook' for debounce routine
// starred comments '*' are required for using debounce on a button
// preferred method for switch is to set button to HIGH with internal pull-up resistor
// preferred method is to use interrupt for switch so it may be pressed any time
// 'Wild' prefix for non-debounced usage as comparison, not needed in program
// note: interrupts on digital pins restricted: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
// digital interrupts available...uno:2,3 mega:2,3,18,19
// notice debounced button only triggers ONCE but non-debounced maybe multiple or unreliable state
// GREEN is good with debounce. Notice single message and short LED
// RED is unstable without debounce. Notice multiple messages and longer LED from multiples can lead to instability
// each button uses distinct interrupt
// internal pullup resistors used for buttons so no 5v necessary only GND
// 220 Ohm resistors used for LEDs, including pin 13 that has onboard LED but NO internal resistor
#define inputPin 2 // which input pin is connected to button *
const int debounceDelay = 10; // milliseconds to wait until button input stable *
#define inputWildpin 3 // which input ping is connect to button NOT debounced
#define LED 12 // The pin the button-LED is connected to
#define LEDWild 13 // The pin used for second non-debounced connected LED
boolean ledState = LOW;
boolean ledWildState = LOW;
void setup() {
// put your setup code here, to run once
Serial.begin(9600); // initializes serial monitor for troubleshooting and learning
pinMode(inputPin, INPUT); // make button pin mode input *
digitalWrite(inputPin, HIGH); //turn on internal pull-up on pin and set resting state to HIGH *
attachInterrupt(digitalPinToInterrupt(inputPin), buttonPushed, LOW); // assign interrupt to button, procedure to be run and set state to LOW when pushed *
pinMode(LED, OUTPUT); // Declare the button-LED as an output
pinMode(inputWildpin, INPUT); // make second button pin mode input
digitalWrite(inputWildpin, HIGH); //turn on internal pull-up on pin and set resting state to HIGH
attachInterrupt(digitalPinToInterrupt(inputWildpin), buttonPushed2, LOW); // assign interrupt to button, procedure to be run and set state to LOW when pushed
pinMode(LEDWild, OUTPUT); // Declare the button-LED as an output- second comparison LED
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("doing something while waiting for button"); // normal program goes here
delay(1000); // pause to read serial monitor output
}
void buttonPushed() { // detect and debounce button push using assigned interrupt *
if (debounce(inputPin)) { // calls debounce procedure *
Serial.println("Debounce Button Pushed"); // shows button pushed on serial monitor
ledState = !ledState;
digitalWrite(LED, ledState); // Turn the button-LED on for feedback
Serial.println(" something done when button is pushed"); // normal program code for action when button pressed
// Serial.println(""); // blank line for neatness
// delay(1000); // delay to read serial monitor and see LED
// digitalWrite(LED, LOW); // Turn the button-LED back off
}
}
void buttonPushed2() { // detect second button push using assigned interrupt
if (debounce(inputPin)) { // does NOT call debounce procedure
Serial.println("Debounced Button 2 Pushed"); // shows button pushed on serial monitor
ledWildState = !ledWildState;
digitalWrite(LEDWild, ledWildState); // Turn the button-LED on for feedback
Serial.println(" something done when non-debounced button is pushed"); // normal program code for action when button pressed
// Serial.println(""); // blank line for neatness
// delay(1000); // delay to read serial monitor and see LED
// digitalWrite(LEDWild, LOW); // Turn the button-LED back off
}
}
// ***************************************
// ** Debounce pin **
// ** Entire procedure required **
// ** outside of setup or loop **
// ** usually at end **
// ***************************************
// debounce returns true if the switch in the given pin is closed and stable
boolean debounce(int pin)
{
boolean state;
boolean previousState = digitalRead(pin); // store switch state
for (int counter = 0; counter < debounceDelay; counter++) {
delay(1); // wait for 1 millisecond
state = digitalRead(pin); // read the pin
if ( state != previousState) {
counter = 0; // reset the counter if the state changes
previousState = state; // and save the current state
}
}
// here when the switch state has been stable longer than the debounce period
return state;
}