← 返回文章库

语音+动作:把小智变成会动的桌面机器人

最后更新 2026-06-20
⏱ 约 14 分钟 🟡 涉接线/强电
你将学到
  • 看懂小智「听-说」语音链路之外,动作是怎么被大模型当成工具调起来的
  • 在小智的 MCP 工具集里注册 move()/turn()/wave() 这类硬件动作函数(参考实现,端到端见旗舰项目)
  • 分清桌面转头版和移动小车版两种产品形态的取舍
  • 认清动作-语音时序、供电、机械三大坑,提前避雷
⎇ 基于开源项目(学习解读,非搬运)
作者:虾哥(78)
协议:MIT

本文讲解原理与流程、引用关键片段并注明出处,版权归原作者,遵循其开源协议;一切以上游仓库最新版本为准。

小智会聊天了。你对着它说话,它唤醒、识别、回答,声音从喇叭里出来,像个能对话的桌面音箱。聊了几天,一个念头冒出来:它什么时候能?我说「转过来看我」,它的脑袋真的转过来;我说「过来一下」,它真的滚到我手边。

这一篇就是把小智从「会说」推到「会动」的那一步。它是卷 R 和小智旗舰项目的交汇点——小智的语音大脑已经在那儿了,我们要做的是给它接上手脚。

开始前,两条前置链你最好先过一遍:小智旗舰项目总览 讲清楚小智的整体硬件和语音链路是怎么搭起来的;机器人的「大脑」:让 LLM 驱动动作 讲了大模型怎么通过 Agent 范式调用动作工具。本篇就是把那套范式具体落到小智这个开源项目上

本篇基于开源项目 78/xiaozhi-esp32(虾哥 78,MIT 协议)的学习解读。讲的是原理和接入思路,不是整体搬运代码。具体接口、字段、版本以上游仓库为准。

小智现在会什么,缺什么

先把小智的语音链路摆清楚。它已经跑通的是这么一条路:

唤醒词 → ASR(语音转文字) → LLM(大模型理解+决策) → TTS(文字转语音) → 喇叭

你说的每句话都走完这条链。语音链路 ASR/TTS 怎么搭 里讲过这套链路的工程细节,这里不重复。关键是:LLM 这一环,本来就有「决策」能力。它不只是把你的话翻译成回答,它能根据你说的内容决定「该做什么」。

现在 LLM 决定的只有一件事——说什么。它的输出是一段文字,最后变成声音。

加动作,本质上是给 LLM 多一个选项:除了「说」,还能「做」。你说「转过来」,LLM 不该只回一句「好的我转过来啦」然后纹丝不动,它该真的去调一个让舵机转动的函数。

这就是 Function CallingMCP 派上用场的地方。小智本身已经支持 MCP——你可以给它注册一批「工具」,LLM 在对话里判断什么时候该调哪个工具。控制灯、查天气是工具,控制电机和舵机,一样是工具。区别只在于,这些工具的底层是去驱动硬件,而不是查一个 API。

技术路线:把动作注册成工具

思路定了,落地就清楚了。给小智加动作,不是去改它的语音引擎,而是在它的 MCP 工具集里多注册几个硬件动作函数

下面是一段示意,说明「动作工具」长什么样。这是为了讲清楚结构的参考实现,不是可直接编译的完整代码——小智的 MCP 工具注册接口、参数命名、版本差异,一律以 上游仓库 为准;端到端能跑的整套工程,见 小智旗舰项目总览

// 示意:在小智的 MCP 工具集里注册三个动作工具
// 真实接口签名以 78/xiaozhi-esp32 上游为准

// 1. 转头:参数是角度,正值左转、负值右转
RegisterTool("turn",
  "把头/身体转向某个角度,单位度,正左负右",
  [](int degrees) {
    servo_head.setAngle(clamp(degrees, -90, 90));  // 舵机驱动复用现成轮子
    return "已转向 " + std::to_string(degrees) + " 度";
  });

// 2. 前进:参数是距离,移动版才挂这个工具
RegisterTool("move",
  "向前移动一段距离,单位厘米",
  [](int cm) {
    motor_drive.forward(cm);                        // 电机驱动复用现成轮子
    return "已前进 " + std::to_string(cm) + " 厘米";
  });

// 3. 挥手 / 做表情:一段预设动作序列
RegisterTool("wave",
  "挥手打招呼",
  []() {
    servo_arm.playSequence(WAVE_SEQ);
    return "挥手完成";
  });

注意两点。

第一,舵机和电机的驱动别重写。 上面 servo_head.setAngle()motor_drive.forward() 背后的硬件驱动,PCA9685 多路舵机驱动直流电机驱动详解 两篇已经把怎么驱动讲透了。你在小智里要做的,只是把那些驱动封装成 MCP 工具的回调。轮子是现成的,你负责接线。

第二,工具的描述(description)就是 LLM 的说明书。 "把头转向某个角度,正左负右" 这句话不是注释,它会进 LLM 的上下文。你描述得越准,LLM 调用得越对。描述写得含糊,LLM 就会乱调或者不敢调。这是 Function Calling 的老规矩,在小智上一样成立。

你应该看到什么

接好之后,一次完整的交互是这样的——

你对小智说:「转过来看我。

  1. 唤醒 → ASR 把你的话转成文字「转过来看我」;
  2. LLM 拿到这句话,结合工具列表里有个 turn 工具,判断出该调它,决定角度(比如朝声源方向转 30 度);
  3. 小智执行 turn(30),舵机转动,脑袋真的转过来;
  4. LLM 同时生成一句话「转过来啦」,走 TTS 从喇叭出来。

你看到的:它一边说「转过来啦」,一边脑袋真的在转。 声音和动作几乎同时发生。

