使用STM32實(shí)現(xiàn)一個(gè)離線語(yǔ)音控制器
成就一番偉業(yè)的唯一途徑就是熱愛(ài)自己的事業(yè)。如果你還沒(méi)能找到讓自己熱愛(ài)的事業(yè),繼續(xù)尋找,不要放棄。跟隨自己的 心,總有一天你會(huì)找到的。——喬布斯
??
你去關(guān)燈,你去,你去,。。我去。。小伙伴們有沒(méi)有在天氣寒冷時(shí)候,想去關(guān)燈,卻離不開(kāi)心愛(ài)的被窩的經(jīng)歷呢,有的話,跟著小飛哥一起來(lái)DIY一個(gè)離線語(yǔ)音控制器,有了它,我們就可以安穩(wěn)的臥在暖和的被窩了,來(lái),干!
? ? ? ? 先看看演示視頻:
完成目標(biāo)
- HAL庫(kù)串口使用
- 常用串口接收及數(shù)據(jù)協(xié)議解析
- 接收離線語(yǔ)音控制模塊數(shù)據(jù)、解析,實(shí)現(xiàn)相應(yīng)的控制
硬件環(huán)境
- STM32F407ZGT6(或其他主控板)
- 海凌科HLK-V20離線語(yǔ)音控制模塊
- 電容式駐極體話筒(咪頭)
- 杜邦線,LED燈,實(shí)驗(yàn)用到3個(gè)LED燈,面包板(非必備)
軟件環(huán)境
- keil5
- cubemx
1 離線語(yǔ)音模塊控制器
1.1 模塊簡(jiǎn)介
??在某寶購(gòu)買的,只需要9.9元,語(yǔ)音識(shí)別固定,支持57條語(yǔ)音,基本的是夠用了,基本的風(fēng)扇控制、燈控制、電飯煲控制、溫度控制等都具備,基本上比較全面。1.2 模塊特性
處理內(nèi)核:
- 32bit RISC 內(nèi)核, 運(yùn)行頻率 240M
- 支持 DSP 指令集以及 FPU 浮點(diǎn)運(yùn)算單元
- FFT 加速器:最大支持 1024 點(diǎn)復(fù)數(shù) FFT/IFFT 運(yùn)算或者是2048 點(diǎn)的實(shí)數(shù) FFT/IFFT 運(yùn)算
- 定制化語(yǔ)音算法算子
存儲(chǔ):
- 內(nèi)置高速 SRAM
- 內(nèi)置 2MB FLASH
音頻輸入輸出:
- 支持 1 路模擬 Mic 輸入
- 支持雙聲道 DAC 輸出
- 持 I2S input/output
供電和時(shí)鐘:
- 內(nèi)置 5V 轉(zhuǎn) 3.3V, 3.3V 轉(zhuǎn) 1.2V LDO 為芯片供電
- RC 12MHz 時(shí)鐘源和 PLL 鎖相環(huán)時(shí)鐘源
- 置 POR(Power on Reset) , 低電壓檢測(cè)和看門狗
系統(tǒng)功能框圖:
引腳介紹:
??模塊有 16 個(gè)引腳, 包括功放輸出、 差分輸入與串口。具體定義說(shuō)明見(jiàn)下表。機(jī)械尺寸:
功能描述
??HLK-V20模塊是可以控制自身IO的,有幾個(gè)IO可以通過(guò)語(yǔ)音控制使用,實(shí)現(xiàn)基本的控制功能,具體使用如下:- 模塊喚醒后, 使用命令詞” 打開(kāi)空調(diào)” ,對(duì)應(yīng)模塊上 B7 引腳, 使用命令詞” 關(guān)閉空調(diào)” ,B7 輸出對(duì)應(yīng)電平
- 使用命令詞” 打開(kāi)燈光” , 對(duì)應(yīng)模塊上 B6 引腳, 使用命令詞” 關(guān)閉燈光” , B6 輸出對(duì)應(yīng)電平
- 使用命令詞” 打開(kāi)開(kāi)關(guān)” ,對(duì)應(yīng)模塊上 B2 引腳, 使用命令詞” 關(guān)閉開(kāi)關(guān)” , B2 輸出對(duì)應(yīng)電平
1.3 模塊輸出數(shù)據(jù)協(xié)議格式分析
??采用外接MCU的控制方法,那就必須首先對(duì)模塊輸出的數(shù)據(jù)協(xié)議格式進(jìn)行分析,正確解析數(shù)據(jù)之后才能實(shí)現(xiàn)我們的功能,廠家出廠是有一套固定協(xié)議的,如果需要更改為自己的協(xié)議,需要廠家定制,估計(jì)走量的,暫時(shí)用廠家的就可以啦。協(xié)議格式說(shuō)明:??Payload 為喚醒與命令詞對(duì)應(yīng)的 action 標(biāo)識(shí), 喚醒對(duì)應(yīng)的 action 為 wakeup_uni, 命令詞對(duì)應(yīng)的 action 詳見(jiàn)后面介紹,對(duì)于我們來(lái)說(shuō),最重要的是解析出來(lái)action數(shù)據(jù),根據(jù)action數(shù)據(jù)內(nèi)容具體來(lái)定制我們要控制的設(shè)備。??下圖為語(yǔ)音喚醒與命令詞對(duì)應(yīng)的串口數(shù)據(jù)(hex 格式), 8 條數(shù)據(jù)分別表示為喚醒、 打開(kāi)臺(tái)燈、 關(guān)閉臺(tái)燈、 打開(kāi)空調(diào)、 關(guān)閉空調(diào)、 打開(kāi)浴霸、 關(guān)閉浴霸、 退出識(shí)別狀態(tài)??關(guān)于提到的action字段,參考廠家提供的離線命令詞與播報(bào)答復(fù)列表,簡(jiǎn)單列舉一些:
??紅框里面是模塊收到語(yǔ)音控制命令之后,串口輸出的數(shù)據(jù),我們只需要把這部分?jǐn)?shù)據(jù)解析出來(lái),知道當(dāng)前是什么指令,然后控制相應(yīng)的設(shè)備即可。
2 軟件實(shí)現(xiàn)
??主要用到串口1、串口3,定時(shí)器7、定時(shí)器3,串口1用于調(diào)試信息打印,定時(shí)器3用于PWM控制燈光亮度,實(shí)現(xiàn)調(diào)光功能,串口3用于接收模塊串口輸出數(shù)據(jù)、解析數(shù)據(jù),定時(shí)7用于控制串口數(shù)據(jù)接收超時(shí),下面來(lái)小飛哥來(lái)一步步介紹實(shí)現(xiàn)過(guò)程。2.1 cubemx配置
??時(shí)鐘配置,參考上us延時(shí)3種實(shí)現(xiàn)方法一文,就不再做詳細(xì)介紹了。串口配置:
??串口1配置,主要配置下圖紅框中的幾項(xiàng)即可,開(kāi)啟接收中斷,中斷優(yōu)先級(jí)可以選擇默認(rèn)的即可,波特率115200。??串口2配置,基本同串口1配置,也是主要配置下圖紅框中的幾項(xiàng)即可,開(kāi)啟接收中斷,中斷優(yōu)先級(jí)可以選擇默認(rèn)的即可,波特率115200。定時(shí)器配置:
??定時(shí)器3配置,定時(shí)器3時(shí)鐘為 84M/84=1Mhz,重裝載值 500,所以 PWM 頻率為 1M/500=2Khz。??定時(shí)器7配置,定時(shí)7配置為1ms周期,后面串口超時(shí)時(shí)間具體在配置。??配置完之后的中斷開(kāi)啟情況如下圖:??配置完之后的IO使用情況如下圖:2.2 PWM簡(jiǎn)介
??脈沖寬度調(diào)制(PWM),是英文“Pulse Width Modulation” 的縮寫,簡(jiǎn)稱脈寬調(diào)制,是利用微處理器的數(shù)字輸出來(lái)對(duì)模擬電路進(jìn)行控制的一種非常有效的技術(shù)。簡(jiǎn)單一點(diǎn),就是對(duì)脈沖寬度的控制,PWM 原理如圖 所示:??上圖就是一個(gè)簡(jiǎn)單的 PWM 原理示意圖。圖中,我們假定定時(shí)器工作在向上計(jì)數(shù) PWM模式,且當(dāng) CNT2.3 代碼編寫
硬件連接
- 主控MCU與HLK-V20連接
STM32 | HLK-V20 |
---|---|
VCC-5V | VCC |
GND | GND |
RX(PA3) | TX |
- HLK-V20yu 揚(yáng)聲器連接
揚(yáng)聲器 | HLK-V20 |
---|---|
任意端 | SP |
任意端 | SP- |
- 主控MCU與受控設(shè)備連接
STM32 | 受控設(shè)備 |
---|---|
PB0(TIM3-CH3) | 臺(tái)燈LED正極 |
GND | 臺(tái)燈LED負(fù)極 |
PF9 | 開(kāi)燈LED正極 |
GND | 開(kāi)燈LED負(fù)極 |
PB5 | 紅燈LED正極 |
GND | 紅燈LED負(fù)極 |
串口2代碼編寫
??初始化部分由cubemx配置完成,就不啰嗦了,配置的正確,就不會(huì)有問(wèn)題。typedef?struct?{
?char?Rxbuff[100];
?uint8_t?RxData;
?uint8_t?RxCnt;
?uint8_t?RxTimCnt;
?uint8_t?RxRecFlag;
?uint8_t?RxEndFlag;
}uart2_para;
uart2_para?Voice_RevPara;
/**
??*?@brief??串口中斷回調(diào)函數(shù)
??*?????????
??*?@param??
??*?@param??
??*?@retval?none
??*/
void?HAL_UART_RxCpltCallback(UART_HandleTypeDef?*huart)
{
?if(huart->Instance==USART1)
?{
???Voice_RecUartCallBack();
?}
?else?if(huart->Instance==USART2)
?{
???Voice_RecUartCallBack();
?}
}
/**
??*?@brief??語(yǔ)音模塊串口中斷回調(diào)函數(shù)
??*?????????
??*?@param??none
??*?@param??none
??*?@retval?none
??*/
void?Voice_RecUartCallBack(void)?
{
??Voice_RevPara.RxTimCnt?=?0;
??Voice_RevPara.RxRecFlag?=?1;?????
??Voice_RevPara.Rxbuff[Voice_RevPara.RxCnt]?=?Voice_RevPara.RxData;
??Voice_RevPara.RxCnt ;
??if(Voice_RevPara.RxCnt>=100){
???Voice_RevPara.RxCnt=0;
??}
??HAL_UART_Receive_IT(