/*
Code for button press detection and LED control
Source: Arduino Forum
Topic: Button + Interrupt
Subcategory: Programming Questions
Category: Using Arduino
Link: https://forum.arduino.cc/t/button-interrupt/1149498/10
*/
// Define the input button pin
#define buttonPin 2
// Define the pin of the LED to be used to display the status of the toggle.
#define ledPin 5
// Define the debounce delay for button debouncing
#define TIME_DEBOUNCE 10UL // 10 milliseconds
// Define the blink delay for LED blinking
#define TIME_BLINK 500UL // 500 milliseconds
// Button structure/object with debounce function
typedef struct {
uint8_t pin; // Button pin number
bool pullup; // Pullup flag
bool state; // Button state
bool input; // Input State
unsigned long startTime; // Start Time
void mode(uint8_t pinNumber, uint8_t inputMode); // Button mode function
bool read(); // Button read function
} button_t;
// Declare the button structure/object.
button_t button;
// Declare the toggle variable.
bool toggle;
void setup() {
// Setup the button mode (INPUT or INPUT_PULLUP)
button.mode(buttonPin, INPUT_PULLUP);
// Setup LED pin mode for toggle state.
pinMode(ledPin, OUTPUT);
// Setup LED pin mode for blinking status.
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
// Reading the button press state to toggle the toggle variable
if (button.read()) toggle = !toggle;
// Set the LED output with a toggle state.
digitalWrite(ledPin, toggle);
// Set the LED output with a blinking state.
digitalWrite(LED_BUILTIN, Blink());
}
/*
Function: Blink
Description: Function to control the blinking of an LED
Parameters: None
Returns: Blink state
*/
bool Blink() {
// Declare the blink static variable.
static bool blink = true;
// Declare the start time static variable
static unsigned long startTime;
// Save the current time in milliseconds.
unsigned long currTime = millis();
//Return the blink state if the elapsed time is less than the blink delay.
if (currTime - startTime < TIME_BLINK) return blink;
// The elapsed time is longer than or equal to the blink delay.
// Reset the start time
startTime = currTime;
// Toggle the blink state
blink = !blink;
// Return the blink state
return blink;
}
/*
Function: mode
Description: Function to set the mode of the button
Parameters: pinNumber - button pin number, inputMode - Button pin mode
Returns: None
*/
void button_t::mode(uint8_t pinNumber, uint8_t inputMode) {
// Set the PIN into the pin variable.
pin = pinNumber;
// pullup = false when the inputMode is INPUT mode.
// pullup = true when the inputMode is INPUT_PULLUP mode.
pullup = inputMode == INPUT_PULLUP;
// Initial button state with pullup state in release condition
// INPUT mode, release = false.
// INPUT_PULLUP mode, release = true.
state = pullup;
// Set button pin mode
pinMode(pin, inputMode);
}
/*
Function: read
Description: Function to read the button state
Parameters: None
Returns: Pressed state
*/
bool button_t::read() {
// Save previous reading input to a local variable.
bool prevInput = input;
// Read the state of the button into the input variable.
input = digitalRead(pin);
// If the input does not change the state, return false.
// Return false as release state.
if (input == state) return false;
// The input is different from the button state.
// Save the current time in milliseconds.
unsigned long currTime = millis();
// If the input changes due to press/release or noise.
// Reset the start time
if (input != prevInput) startTime = currTime;
// If the elapsed time is less than the debounce delay.
// Return false as release state.
if (currTime - startTime < TIME_DEBOUNCE) return false;
// The input changed state longer than or equal to debounce delay.
// The button state takes the actual current input state.
state = input;
// Return pressed one scan time.
// INPUT mode: pressed, input = true and pullup = false.
// INPUT_PULLUP mode: pressed, input = false and pullup = true.
return state == !pullup;
}