使用STM32实现一个离线语音控制器
扫描二维码
随时随地手机看文章
成就一番伟业的唯一途径就是热爱自己的事业。如果你还没能找到让自己热爱的事业,继续寻找,不要放弃。跟随自己的 心,总有一天你会找到的。——乔布斯
你去关灯,你去,你去,。。我去。。小伙伴们有没有在天气寒冷时候,想去关灯,却离不开心爱的被窝的经历呢,有的话,跟着小飞哥一起来DIY一个离线语音控制器,有了它,我们就可以安稳的卧在暖和的被窝了,来,干!
先看看演示视频:
完成目标
- HAL库串口使用
- 常用串口接收及数据协议解析
- 接收离线语音控制模块数据、解析,实现相应的控制
硬件环境
- STM32F407ZGT6(或其他主控板)
- 海凌科HLK-V20离线语音控制模块
- 电容式驻极体话筒(咪头)
- 杜邦线,LED灯,实验用到3个LED灯,面包板(非必备)
软件环境
- keil5
- cubemx
1 离线语音模块控制器
1.1 模块简介
在某宝购买的,只需要9.9元,语音识别固定,支持57条语音,基本的是够用了,基本的风扇控制、灯控制、电饭煲控制、温度控制等都具备,基本上比较全面。1.2 模块特性
处理内核:
- 32bit RISC 内核, 运行频率 240M
- 支持 DSP 指令集以及 FPU 浮点运算单元
- FFT 加速器:最大支持 1024 点复数 FFT/IFFT 运算或者是2048 点的实数 FFT/IFFT 运算
- 定制化语音算法算子
存储:
- 内置高速 SRAM
- 内置 2MB FLASH
音频输入输出:
- 支持 1 路模拟 Mic 输入
- 支持双声道 DAC 输出
- 持 I2S input/output
供电和时钟:
- 内置 5V 转 3.3V, 3.3V 转 1.2V LDO 为芯片供电
- RC 12MHz 时钟源和 PLL 锁相环时钟源
- 置 POR(Power on Reset) , 低电压检测和看门狗
系统功能框图:
引脚介绍:
模块有 16 个引脚, 包括功放输出、 差分输入与串口。具体定义说明见下表。机械尺寸:
功能描述
HLK-V20模块是可以控制自身IO的,有几个IO可以通过语音控制使用,实现基本的控制功能,具体使用如下:- 模块唤醒后, 使用命令词” 打开空调” ,对应模块上 B7 引脚, 使用命令词” 关闭空调” ,B7 输出对应电平
- 使用命令词” 打开灯光” , 对应模块上 B6 引脚, 使用命令词” 关闭灯光” , B6 输出对应电平
- 使用命令词” 打开开关” ,对应模块上 B2 引脚, 使用命令词” 关闭开关” , B2 输出对应电平
1.3 模块输出数据协议格式分析
采用外接MCU的控制方法,那就必须首先对模块输出的数据协议格式进行分析,正确解析数据之后才能实现我们的功能,厂家出厂是有一套固定协议的,如果需要更改为自己的协议,需要厂家定制,估计走量的,暂时用厂家的就可以啦。协议格式说明: Payload 为唤醒与命令词对应的 action 标识, 唤醒对应的 action 为 wakeup_uni, 命令词对应的 action 详见后面介绍,对于我们来说,最重要的是解析出来action数据,根据action数据内容具体来定制我们要控制的设备。 下图为语音唤醒与命令词对应的串口数据(hex 格式), 8 条数据分别表示为唤醒、 打开台灯、 关闭台灯、 打开空调、 关闭空调、 打开浴霸、 关闭浴霸、 退出识别状态关于提到的action字段,参考厂家提供的离线命令词与播报答复列表,简单列举一些:
红框里面是模块收到语音控制命令之后,串口输出的数据,我们只需要把这部分数据解析出来,知道当前是什么指令,然后控制相应的设备即可。
2 软件实现
主要用到串口1、串口3,定时器7、定时器3,串口1用于调试信息打印,定时器3用于PWM控制灯光亮度,实现调光功能,串口3用于接收模块串口输出数据、解析数据,定时7用于控制串口数据接收超时,下面来小飞哥来一步步介绍实现过程。2.1 cubemx配置
时钟配置,参考上us延时3种实现方法一文,就不再做详细介绍了。串口配置:
串口1配置,主要配置下图红框中的几项即可,开启接收中断,中断优先级可以选择默认的即可,波特率115200。 串口2配置,基本同串口1配置,也是主要配置下图红框中的几项即可,开启接收中断,中断优先级可以选择默认的即可,波特率115200。定时器配置:
定时器3配置,定时器3时钟为 84M/84=1Mhz,重装载值 500,所以 PWM 频率为 1M/500=2Khz。 定时器7配置,定时7配置为1ms周期,后面串口超时时间具体在配置。 配置完之后的中断开启情况如下图: 配置完之后的IO使用情况如下图:2.2 PWM简介
脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制,PWM 原理如图 所示: 上图就是一个简单的 PWM 原理示意图。图中,我们假定定时器工作在向上计数 PWM模式,且当 CNT2.3 代码编写
硬件连接
- 主控MCU与HLK-V20连接
STM32 | HLK-V20 |
---|---|
VCC-5V | VCC |
GND | GND |
RX(PA3) | TX |
- HLK-V20yu 扬声器连接
扬声器 | HLK-V20 |
---|---|
任意端 | SP |
任意端 | SP- |
- 主控MCU与受控设备连接
STM32 | 受控设备 |
---|---|
PB0(TIM3-CH3) | 台灯LED正极 |
GND | 台灯LED负极 |
PF9 | 开灯LED正极 |
GND | 开灯LED负极 |
PB5 | 红灯LED正极 |
GND | 红灯LED负极 |
串口2代码编写
初始化部分由cubemx配置完成,就不啰嗦了,配置的正确,就不会有问题。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 串口中断回调函数
*
* @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 语音模块串口中断回调函数
*
* @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(