两天时间:我和 kimi k3 一起把小智"整容"了:从零烧录固件到 Minecraft 小僵尸
如何让AI助手主动开口说话?本文通过修改小智固件、集成MCP语音工具,带你从零实现Minecraft小僵尸在屏幕上“活”起来。核心内容:1. 改造小智固件,增加MCP语音工具实现外部推送2. 搭建ESP-IDF编译环境,解决Windows命令行长度限制3. 烧录调试与头像定制,最终让“绿崽”在设备上成功运行
一台 M5Stack CoreS3、一个开源的小智(xiaozhi-esp32)固件、一个自己搭的服务端,再加一个 AI 搭子(Kimi Work,K3 模型)。两天时间,我们踩了七八个坑,最后让屏幕上长出了一只会眨眼的 Minecraft 小僵尸——「绿崽」。
这篇文章是整个过程的完整复盘,希望能给同样想折腾小智的你省点时间。

起因:我想让外部系统主动「推消息」给机器人
一切的起点其实是个功能需求:我希望外部系统能主动推送信息给小智,让它开口说话,而不只是人喊它才应答。
翻完 xiaozhi-esp32 的源码后发现:MQTT 模式下设备空闲常连,服务端的 alert 消息可以在屏幕上弹文字,但空闲时无法开口——没有音频通道、没有 speak 工具,固件里 mcp_server.cc 还会把 MCP notifications 直接丢掉。
所以方案定了:改固件,加一个 speak 的 MCP 工具。要改固件,就得能自己编译烧录;要自编译,最好服务端也自己搭。于是有了这条完整的折腾链路:
自搭服务端 → 配 Kimi K3 大模型 → 搭 ESP-IDF 编译环境 → 编译固件
→ 烧录 → 修启动 bug → 设备上线 → 改写默认头像 → 修崩溃 → 上岸
第一关:服务端跑起来(最顺利的一步)
服务端用的是官方配套的 xiaozhi-esp32-server,Docker 一把梭:
- 容器跑起来后,OTA 接口
http://<局域网IP>:8003/xiaozhi/ota/返回正常 - LLM 配的 Kimi(KimiLLM,OpenAI 兼容协议),模型 K3,填上 API Key 后实测 200 连通
这一步意外顺滑,让我产生了「今天能搞定」的错觉。
第二关:ESP-IDF 编译环境,被 Windows 命令行长度背刺
小智 v2.4.0 官方要求 ESP-IDF v6.0+,我装了 v6.0.2。然后遇到了一个非常 Windows 的坑:
Windows 命令行有 32767 字符上限。 这个项目编译时链接命令带了几百个 -I 头文件路径,实测拼出来 36081 个字符——直接超限失败。
解法很土但有效:把 ESP-IDF 和工程全部物理复制到超短路径(比如 C:efesp-idf-v6.0.2 和 C:pfxiaozhi-esp32),路径短了,命令行就够长了。junction、subst 这些花活都试过,CMake 会把路径还原回去,别浪费时间和它斗智斗勇。
第三关:编译成功,烧录成功,然后设备「死」了
改好三个配置(板型 M5STACK_CORE_S3、OTA 地址指向自己的服务器、控制台改到 USB)后编译通过,烧录也显示 Hash verified。
然后设备黑屏,电源键没反应,连正常的 COM 口都不见了。
第一天的最大悬疑就此开始。
真相一:它根本没在运行,而是一直躺在下载模式
长按底侧 RST 键 3 秒亮绿灯可以进下载模式,COM 口回来了。但奇怪的是:刷完机 esptool 明明做了 “Hard resetting via RTS pin”,设备却从不启动。
后来用 esptool 的 --before no-reset 模式一探,发现芯片一直停在 ROM 下载模式——它从来就没跑过我们的固件。黑屏不是「跑了但显示挂了」,是压根没跑。
真相二:DTR 陷阱,一个自己坑自己的经典案例
更诡异的是,我用 pyserial 写脚本抓启动日志,每次打开串口设备反而更「死」。
最后定位到原因:Windows 上打开串口时,DTR 线默认会被拉高,而 ESP32-S3 的 USB-Serial-JTAG 外设里 DTR 连着 GPIO0(BOOT 选择脚)。GPIO0 低电平 = 任何复位都进下载模式。
也就是说,我每次「打开串口准备抓日志」的动作本身,就把设备按回了下载模式。自己成了自己最大的干扰源。
解法:打开串口后立刻 dtr = False(GPIO0 拉高),再脉冲 RTS 复位,设备立刻正常启动,ROM 日志哗哗地流出来。
真相三:PSRAM 模式错了,但这错误藏得极深
拿到启动日志后,死因一目了然:
E (34) octal_psram: PSRAM chip is not connected, or wrong PSRAM line mode
E cpu_start: Failed to init external RAM!
abort() was called
固件按八线(Octal)PSRAM 初始化,然后反复 probe 失败、崩溃、重启。设备进入「启动→崩溃→重启」的死循环,USB 每 10 秒重新枚举一次——这就是之前 COM 口时有时无的原因。
可是 sdkconfig 里明明写着 CONFIG_SPIRAM_MODE_OCT=y,这还是 esp32s3 默认配置里的。直到我翻了官方仓库里 CoreS3 的 main/boards/m5stack-core-s3/config.json:
json"sdkconfig_append": [
"CONFIG_SPIRAM_MODE_QUAD=y",
...
]
官方发布固件用的是 QUAD(四线)模式! 默认配置的 OCT 在这台机器上根本不工作,官方在发布脚本里悄悄覆盖成了 QUAD。改成 QUAD 重新编译烧录,设备「叮」的一声亮了。
教训:玩 xiaozhi 自编译,一定要看你那个板子 config.json 里的 sdkconfig_append,那里有官方没写进文档的板级秘方。
第四关:设备连不上服务器,errno 113 指向防火墙
设备正常启动、连上家里 WiFi(拿到 IP),但 OTA 请求一直失败:
E EspTcp: Failed to connect to 192.168.1.21:8003, code=0x71
0x71 = 113 = EHOSTUNREACH。排查链路:
- 电脑上 curl 自己的局域网 IP,OTA 接口正常 ✅
- ping 设备,通 ✅
- Docker 端口监听在
0.0.0.0✅ - 手机浏览器访问 OTA 地址,打不开 ❌
手机也不通,说明问题在电脑这一侧,与设备无关。Windows 防火墙加了两条入站放行规则(8003/8000),没用;整个防火墙临时关掉,立刻通了。
最终结论:防火墙层面的拦截(如果 Windows 防火墙规则明明放行了还不行,大概率是 360/电脑管家/火绒这类安全软件接管了网络过滤,它们会无视 Windows 规则)。
设备随即上线,服务器日志里出现了它的身影:
OTA请求设备ID: 44:1b:f6:df:59:6c
OTA请求ClientID: 8991a3ae-4017-4533-83a6-337021944701
收到hello消息:{"type":"hello","features":{"mcp":true},...}
第五关:给小智「整容」,一只 Minecraft 小僵尸的诞生
功能跑通后,看默认头像就越来越不顺眼了。小智默认显示一个 FontAwesome 的芯片图标,多少有点敷衍。
我先让 AI 出了 10 个简洁几何风候选(白团子、猫咪、饭团、小云……),最后选了 Minecraft 小僵尸:像素风、僵尸绿、大头宝宝比例、方块大眼带高光、一颗小虎牙、MC 标志性的青色小衣服。取名「绿崽」。
固件实现:比想象中简单
小智 CoreS3 用的是 LcdDisplay(LVGL),中央表情区原本是 emoji 图片/字体图标。改造方式:
- 像素脸:12×14 的像素图,每像素 11 物理像素,用约 20 个 LVGL 矩形对象拼出头、高光、阴影、眼睛、嘴、虎牙、小衣服——不用任何图片资源,纯代码绘制
- 眨眼动画:一个 4.2 秒的 LVGL 定时器,眼睛矩形从 3 像素行缩到 1 像素行、130ms 后恢复
- 说话动嘴:进入
kDeviceStateSpeaking状态时,180ms 定时器让嘴在开合之间切换;回到 idle 就停 - 表情拦截:
SetEmotion不再切 emoji 图片,只跟踪「说/不说」
然后又是一个崩溃循环
第一版烧进去,设备又开始「初始化→联网→重启」无限循环。抓串口日志:
Guru Meditation Error: Core 1 panic'ed (LoadProhibited)
EXCVADDR: 0x00000028
0x28 这种地址,典型的空指针偏移访问。用 xtensa-esp32s3-elf-addr2line 解码调用栈,三秒定位:
lv_obj_set_style_text_color ← lv_obj_style_gen.c:635
LcdDisplay::SetTheme ← lcd_display.cc:1332
Assets::Apply ← assets.cc:54
Application::CheckAssetsVersion
我把 emoji_label_ 置空后,SetTheme() 里还有一处没判空就直接给它设颜色。主题在「激活」阶段一刷新,当场暴毙。加个 if (emoji_label_ != nullptr),世界清净了。
最终效果
- 待机:绿崽安安静静待着,每 4 秒左右眨一次眼
- 喊「你好小智」:正常应答
- 说话的时候:嘴巴一张一合,配合语音非常有喜感
这两天踩过的坑(速查清单)
| 坑 | 解法 |
|---|---|
| Windows 命令行 32767 字符上限 | ESP-IDF 和工程复制到 C:ef、C:pf 短路径 |
| 刷完机设备黑屏「死了」 | 其实一直停在下载模式,用 esptool --before no-reset 探测 |
| 打开串口反而抓不到日志 | DTR 陷阱:开串口后立刻 dtr=False,否则 GPIO0 被拉低 |
octal_psram 初始化失败 | 看板子 config.json 的 sdkconfig_append,CoreS3 要用 QUAD |
| 设备 OTA 报 errno 113 | 电脑侧防火墙/安全软件拦截,手机实测可快速定位 |
LoadProhibited 崩溃循环 | addr2line 解码 backtrace,空指针判空修复 |
| 刷机后 WiFi 要重配 | erase-flash 会清 NVS,日常刷机别加 erase |
下一步
「绿崽」只是开始。最初的目标——让外部系统主动推送消息给小智开口说话——还没做:接下来要在固件里加 self.audio_speaker.speak 这个 MCP 工具,服务端加一个 /push/speak 接口。方案已经设计好,就等动手了。
如果你也在玩小智,欢迎抄作业;如果踩到新坑,也欢迎来交流。
工具链:xiaozhi-esp32 v2.4.0 / xiaozhi-esp32-server(Docker)/ ESP-IDF v6.0.2 / Kimi Work(K3 模型,负责全部源码分析、调试和固件改写)
登录查看剩余 70% 内容
-
07.21
PPIO发布智能模型网关:日均调用量突破1.2万亿
-
07.21
Kiro 实战:让 AI 自动“记住”你的系统——知识自沉淀机制设计
-
07.21
此芯科技发布AGX战略:桌面超算原生跑通150B大模型
-
07.21
Question Base-Question Base即一个AI驱动的知识库
-
07.21
Praxy AI-Praxy AI是针对学生的AI助手工具
-
07.21
WAIC 2026,AI硬件的狂欢?
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