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 16:37] – [Suggested Readings and Knowledge Resources] pczekalski | en:iot-open:practical:hardware:sut:esp32:adv1_1 [2024/03/26 08:46] (current) – [Steps] 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 7: | Line 7: | ||
To implement this scenario, it is necessary to get familiar with at least one of the following scenarios first: | To implement this scenario, it is necessary to get familiar with at least one of the following scenarios first: | ||
* [[en: | * [[en: | ||
+ | |||
+ | A standard LCD handling library is attached to the '' | ||
+ | <code ini> | ||
+ | lib_deps = adafruit/ | ||
+ | </ | ||
===== Suggested Readings and Knowledge Resources ===== | ===== Suggested Readings and Knowledge Resources ===== | ||
Line 16: | Line 21: | ||
==== Task to be implemented ==== | ==== Task to be implemented ==== | ||
- | // | + | Present on the LCD current value of the '' |
==== Start ==== | ==== Start ==== | ||
- | //Write starting conditions, i.e. what to do in the beginning, what to pay attention to before beginning, how the mechanical part should look, etc.// Include needed compiler configuration, | + | Check LCD visibility |
==== Steps ==== | ==== Steps ==== | ||
- | // Write some extra information if, i.e. some steps are optional; otherwise, cancel this paragraph (but do not remove the header).// | + | 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 === | === Step 1 === | ||
- | //Describe activities | + | Include libraries: |
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | </code> | ||
+ | |||
+ | === 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 | ||
+ | </code> | ||
+ | |||
+ | === 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, baseFrequency, | ||
+ | timerAttachInterrupt(Timer2, | ||
+ | timerAlarmWrite(Timer2, | ||
+ | |||
+ | //start LCD | ||
+ | lcd.begin(16, | ||
+ | lcd.clear(); | ||
+ | |||
+ | | ||
+ | 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 n === | + | === Step 7 === |
- | //Describe activities done in Step n.// | + | This way, a main loop is empty: everything runs asynchronously, |
+ | <code c> | ||
+ | void loop() | ||
+ | { | ||
+ | } | ||
+ | </ | ||
==== Result validation ==== | ==== Result validation ==== | ||
- | //Provide some result validation methods for self-assessment.// | + | 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 ===== | ||
- | This section is to be extended as new questions appear. \\ | + | **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 |
- | When using the printed version of this manual, please refer to the latest online version of this document to obtain the valid and up-to-date list of the FAQ. | + | |
- | //Provide some FAQs in the following form:\\ | + | |
- | **Question? | + | |
- | // | + | |
<WRAP noprint> | <WRAP noprint> |