宜昌老张

语音识别、XBee、无线遥控与乐高智能车

0
阅读(3227)

   

   我喜欢逐步把问题搞清楚,慢慢来,急不得,一个个知识点去实践。因此文章题目中的关键词“语音识别、XBee、无线遥控、乐高智能车”,我已经用三篇文章介绍了,看完这三篇文章,今天的文章所介绍的内容也就水到渠成了。前面的三篇文章的标题、图片和网址如下。

《乐高8275科技套件B模型的Arduino电控改造(双单片机蓝牙通信)》,

网址:http://blog.chinaaet.com/detail/28854.html 。

 

《美国DIGI公司的XBee模块无线通讯实验》,

网址:http://blog.chinaaet.com/detail/29230.html 。

 

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

网址:http://blog.chinaaet.com/detail/29414.html 。

   这篇文章所介绍的作品任务是:发布语音命令给遥控器主机,遥控器上有语音识别模块,它识别出语音命令,并处理成相应单字符标志,并及时把单字符通过XBee无线通讯,以RS232串口协议传送给从机控制器,从机控制器再根据这些单字符标志,控制乐高智能车的三个舵机,完成小车前后左右行走和机械手抓放物体的动作。从任务描述看,作品体现出四个关键词:语音识别、XBee、无线遥控、乐高智能车。

语音遥控机械手车作品的功能说明图:

  用的时候,把上图右边的XBee传感器扩展板层叠到右侧的语音识别模块上。

工作视频:

    遥控器主机任务是:当发出人声,前进"qian jin",后退"hou tui",左转"zuo zhuan",右转"you zhuan",抓起"zhua qi",放下"fang xia",停止"ting zhi"时,通过语音识别模块处理后,无线串口通信,向上位机分别发送单字符标志,'a','b'、'c'、'd'、'f'、'g'、's'。

主机遥控器程序:(程序中关键程序段,我用红色字体标注)

向Arduino控制器“写”程序前,先把XBee模块从控制器的XBee专门接口上拔下来,否则程序无法“写”入,“写”完程序后,再插上XBee模块。

#include <Voice.h> //申明语音识别库文件
#define SUM 7 //定义待识别的单词数量
uint8  nAsrStatus=0; //申明语音模块工作状态
//定义识别单词“拼音”内容的数组
char sRecog[SUM][80] = 
{"qian jin","hou tui","zuo zhuan","you zhuan","zhua qi","fang xia","ting zhi"};
char flag;//定义向上位机发送字符命令的变量
//根据单词数组的元素号,执行相应命令
void finally (unsigned char n)
{
   switch(n) 
{
    case 0:
     flag='a';//小车前进
     Serial.print(flag);              
    break;
    case 1:
     flag='b'; //小车后退
              Serial.print(flag);              
     break;
        case 2:
     flag='c'; //小车左转
              Serial.print(flag);
              break;
        case 3:
     flag='d'; //小车右转
              Serial.print(flag);
              break;
        case 4:
     flag='f';//机械手抓起 
              Serial.print(flag);
              break;
        case 5:
     flag='g';//机械手放下 
              Serial.print(flag);
              break;
        case 6:
     flag='s'; //小车停止
              Serial.print(flag);
              break;
      default:        
              flag='e'; 
              Serial.print(flag);
                break;       
}
}
//识别到声音,产生一个触发中断
void ExtInt0Handler ()
{
  Voice.ProcessInt0();//执行中断服务子程序
}
//初始化
void setup()
{
  Serial.begin(115200);//串行通信启动
  Voice.Initialise(MIC);//初始化语音模块
  attachInterrupt(0,ExtInt0Handler,LOW);  
}
//主程序
void loop()
{  
        uint8 nAsrRes;
nAsrStatus = LD_ASR_NONE;
while(1)
{
//当语音模块处于各状态,执行相应工作
 switch(nAsrStatus)
{
case LD_ASR_RUNING:
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(10);
}// while
}
 

    从机控制器任务是:当接收到主机遥控器发送来的单字符命令,'a','b'、'c'、'd'、'f'、'g'、's'时,通过从机控制器处理后,驱动小车的两个舵机和机械手的一个舵机,完成前进,后退,左转,右转,抓起,放下,停止的动作

从机控制器程序:(程序中关键程序段,我用红色字体标注)

#include "Servo.h"  //声明舵机函数库
Servo controlservo;  // 定义机械手舵机对象变量
Servo rightservo;  // 定义小车右车轮舵机对象变量
Servo leftservo;  // 定义小车左车轮舵机对象变量
int power1=80;//定义360°旋转舵机功率变量和初始化设置
int power2=10;
int val;   //存储从机接受主机发送的单字节命令的变量
//初始化
void setup()
{
   Serial.begin(115200);//设置串行通信的波特率,启动串行通信   
   controlservo.attach(3); //定义3号数字量引脚来控制机械手舵机 
   rightservo.attach(9);  //定义9号数字量引脚来控制小车右舵机
   leftservo.attach(10); //定义10号数字量引脚来控制小车左舵机
   //连续旋转的舵机, 执行myservo.write(90),舵机的速度可能不为0,
   //我手头的舵机,执行myservo.write(93),舵机的速度才为0。
   controlservo.write(93);//初始化三个舵机为停止状态
   rightservo.write(93);
   leftservo.write(93);
}
//主程序
void loop()
{
  if(Serial.available()>0) //查询串口有无数据
  {
        val=Serial.read();//读取主机发送的字符
         if(val=='a')//如果主机发送字符为'a'
        {
          //小车前进
           rightservo.write(93+power1);
           leftservo.write(93-power1); 
           controlservo.write(93);        
        }
        if(val=='b')//如果主机发送字符为'b'
        {
          //小车后退
           rightservo.write(93-power1);
           leftservo.write(93+power1);
           controlservo.write(93);           
        }
        if(val=='c')//如果主机发送字符为'c'
        {
           //小车左转
           rightservo.write(93-power2);
           leftservo.write(93-power2); 
           controlservo.write(93);                     
        }
        if(val=='d')//如果主机发送字符为'd'
        {
           //小车右转
           rightservo.write(93+power2);
           leftservo.write(93+power2); 
           controlservo.write(93);         
        }
        if(val=='f')//如果主机发送字符为'e'
        {
           //机械手抓取物体 
            controlservo.write(180);  
            rightservo.write(93);
            leftservo.write(93);         
        }
        if(val=='g')//如果主机发送字符为'f'
        {
            //机械手松开物体
            controlservo.write(0);
            rightservo.write(93);
            leftservo.write(93);           
        }
        if(val=='s')//如果主机发送字符为'n'
        {
          //所有舵机停止
          controlservo.write(93);  
          rightservo.write(93);
          leftservo.write(93);        
        }       
  }     
}