How the W55MH32 works with WeChat Mini-Program and OneNET
How the W55MH32 works with WeChat Mini-Program and OneNET to enable color-adjustable Ethernet streetlights (open source hardware and software)

I bought a fish tank a few days ago and keep some ornamental fish in it. Without lighting, the fish look dull and lackluster. So, I thought I'd add a customizable RGB light strip to enhance the visual appeal. Since I'm a bit lazy, I also wanted remote control functionality. I've used WIZnet's W5500 chip for Ethernet functionality in previous projects. They recently released the W55MH32 Ethernet chip with an MCU, so I can ask them for a development board to play around with. My plan is to connect the device to OneNET via Ethernet and create a WeChat mini-program that also connects to OneNET. I'll eventually control the RGB light strip from the mini-program. The functionality works perfectly, and I'll later switch to POE power for easier wiring. This article documents the development process, and I'll make the code and PCB available later. The article will show the mini-program source code and the project source code. I'll also present the complete project and explain the parameters that need to be changed for quick use. This solution can also be used in other scenarios, such as a bedside ambient light.
This project, based on the W55MH32 Ethernet microcontroller, built an Ethernet-based full-color light strip remote control system. This allows users to remotely adjust the color and dynamic effects (such as flowing lights and rainbow lights) of WS2812B light strips via a WeChat mini-program. This project validates the W55MH32's suitability for IoT lighting control scenarios and the communication efficiency of the MQTT+OneNET architecture.
1. Project Core Value and Implementation
- The RGB sliders in the WeChat mini-program allow precise adjustment of the red, green, and blue ratios to achieve any color output.
- Two dynamic mode switching options are supported:
- Chasing Lights: Single lights rotate sequentially.
- Rainbow Lights: Gradual color cycling.
- Based on the MQTT+OneNET architecture, communication is stable and latency is low.
Core Verification: The W55MH32 has been verified to be highly suitable for IoT lighting control scenarios.
- Two dynamic mode switching options are supported:
Simply put: Using your phone, you can control the color and dynamic effects of light strips anytime, anywhere, making them extremely practical for both home decoration and scene layout.
1.1 Solution Diagram
1.2 Communication Architecture Description
The entire system's communication process is clear and easy to understand:
- The WeChat applet sends control commands (such as color adjustment and mode switching).
- Commands are uploaded to the OneNET cloud platform via the MQTT protocol.
- The W55MH32 connects to the router via Ethernet and receives commands from OneNET.
- The W55MH32 interprets the commands and drives the WS2812B to perform the corresponding actions.
- Device status is reported in real time via the serial port assistant (for easy debugging).
2 Project Environment
2.1 Software Preparation
- Development Environment: Keil uVision 5
- Debugging Tool: WIZ UartTool
- Mini Program Development: WeChat Developer Tools
- Cloud Platform: OneNET
2.2 Hardware Preparation
- W55MH32-EVB
- RGB Light Bar
- RJ45 Network Cable
3 Registering a OneNET Account and Creating a Object Model
Registering an account is not covered here; the focus will be on creating a object model.
3.1 Creating a Product
3.2 Creating an Object Model
The object model is established according to your own needs.
3.3 Obtaining Basic Information
Get the product ID, device name, and key (example):
Product ID: iP20B5FpF6
Device Name: d2
Device Key: TFU3bT**************************=
3.4 Token Key Generation
When a device communicates with the OneNET platform, a token serves as an identity credential for secure authentication. You must use the token generation tool: OneNET Token Generation Tool Documentation
- res field: products/{product id}/devices/{device name} (use device-level keys). Replace {product id} and {device name}.
- et field: Access expiration time (Unix timestamp). You can use the online conversion tool to obtain this.
- key field: Enter the device's key.
- Click generate to generate a token key.
3.5 Object Model Topic (Example)
- Setting a directly connected device property: $sys/iP20B5FpF6/d2/thing/property/set
- Response to setting a directly connected device property: $sys/iP20B5FpF6/d2/thing/property/set_reply
- Reporting a directly connected device property: $sys/iP20B5FpF6/d2/thing/property/post
- Response to reporting a directly connected device property: $sys/iP20B5FpF6/d2/thing/property/post/reply
4 WeChat Mini Program
Mini Program Source Project Download:
Link: Baidu Netdisk. Please enter the extraction code.
Extraction code: xjdg
Modification Steps:
1. After downloading, import the WeChat Developer Tools.
2. Modify the index.js file:
- Modify the Token: Replace the value in header: {"authorization": "your token"} with the generated token.
- Modify the Product ID and Device Name: Replace the product_id and device_name parameters in the URL with the actual values.
// 修改为自己的产品ID和设备名
url: "https://iot-api.heclouds.com/thingmodel/query-device-property?product_id=你的产品ID&device_name=你的设备名"
// 替换为生成的token
header: {"authorization": "你的token"}
3. Modify the object model initialization name and binding image according to the comments.
5. Routine addition and modification
5.1 Modify MQTT connection parameters (do_mqtt.c)
Download the W55MH32 MQTT demo and modify the mqttconn structure parameters to your OneNET information:
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 Adding WS2812B Driver Code (ws2812b.c)
Create the ws2812b.c/h files to implement the light bar control functions:
/**
* @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 Modifying MQTT Command Parsing (do_mqtt.c)
In the function that parses OneNET commands (cJSON parsing), add processing logic for color and mode commands:
/* 处理灯带开关命令 */
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 Processing received data (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 Modify the Main Function (main.c)
In the main() function, perform initialization and call the control function in the main loop:
// ... (其他初始化)
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 Functional Verification
Precise Color Adjustment:
- The mini program provides three sliders: Red (R), Green (G), and Blue (B).
- You can create any color combination by adjusting the slider ratio.
- The LED light strip displays the set color in real time.
Flowing Light Mode:
- Tap the "Flowing Light" button on the mini program.
- The light strip will rotate sequentially according to the currently set color.
Rainbow Light Mode:
- Tap the "Rainbow Light" button on the mini program.
- The light strip will display a gradient, cyclical rainbow effect.
Summary
This article uses the W55MH32 development board and a WS2812B light strip. Connecting to the OneNET cloud platform via the MQTT protocol and using the WeChat mini program, it enables remote color adjustment and dynamic mode control (such as flowing and rainbow) for the Ethernet light strip. Thank you for reading. If you have any questions, please leave a comment in the comments section. I will answer them and help you with your development work.