ESP32 Timers & Timer Interrupts

Published  June 23, 2022   6
ESP32 Timers & Timer Interrupts

Timer interrupts are crucial in the use of ESP32 timer interrupt programming projects for accurate timing control. If you want something to occur on schedule, ESP32 timer interrupts give you the accuracy required. A timer interrupt is a dedicated interrupt that operates as a high-precision clock, counting and controlling time events with microsecond precision. ESP32's on-board hardware timers are utilised for two purposes - providing accurate time delays and acting as counters for some ESP32 timer interrupt example applications.

ESP32 Timers

The ESP32 chip contains two hardware timer groups. Each group has two general-purpose hardware timers. They are all 64-bit generic timers based on 16-bit prescalers and 64-bit up / down counters, which are capable of being auto-reloaded.

ESP32 Timer Interrupt LED Blinker - Quick Overview

Build Time: 1-2 hours | Cost: $8-12 | Difficulty: Beginner

What You'll Learn: Timer interrupts, ISR functions, Hardware timer setup, Non-blocking execution

Applications: LED blinking without delay, Real-time motor control, Periodic sensor polling, Automation timing tasks

ESP32 Timer Interrupt Programming: Complete Guide

Understanding ESP32 Timer Interrupts and Hardware Timers

Timer Interrupts are an effective way to ensure timed events happen to the millisecond, allowing for fine-tuned clock or PWM operations, or just supplying a reliable pulse to an LED. The timer interrupts are the software interrupts generated by the timer. Timer interrupts allow you to perform a task at very specifically timed intervals, regardless of what else is going on in your code. They are similar to external interrupts, but instead of being triggered by an external event, they are triggered by a timer. Once triggered, they will interrupt the thread of execution after the current instruction completes, call the ISR, and return to the next instruction from where it left off when it has finished, just like hardware or external interrupts. Here is an image demonstrating the Timer concept.

ESP32 Timer Interrupt

Timer Interrupt Execution Flow in ESP32 Timer Interrupt Programming:

  • Timer Configuration: ESP32 timerBegin configures the timer values
  • ISR Attachment: ESP32 attachInterrupt attaches a timer to an arbitrary function
  • Continuous Counting: The Timer is continuously counting in the background
  • Interrupt Generation: Once the Targeted Time Expires Timer will generate an interrupt
  • ISR Execution: Program suspends runs ISR, then resumes

 

As these timers are hardware-based, all timing is related to the clock of the timer. The timer speed can be determined by the following formula-

timer speed (Hz) = Timer clock speed (Mhz) / prescaler

For example, the speed of a timer in an ESP32, which is running at a clock frequency of 80MHz, will be 80MHz or 8000000Hz for a set prescaler value of 1 and will be 1MHz or 1000000Hz for a prescaler value of 80.

The prescaler is what the above frequency is divided by to form a "tick" of the timer (increment its counter). The ISR is then configured to trigger after a specific number of ticks. The following image shows the process flow with a timer interrupt.

ESP32 Timer Flow Chart

Just like a hardware interrupt, the timer interrupts are also the best way to run non-blocking functions at a certain interval. For that, we will configure and attach a particular timer interrupt to a specific ISR in the setup function. The controller will execute the main loop continuously. Whenever a timer interrupt is generated, the microcontroller will pause the main loop and proceed with the execution of the Interrupt Service Routine or ISR. Once the ISR is finished executing, the microcontroller will resume the main loop from where it was paused. This process will repeat for every Timer Interrupt.

Commonly Asked Questions about ESP32 Timer Interrupts

⇥ How many Timers do ESP32 have?

The ESP32 offers four 64-bit timers.

⇥ How to use the Timer interrupt in ESP32?

You can attach the desired timer to an interrupt and assign an ISR for the same

⇥ How does the ESP32 timer work?

The timer uses a counter which counts at a certain speed depending on the clock frequency and the prescaler value. This counter will reset once it reaches a set value, and it will trigger an interrupt. We can change the timer intervals by changing this count value

