ESP32-S3 端侧唤醒词「花丫花丫」训练实战|数据采集、TinyML 量化与误唤醒压测全记录

🔧 智能硬件研发日志 📅 2026-10-09
ESP32-S3 TinyML KWS 唤醒词 智能硬件 语音交互 排障复盘

一、实验目的

在 v2.2 研发复盘中,语音链路被列为 P0 缺口:花盆只能通过手机端发起对话,无法像真正的生物一样被「叫醒」,交互的发起权始终在用户手里。本次实验的目标是:在 ESP32-S3 上落地一个常驻的本地关键词唤醒(KWS)模型,做到 离线可唤醒、唤醒后接云端 ASR + LLM 的完整链路,并在真实家庭噪声环境下把误唤醒压到可接受水平。

衡量标准有三条:待机电流降到 20mA 以下(可长期插电不烫手)、安静环境唤醒率 ≥ 95%、日均误唤醒 ≤ 1 次/小时(不会让用户想把它关掉)。

二、实验硬件与环境

项目型号 / 参数
主控ESP32-S3-WROOM-1-N16R8(双核 240MHz、16MB Flash、8MB PSRAM)
麦克风INMP441(I2S、24bit、底部收音孔)
功放MAX98357A(I2S、3W)
开发框架ESP-IDF v5.1 / Arduino-ESP32 2.0.14
训练平台Edge Impulse Studio(免费开发者版)
推理运行时TensorFlow Lite Micro + ESP-NN 加速内核

三、唤醒链路设计(本地唤醒 + 云端理解)

整体采用两段式架构:端侧只做一件事——判断「有没有人在叫我」;一旦唤醒,才把后续音频交给云端做理解与生成。这样待机阶段既不联网也不上传音频,隐私承诺可以真正兑现,流量与 token 成本也随之下降。

常驻循环(端侧,18mA)
  ├─ I2S 采集 16kHz/16bit → 30ms 滑动窗口
  ├─ MFCC 特征 → TFLM 模型推理(int8)
  └─ 置信度 > 0.82 且连续 2 帧命中 → 触发唤醒

唤醒后(联网)
  ├─ 播放「在呢」提示音 + LED 光语
  ├─ VAD 端点检测 → 云端 ASR
  └─ LLM(注入 LMPI 心境 + 记忆)→ TTS 流式 → I2S 播放

阈值与「连续 2 帧」是抑制误唤醒的关键:单帧命中不触发,瞬时噪声(锅铲声、门铃)很难连续两帧都超过阈值。

四、语音数据采集与增强

唤醒词定为四字叠词「花丫花丫」:叠词在声学上重复性强、易与日常对话区分,且与花盆的品牌人格一致。数据集全部自采,未使用公开语料。

类别条数说明
正样本(1m 内)62026 位志愿者(14 男 / 12 女)
正样本(1-3m)480含普通话与 6 种口音
正样本(3-5m 带混响)380客厅 / 厨房远场场景
负样本-日常语料1650电视剧、播客、家庭对话
负样本-近音易混词720「花呀」「发芽」「好呀」「丫头」等
环境噪声350油烟机、水龙头、电视、扫地机器人
合计4200约 3.6 小时

数据增强策略:音量扰动 ±6dB、加性噪声(SNR 5~20dB)、时移 ±100ms、房间混响模拟(RT60 取 0.3 / 0.6 / 0.9s 三档)。增强后训练集约 1.2 万条。

五、模型训练与量化

特征提取用 MFCC:帧长 25ms、帧移 10ms、40 个 Mel 滤波器、取前 13 阶系数并拼接一阶与二阶差分,输入窗口 1000ms。网络采用 4 层深度可分离卷积 + 全局平均池化 + 2 类输出,这是端侧 KWS 的经典结构,参数量与乘加运算都压得很低。

指标float32int8 量化后
模型体积78 KB21 KB
峰值内存46 KB13 KB
单帧推理耗时31 ms9 ms
验证集准确率97.1%96.4%
CPU 占用(240MHz 双核)约 11%约 3%

