/*
Forum: https://forum.arduino.cc/t/esp32-timer-reloading/1364408
Wokwi: https://wokwi.com/projects/425693519758915585
References: [1] https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/timer.html
[2] https://docs.espressif.com/projects/arduino-esp32/en/latest/migration_guides/2.x_to_3.0.html#timer
2025/03/17
ec2021
Due to an example in reference [1] it is allowed to use digitalRead/write in the ISR outside of the critical part
As the timer did not stop (as expected from the documentation) it is freed and newly created in the routines
*/
#include <Arduino.h>
constexpr byte BTN_START_ALARM {12};
constexpr byte LED_PIN {14};
volatile byte _ledState = LOW;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
boolean detectLowSignal = false;
void ARDUINO_ISR_ATTR onTimer() {
setLed(LOW);
}
void setup() {
Serial.begin(115200);
pinMode(BTN_START_ALARM, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
byte inputState = digitalRead(BTN_START_ALARM);
if (inputState == LOW && !ledState()) {
setLed(HIGH);
detectLowSignal = true;
Serial.println("Led ON");
startTimer();
}
if (detectLowSignal && !ledState()) {
stopTimer();
Serial.println("Led OFF");
detectLowSignal = false;
}
}
void startTimer(){
timer = timerBegin(1000000);
timerAttachInterrupt(timer, &onTimer);
timerAlarm(timer, 6000000, false, 0);
Serial.println("Timer started");
}
void stopTimer(){
if (timer){
timerEnd(timer);
Serial.println("Timer stopped");
}
}
void setLed(byte state){
digitalWrite(LED_PIN, state);
portENTER_CRITICAL_ISR(&timerMux);
_ledState = state;
portEXIT_CRITICAL_ISR(&timerMux);
}
byte ledState(){
portENTER_CRITICAL_ISR(&timerMux);
byte state = _ledState;
portEXIT_CRITICAL_ISR(&timerMux);
return state;
}