The Pico In MicroPython: PWM
Written by Harry Fairhead & Mike James   
Monday, 26 July 2021
Article Index
The Pico In MicroPython: PWM
Changing The Duty Cycle
Duty Cycle Resolution

Duty Cycle Resolution

It seems as if you can set the duty cycle to a 16-bit value giving you 65535 different settings, however, this is only true in a few cases. The Pico’s PWM hardware implements the following algorithm:

set GPIO line high
for count in range(wrap):
	wait one clock cycle
	if count>level:
		set GPIO line low

In other words, the frequency of the PWM signal depends on the value of wrap and the clock frequency and duty cycle depend on level. When you set the frequency of the PWM signal that you want, the software works out the best value for the clock frequency and wrap value. In an ideal wold the wrap would always be the maximum 16-bit value, 65535, but to achieve the desired frequency it often has to be less. Clearly you can only set the duty cycle between 0 and wrap and this can limit the precision that you can set.
For example, if wrap is 4 then you can only set duty cycles of 0, 25%, 75% and 100%, i.e. level= 0, 1, 2, 3, and such low values of wrap do occur.

In other words, the frequency you select affects the accuracy of the setting of the duty cycle. In most cases the wrap value is large enough to ignore the problem, but sometimes it is important. MicroPython doesn’t provide any way to explicitly set or get the wrap value, but it is easy to add a function to get it:

def pwm_get_wrap(sliceNo):
    Addr = 0x40050000 +0x10+0x14*sliceNo    
    return (machine.mem32[Addr])

Problems with small wrap values usually occur at high frequencies. The reason is that the clock runs at 125MHz and so if you want a PWM frequency of say 30MHz then the wrap value has to be 4 and hence the duty cycle can only be 0,1,2,3. You can see that this is the case in the following example:

pwm16 = PWM(Pin(16))

You will see the wrap is 2 and if you examine the output using a logic analyzer you will see that the duty cycle is not 50%.

At lower frequencies the duty cycle precision is usually close to 16-bits. Also notice that the duty cycle is always set as if it was a full 16-bit value and MicroPython scales this into the range that wrap makes possible.

There is an additional effect related to the clock that you need to consider. The clock divider can be fractional and in this case the fractional division is achieved by varying the division between two integer dividers so that the average frequency is as requested. This can lead to jitter in the pulse positions.

In Chapter But Not In This Extract

  • Uses Of PWM – Digital To Analog
  • Frequency Modulation
  • Controlling An LED
  • What Else Can You Use PWM For?


  • PWM, Pulse Width Modulation, has a fixed repetition rate but a variable duty cycle, i.e. the amount of time the signal is high or low changes.

  • PWM can be generated by software simply by changing the state of a GPIO line correctly, but it can also be generated in hardware so relieving the processor of some work.

  • As well as being a way of signaling, PWM can also be used to vary the amount of power or voltage transferred. The higher the duty cycle, the more power/voltage.

  • The Pico has eight hardware PWM generators and these are capable of a range of operational modes.

  • The PWM lines are controlled by a counter and two values wrap which gives the frequency and level which gives the duty cycle. This is mostly hidden from the MicroPython programmer and you can specify frequency and duty cycle without worrying too much about how they are generated.

  • You can generate phase-correct PWM or allow the phase to vary with the duty cycle.

  • The higher the wrap value, the higher the resolution of the duty cycle. It is possible to work out the best value for the clock frequency for any PWM frequency to maximize the duty cycle resolution.

  • PWM can be used to implement digital to analog conversion simply by varying the duty cycle. In the same way, by varying the duty cycle, you can dim an LED.


Programming the Raspberry Pi Pico In MicroPython

By Harry Fairhead & Mike James


Buy from Amazon.


  • Preface
  • Chapter 1 The Raspberry Pi Pico – Before We Begin
  • Chapter 2 Getting Started
  • Chapter 3 Getting Started With The GPIO
  • Chapter 4 Simple Output
  • Chapter 5 Some Electronics
  • Chapter 6 Simple Input
             Extract: Simple Input ***NEW!
  • Chapter 7 Advanced Input – Events and Interrupts
  • Chapter 8 Pulse Width Modulation
             Extract: PWM 
  • Chapter 9 Controlling Motors And Servos
             Extract: DC Motors
  • Chapter 10 Getting Started With The SPI Bus
  • Chapter 11 A-To-D and The SPI Bus
  • Chapter 12 Using The I2C Bus
  • Chapter 13 Using The PIO   
  • Chapter 14 The DHT22 Sensor Implementing A Custom Protocol
             Extract: A PIO Driver For The DHT22  
  • Chapter 15 The 1‑Wire Bus And The DS1820
  • Chapter 16 The Serial Port
  • Chapter 17 WiFi Using The ESP8266
  • Chapter 18 Direct To The Hardware
             Extract: Direct To The Hardware






To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.


Apache Ignite Changes SQL Engine

Apache Ignite has been updated to use a new SQL engine based on Apache Calcite, and new 'read repair' strategies.

Edge Overtakes Safari To Be Second Browser

In April Edge, Microsoft's Chromium-based browser gained a global browser market share of 10.07%, surpassing 10% for the first time since its introduction. In doing so it overtook Safari as the s [ ... ]

More News





or email your comment to:

Last Updated ( Monday, 26 July 2021 )