7. Timer
7.1 Introduction to Timers
A timer is integrated inside the microcontroller and can be controlled through programming. The timing function of the microcontroller is realized through counting. When the microcontroller generates one pulse per machine cycle, the counter increments by one. The main function of a timer is to keep track of time. When the time is reached, an interrupt can be generated to remind that the timing period has expired, and then the corresponding function can be executed in the interrupt function. For example, if we want an LED to toggle once every 1 second, we can use a timer configured to trigger an interrupt every 1 second and then execute the LED toggle program in the interrupt function.
7.2 Hardware Timers and Software Timers
Timers can be implemented based on hardware or based on software. Both have their own characteristics and applicable scenarios:
- A hardware timer is a timing function provided by the microcontroller hardware, implemented by dedicated timing/counting circuits. The biggest advantage of hardware timers is their high precision and strong reliability because they are not affected by software tasks and operating system scheduling. When very precise timing functions are needed, such as generating PWM signals or obtaining precise time measurements, hardware timers are the first choice. Since timing operations are performed directly by hardware, even if the main CPU is busy with other tasks, the timer can still accurately execute callback operations at the scheduled time.
- A software timer is a timer implemented by the operating system or a software library, which uses the mechanism provided by the operating system to simulate timer functions. The implementation of software timers is affected by the current system load and task scheduling policy, so they are relatively less precise than hardware timers. However, software timers are usually more flexible, allowing a large number of timers to be created, and are suitable for applications that do not require precise time control.
In some cases, software timers may cause timing precision issues, for example, under high-load conditions or when there are many other high-priority tasks in the system. For simple delays that do not require high precision, software timers are usually sufficient.
7.3 Timer Limitations and Performance Considerations
In the MicroPython environment, although the use of timers brings convenience, there are also some limitations and performance considerations:
- Resource limitation: In MicroPython, the number of available hardware timers is limited, so you must carefully choose when and where to use hardware timers.
- Callback function limitation: The timer's callback function is called in the interrupt context, which means that the code in the callback function must be short and fast to execute. Performing complex operations or long-running tasks in these callback functions may degrade system performance and affect the accuracy of other timed tasks.
- Interrupt masking issue: If there is too much computation in the callback function, or resources are shared with other interrupts, interrupt masking may occur, thereby blocking the processing of other important interrupts.
- Threads and concurrency: MicroPython usually runs in an environment without an operating system, and multithreading is not supported in the standard implementation. This means that all operations are executed sequentially, and certain long-running tasks may block the execution of other code, including timer responses.
- Garbage collection impact: In MicroPython, memory management is implemented through garbage collection. The execution of garbage collection is unpredictable and may take considerable time, which affects the execution of timed tasks to a certain extent.
When designing a system that uses timers, it is recommended to write callback functions that are as short and efficient as possible. Heavy operations or potentially blocking code should be handed off to independent tasks or processed asynchronously through other mechanisms to avoid affecting the timely response of the timer.
7.4 Basic Timer Parameters
The ESP32S3 chip provides integrated hardware timers with multiple hardware timers, such as Timer0, Timer1, Timer2, etc. These timers can be used for precise time control tasks, such as periodic operations, PWM signal generation, and event counting. They are directly supported by the microcontroller hardware, can be configured in one-shot or periodic trigger modes, and can generate interrupts when the set time is reached, thereby executing fast tasks or processing. When developing with MicroPython, there is a dedicated class that allows us to easily access and use these hardware resources. Basic timer parameters include: timer number, channel number, prescaler, auto-reload value, timer interrupt enable, etc.
Refer to the official MicroPython documentation: http://www.86x.org/en/latet/library/machine.Timer.html#machine-timer
7.5 Timer Usage Process
- First, import the necessary modules and libraries
from machine import Timer- Next, you can create and initialize a timer object
timer = Timer(-1) # Use a free timerWhere -1 means using a free, unspecified timer. The -1 parameter can also be changed to 0, 1, 2, 3, which means using Timer 0, Timer 1, and so on.
- Create a handler function that will be called automatically by the timer
For example, here is a simple function that prints "Tick", which will be called every time the timer triggers.
def tick(timer):
print('Tick')
```
4. Initialize the timer
Use the init() method to initialize the timer and set it to periodic mode while specifying the interrupt handler function. For example, the following code will call the tick function once every 1 second;
# 1000 milliseconds, that is, 1 second
timer.init(period=1000, mode=Timer.PERIODIC, callback=tick)
The parameter descriptions are as follows:
1. period: Specifies the time between timer overflows in milliseconds. For example, period=1000 sets the timer period to 1 second.
2. mode: Sets the operating mode of the timer. Common modes are:
- Timer.ONE_SHOT: The timer runs only once. After reaching the set time, it triggers the callback function once and then stops.
- Timer.PERIODIC: The timer continuously resets, triggering the callback function each time the set period is reached.
3. callback: This is a function pointer that will be called when the timer overflows. It must be a function that accepts the timer object as its only parameter.2
3
4
5
6
7
8
9
10
11
12
13
- Finally, if you want to stop the timer or release timer resources, you can use the deinit() method
timer.deinit()This will deactivate the timer, and you can reinitialize it when needed.
Here is a complete example:
from machine import Timer
def tick(timer):
print('Tick')
timer = Timer(-1)
timer.init(period=1000, mode=Timer.PERIODIC, callback=tick)
# ... Your other code can go here. Once per second, 'Tick' will be printed.
# When you want to stop the timer:
# timer.deinit()2
3
4
5
6
7
8
9
10
11
7.6 Hardware Connection and Preparation
In this case, we use an LED to test the timing function of the timer. The LED state change is placed in the timer interrupt handler function. Set the timer's period to 1 second. When the timer's timing period expires, an interrupt is triggered and the LED state is changed;
7.7 Timer Verification
import time
from machine import Pin, Timer
# Define the Pin control pin
led = Pin(48, Pin.OUT)
# Define the timer interrupt callback function
def timer_irq(timer_pin):
led.value(not led.value())
# Define the timer
timer = Timer(0)
# Initialize the timer
timer.init(period=500, mode=Timer.PERIODIC, callback=timer_irq)
while True:
time.sleep(1)2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
7.8 Timer Effect
Toggles on and off every 0.5 seconds.