ESP32-S3 MultiNet新增离线语音指令完整教程:Command ID、拼音注册与动作映射
前言
ESP32-S3已经能识别“打开电灯”和“彩虹模式”,如果还想增加一句“恢复亮度”,需要重新训练MultiNet模型吗?
在本文使用的工程里,答案通常是否定的。新增一条离线语音控制指令,核心不是重新训练模型,而是打通三层映射:
命令短语 → Command ID → 实际执行动作本文基于以下环境:
- 芯片:ESP32-S3-N16R8;
- ESP-IDF:5.1.2;
- ESP-SR:2.4.6;
- 中文MultiNet模型;
- 启动时通过API注册命令词。
不同ESP-SR版本的接口和命令格式可能不同,请先确认自己工程使用的是运行时API、命令文件还是menuconfig配置方式。
一、一条可执行命令至少包含三层
假设用户说“彩虹模式”,系统内部需要完成:
“彩虹模式” ↓ CMD_RAINBOW ↓ led_controller_set_effect(LED_EFFECT_RAINBOW)三层分别是:
- 命令短语:用户实际说出的内容;
- Command ID:MultiNet识别后返回的编号;
- 执行动作:应用程序根据编号控制灯带、舵机、继电器或电机。
只注册短语而不处理ID,程序即使识别成功也不知道该做什么;只写执行函数而没有把短语注册给MultiNet,设备又永远听不到这条命令。
二、第一步:给新指令分配Command ID
推荐使用枚举管理命令,避免手动维护数字编号:
enum{CMD_LIGHT_ON=1,CMD_LIGHT_OFF,CMD_NEXT_EFFECT,CMD_BRIGHTER,CMD_DARKER,CMD_RAINBOW,CMD_BREATH,CMD_COMET,CMD_RESET_BRIGHTNESS,};需要注意:
- Command ID不要使用0;
- 每一种不同动作最好使用独立ID;
- 枚举可以减少重复编号和手动写错的问题。
如果两种说法对应同一个动作,它们可以共用同一个Command ID,不必重复增加业务分支。
三、第二步:把中文短语转换成拼音
本文工程使用的中文MultiNet API接收空格分隔的汉语拼音,而不是直接填写汉字:
恢复亮度 → hui fu liang du 打开电灯 → da kai dian deng 彩虹模式 → cai hong mo shi注册代码如下:
ESP_ERROR_CHECK(esp_mn_commands_add(CMD_RESET_BRIGHTNESS,"hui fu liang du"));拼音格式需要满足:
- 全部使用小写字母;
- 音节之间保留一个空格;
- 不写声调;
- 中文命令中不要混入阿拉伯数字、特殊符号或英文单词。
如果不确定拼音格式,可以使用ESP-SR组件提供的tool/multinet_pinyin.py辅助转换。
四、第三步:不要漏掉esp_mn_commands_update
完整的命令注册函数可以写成:
staticesp_err_tconfigure_commands(constesp_mn_iface_t*multinet,model_iface_data_t*model_data){ESP_ERROR_CHECK(esp_mn_commands_clear());ESP_ERROR_CHECK(esp_mn_commands_add(CMD_LIGHT_ON,"da kai dian deng"));ESP_ERROR_CHECK(esp_mn_commands_add(CMD_RAINBOW,"cai hong mo shi"));ESP_ERROR_CHECK(esp_mn_commands_add(CMD_RESET_BRIGHTNESS,"hui fu liang du"));esp_mn_error_t*invalid_commands=esp_mn_commands_update();if(invalid_commands!=NULL){ESP_LOGE(TAG,"Command phrase could not be parsed");returnESP_ERR_INVALID_ARG;}multinet->print_active_speech_commands(model_data);returnESP_OK;}这是整个过程最容易遗漏的地方。
esp_mn_commands_add()、remove()、modify()和clear()只是在修改缓存中的命令表。只有调用esp_mn_commands_update(),变化才会真正应用到MultiNet。
因此,add()返回成功,并不代表新命令已经进入有效识别列表。
建议启动时调用:
multinet->print_active_speech_commands(model_data);通过串口打印有效命令,可以直接确认拼音短语是否已经成功注册。
五、第四步:把Command ID映射到硬件动作
短语注册完成后,还要在应用层处理新ID:
staticvoidexecute_command(intcommand_id){switch(command_id){caseCMD_LIGHT_ON:led_controller_set_power(true);break;caseCMD_RAINBOW:led_controller_set_effect(LED_EFFECT_RAINBOW);break;caseCMD_RESET_BRIGHTNESS:led_controller_set_brightness(100);break;default:ESP_LOGW(TAG,"Unknown command id: %d",command_id);break;}}其中led_controller_set_brightness(100)只是示例,需要替换为工程中实际存在的亮度控制函数。
如果“切换灯效”和“下一个灯效”希望执行相同动作,可以把两个短语映射到同一个ID:
ESP_ERROR_CHECK(esp_mn_commands_add(CMD_NEXT_EFFECT,"qie huan deng xiao"));ESP_ERROR_CHECK(esp_mn_commands_add(CMD_NEXT_EFFECT,"xia yi ge deng xiao"));这样业务层只需要一个CMD_NEXT_EFFECT分支。
六、编译、烧录与串口验证
完成代码修改后重新编译和烧录:
idf.py build idf.py-p COM13 flash monitor将COM13替换为电脑上的实际端口。
建议按照以下顺序验证:
- 启动后确认有效命令列表中出现新拼音短语;
- 说唤醒词“你好小智”;
- 等设备进入MultiNet监听窗口;
- 清晰说出“恢复亮度”;
- 检查串口返回的Command ID、文本和概率;
- 确认灯带或其他硬件执行了正确动作。
识别成功时,日志可能类似:
Command id=9, text=hui fu liang du, probability=0.873如果串口已经返回正确ID但硬件没有动作,优先检查应用层switch映射,而不是继续怀疑MultiNet模型。
七、添加指令后需要重新烧录srmodels.bin吗
如果只是通过运行时API增加、删除或修改短语,通常不需要重新训练MultiNet,也不需要因为每一句新命令而更换基础模型。命令表会在程序启动时更新。
以下情况需要重新关注模型分区:
- 在menuconfig中更换了MultiNet模型版本或语言;
- 修改了需要打包进模型的离线命令文件;
- 擦除了整个Flash或
model分区; - 启动时出现找不到中文MultiNet模型的错误。
ESP-SR模型通常位于独立的model分区,构建过程会生成srmodels.bin。全量烧录时不要遗漏该文件。
八、五个高频问题
1. 拼音格式错误
检查是否误写了汉字、声调、连续拼音或特殊字符,并查看esp_mn_commands_update()的返回值。
2. 指令过于相似
“打开灯光”和“打开灯带”前半部分高度相同,在噪声环境中容易混淆。优先选择节奏和音节差异更明显的短句。
3. 说话时机不正确
先确认WakeNet已经唤醒,再在MultiNet监听窗口内说出指令。
4. 没有处理新ID
串口出现Unknown command id,通常说明execute_command()缺少对应分支。
5. 忘记调用update
esp_mn_commands_add()成功不代表命令已经生效,最后必须更新有效命令表。
总结
给ESP32-S3增加一条离线语音指令,核心步骤只有四个:
- 定义新的Command ID;
- 用拼音把短语注册给MultiNet;
- 调用
esp_mn_commands_update()应用命令表; - 在
execute_command()中把ID映射到实际动作。
理解“短语、ID、动作”三层后,增加灯效、舵机、继电器或电机命令,本质上都是同一套方法。
本文以ESP-IDF 5.1.2、ESP-SR 2.4.6和ESP32-S3中文MultiNet工程为例。其他版本请以对应版本官方文档为准。
我是阿白,感谢你的观看。
参考资料:
- 乐鑫MultiNet命令词文档
- 乐鑫ESP-SR入门指南
