ESP32 LEDC: Precise Control for Diverse Applications

In microcontroller programming, Pulse Width Modulation (PWM) technology plays a crucial role, enabling us to control analog devices such as motors, lights, etc., using digital signals, thus achieving precise control over these devices. In the ESP32 microcontroller, there is a built-in powerful module called LEDC (LED PWM Controller), which provides us with the convenient and flexible ability to control multiple LEDs or RGB LEDs, making the ESP32 an ideal choice for implementing various lighting and display effects. In this article, we will delve into the LEDC functionality of the ESP32, including its working principles, programming methods, and application examples, to help readers better understand and apply this feature.

LEDC vs Traditional PWM

Traditional PWM technology is a software-based method for controlling LED brightness using the microcontroller’s GPIO pins and timers. While it is a proven method, it has some limitations in terms of multi-channel control, resolution, and flexibility. In contrast, the LEDC module of the ESP32 provides more flexible and powerful LED control capabilities.

  • Independent Channels: The LEDC module of the ESP32 supports up to 8 independent PWM channels, and each channel can independently control the brightness and PWM output of LEDs, allowing the LEDC to control multiple LEDs simultaneously, with each LED’s brightness independently adjustable, thereby achieving more diverse and rich lighting effects.
  • High Resolution: LEDC supports PWM resolution of up to 14 bits, allowing the brightness of LEDs to be adjusted to 16384 different duty cycle levels, thus enabling finer and smoother brightness adjustments.
  • Flexible Adjustment: LEDC allows users to flexibly adjust LED control parameters including PWM frequency, duty cycle, rise and fall times, etc., according to specific application requirements, thereby achieving more personalized and optimized lighting effects.
  • Waveform Generation: LEDC can not only be used for simple PWM control but also for generating complex waveform sequences, thus expanding its application scenarios including lighting effects, color light control, etc.

LEDC Operating Modes

The LEDC module provides two main operating modes in the ESP-IDF development framework: high-speed mode and low-speed mode. These two modes have their own advantages in application scenarios, let’s take a look at their differences:

In high-speed mode, the LEDC module utilizes the high-speed timers of the ESP32 and uses APB_CLK as the clock source. This configuration enables LEDC to generate high-frequency PWM signals, with frequencies reaching tens or even hundreds of kilohertz. This high-frequency PWM signal is ideal for LED lighting because the human eye cannot perceive any flicker, providing smooth light adjustment and a better visual experience.

					// Define LED PWM timer configuration
