一、立项背景和目标
我国老龄化加剧,慢病患者需长期按时按种服药,但老人常记不住时间、分不清药品,漏服错服直接影响疗效;市面药盒多为被动分格容器,无提醒、无交互。本项目以 ESP32-S3 为主控研制智能语音药盒:用语音代替按键与手机 App,实现"唤醒—问药—确认—开柜"的自然交互;三路电磁锁独立控制三个药柜,必须二次确认才开锁;状态屏同步显示问答与柜号,断网仍可本地语音取药。
二、软件功能、核心功能模块
系统基于 ESP-IDF v5.5.4 的 FreeRTOS 多任务架构:INMP441 采集 16kHz PCM,ESP-SR AFE 完成 AEC/VAD/唤醒("你好小安"),播放 PCM 回灌作 AEC 参考,边播报边可唤醒;voice_session 统一收口会话阶段,logic_dispatcher 单队列串行处理唤醒、ASR、TTS、开盒四类命令;ASR/TTS 走百度 WebSocket,audio_service 用 2MB PSRAM 环形缓冲统一承载采集与播放;dialog_router 保留 6 轮上下文,按"本地指令→固定问答→云端对话"路由;Open_Box 驱动三路继电器脉冲开锁后回到断电状态;状态屏中文分页显示、空闲 60 秒熄屏;断网由本地固定指令兜底。
三、业务流程、功能路径描述
联网:说"你好小安"唤醒,中央队列立即停播并取消在途请求,录音会话独占麦克风采集,PCM 上传百度 ASR 得到文本,再按"本地指令→固定问答→云端对话"路由;回复为纯数字 1~3 时提示药品柜号并确认取药,-1 表示无药,其余交 TTS 播报并在状态屏分页显示。离线:断网转本地识别,说"打开一号柜"后显示柜号并播放提示音,第二轮说"确认开盒"才提交,超时、低置信度或模糊候选都不开柜。开盒路径:确认文本连同会话代次经 logic_send_asr_cmd() 进入中央队列,逻辑任务驱动继电器脉冲开锁,脉冲结束回到断电状态,代次过滤保证旧结果不误触发。
一、整体架构和设计思路,技术栈
以单颗 ESP32-S3 承载全部功能,基于 ESP-IDF v5.5.4 + FreeRTOS 双核,分驱动、服务、会话调度、业务路由、交互五层。设计遵循四点:单点所有权,音频总线、开盒动作、中央队列各只有一个持有者;事件驱动加状态机,会话阶段统一收口;代次取消,唤醒即作废在途请求;分级降级,屏幕失败不停语音、断网降本地识别。内存上 ISR/DMA 用内部 RAM,大块 PCM 与文本走 PSRAM。技术栈:ESP-SR AFE(AEC/VAD/WakeNet,"你好小安")+ MultiNet5 本地指令、I2S 采集播放、百度 ASR/TTS WebSocket、DeepSeek-V3.2 流式对话、OneNET MQTT、SPI 中文屏。
二、"我"的负责模块和结果
作为固件主要负责人,独立完成架构设计与全部嵌入式软件,交付 22 个 C 文件、23 个头文件与 9 篇技术文档。量化成果:音频服务用 2MB PSRAM 环形缓冲承载约 65 秒音频,采集与播放互斥;ASR 采集与上传解耦为 16 块×1024 字节(512ms)队列;中央队列串行处理 4 类命令;对话保留 6 轮、上限 32KB、闲置 300 秒清空;离线 3 条开柜指令加二次确认,模型装入原 5168KB 分区、未改分区表。实测指标待补:唤醒成功率 __%、开口延迟 __ms、内部 RAM 峰值 __KB。
三、"我"遇到的难点、坑与解决方案
播报时唤醒失灵:扬声器回声误触发唤醒词。在功放 DMA 完成回调(IRAM)把实际播放 PCM 写入 AEC 参考队列。
录音时网络发送阻塞 I2S 丢采样:采集与上传解耦,录音只复制入队,独立任务发送,先归还音频总线再发 FINISH。
PSRAM 空闲却报 ESP_ERR_NO_MEM:只开 CAPS_ALLOC 时普通 malloc 仍占内部 RAM,改 USE_MALLOC 并调整阈值。
旧回复在新唤醒后突然播报:引入输出代次与会话代次,唤醒即递增,旧回调直接丢弃。