【花雕动手做】嵌入式 AI Agent 实战:MimiClaw ESP32-S3 接入飞书,远程控制板载 RGB 全彩灯效

2026-04-06112
AI 快速预览详细 收起
本文介绍了如何使用MimiClaw框架在ESP32-S3上实现通过飞书机器人远程控制板载RGB全彩灯效。文章详细讲解了从源码修改到飞书配置的全过程,重点解决了LLM对颜色指令识别不稳定的问题。通过预处理匹配方案,实现了毫秒级固定指令响应。此外,还提供了扩展方向,如增加更多颜色选项、支持亮度调节、接入传感器联动等,丰富了嵌入式AI Agent的应用场景。

原标题
《【花雕动手做】嵌入式 AI Agent 实战:MimiClaw ESP32-S3 接入飞书,远程控制板载 RGB 全彩灯效》
——从源码修改到飞书指令,手把手打造一个能“听懂颜色话”的嵌入式 AI 智能体

00-1.jpg

二、MimiClaw 项目简介

MimiClaw 是一款专为 ESP32-S3 设计的轻量级 AI 代理框架,兼顾性能与易用性,核心特点如下:

- 纯 C 语言实现:基于 ESP-IDF 5.5 开发,无 Linux、Node.js 依赖,MCU 工程师可快速上手,贴合嵌入式开发习惯。

- 双核协同架构:ESP32-S3 双核分工明确,Core 0 专门负责网络 I/O 交互,Core 1 专注运行 AI 推理,通过 FreeRTOS 任务调度实现软实时响应,兼顾流畅度与稳定性。

- 本地记忆持久化:对话历史、用户偏好等数据自动写入 Flash(对应 SOUL.md、USER.md、MEMORY.md 文件),断电重启后记忆不丢失,实现“持续学习”的体验。

- 多 LLM 灵活切换:支持 Anthropic Claude、OpenAI、DeepSeek 等主流大语言模型,可根据需求切换,适配不同场景的推理需求。

- 灵活的工具调用系统:内置网页搜索、定时任务、GPIO 控制等基础工具,开发者只需添加几行 C 代码,即可扩展自定义工具,实现更多硬件操控或功能扩展。

硬件适配方面,MimiClaw 要求 ESP32-S3 开发板具备 16MB Flash 和 8MB PSRAM,市面上常见的 LILYGO T7-S3、FireBeetle 2、Seeed XIAO ESP32S3 Plus 等型号均可兼容。本文采用国产 ESP32-S3 核心板,板载 WS2812 彩灯默认连接至 GPIO 48 引脚,无需额外接线即可直接使用。

三、硬件与环境准备

1、硬件清单

01.jpg

注意:本文无需额外外接 LED 灯,开发板板载的 WS2812 彩灯可直接用于测试和使用。

04-.jpg


2、开发环境搭建

开发环境核心为 ESP-IDF 框架,具体搭建步骤如下:

(1)安装 ESP-IDF v5.5 或更高版本,确保框架支持 ESP32-S3 芯片(安装教程可参考 ESP 官方文档,Windows、macOS、Linux 系统均支持)。

(2)克隆 MimiClaw 源码到本地,打开终端执行以下命令:
git clone https://github.com/memovai/mimiclaw.git
cd mimiclaw

(3)设置开发目标芯片为 ESP32-S3,终端执行:idf.py set-target esp32s3

环境搭建完成后,可通过 idf.py --version 命令验证 ESP-IDF 版本,确保环境正常。


3、飞书机器人创建与配置

MimiClaw 通过飞书机器人接收指令、反馈结果,需先在飞书开放平台创建企业自建应用并完成配置,全程无需公网 IP,操作如下:

(1)创建企业自建应用

a 访问 飞书开放平台,使用飞书账号登录(个人账号即可,无需企业认证)。

b 点击页面右上角“创建企业自建应用”,填写应用名称(如“MimiClaw RGB Controller”),选择应用类型为“工具类”,点击“创建”。

c 进入应用管理页面后,在左侧菜单「凭证与基础信息」中,复制「App ID」(格式为 cli_xxx)和「App Secret」,妥善保存(后续配置 MimiClaw 需用到)。

(2)添加机器人能力并配置权限

a 在应用管理左侧菜单,点击「添加应用能力」,在弹出的列表中找到「机器人」,点击「配置」,启用机器人能力。

b 启用后,进入「权限管理」页面,搜索并添加以下 4 个核心权限(缺一不可):

- im:message:允许机器人发送消息

