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.

πŸ”§ Key Advantage Unlike Arduino Uno (only pins 3,5,6,9,10,11 support PWM), the ESP32 can output PWM on any GPIO. This gives you complete freedom in PCB layout and pin assignment.

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 StepsMax Frequency (approx)Best For
15-bit0–32767~1 kHzLED dimming (smooth)
13-bit0–8191~5 kHzLED dimming
10-bit0–1023~40 kHzGeneral purpose
8-bit0–255~312 kHzMotor control, servos
6-bit0–63~5 MHzHigh-frequency applications
1-bit0–1~40 MHzDigital 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 Pinout

Frequently 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.

Related Guides