We have to detect single, double, and long press events from the push button
Control LED1 and LED2 based on the press events
What do we have to achieve?
What is Debouncing logic?
timer_2
can count is 16 ms. Thus, we will loop 3 times to complete the 48ms wait time.Timer_2
is reset to 0 again.How do we detect the type of button press?
There are 2 cases after 500ms occurs
#define LED1_PIN 5 // Pin for LED1
#define LED2_PIN 6 // Pin for LED2
#define BUTTON_PIN 2 // Pin for the button
volatile bool isT1running = false; // Flag to indicate if Timer1 is running
volatile bool isT2running = false; // Flag to indicate if Timer2 is running
volatile int clicksCount = 0; // Counter for button clicks
volatile int t1Counter = 0; // Counter for Timer1 compare events
volatile int t2Counter = 0; // Counter for Timer2 compare events
void setup() {
pinMode(LED1_PIN, OUTPUT); // Set LED1 pin as output
pinMode(LED2_PIN, OUTPUT); // Set LED2 pin as output
pinMode(BUTTON_PIN, INPUT_PULLUP); // Set button pin as input with pull-up resistor
// Configure Timer1 for a 500ms timeout
TCCR1A = 0; // Set Timer1 to Normal mode
TCCR1B = 0; // Stop Timer1
OCR1A = 31249; // Set compare value for 500ms
TCNT1 = 0; // Reset Timer1 counter
TIMSK1 = (1 << OCIE1A); // Enable Timer1 Compare Match A interrupt
// Configure Timer2 for debounce logic
TCCR2A = (1 << WGM21); // Set Timer2 to CTC mode
TCCR2B = 0; // Stop Timer2
OCR2A = 255; // Set compare value for debounce duration
TCNT2 = 0; // Reset Timer2 counter
TIMSK2 = (1 << OCIE2A); // Enable Timer2 Compare Match A interrupt
// Configure external interrupt for the button (INT0)
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), ISR_INT0, FALLING);
// Enable global interrupts
sei();
}
void loop() {
while (true) {
//In this loop Microcontroller is busy in monitoring and performing important tasks constantly.
}
}
// Interrupt Service Routine for button press (INT0)
void ISR_INT0() {
// If Timer1 is not running and no clicks are counted yet, start Timer1
if (!isT1running && clicksCount == 0) {
TCCR1B = (1 << WGM12) | (1 << CS12); // Start Timer1
isT1running = true;
}
// Start Timer2 for debounce logic if it's not running
if (!isT2running) {
TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20); // Start Timer2
isT2running = true;
}
}
// Interrupt Service Routine for Timer2 (Debounce logic)
ISR(TIMER2_COMPA_vect) {
t2Counter++;
if (t2Counter >= 3) { // After debounce duration (~3 cycles)
if (digitalRead(BUTTON_PIN) == LOW && isT1running) {
clicksCount++; // Increment click count if button is still pressed
}
TCCR2B = 0; // Stop Timer2
isT2running = false; // Reset debounce flag
t2Counter = 0; // Reset Timer2 counter
}
}
// Interrupt Service Routine for Timer1 (Click detection logic)
ISR(TIMER1_COMPA_vect) {
t1Counter++;
if (t1Counter == 1) { // First timeout (500ms after button press)
if (clicksCount > 1) {
digitalWrite(LED2_PIN, !digitalRead(LED2_PIN)); // Toggle LED2 on double-click
t1Counter = 3; // Skip further checks
} else if (digitalRead(BUTTON_PIN) == HIGH && clicksCount == 1) {
digitalWrite(LED1_PIN, !digitalRead(LED1_PIN)); // Toggle LED1 on single click
t1Counter = 3; // Skip further checks
}
} else if (t1Counter == 2) { // Second timeout (long press detected)
if (digitalRead(BUTTON_PIN) == LOW && clicksCount == 1) {
digitalWrite(LED1_PIN, LOW); // Turn off LED1
digitalWrite(LED2_PIN, LOW); // Turn off LED2
}
t1Counter = 3; // Ensure Timer1 stops
}
if (t1Counter >= 3) { // Stop Timer1 after logic completion
TCCR1B = 0; // Stop Timer1
isT1running = false; // Reset Timer1 running flag
clicksCount = 0; // Reset click counter
t1Counter = 0; // Reset Timer1 counter
}
}
1. Global Variables:
T1running
and isT2running
: Flags to track if Timer1 and Timer2 are active.clicksCount
: Counts the number of button clicks.t1Counter
and t2Counter
: Counters for Timer1 and Timer2 interrupts loops. 2. setup()
Function
BUTTON_PIN
is set as an input with a internal pull-up resistor.OCR1A
is set to 31249 for 500 ms.OCR2A
is set to 255 for 16 ms.sei()
.3. loop()
Function
loop()
performing important tasks and all the logic is handled by interrupts.4. Interrupt Service Routines (ISRs)
Button Press ISR (ISR_INT0)
Timer2 ISR (Debounce Logic)
clicksCount
is incremented.Timer1 ISR (Click Detection Logic)
clicksCount > 1
, it's a double-click: toggle LED2.clicksCount == 1
and the button is released, it's a single click: toggle LED1.clicksCount == 1
, it's a long press: turn off both LEDs.