🌐
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.
🌐
ElectronicWings
electronicwings.com › esp32 › esp32-timer-interrupts
ESP32 Timer Interrupts | ESP32
“timerAlarmWrite” function is used for defining the value for which the timer will generate the interrupt.
🌐
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...
🌐
Luis Llamas
luisllamas.es › inicio › tutoriales arduino › curso esp8266 / esp32
How to use ESP32 timers
November 25, 2024 - With timerAlarmWrite(), the value the Timer must count to before generating an interrupt or executing an action is set. Finally, the Timer is enabled using timerAlarmEnable(). Below is an example of how to use a Timer in the ESP32.
🌐
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.
🌐
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.
🌐
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.
Find elsewhere
🌐
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.
🌐
ESP32 Forum
esp32.com › viewtopic.php
Changing timer alarm in ISR - ESP32 Forum
February 25, 2019 - #define PIN_A 32 hw_timer_t * timerA = NULL; volatile bool dcA = false; int durationON = 80000; int durationOFF = 120000; void IRAM_ATTR onTimerA() { if (dcA) // ON cycle { digitalWrite(PIN_A, LOW); dcA = false; timerAlarmWrite(timerA, durationON, true); } else // OFF cycle { digitalWrite(PIN_A, HIGH); dcA = true; timerAlarmWrite(timerA, durationOFF, true); } } void setup() { pinMode(PIN_A, OUTPUT); timerA = timerBegin(2, 80, true); timerAttachInterrupt(timerA, &onTimerA, true); timerAlarmWrite(timerA, durationON, true); timerAlarmEnable(timerA); } void loop() { } I understand this is happening because timerAlarmWrite is not an IRAM_ATTR function.
🌐
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() { } ... While it is weird, I think it is correct. Call timerRestart in your alarm function, or have a separate one shot timer that then starts the normal cycle for better precision. ... I found this while rewriting library from AVR to ESP32.
🌐
QuadMeUp
blog.quadmeup.com › home › programming › esp32, arduino and timer/alerts
ESP32, Arduino and Timer/Alerts » QuadMeUp
May 20, 2025 - timer = timerBegin(0, 80, true); If you run ESP32 with a different clock, you have to modify the prescaler. 80 is valid for 80MHz clock · timerAlarmWrite(timer, 1000, true); the last true sets alarm to autorepeat.
🌐
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 !
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(){}
🌐
Phatiphat Thounthong
phatiphatt.wordpress.com › esp32-sampling_mode
ESP32 Timer Interrupt (Sampling Mode) – Phatiphat Thounthong
October 21, 2020 - //Step #3 timerAlarmWrite(My_timer, 2000000, true); //timerAlarmWrite(timer?, Sampling Time, bool autoreload); //Sampling Time=> 2 s = 2000000/(80,000,000 MHz/prescale 80) //autoreload: if it is true, timer will repeat. //Step #4 timerAlarmEnable(My_timer); //Just Enable · } void loop() { } // END ESP32_Timer_Interrupt_1.ino ·
🌐
ESP32 Forum
esp32.com › viewtopic.php
ESP32 Timer changes - ESP32 Forum
November 26, 2024 - This is not explained in the two example applications in the latest Arduino-ESP32 Timer API either. Anyway, I was able to solve three compiler errors. 1. the removed API: Code: Select all · timerAlarmWrite(hw_timer[timer_no], alarm_value, timer_reload); replaced with new API: Code: Select all ·
🌐
Jmgandarias
jmgandarias.com › industrial_informatics › microcontrollers_programming › arduino_esp32_core
Arduino ESP32 core 2.x and 3.x - Industrial Informatics Course
September 29, 2025 - The default ESP32 clock runs at 80MHz. If we set 80, we divide the clock by 80, giving 1,000,000 ticks/s (i.e., 1 tick per µs) // Parameter 3: true indicates the timer counts up, false would count down timer = timerBegin(0, 80, true); // Timer 0, clock divider 80 timerAttachInterrupt(timer, &timerInterrupt, true); // Attach the interrupt handler timerAlarmWrite(timer, 5e5, true); // Interrupt every 500ms (500000 µs), auto-reload // ...some code...
🌐
Arduino Forum
forum.arduino.cc › projects › programming
ESP32 Timer Interrupt - Programming - Arduino Forum
June 10, 2024 - Hi Folks, I am using Esp32 Dev Module to develop the timer interrupt code .but when I am using timerBegin() function I am getting errors like that: timerBegin() function can accept only one argument.Please help me out t…
🌐
ESP32 Forum
esp32.com › viewtopic.php
repetitive timerAlarmWrite problem? - ESP32 Forum
December 18, 2020 - I put the timer code to work in core0 and all encoder code in core1. An isr is attached to the encoder pin and after a number of pulses the encoder speed is calculated and the stepper motor speed is adjusted accordingly, changing the frequency of the pulses, using "timerAlarmWrite" ...