我根据样例程序,编写出这次项目的程序,任务是:当发出“亮灯”(liang deng)和“关灯”(guan deng)声音,识别后通过串口,向上位机Labview分别发出字符‘a’和‘b’,否则发出字符‘e’。我把程序中需特别关心的程序段用红色字体标注出来。
#include Voice.h //申明语音识别库文件
#define SUM 2 //定义待识别的单词数量
uint8 nAsrStatus=0; //申明语音模块工作状态
char flag;//定义向上位机发送字符命令的变量
//定义识别单词“拼音”内容的数组
char sRecog[SUM][80] = {liang deng, guan deng};
//根据单词数组的元素号,执行相应命令
void finally (unsigned char n)
{
switch(n)
{
case 0:
flag='a';//亮灯命令
Serial.print(flag);
break;
case 1:
flag='b';//关灯命令
Serial.print(flag);
break;
default:
flag='e';
Serial.print(flag);
break;
}
}
//识别到声音,触发中断
void ExtInt0Handler ()
{
Voice.ProcessInt0(); //执行中断服务子程序
}
//初始化
void setup()
{
Serial.begin(9600); //启动串行通信
Voice.Initialise(MIC);//初始化语音模块设置
attachInterrupt(0,ExtInt0Handler,LOW);
}
//主程序
void loop()
{
uint8 nAsrRes;
nAsrStatus = LD_ASR_NONE;
while(1)
{
//当模块处于各状态,执行相应工作
switch(nAsrStatus)
{
case LD_ASR_RUNING:
flag='e';
Serial.print(flag);
break;
case LD_ASR_ERROR:
break;
case LD_ASR_NONE:
{
nAsrStatus=LD_ASR_RUNING;
if (Voice.RunASR(SUM,80,sRecog)==0)
{
nAsrStatus= LD_ASR_ERROR;
//Serial.println( ASR_ERROR);
}
//Serial.println( ASR_RUNING.....);
break;
}
//识别到单词是设定单词
case LD_ASR_FOUNDOK:
{
//Serial.print( ASR_FOUN ONE: );
//提取所识别到的单词是数组的第几个元素
nAsrRes =Voice.LD_GetResult();
//根据数组元素号,执行相应命令
finally(nAsrRes);
nAsrStatus = LD_ASR_NONE;
break;
}
//识别到单词“不是”设定单词
case LD_ASR_FOUNDZERO:
{
//Serial.println( ASR_FOUND ZERO);
nAsrStatus = LD_ASR_NONE;
break;
}
default:
{
nAsrStatus = LD_ASR_NONE;
break;
}
}// switch
delay(40);
}// while
}
Labview 是由美国国家仪器公司推出的,主要面向计算机测控领域的虚拟仪器软件开发平台,是一种基于图形开发、调试和运行的集成化环境。
Labview虚拟仪器程序由前面板和框图程序组成,前面板是人机交互的界面,界面上有用户输入和显示输出两类控件;框图程序则是用户编制的程序源代码,以定义和控制在前面板上的控件输入和输出功能。
上位机的Labview软件通过串口读取Arduino下位机上传的字符命令,并处理和显示出“虚拟灯”的亮灭情景。
Labview前面板:
把层叠了语音识别模块的Arduino控制器与PC机用USB电缆连接起来,您在windows操作系统的设备管理器里的“端口”栏目里会发现Arduino控制器生成的串口号,我生成的串口号是COM3,所以Labview的前面板的串口号,设置为COM3 。由于下位机Arduino程序的串行通信启动命令是Serial.begin(9600),所以labview前面板的波特率也要对应设置为9600 。
Labview框图程序:
上图的图形化框图程序是采用NI_VISA串口Serial函数来访问和控制串口的。VISA中的Serial函数库里包含VISA Configure Serial Port、VISA Write、VISA Read、VISA Close等子函数。用到的三个VISA串口子函数分别是VISA串口配置函数VISA Configure Serial Port、VISA读取函数VISA Read和VISA 关闭函数VISA Close。它们的图标分别下图所示:
对于NI_VISA串口Serial函数的使用请看文章:《基于labview串口通讯的虚拟数字电压表的设计》 http://www.eefocus.com/zhang700309/blog/11-11/233937_797a0.html 。
从Labview框图程序看出,Labview程序每20ms,从下位机读取一个字符,如果字符是'a',则给“布尔”变量赋值true,然后“布尔”变量值送到“灯”、“指纹开关”,于是它们会点亮,同时把字符串“灯亮了”显示出来。如果读取的字符是'b',则“布尔”变量赋值false,“灯”、“指纹开关”会熄灭,同时把字符串“灯熄了”显示出来。如果字符是'e',则“布尔”变量赋值给它本身,所有控件状态保持原状。
这个labview程序用到的稍微高级点技术是图片导入、自定义控件和局部变量,我在三年前曾经录制过它们的视频讲座,没想到今天用上了,可以看看。
Labview图片导入、自定义控件和事件结构:
Labview美化控件方法:
Labview自定义控件制作方法的补充:
局部变量、机械动作和高亮调试:
从DFRobot公司的语音识别模块说明书网页里,可以看到一些提高语音识别准确率的技巧,我也没有仔细研究,我的一个解决之道是如果这个单词拼音容易识别出错,那就换个“铿锵有力”的单词拼音即可,例如把开灯kai deng换成亮灯liang deng。
对语音识别模块的评价:如果操作时,背景噪音不大,并用于科技娱乐和教学实验,应该是胜任的;如果用于工业控制和军事作战当然不靠谱。不知道您将把它用于何处,反正我是用在科技娱乐,所以将来会经常用到它。