Demo 22: How to use Timer interrupt in Arduino ESP32

1. Introduction
- In blinky demo we use delay() function to make the LED blink. In this demo we will replcae delay() function by using Timer (this is hardware timer). Using Timer we can schedule when a task need to be started and repeat or not. Applying to this demo, when the Timer is timeout we will change the current state of LED (ON to OFF to ON) every 1 second.
2. Hardware
Figure: ESP32 connect to LED
Connection:
[ESP32 IO14 and ESP32 GND to LED]
3. Software
In order to use Timer we will use the functions:
"hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp)"
+ num: is order of Timer. We only have 4 timers so the order can be 0,1,2,3.
+ divider: it is a prescaler. To make 1 second scheduler, we will use divider value is 80. ESP32 main clock is 80MHZ so every tick will take T = 1/(80MHZ/80) = 1 microsecond. We need 1000000 ticks for 1 second.
+ countUp: if it is true the timer will count up and vice versa.
"void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge)"
+ fn: is the callback function that will be invoked when timer timeout and timer interrupt will be invoked.
+ edge: if it is true, an alarm will generate an edge type interrupt.
"void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload)"
+ alarm_value: we set it to 1000000 as calculated above
+ autoreload: if it is true, timer will repeat.
"void timerAlarmEnable(hw_timer_t *timer)": enable the Timer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/* create a hardware timer */
hw_timer_t * timer = NULL;

/* LED pin */
int led = 14;
/* LED state */
volatile byte state = LOW;

void IRAM_ATTR onTimer(){
  state = !state;
  digitalWrite(led, state);
}

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

  pinMode(led, OUTPUT);

  /* Use 1st timer of 4 */
  /* 1 tick take 1/(80MHZ/80) = 1us so we set divider 80 and count up */
  timer = timerBegin(0, 80, true);

  /* Attach onTimer function to our timer */
  timerAttachInterrupt(timer, &onTimer, true);

  /* Set alarm to call onTimer function every second 1 tick is 1us
  => 1 second is 1000000us */
  /* Repeat the alarm (third parameter) */
  timerAlarmWrite(timer, 1000000, true);

  /* Start an alarm */
  timerAlarmEnable(timer);
  Serial.println("start timer");
}

void loop() {

}
4. Result

Post a Comment

8 Comments

Anonymous said…
can I make more than one timers?
Aspiring Hobbist said…
is there a command to disable the alarm after enabling it like void timerAlarmDisable?
Tom said…
There are 4 timers in the esp32. To address them use the #'s 0..3; More timers can be created/configured by using the example codemultiple times.

I have written code to use one timer for multiple and different intervals: one timer ticking at 500ms and a list of intervals to compare to like 1000, 2000, 500.

Tom Meyers
emts said…
Hi.
I am using your example code, to turn on and off a led (infrared of 905nm) with "digitalWrtie", but I do not get pulses under 2 microseconds.

I need to generate pulses at a frequency of 6Mhz and 13.3Mhz, please can you help me.
Anonymous said…
@emts don't use digitalwrite as this arduino implementation takes way to long to execute for these high frequency cycles. You need to use the lower level output level command of whatever board you are using.
Your article is very helpful for me.
I totally agree with what you have said!! Thanks for sharing your views.
I found very good information on your blog