尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

arduino-esp32 Zigbee 窗帘(Window Covering)终端设备示例:配置方法、核心 API 与底层实现解析

arduino-esp32 Zigbee 窗帘(Window Covering)终端设备示例:配置方法、核心 API 与底层实现解析 arduino-esp32 Zigbee 窗帘Window Covering终端设备示例配置方法、核心 API 与底层实现解析【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32本文以 arduino-esp32 仓库中的Zigbee_Window_Covering示例为主体讲解如何把一块 ESP32-C6 或 ESP32-H2 开发板配置为 Zigbee 智能家居HA规范下的窗帘终端设备End Device完整覆盖 Arduino IDE 的编译配置项、示例代码中ZigbeeWindowCovering类全部关键 API 的用法并结合仓库源码剖析其 Cluster 注册、指令分发与位置/百分比换算的底层实现帮助你在实际窗帘电机项目上快速落地 Zigbee 百叶窗控制。示例概述与支持的芯片Zigbee_Window_Covering示例演示如何配置一个 Zigbee 终端设备并将其作为一个 Home AutomationHAProfile 下的Window Covering窗帘设备接入 Zigbee 网络。该设备负责控制百叶窗的升降lift与倾斜tilt并持续向网络报告当前位置同时示例还演示了如何用板载按键手动调节升降位置。要验证与 Zigbee 网络的通信是否正常打开串口监视器Serial Monitor观察输出即可。该示例当前支持的目标芯片支持的目标ESP32-C6ESP32-H2支持✔✔从示例同目录下的 ci.yml 可以看到CI 构建还要求满足两个前提条件这也解释了为什么只支持特定芯片fqbn_append: PartitionSchemezigbee,ZigbeeModeed requires: - CONFIG_SOC_IEEE802154_SUPPORTEDy - CONFIG_ZB_ENABLEDy即目标 SoC 必须具备 IEEE 802.154 射频能力并且编译时启用了 Zigbee 协议栈CONFIG_ZB_ENABLED。fqbn_append则说明该示例的 CI 会自动附加PartitionSchemezigbee与ZigbeeModeed两个编译选项——这正是下文 Arduino IDE 中必须手动选择的两项配置。硬件准备一根 USB 数据线用于供电和烧录一块 ESP32-H2 或 ESP32-C6 开发板作为 Zigbee 终端设备烧录Zigbee_Window_Covering示例一个已有的 Zigbee 网络/协调器coordinator可以是仓库其他 Zigbee 示例如开关、灯具示例也可以是 Zigbee2MQTT、Zigbee Home Assistant 之类的网关应用。Arduino IDE 编译配置在 README 中列出的 IDE 配置项如下结合 boards.txt 可以进一步说明每项配置在底层实际做了什么选择正确的开发板Tools - BoardESP32-C6 或 ESP32-H2 系列板型。选择 Zigbee 终端设备模式Tools - Zigbee mode: Zigbee ED (end device)。 对应 boards.txt 中的菜单定义该选项会向编译注入两个关键参数宏定义-DZIGBEE_MODE_ED——示例源码开头正是用#ifndef ZIGBEE_MODE_ED配合#error强制检查该宏未选择 ED 模式时编译会直接报错链接库-lesp_zb_api.ed -lzboss_stack.ed -lzboss_port.native即链接 ED 角色的 Zigbee 协议栈库。启用 USB CDCTools - USB CDC On Boot: Enabled保证串口日志通过 USB 输出。选择 Zigbee 专用分区表Tools - Partition Scheme: Zigbee 4MB with spiffs。 boards.txt 中该项定义为build.partitionszigbee且upload.maximum_size1310720。Zigbee 协议栈需要独立的 NVS 分区存储网络密钥与设备状态因此不能沿用默认分区表。选择 COM 口Tools - Port: xxx。可选开启 Verbose 日志Tools - Core Debug Level: Verbose可以看到 Zigbee 协议栈的完整日志。提示示例源码中Zigbee.begin()的默认角色就是ZIGBEE_END_DEVICE见 ZigbeeCore.h 中begin()的默认参数与上述 IDE 配置共同保证设备以终端设备身份入网。示例代码逐段解析完整示例位于 Zigbee_Window_Covering.ino下面按结构拆解。关键宏与全局状态#define ZIGBEE_COVERING_ENDPOINT 10 #define BUTTON_PIN 9 // ESP32-C6/H2 Boot button #define MAX_LIFT 200 // centimeters from open position (0-900) #define MIN_LIFT 0 #define MAX_TILT 40 // centimeters from open position (0-900) #define MIN_TILT 0Endpoint 10Window Covering 端点号按 Zigbee HA 规范自定义只需保证同一设备上唯一按键引脚 9ESP32-C6/H2 开发板的 BOOT 按键行程范围MAX_LIFT200、MAX_TILT40表示窗帘从全开位置算起的最大行程示例按厘米计注释同时给出了 ZCL 属性允许的完整取值范围 0~900。示例用currentLift/currentTilt厘米和currentLiftPercentage/currentTiltPercentage0~100%两套状态来模拟电机位置。setup()设备配置与入网setup()的完整流程摘自示例zbCovering.setManufacturerAndModel(Espressif, WindowBlinds); zbCovering.setCoveringType(BLIND_LIFT_AND_TILT); zbCovering.setConfigStatus(true, true, false, true, true, true, true); zbCovering.setMode(false, true, false, false); zbCovering.setLimits(MIN_LIFT, MAX_LIFT, MIN_TILT, MAX_TILT); zbCovering.onOpen(fullOpen); zbCovering.onClose(fullClose); zbCovering.onGoToLiftPercentage(goToLiftPercentage); zbCovering.onGoToTiltPercentage(goToTiltPercentage); zbCovering.onStop(stopMotor); Zigbee.addEndpoint(zbCovering); if (!Zigbee.begin()) { Serial.println(Zigbee failed to start!); ESP.restart(); } while (!Zigbee.connected()) { Serial.print(.); delay(100); } zbCovering.setLiftPercentage(currentLiftPercentage); zbCovering.setTiltPercentage(currentTiltPercentage);各配置 API 的含义依据 ZigbeeWindowCovering.h 的声明与注释API作用示例中的取值含义setManufacturerAndModel()设置 Zigbee 设备厂商与型号字符串Espressif / WindowBlindssetCoveringType()设置窗帘类型决定可用属性集合BLIND_LIFT_AND_TILT升降倾斜百叶窗setConfigStatus(operational, online, commands_reversed, lift_closed_loop, tilt_closed_loop, lift_encoder_controlled, tilt_encoder_controlled)设置 7 位 Config Status 位图在线、可运行、命令不反向、升降/倾斜均闭环、均编码器控制setMode(motor_reversed, calibration_mode, maintenance_mode, leds_on)设置 4 位 Mode 位图未反向、处于校准模式、非维护模式、LED 不反馈setLimits(open_lift, closed_lift, open_tilt, closed_tilt)设置已安装行程极限对应esp_zb_zcl_window_covering_info_attr_tlift 0~200tilt 0~40onOpen/onClose/onGoToLiftPercentage/onGoToTiltPercentage/onStop注册收到 Zigbee 命令后的回调分别指向 5 个控制函数之后调用 ZigbeeCore::addEndpoint() 把端点挂到 Zigbee Core再用Zigbee.begin()启动协议栈并等待Zigbee.connected()入网成功最后调用setLiftPercentage()/setTiltPercentage()发布初始位置。loop()按键工厂重置与手动控制if (digitalRead(BUTTON_PIN) LOW) { delay(100); int startTime millis(); while (digitalRead(BUTTON_PIN) LOW) { delay(50); if ((millis() - startTime) 3000) { Serial.printf(Resetting Zigbee to factory settings, reboot.\n); Zigbee.factoryReset(); delay(30000); } } manualControl(); }长按超过 3 秒调用 ZigbeeCore::factoryReset()默认restarttrue将设备与 Zigbee 协议栈恢复出厂设置后重启随后delay(30000)等待重启完成短按进入manualControl()把升降百分比每次增加 20%超过 100% 归零并用setLiftPercentage()向网络上报——模拟本地手动拨动窗帘的场景。五个命令回调回调触发命令示例实现fullOpen()Up/OpencurrentLift MAX_LIFTsetLiftPercentage(100)fullClose()Down/ClosecurrentLift MIN_LIFTsetLiftPercentage(0)goToLiftPercentage(uint8_t)Go To Lift Percentage按百分比换算厘米位置后setLiftPercentage()goToTiltPercentage(uint8_t)Go To Tilt Percentage同上换算倾斜位置后setTiltPercentage()stopMotor()Stop上报当前 lift 与 tilt 的实际位置示例注释中特别强调在真实电机场景中currentLift应在运动过程中持续更新并向控制器反馈实际位置且Stop回调随时可以被调用因此任何运动中都必须支持“停下来并上报当前位置”。示例为了演示方便采用“瞬间到位”的模拟方式。ZigbeeWindowCovering类底层实现剖析以上行为均由 ZigbeeWindowCovering.cpp 实现以下结合源码说明其工作机制。端点初始化注册 5 个 Server 角色 Cluster构造函数ZigbeeWindowCovering.cpp#L63-L90将设备 ID 设为ESP_ZB_HA_WINDOW_COVERING_DEVICE_IDProfile 使用ESP_ZB_AF_HA_PROFILE_IDHA Profile并按ZIGBEE_DEFAULT_WINDOW_COVERING_CONFIG()定义于 ZigbeeWindowCovering.h#L41-L71初始化 Basic、Identify、Groups、Scenes、Window Covering 五个 Cluster 的默认配置。zigbee_window_covering_clusters_create()ZigbeeWindowCovering.cpp#L18-L61创建 Cluster 列表后把 Window Covering 的关键属性指针绑定到 C 成员变量Current Position Lift Percentage/Current Position Tilt PercentageCurrent Position Lift/Current Position TiltInstalled Open/Closed Limit Lift与... TiltPhysical Closed Limit Lift/... Tilt这些属性统一以Server 角色加入 Cluster 列表。由于属性直接绑定到对象成员调用setLiftPercentage()等接口更新成员并写回 ZCL 后网络侧的 Read Attribute 请求能直接读到最新值。窗帘类型枚举ZigbeeWindowCovering.h#L27-L38 中ZigbeeWindowCoveringType枚举与 ZCL 标准值一一对应枚举值支持的运动ROLLERSHADE、ROLLERSHADE_2_MOTOR、ROLLERSHADE_EXTERIOR、ROLLERSHADE_EXTERIOR_2_MOTORLIFTDRAPERY、AWNINGLIFTSHUTTERTILTBLIND_TILT_ONLYTILTBLIND_LIFT_AND_TILTLIFT TILTPROJECTOR_SCREENLIFT示例选择BLIND_LIFT_AND_TILT因此 lift 与 tilt 两组属性都可用如果只做卷帘如ROLLERSHADEtilt 相关属性就不适用。命令分发zbWindowCoveringMovementCmd()来自网络的窗帘命令在zbWindowCoveringMovementCmd()ZigbeeWindowCovering.cpp#L233-L263中按message-command分发UP_OPEN→open()→ 用户注册的onOpen回调DOWN_CLOSE→close()→onClose回调STOP→stop()→onStop回调GO_TO_LIFT_PERCENTAGE→ 先与当前百分比比较仅在目标值与当前值不同时才触发goToLiftPercentage()避免重复运动GO_TO_TILT_PERCENTAGE→ 同理触发goToTiltPercentage()其他命令/非 Window Covering Cluster 的消息被忽略并打印 warning。属性写入zbAttributeSet()对 Mode 的特殊处理zbAttributeSet()ZigbeeWindowCovering.cpp#L195-L231处理网络侧对属性的写操作。对Mode属性8 位位图它不仅把 4 个标志位电机反向、校准模式、维护模式、LED 反馈同步给setMode()还会联动更新 Config Status 位图中的REVERSE_COMMANDS位——即网络侧把电机方向置反时commands_reversed状态位同步翻转。这个细节在自研协调器/网关侧读取设备状态时值得注意。位置与百分比的换算公式setLimits()ZigbeeWindowCovering.cpp#L145-L192把四个“已安装极限”同时写入 6 个属性physical closed limit 与 installed closed limit 取相同值。位置接口的换算逻辑为setLiftPercentage(p)lift_position open_limit (closed_limit - open_limit) * p / 100随后同时更新Current Position Lift与Current Position Lift Percentage两个属性setLiftPosition(x)lift_percentage (x - open_limit) * 100 / (closed_limit - open_limit)反向换算setTiltPosition()/setTiltPercentage()对 tilt 维度做同样的双向换算。以示例参数为例setLiftPercentage(100)会把 Current Position Lift 报告为 200对应完全打开setLiftPercentage(50)对应 100。每次换算后通过setClusterAttribute()写回 ZCL 属性失败时打印错误码并返回false——因此在真实项目中应检查这些接口的返回值。组网与故障排查Troubleshooting这部分完整继承自 README 的 Troubleshooting 章节并补充源码依据终端设备连不上协调器烧录前擦除终端设备的整片 Flash如果重新烧录过协调器固件也强烈建议这样做。两种擦除方式Arduino IDE 中Tools - Erase All Flash Before Sketch Upload设为Enabled代码中调用 ZigbeeCore::factoryReset() 重置设备与 Zigbee 协议栈示例中即长按 BOOT 键 3 秒触发。协调器网络默认是关闭的协调器重启或刷写新固件后默认拒绝新设备加入。开放入网的两种方法对应 ZigbeeCore.h#L185-L186 的声明入网前先调用Zigbee.setRebootOpenNetwork(time);再调用Zigbee.begin();使设备重启后自动开放网络time秒运行时随时调用Zigbee.openNetwork(time);开放网络允许设备加入。其他常见问题README 原文LED 不闪烁检查接线与 IO 引脚选择烧录失败尝试降低串口通信速率COM 口未被识别检查 USB 线与 USB 转串口驱动安装重要务必使用质量可靠的 USB 线和稳定电源。小结与移植要点把该示例移植到真实窗帘电机项目时核心改造点集中在 5 个回调函数把“瞬间更新位置”的模拟逻辑替换为驱动电机 PWM/步进信号并在运动循环中逐步调用setLiftPercentage()/setTiltPercentage()上报实际位置stopMotor()中停止电机并上报两个维度的当前位置setLimits()的取值要改为电机实际的行程上限ZCL 允许 0~900。编译时保持三件套配置不变Zigbee mode: Zigbee ED (end device)、USB CDC On Boot: Enabled、Partition Scheme: Zigbee 4MB with spiffs即可在 ESP32-C6/H2 上运行一个符合 Zigbee HA Window Covering 规范、可被 Zigbee2MQTT / ZHA 等网关识别的窗帘终端设备。【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表