如果你看到的是它说了「转过来啦」但人没动,或者动了但半天不吭声,那就是接对了一半——语音链没问题,但动作工具没被调起来,或者时序没协调好。往下看排查表。

故障排查表

现象 大概率原因 怎么查
说了「好的我转」但纹丝不动 LLM 没调工具,只生成了文字回复 看日志里有没有 tool_call;多半是工具 description 写得太含糊,LLM 没认出该调它
工具调了,舵机/电机没反应 硬件驱动那层断了,跟小智无关 单独跑舵机/电机测试程序,确认 PCA9685 / 电机驱动本身能动
一动起来小智就重启 电机启动瞬间拉低电压,把主控拖垮 电机和主控分开供电,别共用一路;测启动瞬间的电压跌落
动作和说话对不上、抢拍 动作是阻塞调用,把语音线程卡住了 动作放异步执行,别在 TTS 主线程里 delay() 等舵机转完
舵机停下后还在抖、嗡嗡响 到位后没断 PWM / 供电不稳 到位后释放舵机信号;电源加滤波电容

这张表里电源那两行最容易栽,单独说。

三个真实的坑

时序协调。 语音和动作是两条独立的事,挤在一个小芯片上。最常见的翻车是:动作函数写成同步阻塞,舵机转 2 秒,这 2 秒里 LLM 的语音输出全卡住,听起来一顿一顿。动作要异步,让它在后台转,语音该出就出。代价是你得处理「话说完了但动作还没做完」的收尾。

供电。 这是最阴的坑。喇叭功放要电,舵机要电,电机更是电老虎——启动瞬间电流尖峰能拉低整条电源线的电压。主控一旦电压不够就重启,于是你看到小智「一动就死机」。解法是电机/舵机和主控分开供电,或者至少加大电容缓冲尖峰。移动版用锂电池的,这条是底线。

⚠️ 安全

动起来的小智会真的伤人伤己,三件事必须做到:

  • 舵机和电机会夹手。 调试时手指、头发、桌上的线别靠近转动部件,先小角度小距离试,确认行程范围安全再放开跑。
  • 供电别凑合。 电机/舵机和主控分开供电,电流余量留够;线径不够细会发热。USB 口直接带电机很容易过流。
  • 锂电池单独按规矩来。 移动版上锂电,充放电、过流、短路保护一个都不能省,锂电池安全规范 这篇是前置必读,不是可选项。

机械结构。 软件接通了不等于它能稳稳地动。舵机转头要有支架固定,重心不能高到一动就倒;小车底盘要扛得住主板、电池、喇叭的重量。这部分没有捷径,做出来、装上去、发现晃、改结构,循环几次才稳。

两种产品形态,选一个先做

桌面转头版(推荐先做这个)。 一个舵机转头,加一块小屏幕做表情,不用底盘、不用移动。结构简单、供电压力小、不会到处乱跑撞东西。你只需要注册 turnwave 类工具,先把「语音触发动作」这条链跑通。先做这个,把时序和工具注册的坑趟平,再升级。

移动小车版。 装上小车底盘,加 moveturn(这里是转弯不是转头)这类工具,小智能滚到你跟前。麻烦在三处全齐了:电机供电尖峰、移动时的时序、底盘机械。别一上来就做移动版——桌面版没跑通就上小车,你会同时被四五个坑围攻,分不清哪个是哪个。

两个版本共用同一套思路:动作是 MCP 工具,语音链路一字不改。区别只在挂哪些工具、底层驱动是舵机还是电机。

动手挑战:给小智加一个挥手

不写整套,就加一个工具,把链路打通的感觉拿到手。

  1. 先让一个舵机能动——复用 PCA9685 多路舵机驱动 的现成代码,写一个 playWaveSequence(),让舵机来回摆三下;
  2. 在小智的 MCP 工具集里注册一个 wave 工具,回调里调 playWaveSequence(),description 写清楚「挥手打招呼」;
  3. 烧录,对小智说:「跟我打个招呼。

成了的话,你会看到它一边说「你好呀」,舵机一边来回摆。这一个工具跑通,剩下的 turnmove 都是同一个模子套出来的。 卡住了回去对故障排查表第一行——多半是 description 太含糊,LLM 没认出来。

进阶:如果你想让小智部署在自己的服务器上、动作工具也跑在自己这边,小智服务端 xiaozhi-esp32-server 提供了一套可自托管的后端,配合 自托管部署 一篇,能把整条链路攥在自己手里。

小结

把小智变成会动的机器人,核心动作只有一个:把硬件动作注册成 MCP 工具,让 LLM 自己决定何时调。 语音链路一字不改,舵机电机驱动复用现成的,你真正要做的是封装工具、协调时序、解决供电和机械。

路线很清楚——先做桌面转头版趟平坑,再上移动小车版;先加一个挥手工具找到手感,再扩成完整动作集。供电和安全这两件事别省,会动的东西真的会伤人。

下一步往哪走?想看小智之外更广的具身机器人怎么搭,进 机器人专题;想深入「会动的 AI」这个范式本身——感知、决策、行动闭环怎么形成,看 具身智能入门


本篇是基于开源项目 78/xiaozhi-esp32(虾哥 78,MIT 协议)的学习解读,署名上游、以上游为准。文中代码为讲解结构的示意参考实现,具体接口、参数、版本请以上游仓库为准;端到端可运行的完整工程见 小智旗舰项目总览

📄 来源 / 自校链接

本文为公开资料整理,非亲测。关键参数与代码请结合实物与下列官方来源验证。

内容有错、看不懂、或想看下一期?告诉我们 →

本文为公开资料的学习整理,非亲测。涉接线/花钱/合规的步骤请结合实物与官方最新资料验证,风险自负。见免责声明