宜昌老张

DFRobot语音识别模块与Labview虚拟灯的对话

0
阅读(4577)

   

    晚上,在书房微弱的光影照耀下,DFRobot语音模块电路板上LED指示灯静静地发出绿油油的光芒,看着刚做出的Labview前面板上的虚拟灯,思想却飘向了远方,我在什么样的空间,做着什么样的事,这事有什么现实意义,是否自己感觉有意思。仿佛在雾气里探寻什么,用头脑和手去抓住什么,但什么也暂时抓不住,所以一直羡慕国外的创客们,单纯的追求和单纯的幸福,或许正是因为他们天真地在世外桃源里的实践,新的产品和新的行业也由此诞生。

   收回思想,回到书桌前,朝向语音模块上的麦克风,用标准男中音,发出亮灯“liang deng”,关灯"guan deng"的声音,PC机屏幕的Labview前面板上的虚拟灯居然蛮听话的,让它亮灯,它就亮,让它熄灯,它就暗下来,由此通过语音识别模块实现了我与“虚拟灯”的对话。     

   说说这篇文章介绍的主角吧,DFRobot公司研发的中文语音识别模块Voice Recognition,我就是利用它与“虚拟灯”沟通,由于只是应用层面的事,所以也不是什么难事。

  Voice Recognition语音识别模块是一款只需要在主控MCU的程序中设定好要识别的关键词语列表,并动态地把这些关键词语以字符的形式传送到芯片内部,就可以对用户说出的关键词语进行识别,不需要用户事先训练和录音的非特定人语音识别模块。该模块可以设置50项候选识别句,每个识别句可以是单字,词组或短句,长度为不超过10个汉字或者79个字母的拼音串,可由一个系统支持多种场景。

  Voice Recognition语音识别模块采用叠层设计,可以直接插接到Arduino控制器上,用户使用Arduino便可以快速设计产品原型,例如电磁炉/微波炉/洗衣机/智能家电操作,导航仪,MP3/MP4,数码像框,机顶盒/彩电遥控器,智能玩具/对话玩具,PMP/游戏机,自动售货机,地铁自动售票机,导游机,楼宇电视的广告点播,照明系统的声控等等。

Voice Recognition语音识别模块与Arduino控制板层叠图:(上面的电路板是语音模块,下面压着的Arduino控制器,它们通过排针与排座结合)

Voice Recognition语音识别模块的端口分布和功能说明

注意:MONO端口不是外置麦克风的插口,您的声音只能通过板载MIC麦克风传到模块的芯片里进行处理。

   另外看看层叠在Arduino控制板上的Voice Recognition语音识别模块已经占用的Arduino资源,这些资源就不能使用了。

 

Voice Recognition模块语音识别

语音识别,识别的是“语音”。对于非特定人语音识别来说,在描述关键词语时,是用音标标注出要识别的关键词语。

对于Voice Recognition模块支持的中文识别来说,就是用拼音来描述出关键词语。

也就是说,只要是拼音可以拼出的发音,都是可以进行识别的。

因此,在某些场合需要识别一些简单的外文或者纯方言发音的时候,可以用拼音标注的方法来实现。

例如,有些场合需要识别一些简单的英文单词,可以用拼音标注:

one → wan

two → tu

three → si rui

例如,有些场合需要识别一些纯方言发音的词汇,也可以用拼音标注:

上海话的“晚”发音是“ya”,那么“晚报”这个词汇,用普通话标注是“wan bao”,如果要标注成上海话发音,就是“ya bao”,这样上海话说的“晚报”也就可以被识别了。

值得注意的是:模块支持的是中文普通话,有些外文或者方言发音无法用拼音描述,所以模块不一定能够完成所有需要的外文或者方言任务。

Voice Recognition语音识别模块说明书网页:http://goo.gl/fvOVq

 

  我曾经用WIN7自带的语音识别组件,做过类似的实验,文章《用微软MSRDS软件的语音识别技术遥控乐高机器人》,

网址:http://blog.chinaaet.com/detail/27668.html

   您要问我两者有何区别?我感觉语音识别的准确率差不多,不同的是用WIN7自带的语音识别组件来做应用,需要大块头的PC个人电脑,而用DFRobot语音模块,只需把模块层叠在Arduino UNO控制板上,使用起来方便、小巧、灵活!

   现在来谈谈语音识别模块的编程了,当然首先应该安装它的库文件,库文件请下载:11206034951355.zip

 

    Arduino系统之所以好用,不仅是单片微机本身编程容易,而且给它的外设编程时,只要程序稍复杂些,大都可以从网络上或者厂家得到相应的库文件,语音模块自然也有好用的库文件。
      把DFRobot 语音识别模块的库文件存放在Arduino IDE软件文件夹里的libraries目录里,这个库文件就可用了,如下图。
   一定记住这个模块不能用Arduino 0018版软件编程,因为这个版本没有SPI库文件,希望采用Arduino 0022版软件来编写程序。如果用最新的Arduino 1.0版,也不行。
   在Arduino IDE编程环境里,可以打开库文件里自带的样例程序,先学习下。这些样例程序对于初学者还是要耐心研究才能看明白,它的好处是你不需编写程序,就可以试试硬件模块的功效,然后你慢慢改动下程序的内容,看看实验现象,有何变化,这有助于逐步地理解程序。
 
   我根据样例程序,编写出这次项目的程序,任务是:当发出“亮灯”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框图程序:
Labview程序,我是用Labview2010版编写的,可下载:11240913659577.zip

   上图的图形化框图程序是采用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://blog.chinaaet.com/detail/23353.html 。

   从Labview框图程序看出,Labview程序每20ms,从下位机读取一个字符,如果字符是'a',则给“布尔”变量赋值true,然后“布尔”变量值送到“灯”、“指纹开关”,于是它们会点亮,同时把字符串“灯亮了”显示出来。如果读取的字符是'b',则“布尔”变量赋值false,“灯”、“指纹开关”会熄灭,同时把字符串“灯熄了”显示出来。如果字符是'e',则“布尔”变量赋值给它本身,所有控件状态保持原状。

    这个labview程序用到的稍微高级点技术是图片导入、自定义控件和局部变量,我在三年前曾经录制过它们的视频讲座,没想到今天用上了,可以看看。

 Labview图片导入、自定义控件和事件结构:

 

Labview美化控件方法

Labview自定义控件制作方法的补充

局部变量、机械动作和高亮调试

   从DFRobot公司的语音识别模块说明书网页里,可以看到一些提高语音识别准确率的技巧,我也没有仔细研究,我的一个解决之道是如果这个单词拼音容易识别出错,那就换个“铿锵有力”的单词拼音即可,例如把开灯"kai deng"换成亮灯"liang deng"。

    对语音识别模块的评价:如果操作时,背景噪音不大,并用于科技娱乐和教学实验,应该是胜任的;如果用于工业控制和军事作战当然不靠谱。不知道您将把它用于何处,反正我是用在科技娱乐,所以将来会经常用到它。