4. RGB LED调色
任务目标
使用ESP32的三个PWM通道分别驱动RGB LED的红、绿、蓝引脚,通过调节各通道占空比实现颜色混合,最终输出指定的颜色(例如紫色:红255、绿0、蓝255)。
所需硬件与接线
- ESP32开发板 ×1
- 共阴RGB LED ×1(若为共阳,需反转占空比逻辑)
- 220Ω电阻 ×3(分别串联在R、G、B引脚上)
- 杜邦线若干
| RGB LED引脚 | ESP32 GPIO |
|---|---|
| R(红) | GPIO25 |
| G(绿) | GPIO26 |
| B(蓝) | GPIO27 |
| GND(共阴) | GND |
实现原理
ESP32的LEDC(LED Control)外设可输出硬件PWM。本案例使用三个LEDC通道(0、1、2),分别绑定到上述三个GPIO。通过设置占空比(0~255)控制各颜色分量强度,利用人眼视觉暂留效应混合出目标颜色。代码中定义setColor(r, g, b)函数,一次调用即可输出任意RGB组合。
关键完整代码
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_err.h"
#define LED_R_GPIO 25
#define LED_G_GPIO 26
#define LED_B_GPIO 27
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_DUTY_RES LEDC_TIMER_8_BIT // 8位分辨率,占空比0~255
#define LEDC_FREQ_HZ 5000 // 5kHz PWM频率
// 三个通道分别对应R、G、B
#define CH_R LEDC_CHANNEL_0
#define CH_G LEDC_CHANNEL_1
#define CH_B LEDC_CHANNEL_2
// 初始化PWM定时器与三个通道
static void pwm_init(void) {
ledc_timer_config_t timer_conf = {
.speed_mode = LEDC_MODE,
.timer_num = LEDC_TIMER,
.duty_resolution = LEDC_DUTY_RES,
.freq_hz = LEDC_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&timer_conf);
ledc_channel_config_t ch_conf = {
.gpio_num = LED_R_GPIO,
.speed_mode = LEDC_MODE,
.channel = CH_R,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER,
.duty = 0,
.hpoint = 0
};
ledc_channel_config(&ch_conf);
ch_conf.gpio_num = LED_G_GPIO;
ch_conf.channel = CH_G;
ledc_channel_config(&ch_conf);
ch_conf.gpio_num = LED_B_GPIO;
ch_conf.channel = CH_B;
ledc_channel_config(&ch_conf);
}
// 设置RGB颜色,r/g/b取值范围0~255
static void setColor(int r, int g, int b) {
ledc_set_duty(LEDC_MODE, CH_R, r);
ledc_update_duty(LEDC_MODE, CH_R);
ledc_set_duty(LEDC_MODE, CH_G, g);
ledc_update_duty(LEDC_MODE, CH_G);
ledc_set_duty(LEDC_MODE, CH_B, b);
ledc_update_duty(LEDC_MODE, CH_B);
}
void app_main(void) {
pwm_init();
// 输出紫色:红=255,绿=0,蓝=255
setColor(255, 0, 255);
printf("紫色输出中: R=255, G=0, B=255\n");
// 每3秒切换一次颜色,便于观察
while (1) {
vTaskDelay(pdMS_TO_TICKS(3000));
setColor(0, 255, 0); // 绿色
printf("绿色输出中: R=0, G=255, B=0\n");
vTaskDelay(pdMS_TO_TICKS(3000));
setColor(255, 255, 0); // 黄色
printf("黄色输出中: R=255, G=255, B=0\n");
vTaskDelay(pdMS_TO_TICKS(3000));
setColor(0, 0, 255); // 蓝色
printf("蓝色输出中: R=0, G=0, B=255\n");
vTaskDelay(pdMS_TO_TICKS(3000));
setColor(255, 0, 255); // 回到紫色
printf("紫色输出中: R=255, G=0, B=255\n");
}
}
编译与烧录
- 在ESP-IDF环境中创建项目,将上述代码保存为
main.c,替换项目中的默认源文件。 - 在项目根目录执行
idf.py set-target esp32(如未设置)。 - 执行
idf.py build编译。 - 连接开发板,执行
idf.py -p /dev/ttyUSB0 flash monitor烧录并打开串口监视器(Windows端口号请按实际修改)。
验证方法与通过标准
- 观察RGB LED颜色是否按串口日志顺序变化:紫色→绿色→黄色→蓝色→紫色循环,每3秒切换一次。
- 若LED为共阳型,需将
setColor中的占空值改为255 - r、255 - g、255 - b,否则颜色会互补。 - 串口输出与LED实际颜色一致即判定通过。若颜色偏差明显,检查GPIO接线是否正确、电阻是否遗漏。
常见问题
- LED不亮:检查GPIO号是否与代码一致,共阴LED的GND是否接对。
- 颜色偏暗:确认PWM频率不低于1kHz,避免肉眼可见闪烁;检查电阻阻值是否过大。
- 颜色不准:不同批次LED亮度曲线不同,可微调各通道占空比上限(如将255改为200)以平衡亮度。