基于matlabCUI以及STM32F103单片机的消防小车设计
前言
基于课程的设计训练的原因,我们需要在脑电、肌点等信号控制的题目中选择一个项目进行上述信号控制智能小车或者机械臂的需要,由于目前技术水平的限制,并考虑到最终完成的效果,我构思了模拟语音智能小车定点取水,并到达预定地点报警并进行不同方向的喷水消防的设计,经过长时间的试错,最终功能基本实现。
提示:以下是本篇文章正文内容,下面案例可供参考,由于前期语音识别系统借用哈尔滨工业大学一位同学的设计,但不做商业用途,侵权请删。
一、模块分类
1.语音识别系统
本模块的内容只是提供借鉴,如果功力深厚的同学可以运用此系统改造成传送系统,而不用下文提到的传送系统进行与小车交互。
2.语音传送系统
本模块利用的是API进行识别,说是识别,准确来说就是翻译,在此走了捷径,因为最后功能实现的需要不得已改为利用API的方法,如果时间足够完全可以利用语音识别系统进行训练识别。
3.语音接收执行系统
这个模块就是我们所熟知的智能小车,通过蓝牙模块,当然也可以是WIFI模块进行信号的传输,两个难度差不多,我使用的是蓝牙模块传输信号,小车接收信号后执行一系列的命令操作。
二、语音识别系统
1.训练
训练的内容需要自己进行录制导入,而我的模板主要是采用语音合成作为模板,当然也选择了最简单的123的数字,也可以选择前进后退等指令。训练模块需要注意的就是你的路径选择,如果语音模板文件没在路径中训练一般很难完成,同时也包括的你所需要的M文件,尽量放在同一个文件夹下,MATLAB界面导入路径。
训练代码如下:
k = 16; % number of centroids required
path='C:\Matlab2019\模板\';
for i = 1:n % 对数据库中的代码形成码本
file = sprintf('%ss%d.wav',path, i);
disp(file);
[s, fs] = audioread(file);
v=mfcc(s,fs); % 计算 MFCC's 提取特征特征,返回值是Mel倒谱系数,是一个log的dct得到的
code{i} = vqlbg(v, k); % 训练VQ码本 通过矢量量化,得到原说话人的VQ码本
end
```c
当然不止训练这个内容,其中还包括提取特征得到倒谱系数,并通过训练形成VQ码本等内容,具体链接及代码在最后给出,希望对大家有所帮助。
2.测试
测试部分可分为两种测试,百度有专业术语,搜索语音识别会给出术语解释,简单来说区别就在于一个基于识别内容,一个基于识别的人,基于内容也就是说只要你和我模板内容达到一定距离就认为识别成功;而基于人的识别是判断目前说话的这个人是不是录制模板的人,同样需要计算距离。而这里计算距离也就是识别成功与否的关键,在测试模块就包含了两个内容,一是录制现场声音文件通过训练形成模板,二是计算现场录制模板与提前录制好的模板的距离。
测试代码如下;
1.基于内容的测试
function testmsg = testDB(testdir,n,code)
nameList={'1','2','3','4','5','6','7','8','9' }; %这个是我们要识别的9个数
for k = 1:n
file = sprintf('%sa%d.wav', testdir, k); %找出文件的路径
disp(file);
[s, fs] = audioread(file);
k1=1;
v = mfcc(s, fs); % 对找到的文件取mfcc变换
distmin = inf;
for l = 1:length(code)
d = disteu(v, code{l});
dist = sum(min(d,[],2)) / size(d,1);
if dist < distmin
distmin = dist;%%这里和test函数里面一样 但多了一个具体语者的识别
k1=2;
end
end
msg=nameList{i}
msgbox(msg);
end
同样,训练形成VQ码本以及计算距离的M文件等内容,具体链接及代码在可免费索取。
三.语音传送系统
语音传送系统也正是我们用于语音信号处理传送的系统,主要分为四个模块:声音文件录入、API识别、结果对比、信号传输,此模块与上述的语音识别系统设计成GUI的模式,包括进入界面及两个系统界面,通过shibie.fig打开即可进入,此系统可直接使用,语音识别系统限于时间原因未能完善。
下面就是传送系统的各个模块。
1.声音文件录入及API识别
function pushbutton4_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton4 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global i;
Host = webread( 'https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=NWInBNZCuzQSMdUNGZOqIAuy&client_secret=7lUVyQRuaRGVE2xQGqHKRWETocajkv5E' );
Access_Token = Host.access_token;
request_url = 'http://vop.baidu.com/server_api';
fs=16000;
fprintf('录音中\n');
y=audiorecorder(fs,16,1);
recordblocking(y,1.5);
s1=getaudiodata(y,'int16');
axes(handles.axes1)
plot(s1)
xlabel('测试采样序列'),ylabel('信号幅');
fprintf('录音结束\n');
filename='C:\Matlab2019\测试\a1.wav';
audiowrite(filename,s1,fs);
fprintf('已保存\n');
[ Data, Freq] = audioread('C:\Matlab2019\测试\a1.wav');
newFreq = 16000;
[ P, Q ] = rat( newFreq/Freq );
Data = resample( Data, P, Q );
wavFilename = 'WavFile.wav';
audiowrite(wavFilename, Data, newFreq);
[base64string, base64len]= base64file('WavFile.wav');
options = weboptions('RequestMethod', 'post','HeaderFields',{ 'Content-Type','application/json'});
options.Timeout = 10;
Webpar = struct;
Webpar.format = 'wav';
Webpar.token = Access_Token;
Webpar.len = base64len;
Webpar.rate = 16000;
Webpar.speech = base64string;
Webpar.cuid = 'CUID';
Webpar.channel = 1;
Content = webwrite(request_url,Webpar,options);
disp(Content.result{:});
disp(Content.result{:});
i=Content.result{:};
2.识别结果对比
注意:此处指令同单片机程序指令对应。
global scom;
f=get(handles.edit1,'String');
switch(f)
case '前进'
fprintf(scom, '0');
case '左转'
fprintf(scom, '1');
case '右转'
fprintf(scom, '2');
case '停止'
fprintf(scom, '3');
case '45'
fprintf(scom, '4');
case '135'
fprintf(scom, '5');
case '喷水'
fprintf(scom, '6');
case '关闭'
fprintf(scom, '7');
case '抽水'
fprintf(scom, '8');
case '后退'
fprintf(scom, '9');
end
3.识别结果发送
注意:电脑蓝牙可能由于版本问题出现连接不上的情况,可更新蓝牙版本等方式实现正常连接,并且蓝牙打开时间较长,建议测试时保存蓝牙蓝牙连接。
打开蓝牙:
instrhwinfo('Bluetooth','Color Box');
scom=Bluetooth('Color Box',1);
fopen(scom);
fprintf('蓝牙已打开');
发送:
fprintf(scom, '0');%此处发送内容即是0、1、2等,务必与单片机上程序对应
关闭蓝牙:
fclose(scom);
delete(scom);
clear scom;
四.STM32接收执行
接收执行的智能小车实现语音发送指令的命令执行,主函数内容用Switch语句实现usart的中断接收,各个C文件包括小车的前进后退左转右转停止、水泵泵水、舵机不同角度转动、报警灯报警、usart接收等。
1.主程序
#include "stm32f10x.h"
#include "pwm.h"
#include "delay.h"
#include "moto.h"
#include "bsp_timer1.h"
#include "beng.h"
#include "led.h"
#include "bluetooth.h"
#include "sys.h"
extern u8 receByte;
int main(void)
{
delay_init(); //ÑÓʱº¯Êý³õʼ»¯
beng_Confing();
My_TIM3_Init(19999,71);//ÖÜÆÚΪ20ms £¨arr+1)(psc+1)/Tclk =72MHz72000000hz=0.02s
MOTO_GPIO_Config();
LED_Init();
Bluetooth_Init(9600);
NVIC_Configuration();
TIM1_PWM(100,36);
delay_ms(200);
// GPIO_ResetBits(GPIOA,GPIO_Pin_11);
// GPIO_ResetBits(GPIOA,GPIO_Pin_12);
// TIM_SetCompare1(TIM3,0);
// ZYSTM32_run(0,0);
// Car_Stop();
while(1)
{
if(receByte==0x30){
MOTO_Z_PWM_Out(70, 70); //ºóÂÖ70%PWM
MOTO_Y_PWM_Out(74, 74); //Ç°ÂÖ70%PWM
Car_Go();
}else if(receByte==0x31){
MOTO_Z_PWM_Out(50, 50); //ºóÂÖ70%PWM
MOTO_Y_PWM_Out(80, 80); //Ç°ÂÖ70%PWM
delay_ms(100);
Car_Left();
}
else if(receByte==0x32){
MOTO_Z_PWM_Out(80, 80); //ºóÂÖ70%PWM
MOTO_Y_PWM_Out(20, 20); //Ç°ÂÖ70%PWM
delay_ms(100);
Car_Right();
}else if(receByte==0x33){
Car_Stop();
delay_ms(200);
TIM_SetCompare1(TIM3,1600);//90¶È
delay_ms(200);
}
else if(receByte==0x34){
TIM_SetCompare1(TIM3,2000);
}
else if(receByte==0x35){
TIM_SetCompare1(TIM3,1200);
}
else if(receByte==0x36){
baojing();
ZYSTM32_run();
}
else if(receByte==0x37){
ZYSTM32_stop();
guandeng();
}
if(receByte==0x38){
ZYSTM32_back();
delay_ms(50);
}
if(receByte==0x39){
MOTO_Z_PWM_Out(70, 70); //ºóÂÖ70%PWM
MOTO_Y_PWM_Out(72, 72); //Ç°ÂÖ70%PWM
Car_Back();
}
}
}
其他部分就不加上了,所有代码在最后附录。本设计可以不加调速模块,但建议是加上,很大程度调试过程会出现左右轮速度不一致而不能直行的情况,同时建议使用一般市面上的黄色小车,此种车可实现较高角度转弯。
总结
1.设计过程中需要较多调试,需要特别注意的是蓝牙连接,此过程可不进行电脑GUI发送命令手机接收的实验过程(这需要另外的与手机的配对连接),可直接连接单片机;
2.左右轮需要耐心调速;
3.使用水泵时请阅读使用说明。由于本次水泵为借用别人的,以前未有使用水泵的经验,在用水泵过程中犯了很多低级错误,水泵有些需要需要整个浸水,有些不需要,得注意。