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 22:14] – [Steps] pczekalski | en:iot-open:practical:hardware:sut:esp32:adv1_1 [2025/10/03 14:22] (current) – [FAQ] pczekalski | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== 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. You can think about these handlers as they are interrupted handling functions, but instead of externally triggered interrupts, those are initiated internally by the hardware timer.\\ | ||
| + | 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 '' | ||
| + | |||
| + | ===== Prerequisites ===== | ||
| + | To implement this scenario, it is necessary to get familiar with at least one of the following scenarios first: | ||
| + | * [[en: | ||
| + | |||
| + | A standard LCD handling library is attached to the '' | ||
| + | <code ini> | ||
| + | lib_deps = adafruit/ | ||
| + | </ | ||
| + | |||
| + | ===== Suggested Readings and Knowledge Resources ===== | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | * [[https:// | ||
| + | ===== Hands-on Lab Scenario ===== | ||
| + | |||
| + | ==== Task to be implemented ==== | ||
| + | Present on the LCD current value of the '' | ||
| + | |||
| + | ==== Start ==== | ||
| + | Check LCD visibility in the camera FOV. You may also disable LED if it interferes with the camera video stream, as described in the scenario [[en: | ||
| + | |||
| + | ==== Steps ==== | ||
| + | We used to separate tasks, but for this case, complete code is provided in chunks, including LCD handling. It presents relations on where particular parts of the code should be located when using timers and how timing relates between components. | ||
| + | |||
| + | <note tip>It is important, e.g. when LCD had to be set up and configured before asynchronous handlers execute writing to it, so set up order is meaningful!</ | ||
| + | === Step 1 === | ||
| + | Include libraries: | ||
| + | <code c> | ||
| + | #include < | ||
| + | #include < | ||
| + | </ | ||
| + | |||
| + | === Step 2 === | ||
| + | Define LCD configuration pins (see details and explanation in the scenario: [[en: | ||
| + | <code c> | ||
| + | #define LCD_RS 2 | ||
| + | #define LCD_ENABLE 1 | ||
| + | #define LCD_D4 39 | ||
| + | #define LCD_D5 40 | ||
| + | #define LCD_D6 41 | ||
| + | #define LCD_D7 42 | ||
| + | </ | ||
| + | |||
| + | === Step 3 === | ||
| + | Declare variables and classes (timers): | ||
| + | <code c> | ||
| + | volatile byte i = 0; | ||
| + | hw_timer_t *Timer1 = 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 interval1 = 1000000; | ||
| + | const int interval2 = 3000000; | ||
| + | </ | ||
| + | The base frequency for the timers in ESP32 is 80 MHz. Each timer counts in microseconds, | ||
| + | |||
| + | === Step 5 === | ||
| + | Declare and implement functions that are timer handles: timer calls the bound function every execution period: | ||
| + | <code c> | ||
| + | void IRAM_ATTR onTimer1() //handler for Timer1 | ||
| + | { | ||
| + | i++; | ||
| + | } | ||
| + | |||
| + | void IRAM_ATTR onTimer2() //handler for Timer2 | ||
| + | { | ||
| + | lcd.clear(); | ||
| + | lcd.setCursor(0, | ||
| + | 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(){ | ||
| + | //Timer1 config | ||
| + | Timer1 = timerBegin(0, | ||
| + | timerAttachInterrupt(Timer1, | ||
| + | timerAlarmWrite(Timer1, | ||
| + | | ||
| + | //Timer2 config | ||
| + | Timer2 = timerBegin(1, | ||
| + | timerAttachInterrupt(Timer2, | ||
| + | timerAlarmWrite(Timer2, | ||
| + | | ||
| + | //start LCD | ||
| + | lcd.begin(16, | ||
| + | lcd.clear(); | ||
| + | | ||
| + | //start both timers | ||
| + | timerAlarmEnable(Timer1); | ||
| + | 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() | ||
| + | { | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | ==== 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 '' | ||
| + | |||
| + | ===== FAQ ===== | ||
| + | **How many timers can I use?**: ESP32-S3 has 4 hardware timers. You can circumvent this limitation by using smart handlers that have, for example, an internal counter and execute every Nth cycle internally. This helps simulate multiple timers in a software-based manner. | ||
| + | |||
| + | <WRAP noprint> | ||
| + | ===== Project information ===== | ||
| + | {{: | ||
| + | This Intellectual Output was implemented under the Erasmus+ KA2.\\ | ||
| + | Project IOT-OPEN.EU Reloaded – Education-based strengthening of the European universities, | ||
| + | Project number: 2022-1-PL01-KA220-HED-000085090. | ||
| + | |||
| + | **__Erasmus+ Disclaimer__**\\ | ||
| + | This project has been funded with support from the European Commission. \\ | ||
| + | This publication reflects the views of only the author, and the Commission cannot be held responsible for any use that may be made of the information contained therein. | ||
| + | |||
| + | **__Copyright Notice__**\\ | ||
| + | This content was created by the IOT-OPEN.EU Reloaded consortium, 2022, | ||
| + | The content is Copyrighted and distributed under CC BY-NC [[https:// | ||
| + | <figure label> | ||
| + | {{: | ||
| + | </ | ||
| + | |||
| + | |||
| + | </ | ||