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
ledc_timer_config(&ledc_timer);
// Initialize the LEDC channel
ledc_channel_config(&ledc_channel);
// Set the duty cycle of the channel to a certain value, for example, 50%
ledc_set_duty(ledc_channel.speed_mode, ledc_channel.channel, (1 << (ledc_timer.duty_resolution)) / 2);
ledc_update_duty(ledc_channel.speed_mode, ledc_channel.channel);
Using LEDC in ESP-IDF
ESP-IDF provides a series of API functions for configuring and controlling LEDC. The following are the basic steps for programming with LEDC:
- 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
};
ledc_timer_config(&ledc_timer);
- 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
};
ledc_channel_config(&ledc_channel);
- 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, ledc_channel.channel, duty);
ledc_update_duty(ledc_channel.speed_mode, ledc_channel.channel);
Servo Motor Example

#include
// 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
delay(1000);
dutyCycle = (pow(2, LEDC_RESOLUTION) - 1) * 0.0875; // Calculate duty cycle value using 10-bit resolution
ledcWrite(LEDC_CHANNEL, dutyCycle);
delay(1000);
dutyCycle = (pow(2, LEDC_RESOLUTION) - 1) * 0.075; // Calculate duty cycle value using 10-bit resolution
ledcWrite(LEDC_CHANNEL, dutyCycle);
delay(1000);
dutyCycle = (pow(2, LEDC_RESOLUTION) - 1) * 0.0625; // Calculate duty cycle value using 10-bit resolution
ledcWrite(LEDC_CHANNEL, dutyCycle);
delay(1000);
}
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

This project integrates sonar, servo motors, and the ESP32 microcontroller to create an object detection system with applications in robotics, security, and more. It uses sound waves for distance measurement and servo motors for precise control. Key code elements control the sonar sensor and servo motor. A Processing app enhances data visualization, making this project valuable for various applications.

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.

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.

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!

This article delves into PWM on the ESP32, crucial for precise control in applications like LED dimming, motor regulation, and audio generation. It explains the duty cycle’s role in signal activity and highlights the impact of resolution on control precision. The article also provides an ESP32 PWM code example for gradual LED brightness control. In summary, it empowers developers to utilize PWM effectively in microcontroller applications.

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.

This project explores the creation of an ESP32-based web server that allows remote control of two LEDs via a web interface. Leveraging the ESP32’s Wi-Fi capabilities and web server functionality, users can toggle LEDs from any device with a web browser. It highlights the ESP32’s potential for IoT and home automation, showcasing its adaptability and convenience for controlling connected devices remotely. The project serves as a foundation for expanding web-enabled IoT applications.

The ESP32 is a versatile microcontroller with extensive functionalities. Its pinout includes GPIO pins for digital, analog, and capacitive touch, PWM pins for precise control, I2C pins for communication with compatible devices, SPI pins for high-speed serial communication, and UART pins for asynchronous serial communication. GPIO interrupts allow the ESP32 to respond to external events. Strapping pins determine the boot mode, and power pins (VIN and 3V3) ensure proper functioning.