ESP32 PWM Pins: Complete Guide to Pulse Width Modulation
The ESP32 has 16 independent PWM channels through its LED Control (LEDC) peripheral, making it one of the most flexible microcontrollers for PWM applications. Unlike many MCUs where only specific pins support PWM, the ESP32 can output PWM on almost any GPIO pin via its IO MUX.
This guide covers everything you need to know about ESP32 PWM: how the LEDC works, how to configure frequency and resolution, Arduino code examples for LED dimming, motor control, servo control, and best practices.
ESP32 PWM Architecture
The ESP32 LED Control (LEDC) peripheral has two groups of 8 channels:
- High-speed channels (0β7): Operate from a 80 MHz base clock
- Low-speed channels (8β15): Operate from a 1 MHz base clock
Each channel has its own configurable frequency and resolution, and can be mapped to any GPIO pin through the IO MUX matrix.
PWM Frequency vs Resolution Trade-off
The ESP32 PWM resolution is tied to the clock divider. Higher resolution means lower maximum frequency:
| Resolution (bits) | Duty Cycle Steps | Max Frequency (approx) | Best For |
|---|---|---|---|
| 15-bit | 0β32767 | ~1 kHz | LED dimming (smooth) |
| 13-bit | 0β8191 | ~5 kHz | LED dimming |
| 10-bit | 0β1023 | ~40 kHz | General purpose |
| 8-bit | 0β255 | ~312 kHz | Motor control, servos |
| 6-bit | 0β63 | ~5 MHz | High-frequency applications |
| 1-bit | 0β1 | ~40 MHz | Digital signal generation |
Arduino Code: LED Fading with PWM
// ESP32 PWM LED Fade Example
const int ledPin = 2; // Built-in LED on most dev boards
const int freq = 5000; // 5 kHz PWM frequency
const int resolution = 8; // 8-bit resolution (0-255)
void setup() {
ledcSetup(0, freq, resolution); // Channel 0
ledcAttachPin(ledPin, 0); // Attach GPIO2 to channel 0
}
void loop() {
// Fade in
for (int duty = 0; duty <= 255; duty++) {
ledcWrite(0, duty);
delay(5);
}
// Fade out
for (int duty = 255; duty >= 0; duty--) {
ledcWrite(0, duty);
delay(5);
}
}
ESP32 PWM with Servo Motor
Servo motors typically need a 50 Hz PWM signal with 1β2 ms pulse width (0Β°β180Β°). Here's how to drive a servo:
// ESP32 Servo Control (50 Hz PWM)
const int servoPin = 18;
const int freq = 50; // 50 Hz for servos
const int resolution = 16; // High resolution for precise pulse width
void setup() {
ledcSetup(1, freq, resolution);
ledcAttachPin(servoPin, 1);
}
void setServoAngle(int angle) {
// Map angle (0-180) to pulse width (1000-2000 microseconds)
int pulseWidth = map(angle, 0, 180, 1000, 2000);
// Convert to duty cycle for 16-bit at 50 Hz
int duty = pulseWidth * 65536 / 20000;
ledcWrite(1, duty);
}
void loop() {
setServoAngle(0);
delay(1000);
setServoAngle(90);
delay(1000);
setServoAngle(180);
delay(1000);
}
Configuring PWM Frequency Dynamically
You can change PWM frequency at runtime for applications like variable-speed motor control:
// Change PWM frequency at runtime
void setPwmFrequency(int channel, int newFreq) {
ledcChangeFrequency(channel, newFreq, resolution);
}
// Example: motor speed ramp
void setup() {
ledcSetup(2, 1000, 10);
ledcAttachPin(32, 2);
}
void loop() {
for (int f = 100; f <= 10000; f += 100) {
setPwmFrequency(2, f);
ledcWrite(2, 512); // 50% duty
delay(50);
}
}
PWM-Compatible GPIO Pins on ESP32
Since the ESP32 can output PWM on any GPIO, the question is not "which pins support PWM" but "which pins should I avoid for PWM?"
- Avoid: GPIO6βGPIO11 (flash memory bus β will crash the system)
- Avoid for new designs: GPIO1 and GPIO3 (UART0, connected to USB-Serial)
- Use with caution: Strapping pins GPIO0, GPIO2, GPIO5, GPIO12, GPIO15 (may affect boot)
- Best choice: GPIO13, GPIO14, GPIO16, GPIO17, GPIO18, GPIO19, GPIO21, GPIO22, GPIO23, GPIO25, GPIO26, GPIO27, GPIO32, GPIO33
π§ Visualize PWM Pins on Our Interactive Tool
Use our interactive pinout tool to see which pins support PWM and check for conflicts with other peripherals.
Open Interactive PinoutFrequently Asked Questions
What is the difference between PWM channels and pins?
PWM channels are the hardware timer resources (16 total). PWM pins are the GPIOs where the signal appears. A single channel can drive multiple pins at the same frequency/duty, but each pin needs its own channel for independent control.
Can I run all 16 PWM channels at different frequencies?
No. The 8 high-speed channels share a common base clock (80 MHz) and the 8 low-speed channels share a different base clock (1 MHz). Within each group, channels can have different frequencies, but the clock source limits the range.
Does ESP32 PWM work during deep sleep?
No. PWM is driven by the LEDC peripheral, which is powered down in deep sleep. For low-power PWM applications, use an external PWM driver like the PCA9685.