This tutorial will guide you to interface with hardware timers or create virtual timers using MicroPython. The code detailed here can be used for MicroPython-supported boards like Raspberry Pi Pico & Pico W, ESP32, or ESP8266.
Any of the following development boards:
- Raspberry Pi Pico or Pico W.
Your microcontroller has to be flashed with a MicroPython firmware file to program it in MicroPython. You can refer to the guides linked below.
- Flash & Run MicroPython On ESP32 Using Thonny IDE.
- Getting Started with MicroPython On ESP32 Using uPyCraft IDE.
For Raspberry Pi Pico:
2. Timers in Microcontrollers
In microcontrollers, timers are hardware peripherals that can keep count and help with timing events. They are circuit blocks consisting of memory registers incrementing in value with clock pulses. These timers can be activated and deactivated and can alert the CPU when a particular count is reached. There can be multiple timers in a chip.
Some of the common uses of such timers are:
- Generating Delays: Timers can be configured to generate precise delays by counting a certain number of clock cycles.
- Interrupt Generation: Timers can generate interrupts at specific intervals, allowing the microcontroller to perform critical tasks with precise timing.
- Pulse Width Modulation (PWM): Timers are often used to implement PWM signals, which are essential for controlling the speed of motors, brightness of LEDs, and other analog-like outputs.
- Task Scheduling: Timers can help to perform some tasks at regular intervals.
3. MicroPython Timers Overview
MicroPython abstracts the hardware timer and provides software functions to control and read the timer registers.
There are two MicroPython timer modes which shall be discussed shortly:
- Periodic mode: The timer runs periodically at a configured frequency.
- One-shot mode: The timer runs once until a pre-set configured period.
Timer class of the
machine module in MicroPython to interface with timer peripherals. For example, create an object
tim of the
Timer class with id=-1 as follows:
Now you can use the following method to initialize a periodic timer:
tim.init(mode=Timer.PERIODIC, period=1000, callback=interrupt_func)
To stop a timer or to disable the timer peripheral, use
The examples shown later in this article will help you to understand better. Let us see how we can use the hardware timers in some microcontrollers using MicroPython.
3.1 Timers in Raspberry Pi Pico
The RP2040 microcontroller on Raspberry Pi Pico has a single 64-bit hardware timer, which increments once per microsecond. MicroPython port of RP2040 allows the creation of unlimited software timers, as long as memory does not run out. We can also skip defining the ID of the timer object as only id=-1 is supported and the ID defaults to this.
id=-1 creates a virtual(software) timer.
3.2 Timers In ESP32
ESP32 MicroPython firmware supports four hardware timers. You can interface with them by using the timer ID from 0 to 3. Virtual timers are not supported.
3.3 Timers in ESP8266
Virtual timers are supported in the MicroPython port of ESP8266. Here too, we have to use the timer ID of -1.
4. MicroPython Timers Periodic Mode
The example below shows how we can implement timer-based interrupts in Raspberry Pi Pico. For external interrupts, refer to the Raspberry Pi Pico External Interrupts Tutorial.
4.1 Example to Blink an LED Periodically
Here is the code to blink the onboard LED in Raspberry Pi Pico/Pico W at an interval of 1000 milliseconds using the periodic timer mode and a virtual MicroPython timer:
from machine import Pin, Timer
led = Pin("LED", Pin.OUT)
tim.init(mode=Timer.PERIODIC, period=1000, callback=interrupt_func)Code language: Python (python)
4.2 Code Explanation
- We first import the
Timerclasses from the
machinemodule in MicroPython. Then an object
ledis created of the
Pinclass to control the onboard LED.
- Next, create a
timobject of the
Timerclass with id=-1. For ESP32, this value should be between 0 and 3 as explained earlier.
- Then we define a function
interrupt_func(t)that will be called later whenever the timer overflows. This function’s argument has to be specified. Otherwise, an exception will occur when the timer expires.
- The line code of
led.toggle()will switch the state of the onboard LED in Raspberry Pi Pico.
- Finally, we initialize the timer in
PERIODICmode with a period of
1000milliseconds. We designate
interrupt_funcas the callback function. The callback function is executed every 1000ms when the timer expires.
Instead of defining a period, you can set a frequency for the timer interrupt. Here is an example that will perform the same function as the code above:
timer = Timer(mode=Timer.PERIODIC, freq=1, callback=interrupt_func)
In the code above,
freq represents the timer frequency in Hertz.
5. MicroPython Timers One Shot Mode
In one-shot mode, we can set a time interval after which a task will be performed only once. This is similar to a countdown timer.
5.1 Toggle LED Countdown Timer
from machine import Pin, Timer
led = Pin("LED", Pin.OUT)
tim.init(mode=Timer.ONE_SHOT, period=5000, callback=interrupt_func)Code language: Python (python)
The code works in the same way as the periodic mode code, except that the callback function will be called only once when the period of
5000 milliseconds is over. The LED stays ON initially when the code is run and switches OFF after 5 seconds.
Remember to change the timer ID depending on the board you use.
Timers are hardware peripherals that work differently in MCUs and SoCs from different manufacturers. Hence the MicroPython code may differ for various use cases. For example, in the case of WiPy boards, we have to use the class
machine.TimerWiPy for timers.
In conclusion, we use the
Timer class in MicroPython to interface with hardware timers or to create virtual timers. The periodic mode and one-shot mode facilitate the precise timing of tasks and events.