This article will guide you to control the brightness of an LED using Pulse Width Modulation(PWM) in Raspberry Pi Pico RP2040. First, we shall briefly discuss how PWM can be used to dim an LED. Then we will learn to interface a potentiometer to control the brightness of the LED. The analog value of the potentiometer will be read using the Analog-to-digital converter(ADC) and the LED brightness will change according to the ADC value.

Components Required
- A Raspberry Pi Pico with MicroPython installed.
- An LED and a resistor with a value of 220 ohm/330 ohm.
- Breadboard and connecting wires.
Your Raspberry Pi Pico needs to be preloaded with a MicroPython UF2 file to program it in MicroPython. You can read our getting started guide for Raspberry Pi Pico where we show all steps required to start programming Raspberry Pi Pico(RP2040) in MicroPython.
What is Pulse Width Modulation(PWM)?
PWM is a modulation technique using which the width of waves in a pulse train can be varied. It has a wide variety of applications such as:
- Generation of analog voltages using a digital signal.
- Speed control of electric motors.
- Telecommunications.
- Audio synthesis and amplification.
Duty Cycle, frequency, and period are three notable parameters of a PWM signal. Frequency relates to the number of times a PWM signal switches between ON and OFF state per second. In the case of LVTTL(Low voltage Transistor-Transistor Logic), the ON/HIGH state is 3.3V and the OFF/LOW state is 0V for most applications. As Raspberry Pi Pico features RP2040 which operated at LVTTL levels, we will use these standard voltages for PWM demonstration.

A PWM signal resembles a square wave where the signal is ON for some duration and then it is OFF for some duration. The sum of ON time and OFF time is the period of a PWM wave. The Duty Cycle of the PWM wave is the percentage of time the signal remains at the ON state relative to the period of the PWM signal.

By varying the duty cycle, we can vary the average voltage supplied to an electronic component such as an LED. The more the duty cycle of a PWM signal, the more voltage will be delivered to a load.
Raspberry Pi Pico PWM Pinout
The RP2040 in Raspberry Pi Pico has 8 identical slices of PWM block. Each slice has the ability to monitor the frequency or duty cycle of an input signal as well as produce two PWM output signals. So there are 16 controllable PWM outputs. The PWM block may operate each of the 26 available GPIO pins onboard the Raspberry Pi Pico.

Connecting LED and Potentiometer To Raspberry Pi Pico
Connect an LED, a 220ohm resistor, and a 10K potentiometer as shown below. The values of these components can vary within practical limits. Remember to connect the LED with the correct polarity.

We have an article that describes how to interface a potentiometer with Raspberry Pi Pico. Since this article is primarily focused on controlling the brightness of an LED, readers can visit the linked article to learn more about interfacing potentiometers with Pi Pico. The article also explains the Analog to Digital(ADC) converter in Raspberry Pi Pico.
Instead of using an external LED, you can also use the onboard LED in Raspberry Pi Pico.
MicroPyhon Code For Raspberry Pi Pico PWM Control Of An LED
Let us now write a simple MicroPython script to control LED brightness using Raspberry Pi Pico W. The next steps will be discussed using Thonny IDE.
- Connect Pi Pico to your computer. Open Thonny and paste the following into a new project space.
from machine import Pin, PWM, ADC
adc = machine.ADC(28)
pwm0 = PWM(Pin(15))
pwm0.freq(1000)
while True:
digital_value = adc.read_u16()
pwm0.duty_u16(digital_value) # set duty cycle, range 0-65535
Code language: Python (python)
- Run the code by clicking the Run button or by pressing F5.

- Save the code to Raspberry Pi Pico.

- Save it as main.py or with any other name with a “.py” filename extension.

You should now be able to vary the brightness of the LED by rotating the potentiometer.
Also see: Interface NeoPixel WS2812B RGB LED With Raspberry Pi Pico(MicroPython)
LED Dimming Code Explanation.
We first import the necessary libraries and classes required for the code to work. The Pin class is used to send/read data from the GPIOs, the PWM class will be used for pulse width modulation using the GPIOs and the ADC class will help us to read analog values from a potentiometer.
from machine import Pin, PWM, ADC
import time
Code language: JavaScript (javascript)
GPIO 28 is set as an ADC input pin. You can also set it as any other pin available for ADC in Raspberry Pi Pico.
adc = machine.ADC(28)
Next, we set GPIO 15 as the PWM output pin and set the frequency of the PWM as 1Khz. An object pwm0 is initiated with these parameters.
pwm0 = PWM(Pin(15))
pwm0.freq(1000)
The code inside the while loop gets the reading from ADC and sets the duty cycle of PWM. The method adc.read_u16() returns ADC values in the 0 to 65535 (2^16-1) range. Raspberry Pi Pico can set duty cycle in the range of 0 to 65535, where 0 will give a PWM signal of 0% duty cycle and 65535 will output a PWM signal of 100% duty cycle. The method pwm0.duty_u16(digital_value) will set the duty cycle of the PWM according to the value read by the ADC.
digital_value = adc.read_u16()
pwm0.duty_u16(digital_value)
MicroPython Methods For PWM
Apart from the code that we discussed above, here are some other useful MicroPython PWM methods that you can use to interact with Raspberry Pi Pico RP2040.
- pwm0.frequency: get the current PWM frequency.
- pwm0.duty_u16(): get the current duty cycle of PWM.
- pwm0.deinit(): turn off PWM for the pin associated with pwm0 object.
Leave a Reply