⇥ What are the common applications of ESP32 timer interrupts?
Examples of typical ESP32 timer interrupt applications. Industrial use cases involving ESP32 timer interrupt programming are motor control (including servo control), data logging, and automation systems. All these examples show the usefulness of timer interrupts for flexibility in implementing non-blocking time-sensitive operations. The ESP32 timer interrupt programming gives the programmer freedom to create an accurate timing control that is necessary for real-time robotics usage, IoT devices, measurement equipment, and automation systems, where time accuracy in microseconds is necessary.

⇥ Is there a way to execute several ESP32 timer interrupts simultaneously?
Yes, the ESP32 has four hardware timers to execute four ESP32 timer interrupts simultaneously. Each timer runs independently and can have different ESP32 timerBegin, ESP32 attachInterrupt, and ISR function settings. More sophisticated ESP32 timer interrupt programming projects may implement multiple timer interrupts to, for example, construct a complicated timing sequence, multiplex sensor data, or handle timed communication protocols. Timer programming complexity increases, requiring careful prioritisation of each ISR along with efficient code in each ISR, to accomplish successful multi-timer operations without interference. Concurrent ESP32 timer interrupts make the ESP32 attractive for advanced embedded applications that need multiple timing operations simultaneously.

⇥ What are some guidelines for the ESP32 timer interrupt programming ISR functions?
In the design of the ISR in ESP32 timer interrupt programming, there are a few best practices to follow. First, the ISR must have as little execution time as possible. Second, the ISR should use the IRAM_ATTR attribute so that it executes from IRAM instead of flash memory. ISR code cannot execute Serial.print() or delay() as both functions take too long and can block interrupts. Use ISR functions that are as simple as possible and switch complex processing to the main loop with the use of flags. 

ESP32 Timer Interrupt Example: LED Blinking Program

In this example, we are going to test an LED blink program. But instead of using delay, we are going to use a timer interrupt. To do that, make the connections on a breadboard as shown in the circuit diagram below.

Circuit Setup for ESP32 Timer Interrupt Programming

ESP32 LED Blink Circuit

Here is the actual circuit connected on a breadboard as per the circuit diagram.

ESP32 Timer Tutorial

Connect the Anode of the LED to GPIO21 and connect the cathode to GND through a 220-ohm resistor.

ESP32 Timer Interrupt Code Implementation

Download the code attached to the bottom of this article and upload it to the ESP32. You will observe that the LED is blinking at a rate of 1Hz. Let’s discuss each part of the code.

#define LED 21
hw_timer_t *My_timer = NULL;

In the global variable area, we have defined the LED pin as GPIO21. Then we have created a pointer variable named My_timer of the type hw_timer_t in order to configure the timer.

void IRAM_ATTR onTimer(){
digitalWrite(LED, !digitalRead(LED));
}

Then we created the ISR for the timer interrupt. In the ISR, we have written a function to invert the state of GPIO21. This ISR will be executed when the timer interrupt occurs.

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.

ESP32 timerBegin 

My_timer = timerBegin(0, 80, true);

To initialise the timer, we are using the ESP32 timerBegin function with the following variables. The first one is the number of the timer we want to use (from 0 to 3, since we have 4 hardware timers), the second one is the value of the prescaler, and the last one is a flag indicating if the counter should count up (true) or down (false). In this example, we are using timer 0 with the prescaler 80 and the counter to count up.

ESP32 AttachInterrupt Implementation for Timer Events

timerAttachInterrupt(My_timer, &onTimer, true);

Before enabling the timer, we need to attach it to an ISR, which will be executed when the interrupt is generated. This is done with a call to the ESP32 attachInterrupt Function. In this example, we have attached the ISR function called onTimer to the timer interrupt.

Esp32 timerAlarmWrite

timerAlarmWrite(My_timer, 1000000, true);

timerAlarmWrite function is used to specify the counter value at which the timer interrupt should be generated. So, for this example, we assume that we want to generate an interrupt each second, and thus we pass the value of 1000000 microseconds, which is equal to 1 second. For the third argument, we will pass the value true, so the counter will reload and thus the interrupt will be generated periodically.

timerAlarmEnable(My_timer);

At last, we are enabling the timer interrupt using the function timerAlarmEnable.

 

Advanced ESP32 Timer Interrupt Programming Techniques

Professional ESP32 timer interrupts programming can include using multiple timers to schedule events, issues of priority, and sharing of resources. For advanced ESP32 timer interrupt sample projects, developers may be coordinating multiple timers to develop complicated timing sequences, sensor sampling, and communication protocols.

It is important to consider certain key issues for systematic ESP32 timer interrupt programming, these include: - Keep ISR execution time to a minimum - Ensure choices for the ESP32 timerBegin parameters - Use ESP32 attachInterrupt at the correct time when added complexity is needed for an ISR - Memory management in interrupt contexts - Sharing timer resources within different application modules

Supporting Files

More ESP32 Projects That Push the Limits

Build your confidence with timers, interrupts, and real-time applications by exploring these ESP32-powered projects. Whether you're syncing time from the internet, using external RTC modules, or diving deeper into interrupt handling, these tutorials expand your toolkit for creating time-aware systems with precision and control.

ESP32 Interrupt Tutorial

ESP32 Interrupt Tutorial

ESP32 has a total of 32 interrupts for it’s each core. Each interrupt has a certain priority level. The major classification of interrupts in ESP32 is based on the interrupt source. And they are Hardware Interrupts and Software interrupts.

Internet Clock using ESP32 and OLED Display

Internet Clock using ESP32 and OLED Display

ESP32 is a Wi-Fi module and can be easily connected to the internet so we will use NTP (Network Time Protocol) and UDP (User Datagram Protocol) to fetch Time from the internet using Wi-Fi.

ESP32 Real Time Clock using DS3231 Module

ESP32 Real Time Clock using DS3231 Module

Learn about Real Time Clock (RTC) and its interfacing with the ESP32 and OLED display. We will use DS3231 RTC module to keep track of the correct time and display it on SPI OLED by using ESP32 as microcontroller.

Complete Project Code

#define LED 21
hw_timer_t *My_timer = NULL;
void IRAM_ATTR onTimer(){
digitalWrite(LED, !digitalRead(LED));
}
void setup() {
pinMode(LED, OUTPUT);
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, 1000000, true);
timerAlarmEnable(My_timer); //Just Enable
}
void loop() {
}
Have any question related to this Article?

Comments

Hello, it seems that this solution does not work for me. I keep getting this error message when trying to create the pointer variable named My_timer of the type hw_timer_t in order to configure the timer.

I have copied the exact same code that is uploaded. 

If anyone has had this same problem please let me know. 

Thanks

Thank you, most helpful.

What does the 'true' signify in 'timerAttachInterrupts'?

Should the '8000000MHz' read '8000000Hz'?

Thank you for your support... I would like to know how many timers variables can be initialised ?

I don't know where the above code comes from but it doesn't work.

This is tested and works. (ESP-32S, Arduino IDE 2.3.6, Arduino ESP32 Boards 2.0.18, ESP32 (Espressif) 3.3.0, 29 July 2025. )


#define LED 02  // Inbuilt for some ESP32 boards. Adjust as necessary.

// Create a reference to a timer structure
hw_timer_t *timer = NULL;

// Create an interrupt service routine
void ARDUINO_ISR_ATTR onTimer() {
 digitalWrite(LED, !digitalRead(LED));
}

void setup() {
 pinMode(LED, OUTPUT);
 // Create the timer structure, assign it to the reference
 //  variable and start it running at 1MHz.
 timer = timerBegin(1000000);  
 // Attach the interrupt to the timer
 timerAttachInterrupt(timer, &onTimer);
 // Set alarm to trigger evey second (1000000uS), autoreload,
 //  and continue forever.
 timerAlarm(timer, 1000000, true, 0);
}

Add New Comment

Login to Comment Sign in with Google Log in with Facebook Sign in with GitHub