3. PWM呼吸灯
任务目标
使用ESP32的LEDC(PWM)外设驱动LED,实现从熄灭到最亮再回到熄灭的平滑呼吸效果。通过本案例理解两个核心概念:占空比(一个PWM周期内高电平时间占比)和频率(每秒PWM周期数)。
所需硬件与接线
- ESP32开发板 × 1
- LED × 1(颜色不限)
- 限流电阻 × 1(220Ω~1kΩ均可)
- 面包板与跳线若干
接线方式:将LED阳极(长脚)串联电阻后连接至GPIO2,阴极(短脚)接GND。
核心原理
ESP32的LEDC控制器可产生硬件PWM信号。本案例设置PWM频率为5kHz(高于人眼闪烁感知阈值,LED亮度稳定无闪烁),分辨率8位(占空比范围0~255)。呼吸效果通过定时改变占空比实现:占空比从0逐步增至255(渐亮),再从255逐步减至0(渐暗),循环往复。每次调整间隔10ms,使亮度变化平滑连续。
完整代码
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define LED_GPIO 2
#define PWM_FREQ_HZ 5000 // PWM频率:5kHz
#define PWM_RES_BITS 8 // 分辨率:8位,占空比0~255
#define PWM_MAX_DUTY ((1 << PWM_RES_BITS) - 1) // 255
#define STEP_DELAY_MS 10 // 每级亮度间隔
static const char *TAG = "pwm_breath";
void app_main(void)
{
// 1. 配置LEDC定时器
ledc_timer_config_t timer_conf = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.duty_resolution = PWM_RES_BITS,
.freq_hz = PWM_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&timer_conf));
// 2. 配置LEDC通道
ledc_channel_config_t channel_conf = {
.gpio_num = LED_GPIO,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&channel_conf));
ESP_LOGI(TAG, "PWM呼吸灯启动: 频率=%dHz, 分辨率=%d位", PWM_FREQ_HZ, PWM_RES_BITS);
while (1) {
// 渐亮:占空比从0增加到255
for (int duty = 0; duty <= PWM_MAX_DUTY; duty++) {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));
vTaskDelay(pdMS_TO_TICKS(STEP_DELAY_MS));
}
// 渐暗:占空比从255减小到0
for (int duty = PWM_MAX_DUTY; duty >= 0; duty--) {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));
vTaskDelay(pdMS_TO_TICKS(STEP_DELAY_MS));
}
}
}
编译与烧录
- 在ESP-IDF环境中创建项目,将上述代码保存为项目主目录下的
main.c(替换模板默认文件)。 - 在项目根目录执行
idf.py set-target esp32设置目标芯片。 - 执行
idf.py build编译项目。 - 连接开发板,执行
idf.py -p /dev/ttyUSB0 flash monitor烧录并打开串口监视器(Windows下端口号请替换为实际设备名,如COM3)。
验证方法与判定标准
- 视觉验证:烧录成功后,LED应呈现平滑的渐亮→渐暗循环效果,每个完整周期约5.1秒(256级×2×10ms)。若LED闪烁而非平滑变化,说明PWM频率过低,应提高
PWM_FREQ_HZ至1kHz以上。 - 串口日志:串口监视器应输出
PWM呼吸灯启动: 频率=5000Hz, 分辨率=8位,表明初始化成功。 - 概念验证:修改
STEP_DELAY_MS为100后重新编译烧录,可观察到呼吸速度明显变慢(周期约51秒),直观感受占空比变化速率对效果的影响;修改PWM_FREQ_HZ为50后烧录,可看到LED明显闪烁,直观理解频率对视觉连续性的作用。
常见问题
- LED不亮:检查GPIO2接线是否正确,确认LED极性(长脚接电阻到GPIO2,短脚接GND)。
- 编译报错:确认项目已正确初始化ESP-IDF环境,且代码文件位于main目录下。
- 亮度跳变不连续:检查
STEP_DELAY_MS是否过小(小于1ms可能导致任务调度不稳定),建议保持10ms以上。