學完本章你將能夠:
區分 KWS(關鍵詞偵測)與 ASR(指令/連續語音)的責任。
完成路徑 A:解析模組輸出並對照指令表。
描述路徑 B:特徵(MFCC/Log-Mel)\(\rightarrow\) 量化模型 \(\rightarrow\) X-CUBE-AI。
設計拒絕機制:低信心、未知詞、聆聽窗外的指令一律丟棄。
「語音控制」在工程上是兩段:先判斷有沒有人在叫我(喚醒),再判斷 叫我做什麼(指令)。兩段都允許誤拒(沒反應),但要極力避免誤接受 (自己開燈)。
狀態:Idle \(\rightarrow\) Listen \(\rightarrow\) Execute
Idle 只跑 KWS(或等模組的喚醒碼)。Listen 才允許指令表。Execute 把 |cmd_msg_t| 送進第 6 章的佇列,然後回 Idle。Event Group 的 |EVT_LISTEN| 與這個狀態對齊。
路徑 A:外部模組
以常見離線模組為例(指令碼請換成你模組的手冊值):
typedef struct const char *phrase; cmd_id_t cmd; asr_map_t;
static const asr_map_t k_map[] = "xiao-ke", CMD_NONE , /* 喚醒,不進設備佇列 */ "kai-deng", CMD_LIGHT_ON , "guan-deng", CMD_LIGHT_OFF , "liang-yi-dian", CMD_LIGHT_UP , "kai-feng-shan", CMD_FAN_ON , "kai-men", CMD_DOOR_OPEN , "quan-bu-guan", CMD_ALL_OFF , "shui-jiao", CMD_ENTER_SLEEP , ;
模組 UART 一行進來後,去掉 \r\n, 線性搜尋。喚醒詞只呼叫 |voice_on_wake()|。其他詞若未處於 |EVT_LISTEN|,記錄一次 log 並丟棄——這能大幅降低電視聲音誤觸。
很多模組可自訂 3–5 字中文詞。課堂請避開單音節(「開」「關」),改用 「打開電燈」「關閉風扇」。詞愈長,假陽性愈低。
路徑 B:板上 Edge AI
典型管線:
每 10–20 ms 取一幀 PCM,重疊 50%。
預強調、分幀、加窗、FFT,得到 Log-Mel 或 MFCC(約 40 維 \(\times\) 49 幀構成一張「圖」)。
量化成 int8,送入 X-CUBE-AI 產生的 |ai_run()|。
Softmax/argmax 得到類別與分數;低於門檻視為 silence/unknown。
Cube.AI 流程摘要:在 STM32CubeMX 安裝 X-CUBE-AI 套件 \(\rightarrow\) 匯入 Keras/ONNX/TFLite \(\rightarrow\) 看 Flash/RAM 佔用與 MACC \(\rightarrow\) 產生 network.c 與分析報告。官方音訊範例(如 FP-AI-NANOEDG1、 X-CUBE-AI 的 KWS 示範,以及 STM32H747 發現板的音訊 AI 應用)可直接對照 特徵參數,避免自己從零調 Mel 濾波器。
F429 的 SRAM 能跑極小的 DS-CNN,但餘裕不大。課程把路徑 B 的完整模型 部署放在 H7 發現板;F4 上可用「能量 + 極簡單的模板比對」做概念驗證, 或只跑官方縮小模型。不要為了在 F4 塞進大模型而關掉所有安全檢查。
推論必須在 ASR 任務中執行,且該任務堆疊與模型活化緩衝分開。|ai_run| 期間 Device 任務仍可跑——這是 RTOS 相對超迴圈的具體好處。
拒絕與防抖
信心門檻:例如 0.70。印出分數一週,再決定數字。
時間防抖:同一指令 400 ms 內不重複執行。
未知類:模型應含
unknown/silence類,不要強迫 argmax 總是對應一個家電。聆聽窗:窗外只接受喚醒。
BaseType_t asr_try_dispatch(cmd_id_t cmd, uint8_t score) EventBits_t e = xEventGroupGetBits(g_evt); if (cmd == CMD_NONE) voice_on_wake(); return pdTRUE; if ((e & EVT_LISTEN) == 0) return pdFALSE; if (score < APP_MIN_SCORE) return pdFALSE; cmd_msg_t m = .id = cmd, .arg = score, .tick = xTaskGetTickCount() ; return xQueueSend(g_cmd_q, &m, 0);
實驗
firmware/lab08_asr_module/ 實作路徑 A 完整對照表與聆聽窗。 firmware/lab08_asr_edgeai/ 提供特徵+假模型(argmax 模板) 與 X-CUBE-AI 接線註解:你把 Cube.AI 產生檔丟進專案後,把 |kws_infer()| 換成 |ai_run()| 即可。
用 PC 終端模擬模組,依序輸入:
xiao-ke kai-deng guan-deng
第一行應只亮聆聽 LED;第二行燈才亮;若省略喚醒直接 kai-deng, 燈不應動作。
加入「連續兩次未知詞就退出聆聽窗」。再為喚醒加上語音回饋:成功喚醒 時 |dev_buzzer_beep(80)| 一次,讓使用者不必看 LED。最後讀一篇 ST 官方 KWS 應用筆記,把你的 Mel 參數(窗長、hop、濾波器數)抄進筆記, 和下週狀態機對接。