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

[项目] 给小智AI装上“手脚”:掌控板语音控制灯带与电机实战

[复制链接]
本帖最后由 云天 于 2026-3-2 21:52 编辑

让小智AI不仅能听会说,还能控制灯带和电机,打造真正的智能硬件终端

【项目缘起】

       小智AI 是一款开源的端侧语音助手项目,基于 ESP32 实现,支持唤醒词、语音识别、大模型对话等功能。它的代码结构清晰,硬件抽象层完善,非常适合作为智能硬件的“大脑”。而掌控板作为国内创客教育常用的主控板,集成了 OLED 屏幕、按键、I2C 接口等资源,性价比极高。如果能将小智AI 移植到掌控板上,并扩展出控制灯带、电机的能力,就能打造出一个既能语音交互又能驱动外设的智能终端。

       经过一段时间的折腾,我成功将小智AI v2.0.5 移植到了掌控板 1.0 和 2.0 上,并通过 MCP(Model Context Protocol)工具让 AI 可以直接控制 WS2812 灯带和直流电机。这篇文章将分享完整的改造过程,希望给同样想折腾的朋友一些启发。

【准备工作】

       硬件清单
       掌控板 2.0(或 1.0) ×1  
       WS2812 灯带(12/24 灯珠) ×1  
       行空板 K10 IO 扩展板(用于驱动灯带) ×1  
       micro:bit 掌控 IO 扩展板(用于驱动电机,兼容行空板 M10/K10) ×1  
       直流电机 ×2  
       杜邦线、面包板、5V 电源(电机供电)

       软件环境
       操作系统:Windows 10/11
       ESP-IDF v5.5.1(官方推荐)
       小智AI 开源代码(版本 2.0.5,从 [GitHub](https://github.com/78/xiaozhi-esp32) 克隆)
       Git等工具

【移植核心步骤】

       适配掌控板引脚配置

       小智AI 的板级文件位于 `main/boards/` 目录下,我们以 `bread-compact-esp32` 为模板,修改 `config.h` 中的引脚定义,匹配掌控板的硬件连接:

       麦克风 I2S:使用 P8/P9/P13(对应 GPIO26/25/18)
       扬声器 I2S:使用 P14/P15/P16(对应 GPIO19/21/5)
       OLED 屏幕(sh1106,128x64):I2C 引脚 SDA=GPIO23,SCL=GPIO22
       按键:A 键=GPIO0(BOOT),B 键=GPIO2
       WS2812 灯带:GPIO33
       电机驱动 I2C:复用 OLED 的 I2C 总线(地址 0x10)

       关键配置如下(已省略无关项):

  1. // config.h
  2. #define AUDIO_I2S_MIC_GPIO_WS   GPIO_NUM_25
  3. #define AUDIO_I2S_MIC_GPIO_SCK  GPIO_NUM_26
  4. #define AUDIO_I2S_MIC_GPIO_DIN  GPIO_NUM_18
  5. #define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_19
  6. #define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_21
  7. #define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_5
  8. #define BOOT_BUTTON_GPIO        GPIO_NUM_0   // A键
  9. #define ASR_BUTTON_GPIO         GPIO_NUM_2   // B键
  10. #define DISPLAY_SDA_PIN GPIO_NUM_23
  11. #define DISPLAY_SCL_PIN GPIO_NUM_22
  12. // 禁用 ML307 4G 模块(掌控板没有该硬件)
  13. #define ML307_RX_PIN            GPIO_NUM_NC
  14. #define ML307_TX_PIN            GPIO_NUM_NC
  15. // 灯带引脚
  16. // 注意:circular_strip.h 中会使用此GPIO 33引脚,但在 mcp_server.cc 中直接写死了 33
  17. // 可自行统一到 config.h
复制代码


       禁用 4G 模块,默认 WiFi

       原项目默认启用了 ML307 4G 模块,我们将其引脚设为 `GPIO_NUM_NC`,并在 `dual_network_board.h` 中将默认网络类型改为 WiFi(`default_net_type = 0`),避免程序启动时卡在检测 4G 模块。

       板级文件修改

       `esp32_bread_board.cc` 是掌控板的主板类,我们需要:
       初始化 I2C 总线(用于 OLED 和电机驱动)
       重写 `GetI2CBus()` 虚函数,供 MCP Server 获取总线句柄
       注释掉原有的 `LampController`(本例未使用)
       适配 SH1106 屏幕:掌控板的 OLED 控制器为 SH1106,与常见的 SSD1306 略有不同。因此,在显示初始化部分需要包含头文件 <esp_lcd_panel_sh1106.h>,并调用 esp_lcd_new_panel_sh1106() 而不是 esp_lcd_new_panel_ssd1306()。原代码中已正确修改。
       关键代码:
  1. #include <esp_lcd_panel_sh1106.h>
  2. class CompactWifiBoard : public DualNetworkBoard {
  3.     // ...
  4. public:
  5.     virtual i2c_master_bus_handle_t GetI2CBus() const override {
  6.         return display_i2c_bus_;   // 返回 OLED 的 I2C 总线
  7.     }
  8. };
复制代码

       添加 WS2812 灯带驱动与 MCP 工具

       我们使用 `circular_strip.h` 封装好的灯带驱动,在 `mcp_server.cc` 的 `AddCommonTools()` 函数中创建静态对象并注册工具:

  1. #include "led/circular_strip.h"
  2. void McpServer::AddCommonTools() {
  3. // ... 其他工具 ...
  4. static CircularStrip s_led_strip(static_cast<gpio_num_t>(33), 12);  // GPIO33, 12灯珠
  5. AddTool("self.led_strip.set_all", "设置所有灯珠颜色",
  6. PropertyList({Property("red", kPropertyTypeInteger,0,255), ...}),
  7. [](const PropertyList& p) -> ReturnValue {
  8. s_led_strip.SetAllColor({/* 颜色 */});
  9. return true;
  10. });
  11. // 还支持 set_single, blink, breathe, scroll 等效果
  12. }
复制代码

       这样 AI 就能通过调用 `self.led_strip.set_all` 等工具控制灯带。

       添加电机驱动与 MCP 工具

       电机驱动板通过 I2C 控制(地址 0x10),原 DF的Arduino 库提供了 `IOBOX_Motor` 类,我们将其移植为 ESP-IDF 风格的 `IOBoxMotor` 类,使用 ESP-IDF 的 I2C 驱动。

       "io_box_motor.h":

  1. #include "driver/i2c_master.h"
  2. class IOBoxMotor {
  3. public:
  4. IOBoxMotor(i2c_master_bus_handle_t bus_handle);
  5. void runMotor(int index, int direction, int speed);
  6. void stopMotor(int index);
  7. static const int M1 = 0, M2 = 1, ALL = 2;
  8. };
复制代码

       "io_box_motor.cpp" 中实现 I2C 通信,发送三字节命令:`[cmd, dir, speed]`,其中 cmd 为 0x00(M1)或 0x02(M2)。

       然后在 `mcp_server.cc` 中,通过 `board.GetI2CBus()` 获取总线,创建电机对象并注册工具:

  1. i2c_master_bus_handle_t i2c_bus = board.GetI2CBus();
  2. if (i2c_bus != nullptr) {
  3. static IOBoxMotor s_motor(i2c_bus);
  4. AddTool("self.motor.run", "运行电机",
  5. PropertyList({
  6. Property("index", kPropertyTypeString),
  7. Property("direction", kPropertyTypeInteger,0,1),
  8. Property("speed", kPropertyTypeInteger,0,255)
  9. }),
  10. [&s_motor](const PropertyList& p) -> ReturnValue {
  11. // 解析参数并调用 s_motor.runMotor
  12. return true;
  13. });
  14. AddTool("self.motor.stop", "停止电机", ...);
  15. }
复制代码

       修改 CMakeLists.txt和 board.h

       在 `main/CMakeLists.txt` 中添加 `circular_strip.cpp` 和 `io_box_motor.cpp` 到源文件列表,并依赖 `driver` 和 `led_strip` 组件。
       修改 `board.h`,添加虚函数 `virtual i2c_master_bus_handle_t GetI2CBus() const { return nullptr; }`,并包含 `<driver/i2c_master.h>`。

【实际演示】

       场景一:语音控制灯带

       硬件连接:将 WS2812 灯带的数据线接掌控板 GPIO33,电源和地接 5V 电源(共地)。使用行空板 K10 IO 扩展板接线。
给小智AI装上“手脚”:掌控板语音控制灯带与电机实战图1

给小智AI装上“手脚”:掌控板语音控制灯带与电机实战图2
       唤醒小智 AI 后,说:“打开灯带,红色,亮度 50%”。AI 理解后调用 `self.led_strip.set_all` 工具,灯带瞬间亮起红光。还可以说“流水灯模式”触发滚动效果,或者“呼吸灯,从蓝色到紫色”触发呼吸效果。
给小智AI装上“手脚”:掌控板语音控制灯带与电机实战图3
       演示视频

       场景二:语音控制电机

       硬件连接:将掌控板插在"micro:bit 掌控 IO 扩展板"上,电机接 M1+/M1- 和 M2+/M2-,另需给电机独立供电(如 5V 电池)。注意 I2C 地址必须为 0x10(扩展板默认)。
       对小智说:“**M1 电机正转,速度 200**”,电机立即转动。说“**停止所有电机**”,电机停止。如果接上轮子,就可以语音控制小车前进后退。
给小智AI装上“手脚”:掌控板语音控制灯带与电机实战图4

给小智AI装上“手脚”:掌控板语音控制灯带与电机实战图5
       演示视频
       注意:电机驱动需要足够功率,供电不足会导致 I2C 通信失败(出现 NACK 错误)。我一开始就遇到了这个问题,给电机单独供电后解决。

【遇到的问题与解决】

       ESP-IDF 版本过低:最新小智AI开源代码2.2.2要求 ESP-IDF≥5.5.2,我本地的 5.5.1 报错,所以我用的智AI开源代码是2.0.5后解决。
       ML307 模块初始化卡死:将默认网络改为 WiFi,并禁用引脚。
       全局静态对象导致崩溃:灯带对象如果在全局构造,会在驱动未初始化时访问硬件,导致 Guru Meditation 错误。改为函数内静态局部变量后正常。
       I2C NACK 错误:起初电机驱动无响应,检查发现是供电不足。给电机驱动板单独供电后问题消失。

【总结与展望】

       通过这次移植,我深刻体会到小智AI 框架的灵活性。它的 MCP 机制让添加新硬件变得异常简单——只需实现硬件驱动,然后在 MCP Server 中注册工具,AI 就能像调用函数一样控制外设。掌控板作为主控,性能足够、接口丰富,非常适合做语音交互的载体。

       未来,我计划继续扩展更多传感器和执行器,比如舵机、温湿度传感器、摄像头等,让小智AI 能感知环境并做出更复杂的动作。也希望这篇文章能抛砖引玉,让更多人玩转小智AI,创造出有趣的智能硬件项目。

【项目附件】
       修改后的核心代码文件(config.h、esp32_bread_board.cc、mcp_server.cc、io_box_motor.h/cpp、dual_network_board.h、board.h、CMakeLists.txt)已打包,可下载。

下载附件main.zip




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

本版积分规则

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

硬件清单

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

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

mail