ledc_timer_config_t ledc_timer = {
  .duty_resolution = LEDC_TIMER_13_BIT, // PWM duty resolution is 13 bits
  .freq_hz = 5000,                      // PWM frequency is 5000Hz
  .speed_mode = LEDC_HIGH_SPEED_MODE,   // Use high-speed mode
  .timer_num = LEDC_TIMER_0             // Use timer 0
ledc_timer_config(&ledc_timer); // Configure PWM timer
// Define LED PWM channel configuration
ledc_channel_config_t ledc_channel = {
  .channel    = LEDC_CHANNEL_0, // PWM channel 0
  .duty       = 0,              // Initial duty cycle is 0
  .gpio_num   = 18,             // GPIO pin is 18
  .speed_mode = LEDC_HIGH_SPEED_MODE, // Use high-speed mode
  .timer_sel  = LEDC_TIMER_0    // Use timer 0
ledc_channel_config(&ledc_channel); // Configure PWM channel


On the other hand, in low-speed mode, the LEDC module uses the low-speed timers of the ESP32 and can select either APB_CLK or RTC_CLK as the clock source. In this mode, the PWM signal frequency is lower, typically ranging from a few hertz to several kilohertz. Although this frequency is not ideal for LED lighting, it is suitable for many motor control applications. When RTC_CLK is selected as the clock source, the PWM signal can continue to operate even in deep sleep mode, minimizing system power consumption.

					#include "driver/ledc.h"
// Define the GPIO pin connected to the LED
#define LED_PIN 2
// Initialize the configuration structure of the LEDC timer
ledc_timer_config_t ledc_timer = {
  .speed_mode = LEDC_LOW_SPEED_MODE,    // Low-speed mode
  .duty_resolution = LEDC_TIMER_13_BIT, // 13-bit resolution
  .timer_num = LEDC_TIMER_0,            // Timer number
  .freq_hz = 1000,                      // Frequency of the PWM signal, for example, 1000 Hz
  .clk_cfg = LEDC_AUTO_CLK              // Automatic clock source selection
// Initialize the configuration structure of the LEDC channel
ledc_channel_config_t ledc_channel = {
  .gpio_num   = LED_PIN,
  .speed_mode = LEDC_LOW_SPEED_MODE,
  .channel    = LEDC_CHANNEL_0,
  .timer_sel  = LEDC_TIMER_0,
  .duty       = 0,  // Initial duty cycle is 0
  .hpoint     = 0
// Initialize the LEDC timer
// Initialize the LEDC channel
// Set the duty cycle of the channel to a certain value, for example, 50%
ledc_set_duty(ledc_channel.speed_mode,, (1 << (ledc_timer.duty_resolution)) / 2);



ESP-IDF provides a series of API functions for configuring and controlling LEDC. The following are the basic steps for programming with LEDC:

  1. Configure LEDC Timer:

Before using LEDC, each LEDC channel needs to be associated with a timer to define the PWM signal’s frequency and resolution. This step is done through the ledc_timer_config() function, where you can specify the PWM resolution, frequency, speed mode, and timer number.

					ledc_timer_config_t ledc_timer = {
    .duty_resolution = LEDC_TIMER_8_BIT, // PWM resolution
    .freq_hz = 5000,                     // PWM frequency
    .speed_mode = LEDC_HIGH_SPEED_MODE,  // Speed mode
    .timer_num = LEDC_TIMER_0            // Timer number
  1. Configure LEDC Channel:

Each LEDC channel can be connected to a GPIO pin and can independently control the PWM signal’s duty cycle. The ledc_channel_config() function is used to configure LEDC channels, specifying the channel number, initial duty cycle, GPIO pin, speed mode, and associated timer number.

					ledc_channel_config_t ledc_channel = {
    .channel    = LEDC_CHANNEL_0,        // Channel number
    .duty       = 0,                     // Initial duty cycle
    .gpio_num   = 18,                    // GPIO pin
    .speed_mode = LEDC_HIGH_SPEED_MODE,  // Speed mode (matched with timer)
    .timer_sel  = LEDC_TIMER_0           // Associated timer number
  1. Control PWM Signal:

Once LEDC channels and timers are configured, API functions can be used to control the PWM signal. The ledc_set_duty() and ledc_update_duty() functions are used to set and update the duty cycle of the PWM, thereby controlling the brightness of the LED.

					// Set PWM duty cycle
ledc_set_duty(ledc_channel.speed_mode,, duty);

Servo Motor Example

esp32 ledc servo example
					#include <Arduino.h>
// Define LEDC channel, GPIO pin, and resolution
#define LEDC_CHANNEL 0
#define LEDC_PIN 12
#define LEDC_RESOLUTION 10 // Set resolution to 10 bits
void setup() {
    // Initialize LEDC channel
    ledcSetup(LEDC_CHANNEL, 50, LEDC_RESOLUTION); // Set frequency to 50Hz, resolution to 10 bits
    ledcAttachPin(LEDC_PIN, LEDC_CHANNEL); // Associate GPIO pin with LEDC channel
void loop() {
    int dutyCycle = (pow(2, LEDC_RESOLUTION) - 1) * 0.075; // Calculate duty cycle value using 10-bit resolution
    ledcWrite(LEDC_CHANNEL, dutyCycle);
    // Delay for 1 second
    dutyCycle = (pow(2, LEDC_RESOLUTION) - 1) * 0.0875; // Calculate duty cycle value using 10-bit resolution
    ledcWrite(LEDC_CHANNEL, dutyCycle);
    dutyCycle = (pow(2, LEDC_RESOLUTION) - 1) * 0.075; // Calculate duty cycle value using 10-bit resolution
    ledcWrite(LEDC_CHANNEL, dutyCycle);
    dutyCycle = (pow(2, LEDC_RESOLUTION) - 1) * 0.0625; // Calculate duty cycle value using 10-bit resolution
    ledcWrite(LEDC_CHANNEL, dutyCycle);


This is an Arduino program used to configure LEDC on the ESP32 microcontroller to generate PWM signals and control the rotation of a servo motor. With this program, we successfully generated a PWM signal with a frequency of 50Hz and a period of 20ms, and used PWM to control the left and right rotation of the servo motor. By using an oscilloscope to observe the PWM waveform, we can clearly see that the PWM waveform changes according to the duty cycle we set.

You Might Be Interested

what is esp32
What is an ESP32

Dive into the world of microcontrollers with TechSparks’ comprehensive guide to the ESP32! Discover the power of this versatile chip, renowned for its integration, low power consumption, and robust security features, perfect for IoT enthusiasts and DIY projects. Explore its architecture, development boards, and key features, and unleash the full potential of your next project!

esp32 ledc
ESP32 LEDC: Precise Control for Diverse Applications

Dive into the world of precise LED control with ESP32’s LEDC module, revolutionizing microcontroller-based PWM technology for versatile applications. Explore the enhanced capabilities, flexible programming methods, and real-world examples to unlock endless possibilities in lighting, motor control, and more!

esp32 connect to wifi
Connecting ESP32 to WiFi in 4 Steps

Unlock the potential of your ESP32 with these 4 simple steps to WiFi connectivity! Dive into the world of IoT and remote control effortlessly, as we guide you through setting up a Web Hotspot Manual Provisioning system. Say goodbye to complex configurations and hello to seamless connectivity.

Getting Started with ESP-IDF in VSCode
Getting Started with ESP-IDF in VSCode

This guide introduces an efficient method, “ESP-IDF + VSCode,” for ESP32 development, simplifying environment setup and allowing seamless switching between ESP-IDF versions. It covers downloading development tools, configuring ESP-IDF, addressing VSCode configuration issues, managing components, and resolving dependencies.

How to Enable Multi-Core on ESP32 Microcontroller
How to Enable Multi-Core on ESP32 Microcontroller

This comprehensive guide elucidates the process of enabling multi-core functionality on the ESP32 microcontroller, leveraging its dual-core architecture for enhanced parallel processing capabilities. Through detailed steps and code examples, developers can effectively harness the power of both cores to optimize resource utilization and achieve versatile application scenarios.

A Step-by-Step Guide to Using LVGL with ESP32
A Step-by-Step Guide to Using LVGL with ESP32

This guide illustrates how to integrate LVGL with the ESP32, enabling the creation of engaging graphical user interfaces for embedded systems. By configuring libraries and writing code, developers can enhance user experiences on ESP32 devices with dynamic interfaces.

Scroll to Top