Control Your Raspberry Pi Pico: Master PWM Through the Arduino IDE
When you first pick up the Raspberry Pi Pico, the promise of its microcontroller core—RP2040—is instantly enticing. But the real power comes when you unlock its Pulse‑Width Modulation (PWM) capabilities. In this guide we’ll walk you through setting up the Arduino IDE, writing your first PWM sketch, and exploring advanced tricks that let you turn the Pico into a versatile driver for motors, LEDs, and more. Whether you’re a seasoned hobbyist or a newcomer, you’ll find clear, step‑by‑step instructions and practical tips that make PWM a breeze.
Getting the Arduino IDE Ready for the Raspberry Pi Pico
Before you can even think of generating PWM signals, you need to convince the Arduino IDE that the Pico is a legitimate target board. This involves adding a new core, installing the RP2040 libraries, and configuring the board settings.
- Install the Arduino IDE: Download the latest release from the official site and install it on Windows, macOS, or Linux.
- Add the Pico Core: Open File > Preferences and paste the following URL into the “Additional Boards Manager URLs” field:
https://github.com/earlephilhower/arduino-pico/releases/download/1.1.0/package_rp2040_index.json - Update Boards Manager: Go to Tools > Board > Boards Manager, search for “Pico”, and click Install. Once done, select Raspberry Pi Pico from the Board list.
- Install the SDK: The Pico core automatically pulls the necessary RP2040 SDK during compilation, so no extra steps are required.
Once those steps are complete, you’re ready to write code that talks directly to the RP2040’s hardware.
Understanding PWM on the Raspberry Pi Pico
PWM is a technique that modulates the duty cycle of a digital output to simulate an analog voltage. The Pico’s RP2040 features 16 independent PWM slices, each capable of generating up to four output channels. This means you can drive multiple devices—each with its own frequency and duty cycle—without additional hardware.
Key hardware features:
- 8‑bit to 16‑bit resolution for fine-grained control.
- Programmable frequency range from 1 Hz to 125 kHz.
- Hardware dead‑time insertion for motor control applications.
- Support for dual‑channel outputs on the same PWM slice.
These capabilities make the Pico an excellent platform for LED dimming, servo control, or any application where precise timing matters.
Writing Your First PWM Sketch
Let’s start with a classic example: dimming an LED. The following sketch sets up PWM on pin 15 (GPIO15) at 1 kHz, then oscillates the duty cycle smoothly from 0 % to 100 % over two seconds.
#include <Arduino.h>const uint8_t pwmPin = 15; // GPIO15
const uint16_t pwmPeriod = 1000; // 1 kHz
const uint32_t stepDelay = 20; // 20 ms between steps
void setup() {
// Configure the chosen pin as a PWM output
pinMode(pwmPin, PWM);
// Set the PWM period (frequency)
analogWriteFrequency(pwmPin, pwmPeriod);
// Start with zero duty cycle
analogWrite(pwmPin, 0);
}
void loop() {
// Fade in
for (uint16_t duty = 0; duty <= 255; duty++) {
analogWrite(pwmPin, duty);
delay(stepDelay);
}
// Fade out
for (int16_t duty = 255; duty >= 0; duty--) {
analogWrite(pwmPin, duty);
delay(stepDelay);
}
}
Explanation:
- pinMode(pwmPin, PWM) tells the core to use the pin for PWM.
- analogWriteFrequency() sets the frequency for that pin’s PWM slice.
- analogWrite() adjusts the duty cycle as a value between 0 (0 %) and 255 (100 %).
Compile and upload this sketch to your Pico. You should see the LED pulse smoothly. If the LED flickers or the frequency feels wrong, double‑check the pin mapping and ensure the PWM core is correctly selected.
Advanced PWM Techniques
Once you’re comfortable with basic PWM, you can push the Pico’s capabilities further:
Multi‑Channel Control
Because each PWM slice supports four channels, you can run several independent signals simultaneously. Simply assign a unique pin to pinMode(pin, PWM) and set individual frequencies and duty cycles.
Fine‑Tuning Frequency
The default analogWriteFrequency uses integer values. If you need a non‑standard frequency, you can access the pwm_config API directly in a native C++ sketch, adjusting the clock_div and wrap values for exact timing. This level of control is especially useful for audio or motor applications.
Software PWM as a Backup
In rare cases, you might want to generate PWM on pins not mapped to hardware slices or when you need more than 16 channels. The Arduino core provides a lightweight softwarePWM() function that uses timers to emulate PWM, though it is less accurate under heavy CPU load.
Troubleshooting Common Issues
- LED does not light or flickers: Verify the LED is connected in the correct orientation and that the pin is configured as PWM, not OUTPUT.
- Wrong frequency or jitter: Ensure you