- im:message.p2p_msg:readonly:允许机器人接收私聊消息

- im:message:send_as_bot:允许机器人以自身身份回复消息

- contact:user.base:readonly:允许机器人读取用户基础信息

c 添加完成后,点击「权限管理」页面的「申请开通」,无需审核,立即生效。

(3)配置事件订阅(长连接模式)

为让嵌入式设备(ESP32-S3)能稳定接收飞书消息,采用长连接(WebSocket)模式订阅事件,无需公网 IP,配置步骤如下:

a 在应用管理左侧菜单,点击「事件与回调」。

b 订阅方式选择「使用长连接接收事件」,点击「保存」(无需填写回调地址)。

c 点击「添加事件」,在搜索框中输入「im.message.receive_v1」,勾选该事件(接收消息事件),点击「确认添加」,完成事件订阅。

长连接模式通过 WebSocket 全双工通道接收飞书回调,延迟低、稳定性高,非常适合嵌入式设备的网络场景。

(4)发布应用并添加机器人

a 在应用管理左侧菜单,点击「版本管理与发布」,点击「创建版本」,填写版本号(如 1.0.0),简要填写更新说明(如“初始版本,支持 RGB 彩灯控制”),提交审核。

b 个人账号创建的应用无需人工审核,提交后立即发布成功。

c 打开飞书客户端,在搜索框中输入创建的机器人名称,找到对应机器人后,点击「添加到聊天」,完成机器人添加。

d MimiClaw 源码修改:添加 WS2812 控制工具

4、MimiClaw 自带工具调用系统,我们只需在源码中添加 WS2812 彩灯驱动、注册颜色控制工具,并优化 LLM 指令识别逻辑,即可实现飞书指令控制彩灯。核心修改文件为 tools/tool_registry.c 和 agent_loop.c。

(1)在 tool_registry.c 中添加 WS2812 驱动与颜色工具

打开 tools/tool_registry.c 文件,在文件顶部添加 WS2812 驱动相关代码(使用 ESP-IDF 官方 led_strip 组件,无需手动编写时序,稳定可靠):

代码
// ====================== WS2812 驱动配置 ======================
#include "driver/led_strip.h"  // 引入官方 led_strip 组件

#define WS2812_GPIO 48        // 板载 WS2812 连接的 GPIO 引脚
static led_strip_handle_t s_led_strip = NULL;  // LED 驱动句柄

// WS2812 初始化函数
static esp_err_t ws2812_init(void)
{
    if (s_led_strip != NULL) return ESP_OK;  // 避免重复初始化

    // LED 灯带配置
    led_strip_config_t strip_cfg = {
        .strip_gpio_num = WS2812_GPIO,    // 连接的 GPIO 引脚
        .max_leds = 1,                    // 灯珠数量(板载为 1 个)
        .led_model = LED_MODEL_WS2812,    // 灯珠型号为 WS2812
        .color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB,  // WS2812 颜色格式为 GRB
    };

    // RMT 外设配置(驱动 WS2812 需用到 RMT 外设)
    led_strip_rmt_config_t rmt_cfg = {
        .clk_src = RMT_CLK_SRC_DEFAULT,   // 默认时钟源
        .resolution_hz = 10 * 1000 * 1000,// 分辨率 10MHz
        .flags.with_dma = false,          // 无需 DMA(单灯珠无需高速传输)
    };

    // 创建 RMT 驱动的 LED 设备
    led_strip_new_rmt_device(&strip_cfg, &rmt_cfg, &s_led_strip);
    led_strip_clear(s_led_strip);  // 初始化后熄灭彩灯
    return ESP_OK;
}

// WS2812 颜色设置函数(r: 红色, g: 绿色, b: 蓝色,取值 0-255)
static esp_err_t ws2812_set(uint8_t r, uint8_t g, uint8_t b)
{
    ws2812_init();  // 确保驱动已初始化
    led_strip_set_pixel(s_led_strip, 0, r, g, b);  // 设置第 0 个灯珠颜色
    led_strip_refresh(s_led_strip);  // 刷新显示,使颜色生效
    return ESP_OK;
}

// 颜色控制工具执行函数(red 红灯)
static esp_err_t tool_red_execute(const char *in, char *out, size_t len) {
    ws2812_set(255, 0, 0);  // 红色:R=255, G=0, B=0
    snprintf(out, len, "Red ON");  // 工具执行结果反馈
    return ESP_OK;
}

