《搭建小智AI对话盒子》系列之三:烧录小智固件,并锁死OTA防止自定义引脚被覆盖
上篇我们把硬件接好了,喇叭会响、麦克风能被识别——但那都是"裸板 + 自己写的音频测试"。本篇要干一件真正关键的事:把"小智"这个AI对话固件烧进去,让你的盒子从"能录能放"变成"能聊天、能给孩子讲睡前故事"。
说实话,环境搭建和接线是"体力活",而烧录小智才是"临门一脚"。我这一周里,git clone 卡死、手动下 ZIP、menuconfig 选项挑花眼、烧进去发现引脚又白调、最后还被OTA自动升级反手覆盖——每一个坑都踩得结结实实。
本系列设计每篇聚焦一个难点,贴关键命令、与大家探讨一下原理、附实测结果,确保真实可复现验证。本文聚焦最深的两个坑:引脚被固件默认配置覆盖,以及OTA自动升级把你的自定义引脚一键打回原形。
目前来看,要"联网对话 + 云端大模型",小智固件是目前最省事的现成方案。
一、获取小智固件源码
小智官方仓库是 xiaozhi-esp32。理论上一条命令搞定:
git clone --recursive https://github.com/78/xiaozhi-esp32.git
但和第一篇的环境一样,我这里的网络又卡了——git clone 进度条不动,死活拉不下来。
破局方法:浏览器手动下 ZIP。
我直接去GitHub页面点了Download ZIP,拿到的是 Xiaozhi_Esp32S3_reSpeaker-main.zip。解压到本地后,剩下的步骤和普通 clone 下来的一模一样。--recursive 的子模块如果也卡,处理方式同第一篇(手动下 + 解压进目录)。
解压后记得先激活环境(接第一篇章的 get_idf 别名):
cd xiaozhi-esp32
get_idf # 激活 ESP-IDF 环境
idf.py set-target esp32s3 # 锁定芯片为 ESP32-S3
二、menuconfig:在板型里选对你的那一个
这是新手最容易懵的一步。执行:
idf.py menuconfig
小智的菜单在 Top -> Xiaozhi Assistant 下面,关键选项有:
| 选项 | 我选的 | 说明 |
|---|---|---|
Board Type | bread-compact-wifi | 对应裸 I2S 麦克风 + 功放的最通用板型 |
Default Language | Chinese | 中文对话 |
Enable Wake Word Detection (AFE) | [*] 勾选 | 离线唤醒词,必须开 |
Enable Acoustic WiFi Provisioning | [ ] | 声波配网,后面烧完再处理 |
注意:
Board Type列表巨长(几十种商业开发板)。我们的板子是纯 I2S 模块,选错板型编出来的固件会去驱动不存在的芯片,直接没声音甚至崩溃。认准"bread-compact-wifi"这种通用项。
三、编译与烧录
配置完直接编:
idf.py build
我这边编译产物大约 xiaozhi.bin 2.5MB,空间充裕。编译通过后烧录——注意串口设备名(接USB后 ls /dev/cu.* 看到的那个,我的是 /dev/cu.usbmodem1101):
idf.py -p /dev/cu.usbmodem1101 flash monitor
flash 烧固件,monitor 顺带打开串口看日志。烧完按一下 RST 复位,设备会自动开一个Wi-Fi热点(通常叫 Xiaozhi-XXXX)。掏出手机连上去,浏览器访问 192.168.4.1,填入你家的Wi-Fi账号密码,配网完成。

