I already found the answer. I had to use : timerWrite(timer, 0) to reset it. Answer from andz on forum.arduino.cc
🌐
DeepBlue
deepbluembedded.com › home › blog › esp32 timers & timer interrupt tutorial (arduino ide)
ESP32 Timers & Timer Interrupt Tutorial (Arduino IDE) – DeepBlueMbedded
February 17, 2025 - #define LED 21 hw_timer_t *Timer0_Cfg = NULL; void IRAM_ATTR Timer0_ISR() { digitalWrite(LED, !digitalRead(LED)); } void setup() { pinMode(LED, OUTPUT); Timer0_Cfg = timerBegin(0, 80, true); timerAttachInterrupt(Timer0_Cfg, &Timer0_ISR, true); timerAlarmWrite(Timer0_Cfg, 1000, true); timerAlarmEnable(Timer0_Cfg); } void loop() { // Do Nothing! } I’ve used Timer0 in this example, but you can use any one of the 4 available timers in ESP32.
🌐
GitHub
github.com › espressif › arduino-esp32 › issues › 1313
Timer timerAlarmEnable() bug · Issue #1313 · espressif/arduino-esp32
April 14, 2018 - #include <esp32-hal-timer.h> hw_timer_t *timer = NULL; void IRAM_ATTR isrTimerExpired() { Serial.println("timer expired"); } void startTimer() { Serial.println("startTimer()"); if (timer == NULL) { timer = timerBegin(0, 80, true); timerAttachInterrupt(timer, &isrTimerExpired, true); } const unsigned long durationMs = 1000; timerAlarmWrite(timer, durationMs * 1000, false); // if the following yield() is removed, the timer will not // be enabled the second time yield(); timerAlarmEnable(timer); Serial.print("isEnabled: "); Serial.println(timerAlarmEnabled(timer)); } void stopTimer() { Serial.println("stopTimer()"); if (timer != NULL) { timerAlarmDisable(timer); timerDetachInterrupt(timer); timerEnd(timer); timer = NULL; } } void setup() { Serial.begin(115200); startTimer(); stopTimer(); startTimer(); } void loop() { // not used delay(1000); }
Author   espressif
Discussions

