12浏览
查看: 12|回复: 12

[ESP8266/ESP32] 【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

[复制链接]
原标题
【花雕动手做】ESP32-S3 + MimiClaw 实战:为板载 WS2812 添加循环红绿蓝与彩虹灯效果
——从静态颜色到动态光效,让你的嵌入式 AI Agent 拥有更丰富的视觉反馈


概述

适用硬件:ESP32-S3 开发板(板载 WS2812 RGB LED)
依赖框架:MimiClaw 嵌入式 AI Agent 框架
核心功能:实现 WS2812 循环红绿蓝、平滑彩虹渐变两种动态灯效,支持飞书自然语言指令控制,毫秒级响应无 LLM 依赖
基本定位:实战开发指南,包含完整设计思路、代码实现、编译测试与扩展方案

引言

在前期教程中,我们已完成飞书控制 WS2812 静态常亮与多色呼吸灯功能。为进一步丰富嵌入式 AI Agent 的视觉反馈与交互体验,本实战将进阶实现两种炫酷动态灯效:
循环红绿蓝:红→绿→蓝顺序循环显示,固定间隔切换
彩虹灯:基于 HSV 色彩空间,实现全色环平滑渐变
这里基于 FreeRTOS 独立任务 实现灯效渲染,保证运行流畅不阻塞主流程;同时集成飞书自然语言指令控制,支持一键启动 / 停止,多灯效互斥避免硬件冲突。

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图1

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

一、动态灯效设计方案

1.1 核心灯效定义

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图4

1.2 系统集成设计
任务互斥机制:启动任意灯效时,自动停止其他动态效果(呼吸灯 / 循环灯 / 彩虹灯),避免多任务同时控制 WS2812 导致冲突
状态管理:通过全局标志位 + 任务句柄,精准控制灯效启动 / 停止
指令优化:在 agent_loop.c 实现指令硬匹配,绕过 LLM,实现毫秒级响应
退出逻辑:停止灯效后,LED 默认熄灭,释放硬件资源

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图2

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图3

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图1

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

二、核心代码实现

所有代码基于 MimiClaw 现有 WS2812 驱动扩展,无额外硬件依赖。

2.1 工具注册:tool_registry.c
该文件实现灯效任务创建、执行、停止逻辑,是核心功能模块。

2.1.1 全局变量声明
在文件头部(呼吸灯变量区域)新增动态灯效统一变量:

  1. // ====================== 动态灯效:统一声明所有变量 ======================
  2. // 呼吸灯原有变量
  3. static TaskHandle_t s_breathing_task = NULL;
  4. static bool s_breathing_enabled = false;
  5. static uint8_t s_breathing_r = 255;
  6. static uint8_t s_breathing_g = 0;
  7. static uint8_t s_breathing_b = 0;
  8. // 循环红绿蓝 任务变量
  9. static TaskHandle_t s_cycle_task = NULL;
  10. static bool s_cycle_enabled = false;
  11. // 彩虹灯 任务变量
  12. static TaskHandle_t s_rainbow_task = NULL;
  13. static bool s_rainbow_enabled = false;
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

