Testing ESP32 Hardware Timers With Interrupts (Beginner-Friendly Guide)

ESP32 microcontrollers include multiple hardware timers that can trigger interrupts with microsecond precision. This makes them perfect for generating pulses, reading sensors, simulating RPM or speed signals, or scheduling tasks without blocking the loop().

In this article, we walk through a simple example that:

  • Creates a hardware timer
  • Attaches an ISR (Interrupt Service Routine)
  • Toggles a pin using the interrupt
  • Starts and stops the timer from the main loop
  • Prints internal counters to demonstrate real behaviour

This is an ideal “self-test” project to understand how ESP32 timers and interrupts work.


Why Use Hardware Timers on ESP32?

Unlike delay() or software timers, ESP32 hardware timers run independently of the main code. This allows you to:

  • Generate precise square waves
  • Simulate speed/RPM sensor pulses
  • Execute functions at exact time intervals
  • Avoid blocking your program
  • Maintain microsecond-level timing even under heavy CPU load

Example Sketch: Testing ESP32 Timer Interrupts

Below is the full sketch, followed by a detailed explanation.

volatile byte state = LOW;
int pin = 13;

hw_timer_t *timer = NULL;
int i = 0;

void IRAM_ATTR needle() {   // ISR: toggles pin state
  state = !state;
  digitalWrite(pin, state);
}

void setup() {
  Serial.begin(115200);
  pinMode(pin, OUTPUT);

  // Create hardware timer (1 MHz clock)
  timer = timerBegin(0, 80, true);   // Timer 0, prescaler=80 → 1µs per tick

  // Attach interrupt handler
  timerAttachInterrupt(timer, &needle, true);

  // Set alarm to fire every 50,000µs (50ms)
  timerAlarmWrite(timer, 50000, true);

  // Start timer
  timerAlarmEnable(timer);
}

void loop() {
  Serial.println(i);
  i++;

  // Stop timer after 10,000 iterations
  if (i == 10000) {
    timerStop(timer);
  }

  // Restart timer at 20,000 iterations
  if (i == 20000) {
    timerStart(timer);
    i = 0;
  }
}

How the Code Works (Step-By-Step)

1. The Interrupt Handler (ISR)

void IRAM_ATTR needle() {
  state = !state;
  digitalWrite(speed_pin, state);
}
  • This function runs automatically whenever the timer triggers.
  • IRAM_ATTR ensures the code runs from internal RAM → faster and safer for interrupts.
  • It simply toggles a GPIO pin to generate a square wave.

2. Creating the Hardware Timer

timer = timerBegin(0, 80, true);

Parameters:

ParameterMeaning
0Timer number (ESP32 has 0–3)
80Prescaler → divides 80 MHz clock → 80 gives 1 MHz
trueCount up (vs count down)

So: 1 tick = 1 microsecond


3. Attaching Interrupt

timerAttachInterrupt(timer, &needle, true);
  • needle is our ISR
  • true = edge triggered, false = level triggered

4. Setting Alarm Frequency

timerAlarmWrite(timer, 50000, true);
  • Alarm triggers every 50,000 microseconds (50 ms)
  • true = auto-reload

This means the ISR runs 20 times per second (20 Hz).


5. Start / Stop Timer in Loop

if (i == 10000) timerStop(timer);
if (i == 20000) {
  timerStart(timer);
  i = 0;
}

This demonstrates dynamic control:

  • Timer runs → ISR fires → pin toggles
  • Timer stops → ISR stops
  • Timer restarts later

Useful for:

  • RPM self-tests
  • Temporary disabling of simulated signals
  • Debugging timing behaviour
  • Power saving

What You Learn From This Test

By running this sketch you learn:

✔ How fast the interrupt fires
✔ How often your main loop runs
✔ That the ISR continues even if the loop is slow
✔ That timers can be paused and resumed
✔ That GPIO toggling inside an interrupt works reliably on the ESP32

This is the foundation for:

  • Speed sensor emulation
  • Engine RPM simulation
  • Stepper motor test pulses
  • Watchdogs
  • Scheduling periodic tasks
  • Precision timing

Common Mistakes (Avoid These)

1. Using delay() inside ISR

Never allowed. The CPU will hang.

2. Printing inside ISR

Serial in interrupts causes crashes.

3. Forgetting IRAM_ATTR

High chance of Guru Meditation errors.

4. Too many interrupts (too fast)

Stay above 20–30 µs ISR interval unless you really know what you’re doing.


Conclusion

ESP32 hardware timers are extremely powerful and allow microsecond-accurate tasks without blocking your main loop. The example above gives you a reliable way to:

  • Test your timers
  • Understand how interrupts behave
  • Validate self-test signals for RPM / speed
  • Learn how to start/stop timers dynamically

This is one of the best exercises for beginners to understand real-time behaviour on the ESP32.

Newsletter Updates

Enter your email address below and subscribe to our newsletter

Leave a Reply

Your email address will not be published. Required fields are marked *