量化用 Edge Impulse 自带的 int8 全整型量化(代表性数据集校准),准确率仅掉 0.7 个百分点,但推理耗时降到原来的 1/3,这是能把它塞进常驻循环的前提。

六、端侧部署要点

  1. 任务绑核:I2S 采集放 Core0 高优先级任务,推理放 Core1,中间用 4 帧环形缓冲衔接,避免采样被推理阻塞;
  2. PSRAM 开启:设置 CONFIG_SPIRAM_USE=y,模型与音频缓冲放 PSRAM,内部 RAM 全部留给 DMA 与协议栈;
  3. 模型编入固件:以 EMBED_FILES 方式编译进 app 分区(预留 4MB),不做文件系统读取,避免读写抖动与掉电损坏;
  4. 双帧确认:置信度阈值 0.82 + 连续 2 帧命中才触发,单帧命中只更新内部状态;
  5. 自唤醒抑制:扬声器播放开始后的 200ms 内关闭 KWS 判定窗口,避免花盆自己说话把自己叫醒。

七、实测数据与误唤醒压测

场景距离唤醒率误唤醒(次/小时)
安静书房1-3m98.2%0.1
电视开着(约 60dB)2m95.6%0.6
厨房(油烟机 + 水流)3m91.3%1.2
夜间(空调约 45dB)3m96.4%0.3
加权日均-96.4%0.8

另做 3 天 24 小时连续挂机:累计误唤醒 58 次,其中 41 次来自含「呀 / 花」的电视台词。优化方向已明确——补充近音负样本,并把阈值从 0.82 提到 0.85。

八、踩坑复盘

  1. I2S 采样率错配(最坑):固件配置 16kHz,训练数据却按 44.1kHz 采集后未重采样,唤醒率从 96% 直接跌到 41%。统一重采样到 16kHz 后恢复;
  2. DMA 缓冲溢出爆音:默认 512 字节缓冲在 WiFi 发送时被打断,改为 1024 字节双缓冲并把 WiFi 任务绑核后消失;
  3. 麦克风增益过高削波:近距离样本出现削顶失真,模型学到的是失真特征,补录近距离数据时把增益从 0.7 降到 0.45;
  4. 供电噪声:与功放共用 USB 供电时底噪抬升约 12dB,改用独立 LDO 给麦克风供电;
  5. 开机自检误触发:上电瞬间 I2S 有直流偏置脉冲,改为开机 300ms 内不进入 KWS 判定;
  6. 模型版本混乱:三次迭代的模型都叫 model.tflite,改为把 git commit 短 hash 写入固件版本字符串,串口日志可直接读到。

九、实验总结与下一步

本次实验把唤醒能力下沉到端侧,花盆第一次具备了「被叫醒」的能力,待机电流 18mA、模型 21KB、安静环境唤醒率 98.2%,三条衡量标准全部达成。更重要的是验证了端侧 TinyML + 云端大模型的两段式链路在 ESP32-S3 上跑得通,为后续声纹、情绪识别的下沉铺好了路。

下一步:① 引入双阶段唤醒(KWS → 声纹二次确认),解决多人家庭的误唤醒;② 唤醒提示音与 LMPI 心境联动,花盆高兴时和蔫了时的应答音色不同;③ 误唤醒样本自动回传(仅回传脱敏特征,不回传音频)用于增量训练。

研发调试中
持续迭代
本文为个人原创实验记录,版权归作者所有,禁止商用转载。
如需技术交流,欢迎通过博客留言或邮件联系。
← 返回硬件专栏 返回首页 →

💬 技术交流

📋 留言规则: 本留言板仅用于技术学习交流,严禁发布广告、外部引流链接、涉政、色情、赌博、 营销推广及一切违法违规内容。本站为个人非经营性网站,不提供任何商业接单、付费咨询服务。 所有留言需经人工审核后展示。

📧 技术交流邮箱:

留言提交功能将在公安网安备案全部通过后开放,感谢理解。

💬 过往技术交流

加载中...
芽语AI助手 芽语 AI 对话