2.1.2 循环红绿蓝任务实现

  1. /**
  2. * @brief 循环红绿蓝灯效任务
  3. */
  4. static void cycle_rgb_task(void *arg)
  5. {
  6.     // 红、绿、蓝 三原色数组
  7.     const int colors[3][3] = {{255,0,0}, {0,255,0}, {0,0,255}};
  8.     int color_idx = 0;
  9.     const int delay_ms = 1000;  // 每个颜色停留 1 秒
  10.     while (s_cycle_enabled) {
  11.         // 设置当前颜色
  12.         ws2812_set(colors[color_idx][0], colors[color_idx][1], colors[color_idx][2]);
  13.         vTaskDelay(pdMS_TO_TICKS(delay_ms));
  14.         // 循环切换索引
  15.         color_idx = (color_idx + 1) % 3;
  16.     }
  17.     // 任务退出:熄灭 LED
  18.     ws2812_set(0, 0, 0);
  19.     s_cycle_task = NULL;
  20.     vTaskDelete(NULL);
  21. }
  22. /**
  23. * @brief 启动循环红绿蓝工具
  24. */
  25. static esp_err_t tool_cycle_rgb_start_execute(const char *in, char *out, size_t len)
  26. {
  27.     (void)in;
  28.     // 停止所有其他动态效果,避免冲突
  29.     if (s_breathing_task) {
  30.         s_breathing_enabled = false;
  31.         vTaskDelay(pdMS_TO_TICKS(100));
  32.         s_breathing_task = NULL;
  33.     }
  34.     if (s_rainbow_task) {
  35.         s_rainbow_enabled = false;
  36.         vTaskDelay(pdMS_TO_TICKS(100));
  37.         s_rainbow_task = NULL;
  38.     }
  39.     // 校验任务状态
  40.     if (s_cycle_task) {
  41.         snprintf(out, len, "Cycle RGB 已运行");
  42.         return ESP_OK;
  43.     }
  44.     // 释放 LED 资源,避免 RMT 冲突
  45.     ws2812_deinit();
  46.     s_cycle_enabled = true;
  47.     // 创建 FreeRTOS 任务
  48.     BaseType_t ret = xTaskCreate(cycle_rgb_task, "cycle_rgb", 4096, NULL, 5, &s_cycle_task);
  49.     if (ret == pdPASS) {
  50.         snprintf(out, len, "循环红绿蓝已启动");
  51.         return ESP_OK;
  52.     } else {
  53.         s_cycle_enabled = false;
  54.         snprintf(out, len, "循环红绿蓝启动失败");
  55.         return ESP_FAIL;
  56.     }
  57. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

2.1.3 彩虹灯任务实现(HSV→RGB 转换)

  1. /**
  2. * @brief 彩虹渐变灯效任务(HSV 转 RGB)
  3. */
  4. static void rainbow_task(void *arg)
  5. {
  6.     int hue = 0;  // 色相值 0~360
  7.     const int delay_ms = 20;  // 刷新间隔,越小速度越快
  8.     while (s_rainbow_enabled) {
  9.         uint8_t r, g, b;
  10.         uint8_t h = hue / 60;
  11.         uint8_t s = 255;   // 饱和度 100%
  12.         uint8_t v = 255;   // 亮度 100%
  13.         uint8_t f = hue % 60;
  14.         uint8_t pv = (v * (255 - s)) / 255;
  15.         uint8_t qv = (v * (255 - (s * f) / 60)) / 255;
  16.         uint8_t tv = (v * (255 - (s * (60 - f)) / 60)) / 255;
  17.         // HSV 转 RGB 核心逻辑
  18.         switch (h) {
  19.             case 0: r = v; g = tv; b = pv; break;
  20.             case 1: r = qv; g = v; b = pv; break;
  21.             case 2: r = pv; g = v; b = tv; break;
  22.             case 3: r = pv; g = qv; b = v; break;
  23.             case 4: r = tv; g = pv; b = v; break;
  24.             default: r = v; g = pv; b = qv; break;
  25.         }
  26.         ws2812_set(r, g, b);
  27.         vTaskDelay(pdMS_TO_TICKS(delay_ms));
  28.         // 循环色相
  29.         hue++;
  30.         if (hue >= 360) hue = 0;
  31.     }
  32.     // 任务退出:熄灭 LED
  33.     ws2812_set(0, 0, 0);
  34.     s_rainbow_task = NULL;
  35.     vTaskDelete(NULL);
  36. }
  37. /**
  38. * @brief 启动彩虹灯工具
  39. */
  40. static esp_err_t tool_rainbow_start_execute(const char *in, char *out, size_t len)
  41. {
  42.     (void)in;
  43.     // 停止所有其他动态效果
  44.     if (s_breathing_task) {
  45.         s_breathing_enabled = false;
  46.         vTaskDelay(pdMS_TO_TICKS(100));
  47.         s_breathing_task = NULL;
  48.     }
  49.     if (s_cycle_task) {
  50.         s_cycle_enabled = false;
  51.         vTaskDelay(pdMS_TO_TICKS(100));
  52.         s_cycle_task = NULL;
  53.     }
  54.     if (s_rainbow_task) {
  55.         snprintf(out, len, "彩虹灯已运行");
  56.         return ESP_OK;
  57.     }
  58.     ws2812_deinit();
  59.     s_rainbow_enabled = true;
  60.     BaseType_t ret = xTaskCreate(rainbow_task, "rainbow", 4096, NULL, 5, &s_rainbow_task);
  61.     if (ret == pdPASS) {
  62.         snprintf(out, len, "彩虹灯已启动");
  63.         return ESP_OK;
  64.     } else {
  65.         s_rainbow_enabled = false;
  66.         snprintf(out, len, "彩虹灯启动失败");
  67.         return ESP_FAIL;
  68.     }
  69. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

2.1.4 统一停止工具实现

  1. /**
  2. * @brief 停止所有动态灯效
  3. */
  4. static void stop_all_dynamic_effects(void)
  5. {
  6.     // 停止呼吸灯
  7.     if (s_breathing_task) {
  8.         s_breathing_enabled = false;
  9.         vTaskDelay(pdMS_TO_TICKS(100));
  10.         s_breathing_task = NULL;
  11.     }
  12.     // 停止循环红绿蓝
  13.     if (s_cycle_task) {
  14.         s_cycle_enabled = false;
  15.         vTaskDelay(pdMS_TO_TICKS(100));
  16.         s_cycle_task = NULL;
  17.     }
  18.     // 停止彩虹灯
  19.     if (s_rainbow_task) {
  20.         s_rainbow_enabled = false;
  21.         vTaskDelay(pdMS_TO_TICKS(100));
  22.         s_rainbow_task = NULL;
  23.     }
  24.     // 释放资源,熄灭 LED
  25.     ws2812_deinit();
  26.     ws2812_set(0, 0, 0);
  27. }
  28. /**
  29. * @brief 停止所有效果工具
  30. */
  31. static esp_err_t tool_stop_effect_execute(const char *in, char *out, size_t len)
  32. {
  33.     (void)in;
  34.     stop_all_dynamic_effects();
  35.     snprintf(out, len, "所有灯效已停止");
  36.     return ESP_OK;
  37. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

2.1.5 工具注册
在 tool_registry_init 函数中添加以下代码,完成工具注册:
  1. // 1. 注册循环红绿蓝工具
  2. mimi_tool_t cycle_tool = {
  3.     .name = "cycle_rgb",
  4.     .description = "启动红绿蓝循环灯效",
  5.     .input_schema_json = "{"type":"object","properties":{},"required":[]}",
  6.     .execute = tool_cycle_rgb_start_execute,
  7. };
  8. register_tool(&cycle_tool);
  9. // 2. 注册彩虹灯工具
  10. mimi_tool_t rainbow_tool = {
  11.     .name = "rainbow",
  12.     .description = "启动彩虹渐变灯效",
  13.     .input_schema_json = "{"type":"object","properties":{},"required":[]}",
  14.     .execute = tool_rainbow_start_execute,
  15. };
  16. register_tool(&rainbow_tool);
  17. // 3. 注册停止所有效果工具
  18. mimi_tool_t stop_tool = {
  19.     .name = "stop_effect",
  20.     .description = "停止所有动态灯效",
  21.     .input_schema_json = "{"type":"object","properties":{},"required":[]}",
  22.     .execute = tool_stop_effect_execute,
  23. };
  24. register_tool(&stop_tool);
复制代码





回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

2.2 指令硬匹配:agent_loop.c
打开 main/agent_loop.c,在 try_direct_command 函数中添加指令匹配规则,实现毫秒级响应:


  1. // ====================== 动态灯效指令匹配 ======================
  2. // 匹配:循环红绿蓝 / cycle rgb / 红绿蓝循环
  3. if (strstr(content, "循环红绿蓝") != NULL || strstr(content, "cycle rgb") != NULL ||
  4.     strstr(content, "红绿蓝循环") != NULL) {
  5.     tool_registry_execute("cycle_rgb", "{}", output, output_size);
  6.     return true;
  7. }
  8. // 匹配:彩虹灯 / 彩虹 / rainbow
  9. if (strstr(content, "彩虹灯") != NULL || strstr(content, "彩虹") != NULL ||
  10.     strstr(content, "rainbow") != NULL) {
  11.     tool_registry_execute("rainbow", "{}", output, output_size);
  12.     return true;
  13. }
  14. // 匹配:停止效果 / 停止所有效果 / stop effect
  15. if (strstr(content, "停止效果") != NULL || strstr(content, "停止所有效果") != NULL ||
  16.     strstr(content, "stop effect") != NULL) {
  17.     tool_registry_execute("stop_effect", "{}", output, output_size);
  18.     return true;
  19. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

本帖最后由 驴友花雕 于 2026-4-7 20:27 编辑

三、编译、烧录与测试

3.1 编译与烧录
执行以下命令完成清理、编译、烧录(替换为你的实际串口):

  1. idf.py fullclean
  2. idf.py build
  3. idf.py -p COM12 flash monitor
复制代码


3.2 串口手动测试
在 mimi> 命令行执行以下指令:


  1. mimi> tool_exec cycle_rgb "{}"      # 启动红绿蓝循环
  2. mimi> tool_exec rainbow "{}"        # 启动彩虹渐变
  3. mimi> tool_exec stop_effect "{}"    # 停止所有灯效
复制代码


3.3 飞书自然语言控制
直接在飞书发送以下指令,设备立即响应:

  1. 循环红绿蓝 → 启动三原色循环
  2. 彩虹灯 → 启动平滑彩虹渐变
  3. 停止效果 → 熄灭 LED,停止所有动态灯效
复制代码



回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

四、效果说明与注意事项

4.1 灯效效果
循环红绿蓝:LED 按红→绿→蓝顺序切换,每个颜色停留 1 秒,无限循环
彩虹灯:平滑遍历红→橙→黄→绿→青→蓝→紫,全程无断层,约 7 秒完成一圈

4.2 关键注意事项
任务互斥:启动任意动态灯效,会自动停止其他效果,杜绝硬件冲突
资源释放:停止灯效后自动调用 ws2812_deinit,释放 RMT 硬件资源
内存占用:单任务栈 4096 字节,ESP32-S3 充足,无内存压力
兼容性:不影响静态颜色指令(如红色、绿色),可自由切换

4.3 功能扩展建议
可调速度:新增参数配置,支持 cycle_rgb {"speed":500} 自定义切换速度
多灯珠扩展:适配 WS2812 灯带,实现流水灯、跑马灯效果
状态联动:将灯效与设备状态绑定(联网→蓝色呼吸、异常→红色闪烁)
音乐律动:结合麦克风,实现灯效随音量 / 节奏变化

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 2 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

五、实验场景图与记录视频


【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图5

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图6

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图7

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图9

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图8

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图10

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图1

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图4

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图3

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图2
回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 2 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

【【花雕动手做】ESP32-S3 + MimiClaw 实战:为板载 WS2812 添加循环红绿蓝与彩虹灯效果让你的嵌入式 AI Agent 拥有更丰富视觉反馈】

https://www.bilibili.com/video/BV1b5DeBBEUm/?share_source=copy_web&vd_source=371a292a55e5ca9be994cbb4a86cc987






回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 2 小时前

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果

六、总结

本实战基于 ESP32-S3 + MimiClaw 框架,通过 FreeRTOS 任务实现了两种高性能 WS2812 动态灯效:
轻量化设计:无额外硬件,纯软件扩展,资源占用极低
极致响应:指令硬匹配绕过 LLM,控制延迟<10ms
稳定可靠:任务互斥 + 资源自动释放,长期运行无冲突
易于扩展:代码模块化,可快速新增更多灯效
完成开发后,你的嵌入式 AI Agent 不仅能听懂指令,更能通过炫酷灯效实现可视化交互,大幅提升产品体验。

附录
所属系列:花雕学编程・花雕动手做・MimiClaw 嵌入式实战
代码仓库:MimiClaw GitHub 官方仓库 https://github.com/memovai/mimiclaw
官方文档:https://mimiclaw.io
适配平台:ESP32-S3 全系列开发板

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图1

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图3

【花雕】MimiClaw实战:WS2812 添加循环红绿蓝与彩虹灯效果图2

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2026 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail