#include <Arduino.h>
#include <FunctionalInterrupt.h>
#ifdef LED_BUILTIN
#define MY_LED LED_BUILTIN // LED_BUILTIN -> On Board Led GPIO pin 2 (D2)
#else
#define MY_LED 2 // On Board Led GPIO pin 2 (D2)
#endif
#define LED_ON HIGH
#define LED_OFF LOW
#define PRJ_NAME "interrupts Buttons" // Project Name
#define PRINT_DASHED_LINES printf("\r-------------------------------------------------------\n\r");
#define BUTTON_1 12
#define BUTTON_2 14
uint8_t BtnPin;
volatile bool FlagChangePinState;
volatile bool FlagLongPress;
// ==================================================
/////////////////////////////////////////////////////////////
class Button {
public:
Button(uint8_t reqPin) : PIN(reqPin) {
pinMode(PIN, INPUT_PULLUP);
};
void begin() {
// LOW -> to trigger the interrupt whenever the pin is low,
// CHANGE -> to trigger the interrupt whenever the pin changes value
// RISING -> to trigger when the pin goes from low to high,
// FALLING -> for when the pin goes from high to low.
// HIGH -> to trigger the interrupt whenever the pin is high.
attachInterrupt(PIN, std::bind(&Button::isr, this), FALLING);//
Serial.printf("-> Started button interrupt on pin %d -\n", PIN);
}
~Button() {
detachInterrupt(PIN);
}
void ARDUINO_ISR_ATTR isr() {
PressStartTime = millis();
pressed = true;
}
void checkPressed() {
if ( pressed ) {
if (millis() - PressStartTime < DEBOUNCE_DELAY_MS) {
return; // Ignore this interrupt due to bouncing
}
// Read current pin state to determine edge type
// bool currentState = digitalRead(PIN);
// State-based debouncing: only process if state actually changed
// if (currentState == lastButtonState) {
// pressed = false;
// return; // No real state change, ignore (hysteresis/noise)
// }
// lastButtonState = currentState;
// if (currentState == LOW) {
// pressed = false;
// numberKeyPresses = numberKeyPresses + 1;
// BtnPin = PIN;
// FlagChangePinState = true;
// Serial.printf("Button on pin: %u - Has been pressed: %lu times\n", BtnPin, numberKeyPresses);
// }
//++++++++++++++++++++++++++++++++
bool currentState = digitalRead(PIN);
if (currentState && LongPressTriggered) {
LongPressTriggered = false;
PressStartTime = millis();
pressed = false;
// Serial.printf("return \n");
return;
}
BtnPin = PIN;
if (currentState == LOW && (millis() - PressStartTime > 1000)) {
numberKeyPresses = numberKeyPresses + 1;
Serial.printf("LONG PRESS on pin: %u - Has been pressed: %lu times\n", BtnPin, numberKeyPresses);
FlagLongPress = true;
LongPressTriggered = true;
pressed = false;
return;
}
if (currentState == HIGH && LongPressTriggered == false) {
numberKeyPresses = numberKeyPresses + 1;
Serial.printf("CLICK on pin : %u - Has been pressed: %lu times\n", BtnPin, numberKeyPresses);
FlagChangePinState = true;
pressed = false;
}
//++++++++++++++++++++++++++++++++
}
}
private:
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
bool LongPressTriggered;
unsigned long PressStartTime = 0;
const uint16_t DEBOUNCE_DELAY_MS = 60; // 50ms debounce delay
};
/////////////////////////////////////////////////////////////
Button button1(BUTTON_1);
Button button2(BUTTON_2);
/////////////////////////////////////////////////////////////
// ---------------------------------------------------------
// setup
// ---------------------------------------------------------
void setup() {
Serial.begin(115200);
delay(10); //
printf("\r\n--------------- Booting ESP ---------------------------\r\n");
printf("Arduino IDE : %d.%d.%d\r\n", ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10);
printf("On Board : %s \r\n", ARDUINO_BOARD);
printf("Starting project : %s \r\n", PRJ_NAME);
printf("Author : Kernel Panic \r\n");
printf("Project Date : %s\r\n", (__DATE__ " - " __TIME__));
PRINT_DASHED_LINES;
button1.begin();
button2.begin();
pinMode(MY_LED, OUTPUT);
digitalWrite(MY_LED, LED_ON);
}
// ---------------------------------------------------------
// loop
// ---------------------------------------------------------
void loop() {
delay(5);
button1.checkPressed();
yield();
button2.checkPressed();
if (FlagChangePinState) {
FlagChangePinState = false;
Serial.printf("\t Click => pin: %d \n", BtnPin);
PRINT_DASHED_LINES;
}
if (FlagLongPress) {
FlagLongPress = false;
Serial.printf("\t Long Press => pin: %d \n", BtnPin);
PRINT_DASHED_LINES;
}
yield();
}
/*********************************
END of this file
**********************************/