Pulse Width Modulation, or PWM, is a cornerstone of microcontroller applicationsโwhether you’re dimming an LED, controlling a motor, or generating tones. The ESP32 takes PWM to the next level with flexible, high-resolution outputs and tons of configurable pins.
In this tutorial, weโll walk through how PWM works on the ESP32, which pins support it, how to configure it in code (using the Arduino IDE), and some tips for advanced usage. ๐ง ๐
๐งฉ What Is PWM?
PWM simulates analog output using a digital signal that turns on and off rapidly.
- Duty cycle: Percentage of time the signal is HIGH in one cycle (0โ100%)
- Frequency: How fast each cycle happens (measured in Hz)
Example:
- 0% duty = always off
- 100% duty = always on
- 50% duty = on half the time โ perceived as half brightness or half speed
โ๏ธ ESP32 PWM Features
| Feature | Value |
|---|---|
| Number of PWM channels | 16 independent channels |
| Resolution | Up to 16 bits (0โ65535 steps) |
| Frequency range | 1 Hz to 40 MHz (hardware dependent) |
| Output pins | Almost all GPIOs except reserved pins |
ESP32 PWM is handled by LEDC (LED Control) hardware, which is highly flexible.
๐ PWM-Capable Pins on ESP32
The beauty of the ESP32? Almost any GPIO can be used for PWM.
However, avoid these reserved pins:
– GPIO6โ11: Used for flash memory
– GPIO34โ39: Input only (no output/PWM)
โ Best PWM Output Pins:
GPIOs: 2, 4, 5, 12โ19, 21โ23, 25โ27, 32, 33
These are safe for both PWM and general I/O.
๐ ๏ธ Setting Up PWM in Arduino IDE
Youโll use the built-in ledcSetup() and ledcWrite() functions.
๐งช Basic Example: Dimming an LED on GPIO 5
int pwmChannel = 0; // Channel 0โ15
int freq = 5000; // 5 kHz PWM
int resolution = 8; // 8-bit resolution (0โ255)
int ledPin = 5; // LED connected to GPIO 5
void setup() {
ledcSetup(pwmChannel, freq, resolution); // configure channel
ledcAttachPin(ledPin, pwmChannel); // bind GPIO to channel
}
void loop() {
for (int duty = 0; duty <= 255; duty++) {
ledcWrite(pwmChannel, duty);
delay(10);
}
for (int duty = 255; duty >= 0; duty--) {
ledcWrite(pwmChannel, duty);
delay(10);
}
}
๐ PWM Channel vs. GPIO: How It Works
Each GPIO gets assigned a PWM channel. You can have multiple pins sharing the same frequency/resolution but using different channels.
| Channel | Pin (GPIO) | Function |
|---|---|---|
| 0 | 5 | LED dimming |
| 1 | 18 | Motor speed |
| 2 | 19 | RGB LED blue |
๐ง Use a new channel for each independent PWM output.
๐๏ธ Controlling Frequency and Resolution
ESP32 supports up to 16-bit resolution, but higher resolution = lower frequency.
| Resolution | Max Frequency (approx.) |
|---|---|
| 8-bit | ~312.5 kHz |
| 10-bit | ~78 kHz |
| 12-bit | ~20 kHz |
| 16-bit | ~1.2 kHz |
Pick based on your application. For LED dimming, 5โ10 kHz is ideal.
๐ PWM for Servos, Motors, LEDs
๐ง Servo (via PWM libraries):
Use a library like ESP32Servo.h to manage timing
๐ง Motor control (DC/Brushless):
- Use 2โ3 PWM channels for H-Bridge or ESC
- Consider 20 kHz+ frequency to eliminate audible whine
๐ง LED (Dimming or RGB):
- Assign each color to a different PWM channel
- Adjust duty cycle for brightness/color control
๐ซ Common Issues and Fixes
| Problem | Likely Cause | Fix |
|---|---|---|
| PWM not working on pin | GPIO not PWM capable | Use a different GPIO |
| No LED brightness change | Wrong channel/duty value | Check resolution & channel setup |
| Pin outputs fixed value | Conflict with another peripheral | Free up pin from other use |
| Flickering at low duty | Resolution too low | Use higher resolution (e.g. 10-bit) |
๐งพ Summary Cheat Sheet
| Task | Function |
|---|---|
| Setup PWM channel | ledcSetup(channel, freq, bits) |
| Attach GPIO to channel | ledcAttachPin(pin, channel) |
| Write duty cycle | ledcWrite(channel, value) |
| Detach GPIO | ledcDetachPin(pin) |
โ Final Thoughts
The ESP32โs PWM capabilities are incredibly robustโ16 channels, high frequency support, and nearly any GPIO as an output. Whether you’re controlling LEDs, fans, motors, or sound devices, PWM on the ESP32 gives you total control.
With just a few lines of code, you can achieve smooth dimming, precise motor control, and advanced embedded interaction. ๐กโ๏ธ