[esp32] How to disable, reset and again enable timer
I am trying to disable and again enable timer on my ESP32 but I have a problem resetting or restarting it. I don't have right words for that, but basically need him to start counting from 0 again. In arduino it is TCNT1 register. I was trying timerRestart(timer) function but without success. More on forum.arduino.cc
🌐 forum.arduino.cc
1
0
January 26, 2021
How to delete and restart hw timer (for interrupts) on demand for esp32 arduino (stepper motor controller application) - Stack Overflow
I am having trouble figuring out how to disable then re-enable (upon a triggering event) the hw (esp32-hal-timer) timer from the esp-arduino library, here for a stepper motor controller application... More on stackoverflow.com
🌐 stackoverflow.com
Hardware Timer ESP32 Dev Module
Nano ESP32 category you chose is only used for discussions directly related to the Arduino Nano ESP32 board · In the future, please take the time to pick the forum category that best suits the subject of your question. There is an "About the _____ category" topic at the top of each category ... More on forum.arduino.cc
🌐 forum.arduino.cc
13
0
July 19, 2024
Hardware timer, how to run once and restart again?
I had some trouble with timers and alarms on my esp32 doit devboard. Spent many hours trying to debug, end of the days its a silicon issue with the REV0 chips. Not sure if this applies to you but more information can be found here: https://github.com/espressif/arduino-esp32/issues/1313 More on reddit.com
🌐 r/esp32
8
5
April 12, 2021
🌐
Luis Llamas
luisllamas.es › inicio › tutoriales arduino › curso esp8266 / esp32
How to use ESP32 timers
November 25, 2024 - Finally, the Timer is enabled using timerAlarmEnable(). Below is an example of how to use a Timer in the ESP32.
🌐
Espressif Docs
espressif-docs.readthedocs-hosted.com › projects › arduino-esp32 › en › latest › api › timer.html
Timer — Arduino-ESP32 2.0.14 documentation
/* Repeat timer example This example shows how to use hardware timer in ESP32. The timer calls onTimer function every second. The timer can be stopped with button attached to PIN 0 (IO0). This example code is in the public domain.
🌐
CircuitDigest
circuitdigest.com › microcontroller-projects › esp32-timers-and-timer-interrupts
ESP32 Timers & Timer Interrupt Tutorial
August 5, 2025 - void setup() { pinMode(LED, OUTPUT) My_timer = timerBegin(0, 80, true); timerAttachInterrupt(My_timer, &onTimer, true); timerAlarmWrite(My_timer, 1000000, true); timerAlarmEnable(My_timer); } void loop() { } And in the Setup function, we have initialised GPIO21 as an output with the help of the pinMode macro. ... To initialise the timer, we are using the ESP32 timerBegin function with the following variables.
🌐
Arduino Forum
forum.arduino.cc › projects › programming
[esp32] How to disable, reset and again enable timer - Programming - Arduino Forum
January 26, 2021 - I am trying to disable and again enable timer on my ESP32 but I have a problem resetting or restarting it. I don't have right words for that, but basically need him to start counting from 0 again. In arduino it is TCNT1 …
Top answer
1 of 2
1

The word 'restart' had me thinking that it would just immediately start the timer again, but it turns out that is not the case. If the reload was set false previously, the timer has to be set again before it will actually execute - which works perfectly for my use case. Below is my new code (figured I would include the wifi and mqtt stuff to help anyone else as well):

#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include "VCDevices.h"

hw_timer_t * motorTimer = NULL;
Motor linMotor2 = Motor(pulsePin, directionPin);
int d = 0;
bool nextRun = false;

const char* ssid = "SSID";
const char* password = "PASSWORD_HERE";
const char* mqtt_server = "MQTT_SERVER_HERE";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char topArr[50];
char msgArr[100];

portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

//Timer ISR
void IRAM_ATTR motorInterrupt(void) 
{
  portENTER_CRITICAL(&timerMux);
  noInterrupts();
  //check if the motor is in motion still
  if (!linMotor2.getMotorStatus())
  {
    d = linMotor2.Update();
    //give timer different delay, dependent on its current speed
    timerAlarmWrite(motorTimer, d, true);
    timerAlarmEnable(motorTimer);
  }
  //kill the timer and interrupt if not
  else
  {
    nextRun = true;
    //set the 'reload' boolean to false, to get it to only trigger one more time
    timerAlarmWrite(motorTimer, 10, false);
    // Serial.println("POSITION REACHED!");
  }

  interrupts();
  portEXIT_CRITICAL(&timerMux); 
}

void reconnect() 
{
  // Loop until we're reconnected
  while (!client.connected()) 
  {
    Serial.print("Attempting MQTT connection...");
    Serial.println(mqtt_server);
    // Attempt to connect
    if (client.connect("ESP8266Client"))
    {
      client.subscribe(motorControlTopic);
      Serial.println("connected");
    } 
    else 
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


void setup_wifi() 
{
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* message, unsigned int length)
{
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  String response;
  
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }

  Serial.println();
  if (String(topic) == String(motorControlTopic))
  {
    if (messageTemp.toInt() > 0)
    {
      //check if motor is available to run
      if (linMotor2.getMotorStatus())
      {
        
        linMotor2.MoveTo(messageTemp.toInt());

        //set the motor timer and enable it
        timerAlarmWrite(motorTimer, 1, true);
        timerAlarmEnable(motorTimer);
        
        response = "moving to " + String(messageTemp.toInt()) + " mm position";
      }
      else
      {
        response = "motor is busy - wait for movement to end!";
      }
      Serial.println(response);
    }
  } 
}

void setup()
{ 
  //Start serial connection
  Serial.begin(115200);

  //Setup wifi and mqtt stuff
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  //Fix up motor settings
  pinMode(pulsePin, OUTPUT);
  linMotor2.SetSpeed(200);
  linMotor2.SetAcceleration(10);

  //Initialize timer here for later use!
  motorTimer = timerBegin(1, 80, true);
  timerAttachInterrupt(motorTimer, &motorInterrupt, true);
  Serial.println("TIMER SET!!");
  digitalWrite(pulsePin, LOW);

}

void loop()
{
  if (!client.connected()) reconnect();
  client.loop();  
  portENTER_CRITICAL(&timerMux);
  vTaskDelay(500);
  count = linMotor2.GetPosition();
  Serial.println("POSITION: " + String(count));
  if (nextRun)
  {
    noInterrupts();
    timerRestart(motorTimer);
    Serial.println("*********TIMER RESTARTED!******");
    nextRun = false;
    interrupts();
  }
  portEXIT_CRITICAL(&timerMux);
}
2 of 2
1

I found this question to be very similar to an issue I am experiencing, also in a stepper application I need to set a pin HIGH fo the stepper to run and then, after 2ms, need to set the pin back to LOW. To do that I am firing a second timer form inside the ISR of the first timer, but no matter what I try/set, the second timer always fires 23us later. To illustrate that I made the below barebone example so one can see that the interval between to two ISR is always 22/23us no matter what. This routine/strategy is part of the very popular TeensyStep library (ESP32 Fork) and the very short pulse length is not really appreciated by the large DRIVERS. What am I doing wrong?

hw_timer_t *timerA = NULL;
hw_timer_t *timerB = NULL;

void IRAM_ATTR onTimerA()
{
  digitalWrite(13, 1);  
  Serial.print("HI ");
  Serial.println(micros());
  timerAlarmEnable(timerB);
}

void IRAM_ATTR onTimerB()
{
  digitalWrite(13, 0);  
  Serial.print("LO ");
  Serial.println(micros());    
}

void setup()
{
  Serial.begin(115200);
  while (!Serial);

  timerA = timerBegin(0, 80, true);
  timerAttachInterrupt(timerA, &onTimerA, true);
  timerAlarmWrite(timerA, 1000000, true);  
  
  timerB = timerBegin(1, 80, true);
  timerAttachInterrupt(timerB, &onTimerB, true);
  timerAlarmWrite(timerB, 200000, false);

  timerAlarmEnable(timerA);
}

void loop(){}
🌐
ESP32 Forum
esp32.com › viewtopic.php
Using Timer Interrupt and Reload Timer - ESP32 Forum
August 18, 2019 - Serial.println("Reload Timer"); timerAlarmDisable(timer); // stop alarm timerDetachInterrupt(timer); // detach interrupt timerEnd(timer); // end timer timer = timerBegin(0, 80, true); // start time again timerAttachInterrupt(timer, &onTimer, true); // attach interrupt again timerAlarmWrite(timer, 5000000, true); // start alarm again timerAlarmEnable(timer); // enable alarm again ·
Find elsewhere
🌐
Espressif
docs.espressif.com › projects › arduino-esp32 › en › latest › migration_guides › 2.x_to_3.0.html
Migration from 2.x to 3.0 - - — Arduino ESP32 latest documentation
timerAlarm used to set up Alarm for the timer and enable it automatically (merged timerAlarmWrite and timerAlarmEnable functions).
🌐
QuadMeUp
blog.quadmeup.com › home › programming › esp32, arduino and timer/alerts
ESP32, Arduino and Timer/Alerts » QuadMeUp
May 20, 2025 - 1000 means every 1000 ticks, 1ms timerAlarmWrite(timer, 1000, true); //And enable the timer timerAlarmEnable(timer); } void loop() { //Here you can do whatever you want } timer = timerBegin(0, 80, true); If you run ESP32 with a different clock, you have to modify the prescaler.
🌐
Arduino Forum
forum.arduino.cc › projects › programming
Hardware Timer ESP32 Dev Module - Programming - Arduino Forum
July 19, 2024 - #include #include hw_timer_t *timer = NULL; const int ledPin = 2; void IRAM_ATTR onTimer() { // Toggle LED state digitalWrite(ledPin, !digitalRead(ledPin)); } void setup() { pinMode(ledPin, OUTPUT); // Initialize timer 0 with a frequency of 1 Hz timer = timerBegin(0, 1); // Attach an ISR function to the timer timerAttachInterrupt(timer, &onTimer, true); // Set an alarm to trigger after 1 second timerAlarmWrite(timer, 1000000, true); // 10...
🌐
TechTutorialsX
techtutorialsx.com › 2017 › 10 › 07 › esp32-arduino-timer-interrupts
ESP32 Arduino: Timer interrupts
In this post we are going to learn how to receive messages sent from the WebSerial UI, on the ESP32.
🌐
GitHub
gist.github.com › futureshocked › 5327bec254a9d5afcc91fa0b673442b6
ESP32 timer interrupts, how to change duration in the loop. · GitHub
void setup() { Serial.begin(115200); timer1 = timerBegin(0, 80, true); timerAttachInterrupt(timer1, &onTimer1, true); // Configura o Timer 1 para o primeiro disparo timerAlarmWrite(timer1, 5000000, false); timerAlarmEnable(timer1); // setupTimer1(); }
🌐
Upsy
upesy.com › tutorials › esp32 › esp32 programming › arduino code › basics › timers
Timer ESP32 with Arduino Code: Master the time - uPesy
February 2, 2023 - hw_timer_t * timer = NULL; void IRAM_ATTR timer_isr() { // This code will be executed every 1000 ticks, 1ms } void setup() { Serial.begin(115200); uint8_t timer_id = 0; uint16_t prescaler = 80; // Between 0 and 65 535 int threshold = 1000000; // 64 bits value (limited to int size of 32bits) timer = timerBegin(timer_id, prescaler, true); timerAttachInterrupt(timer, &timer_isr, true); timerAlarmWrite(timer, threshold, true); timerAlarmEnable(timer); } void loop() { } We define an object hw_timer_t object outside the setup() function to be able to access it from different functions. The function timerBegin(uint8_t id, uint16_t prescaler, bool countUp) allows to configure the timer : The ESP32 has 4 independent timers, selected by an id between 0 and 3.
🌐
Reddit
reddit.com › r/esp32 › hardware timer, how to run once and restart again?
r/esp32 on Reddit: Hardware timer, how to run once and restart again?
April 12, 2021 -

Guys

I have a DevKitC dev board, and I'm trying to set up a HW timer that I want to re-use under certain conditions. In other words, I don't want it to reload automatically, it should run once and then remain dormant until I enable it again. It seems to work the first time, but when I enable the timer a second time it fires immediately, without any delay. It seems I'm not resetting it properly, so that the counter starts from 0 again (?).

What I've tried is this:

initialize timer 0 in setup(), with a prescaler for 80MHz.

myTimer = timerBegin (0, 80, true);
timerAttachInterrupt (myTimer, &isrMyTimer, true);

then when I want to use the timer I enable it as follows (for a duration of 3 seconds):

timerAlarmWrite(myTimer, 3000000), false);
timerAlarmEnable(myTimer);

I am also trying to confirm the frequency to use for the timer, whether it is indeed 80MHz. I get the values as shown below for the different functions. Any thoughts on what they mean?

getCpuFrequencyMhz()		240	
getXtalFrequencyMhz()		40
getApbFrequency()		80000000
Top answer
1 of 4
2
I had some trouble with timers and alarms on my esp32 doit devboard. Spent many hours trying to debug, end of the days its a silicon issue with the REV0 chips. Not sure if this applies to you but more information can be found here: https://github.com/espressif/arduino-esp32/issues/1313
2 of 4
2
I managed to get it working. The trick that worked for me was to reset the timer (counter) before each use, with the following statement: timerRestart() Below is a little pseudo sketch, only showing the relevant statements, to give you or anyone finding this post later, an idea of what worked for me. #include // only needed to get ESP32 frequency detail hw_timer_t * tmrTEST = NULL; // timer used for TESTING unsigned long lngTimerStart = 0; // system micro-seconds at timer start int tmrDuration = 5; // run timer for 5 seconds // Interrupt Service Routine called when TEST timer fires. void IRAM_ATTR isrTimerTEST() { Serial.print(" >>>>> TEST TIMER ISR: "); Serial.print( micros() ); Serial.print(" diff="); Serial.println((micros()-lngTimerStart)/1000/1000); } void setup() { Serial.begin(115200); ... // Set up TEST timer.. tmrTEST = timerBegin (1, 80, true); // use ESP32 Timer 1, pre-scale 80 (for 80MHz freq), count up. timerAttachInterrupt (tmrTEST, &isrTimerTEST, true); // attach the function to call when timer interrupt fires. Edge. Serial.print(" >> CPU Freq: "); Serial.println(getCpuFrequencyMhz()); Serial.print(" >> XTL Freq: "); Serial.println(getXtalFrequencyMhz()); Serial.print(" >> APB Freq: "); Serial.println(getApbFrequency()); ... } void loop() { ... if (tmrDuration > 0) { // initiate TEST timer. duration in micro-seconds. False to run once. timerAlarmWrite(tmrTEST, (tmrDuration * 1000000), false); timerRestart(tmrTEST); // reset timer counter timerAlarmEnable(tmrTEST); // start the timer lngTimerStart = micros(); Serial.print(" >>>>> TimerTEST dur="); Serial.print(tmrDuration); Serial.print(" start: "); Serial.println( lngTimerStart ); } ... } Thanks for your replies and time !
🌐
GitHub
github.com › espressif › arduino-esp32 › blob › master › cores › esp32 › esp32-hal-timer.h
arduino-esp32/cores/esp32/esp32-hal-timer.h at master · espressif/arduino-esp32
#include "esp32-hal.h" #include "driver/gptimer_types.h" · #ifdef __cplusplus · extern "C" { #endif · · struct timer_struct_t; typedef struct timer_struct_t hw_timer_t; · hw_timer_t *timerBegin(uint32_t frequency); void timerEnd(hw_timer_t *timer); ·
Author   espressif
🌐
Reddit
reddit.com › r/esp32 › esp32 timer interrupt
r/esp32 on Reddit: ESP32 Timer Interrupt
March 17, 2025 -

I want a delay to be triggered every time a DS3231 RTC interrupts. The RTC interrupt happens every 30 minutes which will turn on a motor. I want the motor on for 5 minutes. I need to figure out how to use a ESP32 timer to start when it sees the RTC interrupt and send its own interrupt trigger after 5 minutes is up so the code knows when to turn the motor off again. The RTC interrupts works great but I'm not understanding the timer operation for the 5 minute delay.

The code I enclosed is a failed test that used a switch as the trigger and a LED that lights for 100 seconds.  Why does this code flash the led every 200ms without even triggering with the input switch on i/o 35? What needs to to done to allow the above described functionality?

#include <Arduino.h>
#define LED_PIN 38      // Pin connected to the LED
#define INPUT_PIN 35    // Pin connected to the input
volatile uint8_t led_state = 0;

hw_timer_t * timer = NULL;

void IRAM_ATTR timer_isr() 
{
    led_state = !led_state; // Toggle the LED state
    digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle the LED state
    Serial.println("Timer interrupt triggered!"); // Print a message to the serial monitor
    delay(200); 
}

void setup() 
{
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(INPUT_PIN, INPUT); // Set the input pin as input
  uint8_t timer_id = 0;
  uint16_t prescaler = 8000; // Between 0 and 65535
  int threshold = 1000000; // 64 bits value (limited to int size of 32bits)

  timer = timerBegin(timer_id, prescaler, true);    //Timer #, prescaler, count up
  timerAttachInterrupt(timer, &timer_isr, true);    //Timer object, isr, rising edge trigger
  timerAlarmWrite(timer, threshold, false);         //Timer object, Value to reach /trigger at, No Auto reload
  //timerAlarmEnable(timer);
}

void loop() 
{
  if (digitalRead(INPUT_PIN) == LOW) // Check if the input pin is LOW
  {    
    //timerRestart(timer);
    timerAlarmEnable(timer);
  }
}
🌐
ElectronicWings
electronicwings.com › esp32 › esp32-timer-interrupts
ESP32 Timer Interrupts | ESP32
This guide gives details about timers in ESP32, how to configure timers using Arduino IDE, and creating interrupts. Finally, we have tested it using ESP32 Board.
🌐
ESP32 Forum
esp32.com › viewtopic.php
Timers and interrupts not working as expected - ESP32 Forum
January 12, 2024 - hw_timer_t * timer = NULL; void IRAM_ATTR onTimer() { bool state = digitalRead(5); digitalWrite(5, !state); } void setup() { pinMode(5, OUTPUT); Serial.begin(115200); timer = timerBegin(0, 80, true); // Timer 0, prescaler 80, count up timerAttachInterrupt(timer, &onTimer, true); timerAlarmWrite(timer, 100, true); timerAlarmEnable(timer); timerWrite(timer, 50); } void loop() { } Top ·