// 颜色控制工具执行函数(green 绿灯)
static esp_err_t tool_green_execute(const char *in, char *out, size_t len) {
    ws2812_set(0, 255, 0);  // 绿色:R=0, G=255, B=0
    snprintf(out, len, "Green ON");
    return ESP_OK;
}

// 颜色控制工具执行函数(blue 蓝灯)
static esp_err_t tool_blue_execute(const char *in, char *out, size_t len) {
    ws2812_set(0, 0, 255);  // 蓝色:R=0, G=0, B=255
    snprintf(out, len, "Blue ON");
    return ESP_OK;
}

// 颜色控制工具执行函数(yellow 暖黄灯)
static esp_err_t tool_yellow_execute(const char *in, char *out, size_t len) {
    ws2812_set(255, 150, 0);  // 暖黄色:R=255, G=150, B=0(避免纯黄刺眼)
    snprintf(out, len, "Yellow ON");
    return ESP_OK;
}

// 颜色控制工具执行函数(off 熄灭)
static esp_err_t tool_off_execute(const char *in, char *out, size_t len) {
    ws2812_set(0, 0, 0);  // 熄灭:R=0, G=0, B=0
    snprintf(out, len, "Light OFF");
    return ESP_OK;
}

(2)注册颜色控制工具

在 tool_registry.c 文件的 tool_registry_init 函数中,添加颜色工具的注册代码(与其他工具注册逻辑一致),确保 MimiClaw 能识别并调用这些工具:

代码
// 注册 RGB 颜色控制工具(同名简单工具,提高 LLM 调用成功率)
mimi_tool_t red_tool = {
    .name = "red",
    .description = "Turn on the red LED immediately. Use when user says 'red'.",
    .input_schema_json = "{\"type\":\"object\",\"properties\":{},\"required\":[]}",  // 无输入参数
    .execute = tool_red_execute,  // 绑定执行函数
};
register_tool(&red_tool);  // 注册工具

mimi_tool_t green_tool = {
    .name = "green",
    .description = "Turn on the green LED immediately. Use when user says 'green'.",
    .input_schema_json = "{\"type\":\"object\",\"properties\":{},\"required\":[]}",
    .execute = tool_green_execute,
};
register_tool(&green_tool);

mimi_tool_t blue_tool = {
    .name = "blue",
    .description = "Turn on the blue LED immediately. Use when user says 'blue'.",
    .input_schema_json = "{\"type\":\"object\",\"properties\":{},\"required\":[]}",
    .execute = tool_blue_execute,
};
register_tool(&blue_tool);

mimi_tool_t yellow_tool = {
    .name = "yellow",
    .description = "Turn on the yellow LED immediately. Use when user says 'yellow'.",
    .input_schema_json = "{\"type\":\"object\",\"properties\":{},\"required\":[]}",
    .execute = tool_yellow_execute,
};
register_tool(&yellow_tool);

mimi_tool_t off_tool = {
    .name = "off",
    .description = "Turn off the LED immediately. Use when user says 'off'.",
    .input_schema_json = "{\"type\":\"object\",\"properties\":{},\"required\":[]}",
    .execute = tool_off_execute,
};
register_tool(&off_tool);

(3)优化 LLM 指令识别:预处理绕过 LLM 直接匹配颜色词

实测发现,DeepSeek 等 LLM 对 red、green、blue 等简单颜色词的识别并不稳定——有时 red 能正确触发工具调用,green 却被当作普通对话处理,导致彩灯无响应。为解决这一问题,我们在 LLM 调用前增加一层预处理逻辑:精确匹配用户消息中的颜色词,直接调用对应工具并回复,完全跳过 LLM,实现毫秒级响应。

打开 agent_loop.c 文件,添加预处理函数,并在消息处理逻辑中调用:

代码
// 颜色指令预处理函数:匹配颜色词,直接执行工具,跳过 LLM
static bool try_direct_color_command(const char *content, char *output, size_t output_size)
{
    // 去除消息前后空白字符(避免用户输入空格导致匹配失败)
    while (*content == ' ' || *content == '\t' || *content == '\n') content++;
    const char *end = content + strlen(content);
    while (end > content && (*(end-1) == ' ' || *(end-1) == '\t' || *(end-1) == '\n')) end--;
    size_t len = end - content;

    // 精确匹配颜色词,触发对应工具
    if (len == 3 && strncasecmp(content, "red", 3) == 0) {
        tool_registry_execute("red", "{}", output, output_size);
        return true;
    }
    if (len == 5 && strncasecmp(content, "green", 5) == 0) {
        tool_registry_execute("green", "{}", output, output_size);
        return true;
    }
    if (len == 4 && strncasecmp(content, "blue", 4) == 0) {
        tool_registry_execute("blue", "{}", output, output_size);
        return true;
    }
    if (len == 6 && strncasecmp(content, "yellow", 6) == 0) {
        tool_registry_execute("yellow", "{}", output, output_size);
        return true;
    }
    if (len == 3 && strncasecmp(content, "off", 3) == 0) {
        tool_registry_execute("off", "{}", output, output_size);
        return true;
    }

    return false;  // 不匹配颜色词,走正常 LLM 流程
}