四、第一道坑:引脚又被"默认配置"覆盖了
烧进去、配完网、喊"你好小智"——结果麦克风没反应。
原因很隐晦:当前选择的板型,它自己有一套默认引脚表。所以即使第二篇我改好了测试固件的 board_config.h,小智这边用的还是它自己的 config.h,引脚又一次对不上。
解决办法:改小智源码里的 config.h。
路径通常在 main/boards/bread-compact-wifi/config.h。和你的物理接线对齐:
#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4
#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5
#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6
#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7
#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15
#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16
改完 idf.py build 重新烧录,麦克风就认了。
划重点:小智的引脚定义不在
board_config.h,而在它boards/目录下的板型config.h里。两个文件都得改、且得改到同一组数字,这是最容易漏的一步。
五、最阴间的坑:OTA自动升级,把你的修改一键打回原形
你以为改完引脚就万事大吉?并没有。
小智固件开机时会自动检查新版本,如果有更新,就静默下载并覆盖整个固件——包括你刚改好的 config.h 引脚。如果没有注意引脚的设置,一次自动升级,全白调,麦克风又哑了。
源码里这个机制长这样(main/application.cc):
// 开机时检查新固件版本或获取 MQTT 服务器地址
Ota ota;
CheckNewVersion(ota); // ← 这一行触发自动升级检查
而 CheckNewVersion() 内部,一旦发现 HasNewVersion(),就调用 ota.StartUpgrade() 把官方固件刷进去——你的自定义引脚就这么没了。
怎么锁死它?
关键认知:不能简单注释掉 CheckNewVersion(ota) 这一行,因为后面 ota.HasMqttConfig() / ota.HasWebsocketConfig() 还要靠这个 ota 对象去拿 xiaozhi.me 的服务器地址(连接云端大模型就靠它)。所以必须保留 ota 对象,只让"升级检查"不执行。
最干净的做法——在 CheckNewVersion 函数体第一行直接 return:
void Application::CheckNewVersion(Ota& ota) {
return; // 【修改】锁死 OTA 自动升级,保护自定义引脚不被覆盖
// ... 下面原有的检查/升级逻辑全部跳过
}
或者更"显眼"地用 if (false) 把整个函数体包起来(方便日后想升级时一处改回)。这样:设备不再联网拉新固件,你的引脚修改永久生效;但云端连接所需的服务器地址仍由 ota 对象正常提供,不影响对话功能。
一句经验:凡是改了源码引脚/硬件绑定的,烧录前务必先锁OTA。不然每次开机自动升级,等于你永远在和官方默认配置打架。
六、绑定 xiaozhi.me,喊出第一声"你好小智"
固件烧好、引脚锁死、配网完成,接下来去 xiaozhi.me 控制台注册设备(设备会显示一个激活码,填进控制台即可绑定)。绑定后默认走官方免费 Qwen 实时模型,喊"你好小智"就能对话了。
不过我一开始发现一个有趣的现象——小智默认说话带台湾腔。
“为什么小智是台湾腔”
这是默认模型/音色的语言风格使然。在浏览器中修改成你偏好的就可以了。

七、硬件与软件配置清单(实测可复现)
| 项 | 值 |
|---|---|
| 固件 | xiaozhi-esp32(手动下 ZIP,非 clone 拉取) |
| 板型 | bread-compact-wifi |
| 引脚(config.h 修改后) | WS=4, SCK=8, DIN=6 / DOUT=7, BCLK=15, LRCK=16 |
| OTA | 已锁死(CheckNewVersion 首行 return) |
| 配网 | 设备热点 + 192.168.4.1 填密码 |
| 云端 | xiaozhi.me 控制台绑定,默认 Qwen 模型 |
| 唤醒词 | 你好小智 |
八、下一步
到这一步,一个能联网对话、给孩子讲睡前故事的实体AI盒子就真正跑通了。但有两个收尾值得写:
- 自托管服务器——自己部署
xiaozhi-esp32-server,接DeepSeek / Qwen,定制小智性格、音色、限制等,还顺手把"依赖官方服务器"的平台风险降为零。 - 成本复盘——算一笔账:裸板 + 麦 + 喇叭 + 辅料一共多少钱,对比市面 成品 AI 玩具,差距有多大。
如果你也在烧小智,欢迎在评论区留下你卡在的板型或引脚问题。动手是最好的学习方式,我们一起填坑。
更多推荐




所有评论(0)