This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:iot-open:practical:hardware:sut:esp32:adv1_1 [2024/03/25 19:32] – [Steps] pczekalski | en:iot-open:practical:hardware:sut:esp32:adv1_1 [2025/10/03 11:22] (current) – [FAQ] pczekalski | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== ADV1: Using timers to execute code asynchronously ====== | ====== ADV1: Using timers to execute code asynchronously ====== | ||
| - | It is advised to use timers that periodically execute a function to handle repeating tasks. Hardware timers work parallel to the CPU and consume few CPU resources. ESP32-S3 has 4 hardware timers, but each timer can execute multiple handlers. | + | It is advised to use timers that periodically execute a function to handle repeating tasks. Hardware timers work parallel to the CPU and consume few CPU resources. ESP32-S3 has 4 hardware timers, but each timer can execute multiple handlers. |
| - | The idea of using the timer is to encapsulate a piece of compact code that can be run virtually asynchronously and executed is a precisely-defined time manner. In this scenario, we use a timer to update the LCD screen periodically. We choose a dummy example where Timer 1 is used to increment a value of the '' | + | The idea of using the timer is to encapsulate a piece of compact code that can be run virtually asynchronously and executed is a precisely-defined time manner. In this scenario, we use a timer to update the LCD screen periodically. We choose a dummy example where Timer 1 is used to increment a value of the '' |
| Line 21: | Line 21: | ||
| ==== Task to be implemented ==== | ==== Task to be implemented ==== | ||
| - | Present on the LCD current value of the '' | + | Present on the LCD current value of the '' |
| ==== Start ==== | ==== Start ==== | ||
| Line 37: | Line 37: | ||
| </ | </ | ||
| + | === Step 2 === | ||
| + | Define LCD configuration pins (see details and explanation in the scenario: [[en: | ||
| + | <code c> | ||
| #define LCD_RS 2 | #define LCD_RS 2 | ||
| #define LCD_ENABLE 1 | #define LCD_ENABLE 1 | ||
| Line 43: | Line 46: | ||
| #define LCD_D6 41 | #define LCD_D6 41 | ||
| #define LCD_D7 42 | #define LCD_D7 42 | ||
| + | </ | ||
| + | === Step 3 === | ||
| + | Declare variables and classes (timers): | ||
| + | <code c> | ||
| volatile byte i = 0; | volatile byte i = 0; | ||
| hw_timer_t *Timer1 = NULL; | hw_timer_t *Timer1 = NULL; | ||
| hw_timer_t *Timer2 = NULL; | hw_timer_t *Timer2 = NULL; | ||
| + | static Adafruit_LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_D4, LCD_D5, LCD_D6, LCD_D7); | ||
| + | </ | ||
| + | Above, we declare two separate timers: '' | ||
| + | |||
| + | === Step 4 === | ||
| + | Declare constants that define how frequently timers will be calling handlers: | ||
| + | <code c> | ||
| const int baseFrequency = 80; //MHz | const int baseFrequency = 80; //MHz | ||
| const int interval1 = 1000000; | const int interval1 = 1000000; | ||
| const int interval2 = 3000000; | const int interval2 = 3000000; | ||
| + | </ | ||
| + | The base frequency for the timers in ESP32 is 80 MHz. Each timer counts in microseconds, | ||
| - | static Adafruit_LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_D4, LCD_D5, LCD_D6, LCD_D7); | + | === Step 5 === |
| - | + | Declare and implement functions that are timer handles: timer calls the bound function every execution period: | |
| - | void IRAM_ATTR onTimer1() | + | <code c> |
| + | void IRAM_ATTR onTimer1() | ||
| { | { | ||
| i++; | i++; | ||
| } | } | ||
| - | void IRAM_ATTR onTimer2() | + | void IRAM_ATTR onTimer2() |
| { | { | ||
| lcd.clear(); | lcd.clear(); | ||
| Line 64: | Line 81: | ||
| lcd.print(i); | lcd.print(i); | ||
| } | } | ||
| + | </ | ||
| + | |||
| + | <note warning> | ||
| + | <note tip>If you do need to use floating point calculations in ISR or timer functions, you can use '' | ||
| + | |||
| + | <note important> | ||
| + | === Step 6 === | ||
| + | Configure timers, start LCD and enable timers. Note the correct order: LCD have to be ready when the timer calls '' | ||
| + | <code c> | ||
| void setup(){ | void setup(){ | ||
| //Timer1 config | //Timer1 config | ||
| Line 69: | Line 95: | ||
| timerAttachInterrupt(Timer1, | timerAttachInterrupt(Timer1, | ||
| timerAlarmWrite(Timer1, | timerAlarmWrite(Timer1, | ||
| - | timerAlarmEnable(Timer1); | ||
| | | ||
| //Timer2 config | //Timer2 config | ||
| Line 75: | Line 100: | ||
| timerAttachInterrupt(Timer2, | timerAttachInterrupt(Timer2, | ||
| timerAlarmWrite(Timer2, | timerAlarmWrite(Timer2, | ||
| - | timerAlarmEnable(Timer2); | ||
| | | ||
| //start LCD | //start LCD | ||
| lcd.begin(16, | lcd.begin(16, | ||
| lcd.clear(); | lcd.clear(); | ||
| + | | ||
| //start both timers | //start both timers | ||
| timerAlarmEnable(Timer1); | timerAlarmEnable(Timer1); | ||
| timerAlarmEnable(Timer2); | timerAlarmEnable(Timer2); | ||
| } | } | ||
| + | </ | ||
| + | In the code above, '' | ||
| + | Following, '' | ||
| + | Then we define how frequently the execution of the function above will occur: '' | ||
| + | Note that at this moment, timers are not executing the handlers yet; the last step is required: '' | ||
| + | |||
| + | === Step 7 === | ||
| + | This way, a main loop is empty: everything runs asynchronously, | ||
| + | <code c> | ||
| void loop() | void loop() | ||
| { | { | ||
| } | } | ||
| - | + | </code> | |
| - | === Step 2 === | + | |
| - | + | ||
| - | ... | + | |
| - | + | ||
| - | === Step n === | + | |
| - | //Describe activities done in Step n.// | + | |
| ==== Result validation ==== | ==== Result validation ==== | ||
| On the LCD screen, you should see values starting from number 3, then 6, 9, 12 and so on (=3 every 3 seconds). Note, as '' | On the LCD screen, you should see values starting from number 3, then 6, 9, 12 and so on (=3 every 3 seconds). Note, as '' | ||
| ===== FAQ ===== | ===== FAQ ===== | ||
| - | **How many timers can I use?**: ESP32-S3 has 4 hardware timers. You may trick this limitation by using smart handlers that have, e.g., an internal counter and internally | + | **How many timers can I use?**: ESP32-S3 has 4 hardware timers. You can circumvent |
| <WRAP noprint> | <WRAP noprint> | ||