Using PWM on the Pyboard
Contents
What is PWM?
PWM (Pulse Width Modulation) is a digital technique used to emulate analog power. A digital signal is rapidly switched ON and OFF, varying the "on-time" (duty cycle) to change the average power delivered to a device.
The switching happens at a fixed and high frequency making the changes appear analog to the device.
Pyboard Timers, Channels and Pins
PWM is generated on Pyboard digital pins using timers and channels. This article from our MicroPython for Pyboard series discusses the Pyboard's timers.
Each timer has one or more channels associated with it in a parent/child relationship. The timer acts as a master clock for each of its channels. Each channel can be assigned a separate task that is initiated when its timer is triggered.
Most channels have one or more digital pins assigned to them. In this way when the parent timer is triggered, a channel can perform its assigned action on an associated pin e.g. set its value to High or Low.
The Pyboard pinout is used to find the relationship between timers and their available channels as well as the pins referenced by a channel. Here is a link to the Pyboard V1.1 pinout.
For example: Tim2 has four channels; CH1, CH2, CH3 and CH4. Channel CH1 references two digital pins; X1 and X6.
Setting Up PWM on the Pyboard
Channels are created as TimerChannel objects from the pyb.Timer.channel() method. This method associates the TimerChannel object with a Timer object and a digital pin.
PWM is setup on the digital pin using the pyb.TimerChannel.pulse_width_percent() method to assign a percentage (0 to 100) duty cycle. The duty cycle can be a float value.
The physical timer, channel and pin used must match as indicated in the Pyboard pinout otherwise an exception may be thrown.
Step 1: Create a Timer object Timer2 with a frequency of 1 kHz timer = pyb.Timer(2, freq=1000) Step 2: Create a TimerChannel object Use Timer.channel() method to create a TimerChannel object. The channel will be associated with Timer2 and use pin X2. It is configured for PWM. ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin('X2')) Step 3: Assign a duty level to the TimerChannel object. Use TimerChannel.pulse_width_percent() method to assign a duty percentage to the TimerChannel object. ch2.pulse_width_percent(50)
Example: PWM on the Pyboard
Two pins will be configured with PWM. The setup is as given in the program comments.
Code:
# Two pins will be setup for PWM.
# Timer 2 @ 1kHz, Channel 2, pin X2.
# Timer 4 @ 2kHz, Channel 1, pin X9.
from pyb import Timer, Pin
# Configure Timer2 at 1kHz.
timer2 = pyb.Timer(2, freq=1000)
# Configure Timer4 at 2kHz.
timer4 = pyb.Timer(4, freq=2000)
# Configure Channel 2 on Timer2 with pin X2.
ch2 = timer2.channel(2, Timer.PWM, pin=Pin('X2'))
# Configure Channel 1 on Timer4 with pin X9.
ch1 = timer4.channel(1, Timer.PWM, pin=Pin('X9'))
# Channel 2 has 25% duty cycle.
ch2.pulse_width_percent(25)
# Channel 1 has 75% duty cycle.
ch1.pulse_width_percent(75)
The voltage outputs on pins X2 and X9 were examined with an oscilloscope. Both waveforms and timings were as expected.
- Timer2, Channel 2 and pin X2
- Wave period: 1ms (1KHz)
- On 250µs, Off 750µs (25% duty cycle)
- Timer4, Channel 1 and pin X9
- Wave period: 500µs (2KHz)
- On 375µs, Off 125µs (75% duty cycle)
References
- [1]Author: Kriti Kohli, 2023;
Article: What is PWM: Applications, Advantages & Challenges,
Section: What is PWM?,
Available at: https://www.aakash.ac.in/blog/what-is-pwm-applications-advantages-challenges/
Accessed: December, 2025.