/*
ESP32 Interrupt Driven User Interface
Wokwi Compatible
Features:
- Single Press
- Double Press
- Long Press
Button -> GPIO 2
LED -> GPIO 13
*/
#define BUTTON_PIN 2
#define LED_PIN 13
// Timing values
const unsigned long debounceDelay = 50;
const unsigned long doubleClickTime = 400;
const unsigned long longPressTime = 1000;
// Interrupt variables
volatile bool interruptFlag = false;
volatile bool buttonLevel = HIGH;
volatile unsigned long interruptMillis = 0;
// UI variables
bool waitingForSecondPress = false;
unsigned long pressStart = 0;
unsigned long lastRelease = 0;
// =====================================================
// ISR
// =====================================================
void IRAM_ATTR buttonISR() {
interruptMillis = millis();
buttonLevel = digitalRead(BUTTON_PIN);
interruptFlag = true;
}
// =====================================================
// SETUP
// =====================================================
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// Interrupt on both edges
attachInterrupt(
digitalPinToInterrupt(BUTTON_PIN),
buttonISR,
CHANGE
);
Serial.println("ESP32 Interrupt UI Started");
}
// =====================================================
// LOOP
// =====================================================
void loop() {
static unsigned long lastDebounceTime = 0;
// Process interrupt event
if (interruptFlag) {
noInterrupts();
bool currentState = buttonLevel;
unsigned long eventTime = interruptMillis;
interruptFlag = false;
interrupts();
// Debounce
if ((eventTime - lastDebounceTime) > debounceDelay) {
lastDebounceTime = eventTime;
// ==========================================
// BUTTON PRESSED
// ==========================================
if (currentState == LOW) {
pressStart = eventTime;
}
// ==========================================
// BUTTON RELEASED
// ==========================================
else {
unsigned long pressDuration =
eventTime - pressStart;
// ======================================
// LONG PRESS
// ======================================
if (pressDuration >= longPressTime) {
waitingForSecondPress = false;
Serial.println("LONG PRESS");
// Slow blinking
for (int i = 0; i < 3; i++) {
digitalWrite(LED_PIN, HIGH);
delay(300);
digitalWrite(LED_PIN, LOW);
delay(300);
}
}
// ======================================
// SHORT PRESS
// ======================================
else {
// DOUBLE PRESS
if (waitingForSecondPress &&
(eventTime - lastRelease)
<= doubleClickTime) {
waitingForSecondPress = false;
Serial.println("DOUBLE PRESS");
// Toggle LED
digitalWrite(
LED_PIN,
!digitalRead(LED_PIN)
);
}
// Possible SINGLE PRESS
else {
waitingForSecondPress = true;
lastRelease = eventTime;
}
}
}
}
}
// ==========================================
// SINGLE PRESS DETECTION
// ==========================================
if (waitingForSecondPress &&
(millis() - lastRelease)
> doubleClickTime) {
waitingForSecondPress = false;
Serial.println("SINGLE PRESS");
// Blink LED once
digitalWrite(LED_PIN, HIGH);
delay(200);
digitalWrite(LED_PIN, LOW);
}
}