> 技术文档 > 一文读懂:W55MH32 如何携手微信小程序与 OneNET,实现以太网灯条调色自由(软硬件开源)

一文读懂:W55MH32 如何携手微信小程序与 OneNET,实现以太网灯条调色自由(软硬件开源)


我前两天买了个鱼缸,里面养了些观赏鱼,可没灯光照射的话,鱼看起来就黯淡失色。所以我觉得, 需要加装一个可以自定义颜色的RGB灯带,增加些观赏性,并且我是一个比较懒的人,我感觉远程遥控的功能也要有。之前做项目用过WIZnet的W5500芯片实现以太网功能,近期他们出了个带MCU的以太网芯片W55MH32,正好可以跟他们销售申请套开发板玩玩,计划是以太网连接到OneNET,微信弄个小程序也连上OneNET,最终从小程序操控RGB灯带,功能实现没问题,后面弄成POE供电的,方便布线;文章记录下开发过程,后续会把代码以及PCB都open出来,文中会展示小程序源码和工程源码,我会把工程完整的展示同时也会说明快速使用时需要替换的参数。这套方案其实还能用到其他场景,比如在床头装个氛围灯,也很合适。

本项目以 W55MH32 以太网单片机为核心,搭建了一套基于以太网的全彩灯条远程控制系统,实现通过微信小程序远程调节 WS2812B 灯条的颜色及动态效果(如流水灯、彩虹灯)。项目验证了 W55MH32 在物联网灯光控制场景的适用性及 MQTT+OneNET 架构的通信效率。

以太网灯条调色器实现:开源项目链接

原理图和PCB暂时未实现,实现后将会进行补充。

视频现象查看点击跳转

目录

1 项目核心价值与实现效果

1.1 方案图示

1.2 通信架构说明

2 项目环境

2.1 软件准备

2.2 硬件准备

3 注册 OneNET 账号及建立物模型

3.1 创建产品

3.2 创建物模型

3.3 获取基本信息

3.4 Token 密钥生成

3.5 物模型 Topic (示例)

4 微信小程序

5 例程添加与修改

5.1 修改 MQTT 连接参数 (do_mqtt.c)

5.2 添加 WS2812B 驱动代码 (ws2812b.c)

5.3 修改 MQTT 指令解析 (do_mqtt.c)

5.4 处理接收的数据 (do_mqtt.c)

5.5 修改主函数 (main.c)

6 功能验证

总结


1 项目核心价值与实现效果

  • 通过微信小程序的 RGB 滑块,能精准调节红、绿、蓝三色比例,实现任意颜色输出。
    • 支持两种动态模式切换:
      • 流水灯 (Chasing Lights): 单灯按序轮播。
      • 彩虹灯 (Rainbow): 渐变色彩循环。
    • 基于 MQTT+OneNET 架构,通信稳定且延迟低。
  • 核心验证: 验证了 W55MH32 在物联网灯光控制场景的高适用性。

简单来说: 用手机就能随时随地控制灯条的颜色和动态效果,无论是家庭装饰还是场景布置都很实用。 硬件

1.1 方案图示

1.2 通信架构说明

整个系统的通信流程清晰易懂:

  1. 微信小程序发送控制指令(如颜色调节、模式切换)。
  2. 指令通过 MQTT 协议上传至 OneNET 云平台
  3. W55MH32 通过以太网连接路由器,从 OneNET 接收指令。
  4. W55MH32 解析指令后驱动 WS2812B 执行相应动作。
  5. 设备状态通过串口助手实时反馈(方便调试)。

2 项目环境

2.1 软件准备

  • 开发环境: Keil uVision 5
  • 调试工具: WIZ UartTool
  • 小程序开发: 微信开发者工具
  • 云平台: OneNET

2.2 硬件准备

  • W55MH32-EVB
  • RGB灯条
  • RJ45网线

3 注册 OneNET 账号及建立物模型

注册账号在此不赘述,下面重点介绍如何建立物模型。

3.1 创建产品

3.2 创建物模型

物模型的建立根据自己的需要建立。

3.3 获取基本信息

获得产品ID、设备名称以及密钥(示例):

  1. 产品ID: iP20B5FpF6
  2. 设备名称: d2
  3. 设备密钥: TFU3bT**************************=

3.4 Token 密钥生成

设备与 OneNET 平台通信时,Token 作为身份凭证用于安全认证。需使用 Token 生成工具: OneNET Token 生成工具文档

  1. res 字段: products/{产品id}/devices/{设备名} (使用设备级 Key)。替换 {产品id} 和 {设备名}
  2. et 字段: 访问过期时间 (Unix 时间戳)。可使用在线转换工具获取。
  3. key 字段: 填写设备的密钥。
  4. 点击 generate 生成 Token 密钥

3.5 物模型 Topic (示例)

  1. 设置直连设备属性: $sys/iP20B5FpF6/d2/thing/property/set
  2. 直连设备属性设置响应: $sys/iP20B5FpF6/d2/thing/property/set_reply
  3. 直连设备上报属性: $sys/iP20B5FpF6/d2/thing/property/post
  4. 直连设备上报属性响应: $sys/iP20B5FpF6/d2/thing/property/post/reply


4 微信小程序

  • 小程序源工程下载:
    • 链接:百度网盘 请输入提取码
    • 提取码:xjdg
  • 修改步骤:

1.下载后导入微信开发者工具

2.修改 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=你的设备名\"// 替换为生成的tokenheader: {\"authorization\": \"你的token\"}

3.根据注释修改物模型初始化名称及绑定图片。

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 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] <= 0; bit_pos--) { /* 根据当前位值设置PWM占空比 */ uint16_t duty = (grb & (1UL <CCR1 = duty; /* 等待一个PWM周期 */ uint32_t start_time = timer_ptr->CNT; while ((timer_ptr->CNT - start_time) 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 lights\\r\\n\"); // 输出调试日志 g_flowing_light = 1; // 设置流水灯全局使能标志 } else { // 参数值为假(关闭) printf(\"Switch off the chasing lights\\r\\n\"); 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 功能验证

  1. 精准调色:

    • 小程序提供红(R)、绿(G)、蓝(B)三个滑块。
    • 通过调整滑块比例,可以组合出任意颜色。
    • LED灯条实时显示设定颜色 
  2. 流水灯模式:

    • 打开小程序上的“流水灯”按钮。
    • 灯条按照当前设定的颜色进行单灯顺序轮播。 
  3. 彩虹灯模式:

    • 打开小程序上的“彩虹灯”按钮。
    • 灯条显示渐变循环的彩虹效果。 

总结

本文采用W55MH32开发板搭配WS2812B灯条,借助MQTT协议连接OneNET云平台,并配合微信小程序,实现了以太网灯条的远程调色以及动态模式(如流水灯、彩虹灯)控制。感谢大家阅读,若有疑问欢迎在评论区留言,我会为大家解答,助力你的开发工作。