我前两天买了个鱼缸,里面养了些观赏鱼,可没灯光照射的话,鱼看起来就黯淡失色。所以我觉得, 需要加装一个可以自定义颜色的RGB灯带,增加些观赏性,并且我是一个比较懒的人,我感觉远程遥控的功能也要有。之前做项目用过WIZnet的W5500芯片实现以太网功能,近期他们出了个带MCU的以太网芯片W55MH32,正好可以跟他们销售申请套开发板玩玩,计划是以太网连接到OneNET,微信弄个小程序也连上OneNET,最终从小程序操控RGB灯带,功能实现没问题,后面弄成POE供电的,方便布线,文章记录下开发过程,后续会把代码以及PCB都open出来,文中会展示小程序源码和工程源码,我会把工程完整的展示同时也会说明快速使用时需要替换的参数。这套方案其实还能用到其他场景,比如在床头装个氛围灯,也很合适。
本项目以 W55MH32 以太网单片机为核心,搭建了一套基于以太网的全彩灯条远程控制系统,实现通过微信小程序远程调节 WS2812B 灯条的颜色及动态效果(如流水灯、彩虹灯)。项目验证了 W55MH32 在物联网灯光控制场景的适用性及 MQTT+OneNET 架构的通信效率。
以太网灯条调色器实现:开源项目链接
原理图和PCB暂时未实现,实现后将会进行补充。
视频现象查看点击跳转
1 项目核心价值与实现效果
通过微信小程序的 RGB 滑块,能精准调节红、绿、蓝三色比例,实现任意颜色输出。
支持两种动态模式切换:
流水灯 (Chasing Lights): 单灯按序轮播。
彩虹灯 (Rainbow): 渐变色彩循环。
基于 MQTT+OneNET 架构,通信稳定且延迟低。
核心验证: 验证了 W55MH32 在物联网灯光控制场景的高适用性。
简单来说: 用手机就能随时随地控制灯条的颜色和动态效果,无论是家庭装饰还是场景布置都很实用。 硬件
1.1 方案图示
1.2 通信架构说明
整个系统的通信流程清晰易懂:
微信小程序发送控制指令(如颜色调节、模式切换)。
指令通过 MQTT 协议上传至 OneNET 云平台。
W55MH32 通过以太网连接路由器,从 OneNET 接收指令。
W55MH32 解析指令后驱动 WS2812B 执行相应动作。
设备状态通过串口助手实时反馈(方便调试)。
2 项目环境
2.1 软件准备
开发环境: Keil uVision 5
调试工具: WIZ UartTool
小程序开发: 微信开发者工具
云平台: OneNET
2.2 硬件准备
W55MH32-EVB
RGB灯条
RJ45网线
3 注册 OneNET 账号及建立物模型
注册账号在此不赘述,下面重点介绍如何建立物模型。
3.1 创建产品
3.2 创建物模型
物模型的建立根据自己的需要建立。
3.3 获取基本信息
获得产品ID、设备名称以及密钥(示例):
产品ID: iP20B5FpF6
设备名称: d2
设备密钥: TFU3bT**************************=
3.4 Token 密钥生成
设备与 OneNET 平台通信时,Token 作为身份凭证用于安全认证。需使用 Token 生成工具: OneNET Token 生成工具文档
res 字段: products/{产品id}/devices/{设备名} (使用设备级 Key)。替换 {产品id} 和 {设备名}。
et 字段: 访问过期时间 (Unix 时间戳)。可使用在线转换工具获取。
key 字段: 填写设备的密钥。
点击 generate 生成 Token 密钥。
3.5 物模型 Topic (示例)
设置直连设备属性: $sys/iP20B5FpF6/d2/thing/property/set
直连设备属性设置响应: $sys/iP20B5FpF6/d2/thing/property/set_reply
直连设备上报属性: $sys/iP20B5FpF6/d2/thing/property/post
直连设备上报属性响应: $sys/iP20B5FpF6/d2/thing/property/post/reply
4 微信小程序
小程序源工程下载:
链接:https://pan.baidu.com/s/16nBbtMhSUeqvVxuVY35Ezg
提取码:xjdg
修改步骤:
下载后导入微信开发者工具。
修改 index.js 文件:
修改 Token: 替换 header: {"authorization": "你的token"} 中的值为生成的 Token。
修改产品 ID 和设备名: 在 url 中替换 product_id 和 device_name 参数为实际值。
// 修改为自己的产品ID和设备名 url: "https://iot-api.heclouds.com/thingmodel/query-device-property?product_id=你的产品ID&device_name=你的设备名" // 替换为生成的token header: {"authorization": "你的token"}
根据注释修改物模型初始化名称及绑定图片。
5 例程添加与修改
5.1 修改 MQTT 连接参数 (do-mqtt.c)
下载 W55MH32 MQTT 例程,修改 mqttconn 结构体参数为你的 OneNET 信息:
mqttconn mqtt_params = { .mqttHostUrl = "mqtts.heclouds.com", //MQTT服务器的URL地址 .server_ip = {0,}, // 服务器IP地址(此处未使用,保留默认值) .port = 1883, // 连接端口号,1883为MQTT默认非加密端口 .clientid = "d2", // MQTT客户端ID (替换为你的设备名) .username = "iP20B5FpF6", // MQTT用户名 (替换为你的产品ID) .passwd = "vers=md5&sign=YT2N73HSjmyy%2BbQEFMDjMw%3D%3D", // 用户密码 (替换为你的签名信息) .pubtopic = "$sys/iP20B5FpF6/d2/thing/property/post", // 发布主题 (替换产品ID和设备名) .pubtopic_reply = "$sys/iP20B5FpF6/d2/thing/property/post/reply", // 发布响应主题 .subtopic = "$sys/iP20B5FpF6/d2/thing/property/set", // 订阅主题 .subtopic_reply = "$sys/iP20B5FpF6/d2/thing/property/set_reply", // 订阅响应主题 .pubQoS = QOS0, // 发布消息的服务质量等级(0:最多一次) .willtopic = "/wizchip/will", // 遗嘱消息主题,客户端异常断开时发布 .willQoS = QOS0, // 遗嘱消息的服务质量等级 .willmsg = "wizchip offline!", // 遗嘱消息内容 .subQoS = QOS0, // 订阅消息的服务质量等级 };
5.2 添加 WS2812B 驱动代码 (ws2812b.c)
创建 ws2812b.c/h 文件,实现灯条控制函数:
/** * @brief 设置特定LED的颜色 * * @param index LED索引(0起始) * @param red 红色分量(0-255) * @param green 绿色分量(0-255) * @param blue 蓝色分量(0-255) * * @note 颜色数据暂存于缓冲区,需调用ws2812b_update()生效 */ void ws2812b_set_color(uint8_t index, uint8_t red, uint8_t green, uint8_t blue) { if (index < LED_NUM) { s_led_colors[index][0] = green; // WS2812B使用GRB格式 s_led_colors[index][1] = red; s_led_colors[index][2] = blue; } } /** * @brief 设置所有LED为统一颜色 * * @param red 红色分量(0-255) * @param green 绿色分量(0-255) * @param blue 蓝色分量(0-255) * * @note 颜色数据暂存于缓冲区,需调用ws2812b_update()生效 */ void ws2812b_set_all_color(uint8_t red, uint8_t green, uint8_t blue) { for (uint8_t i = 0; i < LED_NUM; i++) { ws2812b_set_color(i, red, green, blue); } } /** * @brief 关闭所有LED(设置为黑色) * * @note 需调用ws2812b_update()生效 */ void ws2812b_clear_all(void) { memset(s_led_colors, 0, sizeof(s_led_colors)); } /** * @brief 将缓冲区颜色数据发送至WS2812B灯带 * * @note 严格遵循WS2812B时序要求,发送GRB格式数据 */ void ws2812b_update(void) { /* 禁用中断以确保精确时序 */ __disable_irq(); TIM_TypeDef *timer_ptr = WS2812B_TIM; timer_ptr-?>CCR1 = 0; // 初始化为低电平 /* 处理所有LED */ for (uint8_t i = 0; i < LED_NUM; i++) { /* 组合24位GRB颜色数据(绿色8位 + 红色8位 + 蓝色8位) */ uint32_t grb = ((s_led_colors[i][0] < 16) | (s_led_colors[i][1] < 8) | s_led_colors[i][2]); /* 从高位到低位逐位发送 */ for (int8_t bit_pos = 23; bit_pos >= 0; bit_pos--) { /* 根据当前位值设置PWM占空比 */ uint16_t duty = (grb & (1UL < bit_pos)) ? s_bit1_duty : s_bit0_duty; timer_ptr-?>CCR1 = duty; /* 等待一个PWM周期 */ uint32_t start_time = timer_ptr->CNT; while ((timer_ptr->CNT - start_time) < s_pwm_period) ; } } /* 发送复位信号(至少50us低电平) */ timer_ptr-?>CCR1 = 0; /* 精确延时50us */ const uint32_t reset_cycles = (SystemCoreClock / 20000); // 计算50us所需的时钟周期数 for (volatile uint32_t i = 0; i < reset_cycles; i++) ; /* 恢复中断 */ __enable_irq(); } /** * @brief 彩虹动画效果 * * @note 循环更新LED颜色以创建流动彩虹效果 */ void ws2812b_rainbow_effect(void) { static uint8_t start_position = 0; for (uint8_t i = 0; i < LED_NUM; i++) { const uint8_t position = (start_position + i) % 256; uint8_t r = 0; uint8_t g = 0; uint8_t b = 0; /* 根据位置计算RGB值 */ if (position < 85) { r = position * 3; g = 255 - position * 3; } else if (position < 170) { const uint8_t adjusted_pos = position - 85; r = 255 - adjusted_pos * 3; b = adjusted_pos * 3; } else { const uint8_t adjusted_pos = position - 170; g = adjusted_pos * 3; b = 255 - adjusted_pos * 3; } ws2812b_set_color(i, r, g, b); } start_position = (start_position + 5) % 256; // 更新起始位置 ws2812b_update(); delay_ms(400); } /** * @brief 跑马灯效果 * * @note 单个LED依次循环点亮 */ void ws2812b_running_light(void) { static uint8_t position = 0; ws2812b_clear_all(); ws2812b_set_color(position, get_red_value(), get_green_value(), get_blue_value()); ws2812b_update(); delay_ms(200); position = (position + 1) % LED_NUM; } /* 获取颜色值的函数实现 */ uint8_t get_blue_value(void) { return g_blue_value; } uint8_t get_red_value(void) { return g_red_value; } uint8_t get_green_value(void) { return g_green_value; }
5.3 修改 MQTT 指令解析 (do_mqtt.c)
在解析 OneNET 下发指令 (cJSON 解析) 的函数中,添加对颜色和模式指令的处理逻辑:
/* 处理灯带开关命令 */ cJSON *light_strip = cJSON_GetObjectItem(params, "LightStrip"); // 从JSON参数中获取灯带控制项 if (light_strip != NULL) { // 当存在灯带控制参数时 if (light_strip->valueint) { // 判断参数值是否为真(开启) strncat(status_msg, "LightStrip:OK;", // 向状态字符串追加灯带开启状态 sizeof(status_msg) - strlen(status_msg) - 1); // 计算剩余缓冲区空间防止溢出 g_rainbow_effect = 1; // 启用全局彩虹特效标志 } else { // 参数值为假(关闭) strncat(status_msg, "LightStrip:OFF;", // 追加灯带关闭状态 sizeof(status_msg) - strlen(status_msg) - 1); g_rainbow_effect = 0; // 禁用彩虹特效 ws2812b_clear_all(); // 调用底层驱动清除所有LED状态 ws2812b_update(); // 执行硬件更新使清除操作生效 } } /* 处理流水灯开关命令 */ cJSON *flowing_light = cJSON_GetObjectItem(params, "FlowingLight"); // 获取流水灯控制参数 if (flowing_light != NULL) { // 当存在流水灯参数时 if (flowing_light->valueint) { // 参数值为真(开启) printf("Switch on the chasing lightsrn"); // 输出调试日志 g_flowing_light = 1; // 设置流水灯全局使能标志 } else { // 参数值为假(关闭) printf("Switch off the chasing lightsrn"); g_flowing_light = 0; // 清除流水灯标志 ws2812b_clear_all(); // 清除LED显示 ws2812b_update(); // 同步硬件状态 } } /* 处理颜色设置命令 */ cJSON *red = cJSON_GetObjectItem(params, "red"); // 提取红色分量参数 if (red != NULL) { // 当存在红色参数时 handle_color_command(red->valueint, "RED", status_msg); // 调用颜色处理函数并更新状态 } cJSON *green = cJSON_GetObjectItem(params, "green"); // 提取绿色分量参数 if (green != NULL) { handle_color_command(green->valueint, "GREEN", status_msg); } cJSON *blue = cJSON_GetObjectItem(params, "blue"); // 提取蓝色分量参数 if (blue != NULL) { handle_color_command(blue->valueint, "BLUE", status_msg); }
5.4 处理接收的数据 (do_mqtt.c)
/** * @brief 处理颜色更新指令 * * @param color_value 要设置的颜色值(0-255) * @param color_type 颜色类型(RED/GREEN/BLUE) * @param status_msg 状态消息缓冲区指针 */ static void handle_color_command(int color_value, const char *color_type, char *status_msg) { // 创建临时字符串存储格式化后的颜色信息 char temp[16] = {0}; // 格式化颜色类型和数值(例如:"RED:255;") snprintf(temp, sizeof(temp), "%s:%d;", color_type, color_value); // 将格式化后的字符串追加到状态消息末尾 strncat(status_msg, temp, STATUS_MSG_MAX_SIZE - strlen(status_msg) - 1); // 根据颜色类型更新对应的全局颜色变量 if (strcmp(color_type, "RED") == 0) { g_red_value = color_value; // 更新红色分量 } else if (strcmp(color_type, "GREEN") == 0) { g_green_value = color_value; // 更新绿色分量 } else if (strcmp(color_type, "BLUE") == 0) { g_blue_value = color_value; // 更新蓝色分量 } // 遍历所有LED灯珠设置颜色 for (uint8_t i = 0; i < LED_NUM; i++) { // 调用底层驱动设置单个LED颜色(GRB格式) ws2812b_set_color(i, g_red_value, g_green_value, g_blue_value); } // 发送更新指令使颜色设置生效 ws2812b_update(); }
5.5 修改主函数 (main.c)
在 main() 函数中进行初始化,并在主循环中调用控制函数:
// ... (其他初始化) WS2812B_Init(); // 初始化WS2812B驱动 (配置定时器GPIO等) WS2812B_Update(); // 初始更新灯条 while (1) { // 检查并执行流水灯效果 if(g_flowing_light == 1) { ws2812b_running_light(); } // 检查并执行彩虹灯效果 if(g_rainbow_effect == 1) { ws2812b_rainbow_effect(); } do_mqtt(); }
6 功能验证
精准调色:
小程序提供红(R)、绿(G)、蓝(B)三个滑块。
通过调整滑块比例,可以组合出任意颜色。
LED灯条实时显示设定颜色
流水灯模式:
打开小程序上的“流水灯”按钮。
灯条按照当前设定的颜色进行单灯顺序轮播。
彩虹灯模式:
打开小程序上的“彩虹灯”按钮。
灯条显示渐变循环的彩虹效果。
总结
本文采用W55MH32开发板搭配WS2812B灯条,借助MQTT协议连接OneNET云平台,并配合微信小程序,实现了以太网灯条的远程调色以及动态模式(如流水灯、彩虹灯)控制。感谢大家阅读,若有疑问欢迎在评论区留言,我会为大家解答,助力你的开发工作。
审核编辑 黄宇
-
物联网
+关注
关注
2933文章
46465浏览量
395667 -
远程控制
+关注
关注
4文章
681浏览量
36022
发布评论请先 登录
第二十六章 W55MH32?上位机搜索和配置示例

第二十三章 W55MH32 MQTT_OneNET示例

第十八章 W55MH32 FTP_Server示例

第十六章 W55MH32 PING示例

第十五章 W55MH32 SNMP示例

第十四章 W55MH32 TFTP示例

第九章 W55MH32 HTTP Server示例

第五章 W55MH32 UDP示例

WIZnet W55MH32以太网单片机开发教程第十一章 通用定时器(下篇)

WIZnet W55MH32以太网单片机开发教程 第十一章 通用定时器(上篇)

W55MH32高性能以太网单片机教程 第九章 窗口看门狗(WWDG)

第二章 开发板与芯片介绍 详解W55MH32芯片及开发板

第一章 W55MH32 高性能以太网单片机的学习方法概述

即刻启程,踏上W55MH32高性能以太网单片机学习之路!

WIZnet高性能以太网单片机W55MH32重磅发布!

评论