esp-iot-solution 电工与照明方案:Lightbulb 调光驱动与 DALI 总线驱动实战指南
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
导读
本文聚焦 Espressif IoT Solution 仓库中的电气照明(Electrical & Lighting)解决方案,围绕两大核心组件展开:面向智能灯泡的 Lightbulb 驱动 与面向 DALI 控制设备的 DALI 总线主驱动。前者通过抽象层封装 PWM、I2C、单总线三类主流调光方案,后者基于 RMT 外设实现 IEC 62386 标准主站协议。读完本文,你将掌握灯泡驱动的配置方法、渐变更原理与校准/限功率手段,以及 DALI 主机的初始化、命令/查询、自动寻址与 DT8 色彩控制等完整实战流程。
本章节入口为 docs/en/electrical_lighting_solution/index.rst,其中文版见 docs/zh_CN/electrical_lighting_solution/index.rst。
一、Lightbulb 驱动:多种调光方案的统一抽象
Lightbulb 组件将灯泡常用的多种调光方案封装在一起,通过一层抽象进行统一管理,使开发者能快速集成到自己的应用中。目前全部 ESP32 系列芯片均受支持。组件源码位于 components/led/lightbulb_driver,公共头文件为 include/lightbulb.h,核心实现位于 src/lightbulb.c 与 src/lighting.c。
所有驱动通过lightbulb_config_t统一配置,其内部使用联合体driver_conf按编译开关(CONFIG_ENABLE_PWM_DRIVER、CONFIG_ENABLE_BP57x8D_DRIVER等)挂载对应驱动结构体,创建函数则按驱动类型分别提供:
| 驱动类型 | 创建接口 | 枚举值 |
|---|---|---|
| PWM(LEDC) | lightbulb_new_pwm_device() | DRIVER_ESP_PWM |
| SM2135EH | lightbulb_new_sm2135eh_device() | DRIVER_SM2135EH |
| SM2182E | lightbulb_new_sm2182e_device() | DRIVER_SM2182E |
| SM2x35EGH | lightbulb_new_sm2x35egh_device() | DRIVER_SM2x35EGH |
| BP1658CJ | lightbulb_new_bp1658cj_device() | DRIVER_BP1658CJ |
| BP57x8D | lightbulb_new_bp57x8d_device() | DRIVER_BP57x8D |
| KP18058 | lightbulb_new_kp18058_device() | DRIVER_KP18058 |
| WS2812 | lightbulb_new_ws2812_device() | DRIVER_WS2812 |
| SM16825E | lightbulb_new_sm16825e_device() | DRIVER_SM16825E |
LED 灯珠组合由lightbulb_led_beads_comb_t描述,从单通道冷/暖白(LED_BEADS_1CH_C、LED_BEADS_1CH_W)、双通道冷+暖(LED_BEADS_2CH_CW)、三通道 RGB,到四通道(RGBC/RGBW/RGBCC/RGBWW)与五通道(RGBCW/RGBCC/RGBWW 等)共十余种组合可选(详见 lightbulb.h)。
1.1 PWM 调光方案
PWM 调光通过调节脉冲宽度控制 LED 亮度,核心是改变电流脉冲的占空比(整个周期内高电平时间的比例)。占空比高,LED 通电时间长、亮度高;占空比低,通电时间短、亮度低。
所有 ESP 芯片均可用硬件 LEDC 或 MCPWM 驱动输出 PWM。官方推荐使用LEDC 驱动,因为它支持硬件渐变更(hardware fading),频率与占空比可配置,最高分辨率达 20 bit。当前支持的 PWM 调光驱动类型:
- RGB + C/W
- RGB + CCT/Brightness
PWM 调光用例:点亮 3 通道 RGB 灯泡
lightbulb_config_t config = { // 1. 选择 PWM 输出并配置参数 .driver_conf.pwm.freq_hz = 4000, // 2. 能力开关:按需开启/关闭 .capability.enable_fade = true, .capability.fade_time_ms = 800, .capability.enable_lowpower = false, /* 如果白色光是硬件独立控制而非软件混色,请开启此项 */ .capability.enable_hardware_cct = true, .capability.enable_status_storage = true, /* 根据灯珠铝基板配置 LED 组合 */ .capability.led_beads = LED_BEADS_3CH_RGB, .capability.storage_cb = NULL, .capability.sync_change_brightness_value = true, // 3. 配置 PWM 输出硬件引脚 .io_conf.pwm_io.red = 25, .io_conf.pwm_io.green = 26, .io_conf.pwm_io.blue = 27, // 4. 限幅参数(默认值通常够用) .external_limit = NULL, // 5. 颜色校准参数(默认值通常够用) .gamma_conf = NULL, // 6. 初始化照明参数;'on' 为 true 时驱动初始化即点亮 .init_status.mode = WORK_COLOR, .init_status.on = true, .init_status.hue = 0, .init_status.saturation = 100, .init_status.value = 100, }; lightbulb_new_pwm_device(&config);PWM 驱动底层通过 LEDC 实现,会自动根据频率配置分辨率。io_conf.pwm_io最多可指定 5 个引脚(red/green/blue/cold_cct/warm_brightness),结合led_beads决定实际启用哪些通道(lightbulb.h)。
1.2 I2C 调光方案
I2C 调光通过 I2C 总线向调光芯片发送控制命令,改变调光芯片的输出电流来调节 LED 亮度。I2C 总线由数据线(SDA)和时钟线(SCL)两根线组成,所有 ESP 芯片均支持使用硬件 I2C 通信的调光芯片。当前支持的调光芯片:
- SM2135EH
- SM2X35EGH(SM2235EGH / SM2335EGH)
- BP57x8D(BP5758 / BP5758D / BP5768)
- BP1658CJ
- KP18058
各芯片驱动源码分别位于 components/led/lightbulb_driver/drivers 下的bp1658cj/、bp57x8d/、kp18058/、sm2135eh/、sm2x35egh/等目录,公共 I2C 封装在 drivers/common/iic/。
I2C 调光用例:BP5758D 点亮 5 通道 RGBCW 灯泡
lightbulb_config_t config = { // 1. 选择所需芯片并配置参数。不同芯片配置参数不同,请仔细查阅芯片手册。 .driver_conf.bp57x8d.freq_khz = 300, .driver_conf.bp57x8d.enable_iic_queue = true, .driver_conf.bp57x8d.iic_clk = 4, .driver_conf.bp57x8d.iic_sda = 5, .driver_conf.bp57x8d.current = {50, 50, 50, 30, 30}, // 2. 能力开关:按需开启/关闭 .capability.enable_fade = true, .capability.fade_time_ms = 800, .capability.enable_lowpower = false, .capability.enable_status_storage = true, .capability.led_beads = LED_BEADS_5CH_RGBCW, .capability.storage_cb = NULL, .capability.sync_change_brightness_value = true, // 3. 配置 IIC 芯片的硬件输出端口 .io_conf.iic_io.red = OUT3, .io_conf.iic_io.green = OUT2, .io_conf.iic_io.blue = OUT1, .io_conf.iic_io.cold_white = OUT5, .io_conf.iic_io.warm_yellow = OUT4, // 4. 限幅参数(默认值通常够用) .external_limit = NULL, // 5. 颜色校准参数(默认值通常够用) .gamma_conf = NULL, // 6. 初始化照明参数 .init_status.mode = WORK_COLOR, .init_status.on = true, .init_status.hue = 0, .init_status.saturation = 100, .init_status.value = 100, }; lightbulb_new_bp57x8d_device(&config);I2C 芯片的输出端口通过lightbulb_chip_out_pin_t枚举(OUT1~OUT5)指定,对应芯片输出端口 1/红、2/绿、3/蓝、4/白、5/黄(lightbulb.h)。current数组按 5 通道分别设置输出电流(本例 RGB 50mA、CW 30mA)。
1.3 单总线调光方案(WS2812)
单总线调光通过一根通信线发送特定通信协议的控制信号来调节 LED 亮度,在 ESP 芯片上可用 RMT 或 SPI 外设实现,官方推荐使用SPI控制 LED 通信。当前支持的 LED 类型:WS2812。
WS2812 用例:点亮 10 颗 WS2812
lightbulb_config_t config = { // 1. 选择 WS2812 输出并配置参数 .driver_conf.ws2812.led_num = 10, .driver_conf.ws2812.ctrl_io = 4, // 2. 能力开关:按需开启/关闭 .capability.enable_fade = true, .capability.fade_time_ms = 800, .capability.enable_status_storage = true, /* WS2812 只能选择 LED_BEADS_3CH_RGB */ .capability.led_beads = LED_BEADS_3CH_RGB, .capability.storage_cb = NULL, // 4. 限幅参数 .external_limit = NULL, // 5. 颜色校准参数 .gamma_conf = NULL, // 6. 初始化照明参数 .init_status.mode = WORK_COLOR, .init_status.on = true, .init_status.hue = 0, .init_status.saturation = 100, .init_status.value = 100, }; lightbulb_new_ws2812_device(&config);二、Fade 渐变原理与低功耗实现
2.1 Fade 渐变原理
灯泡组件的渐变效果由软件实现。每个通道记录当前输出值、目标值、步长和剩余步数;调用 API 设置颜色时,会更新目标值、步长、步数并启动一个渐变定时器。该定时器每12ms触发一次回调,检查各通道剩余步数,只要有剩余步数就按步长调整当前值并更新到底层驱动;所有通道步数归零后渐变完成、定时器停止。
从源码看,渐变时间被限制在MIN_FADE_MS(100)~MAX_FADE_MS(3000)之间(lightbulb.c),且enable_fade关闭时CALCULATE_FADE_TIME返回 0、直接跳变(lightbulb.c)。运行期间可调用lightbulb_set_fade_time()/lightbulb_set_fades_function()动态调整渐变时间与开关。
2.2 低功耗实现流程
为通过 T20 等低功耗认证,在优化灯板供电后还需在软件中做低功耗配置。除 低功耗模式使用指南 提及的设置外,驱动逻辑也需要调整。Lightbulb 组件对 PWM 与 I2C 调光方案均增加了低功耗处理:
- I2C 方案:开关灯时使用调光芯片的低功耗命令进入/退出低功耗;
- PWM 方案:ESP32 需要 APB 时钟源的电源锁管理防止闪烁——开灯时锁定电源并禁用动态调频,关灯时释放锁;其他芯片使用 XTAL 时钟源,无需额外处理。
源码中,低功耗开关灯会结合渐变时间与 NVS 存储延迟,确保渐变与刷写完成后再允许睡眠(lightbulb.c)。
三、颜色校准方案
3.1 CCT 色温模式校准
色温模式校准需要配置以下联合体结构:
union { struct { uint16_t kelvin_min; uint16_t kelvin_max; } standard; struct { lightbulb_cct_mapping_data_t *table; int table_size; } precise; } cct_mix_mode;- 标准模式(standard):校准最大、最小开尔文值,中间值用线性插值填充,再按目标色温调整冷、暖 LED 的输出比例。默认色温范围为 2200K ~ 7000K(源码常量
MIN_CCT_K/MAX_CCT_K,见 lightbulb.c),并可通过lightbulb_kelvin2percentage()/lightbulb_percentage2kelvin()在色温与百分比之间换算。 - 精密模式(precise):在不同色温下校准红、绿、蓝、冷、暖 LED 所需输出比例,用这些校准点直接输出对应比例。校准点越多色温越精确。需在 capability 中开启
enable_precise_cct_control(且enable_hardware_cct必须为 false)。校准表项类型为lightbulb_cct_mapping_data_t,其中rgbcw[5]各通道系数之和必须等于 1 以维持正确功率平衡(lightbulb.h)。
3.2 颜色模式校准
颜色模式校准需要配置以下结构:
union { struct { lightbulb_color_mapping_data_t *table; int table_size; } precise; } color_mix_mode;- 标准模式:无需配置任何参数,内部理论算法将 HSV、XYY 等颜色模型转换为 RGB 比例,LED 直接按比例点亮。
- 精密模式:使用 HSV 模型校准颜色。测量各种色相和饱和度下红、绿、蓝、冷、暖 LED 的输出比例作为校准点,用线性插值填充中间值并按校准比例点亮。需在 capability 中开启
enable_precise_color_control。校准表项类型为lightbulb_color_mapping_data_t,记录特定色相下饱和度 100/50/0 三档对应的 RGBCW 分量(lightbulb.h)。
此外组件还内置 HSV/RGB/xyY 互转工具:lightbulb_hsv2rgb、lightbulb_rgb2hsv、lightbulb_xyy2rgb、lightbulb_rgb2xyy,便于在上层应用直接做色彩模型换算。
四、功率限制方案
功率限制用于平衡并微调特定通道或系统整体的输出电流以满足功率需求。
4.1 整体功率限制
typedef struct { /* 缩放输入值 * 范围: 10% <= value <= 100% * 步进: 1% * 默认最小: 10% * 默认最大: 100% */ uint8_t white_max_brightness; /**< 白光输出最大亮度限制。 */ uint8_t white_min_brightness; /**< 白光输出最小亮度限制。 */ uint8_t color_max_value; /**< 彩光输出最大 value 限制。 */ uint8_t color_min_value; /**< 彩光输出最小 value 限制。 */ /* 动态调整最终功率 * 范围: 100% <= value <= 500% * 步进: 10% */ uint16_t white_max_power; /**< 白光输出最大功率限制。 */ uint16_t color_max_power; /**< 彩光输出最大功率限制。 */ } lightbulb_power_limit_t;参数语义(对应 lightbulb.h 与文档):
white_max_brightness/white_min_brightness:用于色温模式,将色温 API 设置的brightness参数约束在最大、最小值之间;color_max_value/color_min_value:用于颜色模式,将颜色 API 设置的value参数约束在最大、最小值之间;white_max_power:用于色温模式限功率。默认值 100 表示最大输出功率为满功率的一半;设为 200 可达到冷、暖 LED 的满功率;color_max_power:用于颜色模式限功率。默认值 100 表示最大输出功率为满功率的三分之一;设为 300 可达到红、绿、蓝 LED 的满功率。
在配置中通过lightbulb_config_t.external_limit传入,也可在运行期用lightbulb_get_power_limit()读取当前限制。
4.2 单颗 LED 功率/色彩平衡微调
typedef struct { float balance_coefficient[5]; /**< 用于调节每个颜色通道(R、G、B、C、W)强度的浮点系数数组。 这些系数有助于实现期望的光输出色彩平衡。 */ float curve_coefficient; /**< 伽马校正系数。用于修正亮度级别, 以适配人眼视觉的非线性特性,从而改善整体观感。 */ } lightbulb_gamma_config_t;balance_coefficient:用于微调每颗 LED 的输出电流,驱动最终输出按该比例衰减,默认值 1.0 表示不衰减;curve_coefficient:用于将渐变过程中的线性变化转换为曲线变化。
注意:修改
balance_coefficient会影响颜色校准的准确性,因此该参数应在进行颜色校准之前调整。它对于输出电流为 5 或 10 倍数的 I2C 调光芯片尤其有用——需要特定电流时可用该参数调整。
从源码看,lightbulb_gamma_config_t实际上区分了彩光与白光两套伽马曲线(color_curve_coefficient与white_curve_coefficient,默认均为 1.0 线性),组件内部会据此构建 RGB 与 CCT 各自的伽马校正表(lightbulb.c)。
五、DALI 总线驱动(IEC 62386 主站)
5.1 组件概览与特性
DALI 组件提供一个基于 ESP-IDF 的 DALI(IEC 62386)主站驱动。它使用ESP RMT 外设生成前向帧(Forward Frame,FF)并解码后向帧(Backward Frame,BF),应用可直接控制与查询 DALI 控制装置。组件源码位于 components/dali,公共头文件见 include/dali.h、dali_command.h 等。
核心特性:
- 物理层:基于 RMT 的曼彻斯特编码收发(Te = 416.67 µs,容差 ±10%);
- 寻址:短地址(0–63)、组地址(0–15)、广播及特殊命令;
- Part 102(Control Gear):DAPC 调光、间接/配置命令与灯具查询;
- Part 103(Control Device):输入设备的事件上报与设备/实例级命令;
- Part 303/304(传感器):占用(303)与光照(304)传感器支持;
- Part 209(DT8 颜色):RGB、CCT(Tc)与 XY 色度控制;
- 组网:Part 102 与 Part 103 设备的自动短地址分配;
- 双发机制:配置命令内置 100ms 内双倍发送。
5.2 支持的目标芯片
组件元数据(idf_component.yml)声明的支持目标:ESP32、ESP32-S2、ESP32-S3、ESP32-C3、ESP32-C6、ESP32-P4、ESP32-H2。
5.3 快速开始
第 1 步:包含头文件
#include "dali.h" #include "dali_command.h"第 2 步:初始化驱动
dali_master_handle_t dali; dali_master_config_t cfg = { .rx_gpio = GPIO_NUM_4, .tx_gpio = GPIO_NUM_5, .invert_tx = false, .invert_rx = false, }; dali_master_rmt_config_t rmt_cfg = { .mem_block_symbols = 64, }; ESP_ERROR_CHECK(dali_new_master_rmt(&cfg, &rmt_cfg, &dali));第 3 步:发送命令(不需要后向帧)
/* 驱动会在每次事务后自动插入最小帧间隔(> 22 Te),无需显式延时。 */ dali_master_transaction_config_t tx_cfg = { .addr_type = DALI_ADDR_SHORT, .addr = 0, .is_cmd = true, .command = DALI_CMD_RECALL_MAX_LEVEL, .send_twice = false, .tx_timeout_ms = DALI_TX_TIMEOUT_MS, }; ESP_ERROR_CHECK(dali_master_do_transaction(dali, &tx_cfg, NULL));第 4 步:发送查询(期待后向帧)
int reply = DALI_RESULT_NO_REPLY; dali_master_transaction_config_t tx_cfg = { .addr_type = DALI_ADDR_SHORT, .addr = 0, .is_cmd = true, .command = DALI_CMD_QUERY_STATUS, .send_twice = false, .tx_timeout_ms = DALI_TX_TIMEOUT_MS, }; ESP_ERROR_CHECK(dali_master_do_transaction(dali, &tx_cfg, &reply)); if (DALI_RESULT_IS_VALID(reply)) { ESP_LOGI("dali", "QUERY_STATUS = 0x%02X", (unsigned)reply); }第 5 步:组网(自动分配短地址)
/* Part 102 — Control Gear(灯具) */ uint8_t count102 = 0; esp_err_t err = dali_commission(dali, DALI_COMMISSION_ALL, 0, 64, &count102, DALI_TX_TIMEOUT_MS); if (err == ESP_OK) { ESP_LOGI("dali", "Part 102 commissioned: %u gear", count102); } /* Part 103 — Control Devices(传感器) */ uint8_t count103 = 0; err = dali_103_commission(dali, DALI_COMMISSION_ALL, 10, 64, &count103, DALI_TX_TIMEOUT_MS); if (err == ESP_OK) { ESP_LOGI("dali", "Part 103 commissioned: %u devices", count103); }第 6 步:设置 DT8 颜色(Part 209)
/* RGB 模式 — 将地址 4 设为红色 */ dali_color_val_t color = { .rgb = { .r = 254, .g = 0, .b = 0 } }; ESP_ERROR_CHECK(dali_master_set_color(dali, DALI_ADDR_SHORT, 4, DALI_COLOR_RGB, color, DALI_TX_TIMEOUT_MS)); /* CCT 模式 — 将地址 4 设为 2700K(370 Mirek) */ dali_color_val_t cct = { .cct = { .mirek = 370 } }; ESP_ERROR_CHECK(dali_master_set_color(dali, DALI_ADDR_SHORT, 4, DALI_COLOR_CCT, cct, DALI_TX_TIMEOUT_MS));5.4 运行时配置(无需 Kconfig)
所有 DALI 驱动配置均在运行时通过两个配置结构体完成,无需任何 Kconfig 选项:
dali_master_config_t:GPIO 引脚分配(rx_gpio、tx_gpio)与极性反相(invert_tx、invert_rx);dali_master_rmt_config_t:RMT 相关设置,如内存块大小。
dali_master_config_t cfg = { .rx_gpio = GPIO_NUM_4, .tx_gpio = GPIO_NUM_5, .invert_tx = false, /* 默认 TX 极性不反相 */ .invert_rx = false, /* 默认 RX 极性不反相 */ }; dali_master_rmt_config_t rmt_cfg = { .mem_block_symbols = 0, /* 0 = 按 SOC 能力自动检测 */ }; ESP_ERROR_CHECK(dali_new_master_rmt(&cfg, &rmt_cfg, &dali));5.5 命令模型
dali_master_do_transaction()是所有事务类型的统一入口,通过dali_master_transaction_config_t描述事务:
- DAPC 数值写入:
config.is_cmd = false,config.command即 arc power 数值; - 普通命令/查询:
config.is_cmd = true,config.command取自dali_command.h; - 需要双发(send-twice)的命令:设置
config.send_twice = true; - 查询:传入
result != NULL并检查DALI_RESULT_IS_VALID(*result);dali_master_do_transaction()会在每次事务后自动插入要求的帧间隔(> 22 Te),连续调用之间无需手动延时。
源码常量定义于 dali_system_components.h:DALI_TX_TIMEOUT_MS为 110ms,DALI_RESULT_NO_REPLY为 -1,DALI_RESULT_IS_VALID(r)即(r) >= 0。
5.6 时序说明
- DALI 定义了严格的帧间隔与后向帧响应窗口;
- 驱动在每次
dali_master_do_transaction()调用后自动插入最小帧间隔(> 22 Te),满足 IEC 62386 要求; dali_master_do_transaction()为阻塞调用,禁止在 ISR 或时间关键任务中调用。
5.7 示例与测试
- 示例应用:
examples/lighting/dali_basic(README); - 组件测试应用:
components/dali/test_apps/main/dali_test.c(另见pytest_dali.py)。
示例演示的能力包括:
- 组网:Part 102(灯具)与 Part 103(传感器)的自动短地址分配;
- 动态设备发现:按设备类型扫描识别 DT6(调光)与 DT8(彩色)装置;
- DAPC 调光:对所有发现的灯具执行亮度控制序列;
- Part 103 传感器:占用轮询与事件触发动作;
- 同步闪烁:占用时 DT6 灯具同步闪烁、DT8 灯具红/蓝交替;
- 查询命令:状态、实际亮度与设备类型查询。
5.8 术语表(Glossary)
- Te:DALI 半周期单位,标称值 416.67 µs(IEC 62386 允许 ±10% 容差),所有 DALI 时序均为 Te 的整数倍;
- 前向帧(Forward Frame, FF):DALI 主站发送给控制装置的 16 位帧,由 1 个起始位 + 16 个数据位 + 2 个停止位 = 共 38 Te。第一字节编码地址,第二字节携带命令或 arc-power 数值;
- 后向帧(Backward Frame, BF):DALI 从站响应查询命令发送的 8 位应答帧,由 1 个起始位 + 8 个数据位 + 2 个停止位 = 共 22 Te。从站必须在前向帧结束后 7 Te–22 Te 内响应;
- 短地址(Short Address):分配给单个 DALI 控制装置的唯一地址,范围 0–63,前向帧中编码为
0AAAAAAS(A = 地址位,S = 选择位)。Part 102 与 Part 103 设备的短地址相互独立,组网时不会产生地址冲突; - 组地址(Group Address):最多 16 个控制装置共享的地址,范围 0–15,编码为
100AAAAS,无需逐台寻址即可同时控制多个灯具。
六、上手建议与参考资源
- 灯泡驱动:从 examples/lighting/lightbulb 示例入手,阅读 README 与 README_CN.md,结合测试用例 lightbulb_driver_test.c 验证各方案行为;驱动在 Kconfig 中按需开启(
CONFIG_ENABLE_PWM_DRIVER、CONFIG_ENABLE_BP57x8D_DRIVER等)。 - DALI:从 examples/lighting/dali_basic 示例入手,阅读 README,需要接入传感器与 DT8 时参考 dali_device_sensors.h 与 dali_color_control_dt8.h。
- 硬件选型:PWM 方案优先选 LEDC(硬件渐变、20bit 分辨率);大电流多通道调光优先选 I2C 芯片(注意
balance_coefficient与芯片电流倍数配合);灯带类选 WS2812 单总线方案。
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考