// 在 agent_loop_task 函数的消息处理开头,添加预处理调用
void agent_loop_task(void *arg)
{
    // ... 原有代码省略 ...

    while (1) {
        mimi_msg_t msg;
        if (message_bus_pop_inbound(&msg, portMAX_DELAY) != ESP_OK) continue;

        // 新增:颜色指令预处理,匹配则直接执行工具
        char direct_response[128];
        if (try_direct_color_command(msg.content, direct_response, sizeof(direct_response))) {
            ESP_LOGI(TAG, "Direct color command matched, executing tool and responding");
            // 直接回复工具执行结果,跳过 LLM 调用
            mimi_msg_t out = {0};
            strncpy(out.channel, msg.channel, sizeof(out.channel)-1);
            strncpy(out.chat_id, msg.chat_id, sizeof(out.chat_id)-1);
            out.content = strdup(direct_response);
            message_bus_push_outbound(&out);
            free(msg.content);
            continue;
        }

        // ... 原有 LLM 调用、消息处理逻辑不变 ...
    }
}

核心价值:通过预处理逻辑,red、green、blue、yellow、off 五个基础颜色指令实现毫秒级响应,且完全不受 LLM 状态影响;其他复杂对话(如“亮一盏暖一点的灯”)仍走 LLM 流程,实现“快速指令 + 智能对话”的分层设计,兼顾效率与灵活性。

5、编译烧录与串口配置

(1)编译烧录固件

源码修改完成后,执行以下mimi>命令编译、烧录固件(确保开发板通过 USB 连接电脑):

代码
# 清除之前的编译缓存(可选,避免旧代码影响)
idf.py fullclean

# 编译固件
idf.py build

# 烧录固件并打开串口监视器(替换 COM7 为实际串口号)
idf.py -p COM7 flash monitor

串口号查询方法:Windows 系统可通过“设备管理器”查看“端口(COM 和 LPT)”,macOS 系统可通过 ls /dev/tty.usb* 命令查询,Linux 系统可通过 ls /dev/ttyUSB* 查询。

(2)串口终端选择与参数配置

MimiClaw 的 CLI(命令行界面)需要支持 ANSI 转义序列,才能正常使用行编辑、Tab 补全、颜色显示等功能,推荐使用以下终端工具:

- Windows:Windows Terminal(推荐)、PuTTY

- macOS/Linux:系统自带终端、iTerm2

避免使用 IDE 自带的简易串口监视器(如 VS Code 串口插件),可能导致 CLI 显示异常。

串口参数固定如下,无需修改:

波特率:115200,数据位:8,停止位:1,校验位:无,流控:无。

(3)烧录后基础配置

固件烧录完成后,开发板会自动重启,此时需通过串口配置 WiFi、LLM 密钥和飞书凭证,让 MimiClaw 正常联网并接入飞书,步骤如下(在串口终端中输入命令):

代码
# 配置 WiFi(替换为你的 WiFi 名称和密码)
mimi> set_wifi 你的SSID 你的WiFi密码

# 查看 WiFi 连接状态,确认获取 IP 地址(显示 connected 即为成功)
mimi> wifi_status

# 配置 LLM API Key(以 DeepSeek 为例,替换为你的 API Key)
mimi> set_api_key sk-xxxxxxx

# 配置 LLM 模型和提供商(DeepSeek 模型需指定 provider 为 openai 兼容模式)
mimi> set_model deepseek-chat
mimi> set_model_provider openai

# 配置飞书凭证(替换为之前保存的 App ID 和 App Secret)
mimi> set_feishu_creds 你的AppID 你的AppSecret

# 重启 MimiClaw,使配置生效
mimi> restart

重启后,串口终端会显示“Feishu connected”,说明飞书机器人连接成功;显示“WiFi connected, IP: xxx.xxx.xxx.xxx”,说明网络连接正常。

6、测试与效果验证

配置完成后,即可在飞书中发送颜色指令,测试彩灯控制效果。以下为详细测试用例,结合串口日志验证执行结果:

(1)测试用例与预期效果

02.jpg

(2)实际运行日志示例

以下为飞书发送“red”指令后的完整串口日志,可清晰看到指令执行链路:

代码
I (138484) feishu: Message from ou_1f6ce18f5c5d222d9fa9a1719b359ee2: red
I (138484) agent: Processing message from feishu:ou_1f6ce18f5c5d222d9fa9a1719b359ee2
I (138484) tools: Executing tool: red
I (138484) tools: WS2812 initialized on GPIO 48
I (138484) tools: Tool red returned: OK
I (138484) agent: Direct color command matched, executing tool and responding
I (139414) feishu: Got tenant access token (expires in 5323s)
I (140744) feishu: Sent to ou_1f6ce18f5c5d222d9fa9a1719b359ee2 (10 bytes)
I (140744) mimi: Feishu send success for ou_1f6ce18f5c5d222d9fa9a1719b359ee2 (10 bytes)

日志解析:飞书接收消息 → Agent 处理消息 → 预处理匹配颜色词 → 执行 red 工具 → 初始化 WS2812 → 工具执行成功 → 飞书回复结果。整个流程延迟 < 0.5 秒,稳定可靠。

7、实验场景记录图

(1)手机飞书截图

03 (7).jpg

(2)ESP32S3开发板,板载48脚RGB情况

03 (2).jpg
03 (3).jpg
03 (4).jpg
03 (5).jpg
03 (6).jpg

8、关键技术要点总结

- WS2812 驱动优化:采用 ESP-IDF 官方 led_strip 组件,基于 RMT 外设驱动,无需手写复杂时序,只需配置 GPIO 引脚和灯珠参数,即可实现稳定控制,降低开发难度。

- 飞书长连接优势:嵌入式设备无需公网 IP,通过 WebSocket 长连接接收飞书消息,延迟低、稳定性高,适合个人开发和内网部署,无需额外配置服务器。

- 预处理绕过 LLM 创新点:针对固定颜色指令,在 LLM 调用前增加精确匹配逻辑,彻底解决模型对简单词汇识别不一致的问题,实现毫秒级响应,同时不影响复杂对话的智能性。

- 工具注册机制:MimiClaw 通过 tool_registry 统一管理所有工具,新增硬件控制功能时,只需在 tool_registry.c 中注册工具和执行函数,无需修改核心 Agent 逻辑,扩展性极强。

9、 扩展方向

本文实现了基础的颜色控制功能,基于此可扩展更多实用功能,丰富嵌入式 AI Agent 的应用场景:

(1)增加更多颜色选项:在 tool_registry.c 中添加 purple(紫色)、cyan(青色)、white(白色)等颜色工具,并在预处理函数中增加对应匹配,支持更多灯效。

(2)支持亮度调节:扩展 set_rgb 工具,接收亮度参数(0-255),让 LLM 解析“亮一点”“暗一点”等模糊指令,实现更细腻的灯效控制。

(3)接入传感器联动:添加温湿度传感器(如 DHT11)、光照传感器,让 MimiClaw 自动根据环境条件改变灯色(如高温亮红灯、低光照亮暖黄灯)。

(4)定时任务控制:通过飞书发送“每天 19:00 亮暖黄灯”“每天 23:00 关灯”等指令,调用 MimiClaw 内置的 cron_add 工具,实现定时控制。

(5)多灯组控制:修改 WS2812 驱动的 max_leds 参数,接入 LED 灯带,实现多灯珠级联控制,支持流水灯、呼吸灯等复杂灯效。


10、结语

本文完整记录了从 MimiClaw 基础部署、飞书机器人配置,到源码修改、固件烧录,再到飞书远程控制 WS2812 彩灯的全过程,重点解决了 LLM 对颜色指令识别不稳定的核心问题,通过预处理匹配方案,实现了“毫秒级固定指令 + 智能复杂对话”的分层架构。

在“养龙虾”热潮下,嵌入式 AI Agent 正从极客玩具走向真正的实用工具——它无需强大的硬件支撑,只需一块廉价的 ESP32-S3 开发板,就能实现“语音/文字指令 → 硬件响应”的完整闭环。

如果你也想拥有一块能听懂颜色指令、能互动、能干活的嵌入式 AI 助理,不妨从本文开始动手实践,逐步探索嵌入式 AI Agent 的更多可能性。

00 (1).jpg

补充:

手机飞书截图

 

06 (2).jpg

 

MimiClaw 记录日志

 

05.jpg
 

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(0)
- 没有更多了 -