Learn how to generate PWM signals with the Raspberry Pi Pico using Arduino IDE. As an example, we’ll show you how to dim the brightness of an LED by changing the duty cycle over time.
We have a similar guide using MicroPython firmware: Raspberry Pi Pico: PWM Fading an LED (MicroPython).
Table of Contents
- Install the Raspberry Pi Pico in Arduino IDE
- Introducing PWM
- Raspberry Pi Pico GPIOs and PWM
- analogWrite() and other functions
- Fading an LED with Raspberry Pi Pico – Arduino IDE
Prerequisites
You need to install the Raspberry Pi Pico boards on Arduino IDE and you must know how to upload code to the board. Check out the following tutorial first if you haven’t already:
Introducing PWM (Pulse-Width Modulation)
PWM, or Pulse Width Modulation, is a technique that controls the power delivered to devices. It achieves this by turning the power on and off very quickly.
For example, if you alternate an LED’s voltage between HIGH and LOW very fast, your eyes can’t keep up with the speed at which the LED switches on and off; you’ll simply see some gradations in brightness.
That’s basically how PWM works — by producing an output that changes between HIGH and LOW at a very high frequency.
The duty cycle refers to the percentage of time the power is on compared to the total time of the on-off cycle—take a look at the following diagram.
By adjusting the duty cycle, we can control the average power delivered to the device. For instance, a higher duty cycle means the device receives more power, while a lower duty cycle results in less power. This enables us to control things like brightness in LEDs, speed in motors, or volume in speakers.
For example, a duty cycle of 50 percent results in 50 percent LED brightness, a duty cycle of 0 means the LED is fully off, and a duty cycle of 100 means the LED is fully on. Changing the duty cycle is how you produce different levels of brightness.
Raspberry Pi Pico GPIOs
The Raspberry Pi Pico comes with 40 pins, 26 of which are programmable GPIOs that you can use to connect peripherals. All Raspberry Pi Pico GPIOs can output PWM signals—they are marked in the diagrams in light green color.
You can use the following pinouts as a reference to identify and locate each GPIO on your board. The pinout is slightly different for the Pico and Pico W.
The following picture shows the Raspberry Pi Pico pinout (which functions are supported by each pin).
The pins marked in red are power pins that output 3.3V. The black pins are GND pins. All pins in light green can be used as “regular” GPIOs (input and output).
To learn more about the Pico Pinout, read the following guide: Raspberry Pi Pico and Pico W Pinout Guide: GPIOs Explained.
Raspberry Pi Pico – PWM Channels
The Raspberry Pi Pico has 8 independent PWM generators called slices. Each slice has two channels, which makes a total of 16 PWM channels.
The frequency of the PWM signal can range between 8Hz and 62.5MHz, while the microcontroller is running at a frequency of 125MHz.
Two channels of the same slice run at the same frequency, but can have a different duty rate.
analogWrite() and Other Functions
When it comes to generating PWM signals on the Raspberry Pi Pico in an easy way using Arduino C/C++, you can use the following functions:
- analogWriteFreq(uint32_t frequency) to set the frequency of the PWM signal. It supports a frequency of 100Hz to 1MHz*.
- analogWriteRange(uint32_t range) to set the range of the PWM signal — the maximum value you’ll use to set 100% duty cycle. It supports a value from 16 to 65535.
- analogWriteResolution (int resolution) to set the resolution of the PWM signal — up to 16-bit.
- analogWrite(GPIO, duty cycle) to output a PWM signal to a specified pin with a defined duty cycle. It continuously outputs a PWM signal until a digitalWrite() or other digital output is performed.
* there are some restrictions to the combination of frequency and ranges. According to the documentation: “The PWM generator source clock restricts the legal combinations of frequency and ranges. For example, at 1MHz only about 6 bits of range are possible. When you define an analogWriteFreq and analogWriteRange that can’t be fulfilled by the hardware, the frequency will be preserved but the accuracy (range) will be reduced automatically. Your code will still send in the range you specify, but the core itself will transparently map it into the allowable PWM range“.
Wiring the Circuit
Now, let’s create an example to better understand those PWM concepts. We’ll create a simple example to dim an LED (increase and decrease brightness smoothly).
Before proceeding, connect an LED to the Raspberry Pi Pico. We’re connecting to GPIO 20, but you can use any other GPIO.
Parts Required
Here’s a list of the parts you need to build the circuit:
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Schematic – Raspberry Pi Pico
You can use the following diagram as a reference to connect the LED to the Raspberry Pi Pico board.
RPi Pico Fading an LED – Arduino Sketch
The following code creates a PWM signal on GPIO 20 and increases and decreases the duty cycle over time to dim the LED.
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-pwm-analogwrite-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
// Pin connected to the LED
const int ledPin = 20;
// Time interval between brightness steps (in milliseconds)
const int fadeInterval = 10;
// Maximum and minimum brightness values
const int maxBrightness = 255;
const int minBrightness = 0;
// Current brightness value
int brightness = minBrightness;
// Direction flag for fading (true = increasing, false = decreasing)
bool fadingDirection = true;
void setup() {
// Initialize the LED pin as an output
pinMode(ledPin, OUTPUT);
// Adjust PWM properties if needed
/*analogWriteFreq(5000);
analogWriteRange(65535);
analogWriteResolution(16);*/
}
void loop() {
// Update the brightness value based on the fading direction
if (fadingDirection) {
for (int i = brightness; i <= maxBrightness; i++) {
brightness = i;
Serial.println(brightness);
// Set the LED brightness
analogWrite(ledPin, brightness);
// Delay for the fade interval
delay(fadeInterval);
}
fadingDirection = false;
} else {
for (int i = brightness; i >= minBrightness; i--) {
brightness = i;
Serial.println(brightness);
// Set the LED brightness
analogWrite(ledPin, brightness);
// Delay for the fade interval
delay(fadeInterval);
}
fadingDirection = true;
}
}
How the code works
Here are the main steps you need to take into account when controlling an LED with PWM.
First, define the pin that the LED is attached to. In this case, it is connected to GPIO 20. If you’re using a different GPIO number, change that on the code.
const int ledPin = 20;
In the setup(), set the LED as an output using the pinMode() function.
pinMode(ledPin, OUTPUT);
In the setup(), you can adjust the properties of the PWM signal using the analogWriteFreq(), analogWriteRange(), and analogWriteResolution().
// Adjust PWM properties if needed
/*analogWriteFreq(5000);
analogWriteRange(65535);
analogWriteResolution(16);*/
If you don’t specify the range and resolution of the PWM signal, it will use an 8-bit resolution with a maximum range of 255 (100% duty cycle).
In the loop(), you increase and decrease the duty cycle to increase and decrease the LED brightness. The following line outputs the PWM signal with the defined duty cycle values.
analogWrite(ledPin, brightness);
Uploading the Code to the Raspberry Pi Pico
For you to be able to upload code to the Raspberry Pi Pico, it needs to be in bootloader mode.
If the Raspberry Pi is currently running MicroPython firmware, you need to manually put it into bootloader mode. For that, connect the Raspberry Pi Pico to your computer while holding the BOOTSEL button at the same time.
For future uploads using Arduino IDE, the board should go automatically into bootloader mode without the need to press the BOOTSEL button.
Now, select your COM port in Tools > Port. It may be the case that the COM port is grayed out. If that’s the case, don’t worry it will automatically find the port once you hit the upload button.
Upload the code.
You should get a success message.
Demonstration
After uploading the code, the LED should start “breathing”. It will increase and decrease brightness over time gradually.
Wrapping Up
To wrap up, to output a PWM signal on a specified pin of the Raspberry Pi Pico, first, you need to declare that pin as an output. After that, you simply use the analogWrite() function and pass as arguments the GPIO number and the duty cycle.
We hope you’ve found this tutorial useful. If you’re just getting started with the Raspberry Pi Pico, make sure you read our getting started guide:
- Getting Started with Raspberry Pi Pico (and Pico W)
- Programming Raspberry Pi Pico with Arduino IDE
- Raspberry Pi Pico: Control Digital Outputs and Read Digital Inputs (Arduino IDE)
- Raspberry Pi Pico: Read Analog Inputs (Arduino IDE)
Check out all our Raspberry Pi Pico Guides »
Thanks for reading.
but what is the frequency of analogWrite function?