新拿到了一个机器人小车套件: 切诺基4WD移动机器人平台。
想用它来做一个语音控制的小车。总共分为三个部分进行。
硬件列表:
第一部分:小车运动。
步骤一: 硬件搭建。
既然是小车,首先要做的就是让小车走起来,这个难度不大,高手可以直接略过。但是作为机器人小白的我,还是很乐意跟大家分享一下这辆小车的安装调试的。
我拿到的切诺基4WD移动机器人平台上面有一块板子Romeo V2。
在用它和语音模块结合的时候,发现只要将语音控制程序载进去,一上传成功,端口立马消失。这个问题倒腾了很久,后来DFRobot的工程师告诉我,Romeo V2是基于ATmega32u4芯片的Leonardo板卡,在硬件上不支持语音识别模块。:'(:'(:'(让眼泪先飞一会。 当然,这点小问题还是难不倒咱们滴。此路不通,再换一条好啦。这次我使用的是DFRduino UNO R3。
我们的切诺基4WD移动机器人平台是自带电机驱动的,所以不需要再叠加电机驱动扩展板了。 首先将4个电机引出来的线分别连接到M1、M2、M3、M4四个接线柱上。小车运行方向除了可以在程序中通过设置高低电平或者设置正负运行速度来完成,还可以改变接线次序。一般而言,红线接正极,黑线接负极,具体情况可以自行测试。将移动机器人平台上的D4、D5、D6、D7引脚用面包线连接到主控板的数字针脚4、5、6、7。接线图如下:
步骤二:程序编写。 搭建完毕,给板卡下载程序。程序可参考商城给出的样例代码。
- int E1 = 5; //M1 Speed Control
- int E2 = 6; //M2 Speed Control
- int M1 = 4; //M1 Direction Control
- int M2 = 7; //M1 Direction Control
-
- void stop(void) //Stop
- {
- digitalWrite(E1,0);
- digitalWrite(M1,LOW);
- digitalWrite(E2,0);
- digitalWrite(M2,LOW);
- }
- void advance(char a,char b) //Move forward
- {
- analogWrite (E1,a); //PWM Speed Control
- digitalWrite(M1,HIGH);
- analogWrite (E2,b);
- digitalWrite(M2,HIGH);
- }
- void back_off (char a,char b) //Move backward
- {
- analogWrite (E1,a);
- digitalWrite(M1,LOW);
- analogWrite (E2,b);
- digitalWrite(M2,LOW);
- }
- void turn_L (char a,char b) //Turn Left
- {
- analogWrite (E1,a);
- digitalWrite(M1,LOW);
- analogWrite (E2,b);
- digitalWrite(M2,HIGH);
- }
- void turn_R (char a,char b) //Turn Right
- {
- analogWrite (E1,a);
- digitalWrite(M1,HIGH);
- analogWrite (E2,b);
- digitalWrite(M2,LOW);
- }
-
- void setup(void)
- {
- int i;
- for(i=4;i<=7;i++)
- pinMode(i, OUTPUT);
- Serial.begin(19200); //Set Baud Rate
- Serial.println("Run keyboard control");
- digitalWrite(E1,LOW);
- digitalWrite(E2,LOW);
-
- }
-
- void loop(void)
- {
- if(Serial.available()){
- char val = Serial.read();
- if(val != -1)
- {
- switch(val)
- {
- case 'w'://Move Forward
- advance (255,255); //move forward in max speed
- break;
- case 's'://Move Backward
- back_off (255,255); //move back in max speed
- break;
- case 'a'://Turn Left
- turn_L (100,100);
- break;
- case 'd'://Turn Right
- turn_R (100,100);
- break;
- case 'z':
- Serial.println("Hello");
- break;
- case 'x':
- stop();
- break;
- }
- }
- else stop();
- }
-
- }
复制代码
步骤三: 功能实现。
样例程序中通过改变M1、M2的高低电平定义了前进、后退、左转、右转四个函数,通过给E1、E2设定数值0实现小车停止运动。在通过串口控制实现小车运动指令。在串口监视器中输入“w”,小车前进;输入“s”,小车后退;输入“a”,小车左转;输入“d”小车右转;输入“x”,小车停止运动;输入“z”,串口监视器显示“Hello”。
第二部分:语音控制小车运动。
小车测试成功以后,我们来玩语音控制吧。
步骤一:
首先,拿出我们的Voice Recognition 语音识别扩展板。
将其叠加到Uno R3主控板上面。看一下实物图:
在使用语音模块控制小车之前,我们可以先做一个简单的测试,也就是商城中提供的开关灯实验。点击链接查看语音控制中的【使用教程】。
- #include <Voice.h>
-
- #define SUM 2 //SUM识别关键词的个数,最大不超过50个
- uint8 nAsrStatus=0;
-
- char sRecog[SUM][80] = {"kai deng", "guan deng"};//每个关键词拼音字母个数不超过79个,用户可以自行修改 ?
-
- int state=7; //状态指示灯
- int led=8; //受控制数字口
-
-
- void finally (unsigned char n)
- {
- switch(n) //n为数组中对应关键词的序列号,例如数组sRecog中的第一个关键词为“kai deng”则对应的序列号为0;
-
- {
- case 0:
- Serial.println( "kai deng");
- Serial.println( " ");
- digitalWrite(led,LOW);
- break;
- case 1:
- Serial.println( "guan deng");
- digitalWrite(led,HIGH);
- break;
-
- default:
- Serial.println( "error");
- Serial.println( " ");
- break;
- }
- }
-
- void ExtInt0Handler ()
- {
- Voice.ProcessInt0(); //芯片送出中断信号
- }
-
- void setup()
- {
- Serial.begin(9600);
- Voice.Initialise(MIC,VoiceRecognitionV1);//Initialise mode MIC or MONO,default is MIC
- //VoiceRecognitionV1 is VoiceRecognitionV1.0 shield
- //VoiceRecognitionV2 is VoiceRecognitionV2.1 module
- attachInterrupt(0,ExtInt0Handler,LOW);
- pinMode(led,OUTPUT);
- pinMode(state,OUTPUT);
- digitalWrite(state,HIGH);
- digitalWrite(led,HIGH);
- }
- 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");
- }
- digitalWrite(state,LOW);
- Serial.println( "ASR_RUNING.....");
- break;
- }
- case LD_ASR_FOUNDOK:
- {
- digitalWrite(state,HIGH);
- nAsrRes =Voice. LD_GetResult();//一次ASR识别流程结束,去取ASR识别结果
- finally(nAsrRes);
- nAsrStatus = LD_ASR_NONE;
- break;
- }
- case LD_ASR_FOUNDZERO:
- default:
- {
-
- nAsrStatus = LD_ASR_NONE;
- break;
- }
- }// switch
- delay(500);
- }// while
- }
复制代码
通过实验上面的代码,我们可以发现,要将小车与语音控制相结合,只需要将char sRecog[SUM][80] = {"kai deng", "guan deng"};代码中的这一段改成我们要的命令,比如”qian jin“,"hou tui","zuo zhuan","you zhuan","ting zhi"等等。当然,我们也需要在void finally ( )函数中进行相应的修改。比如case 0的情况中,如果第一个指令是前进命令,我们可以在Serial.println()中输出”qin jin“,同时调用小车中的前进函数,这样当我们的语音识别模块检测到外界”前进“命令以后,会在串口中输出”qian jin“,同时,小车向前运动。其他的指令也是如此。
将语音控制LED的关键代码与小车运动代码进行整合。当然,语音识别的灵敏度会是一个很大的问题,这个我们将在以后的例子中继续完善。
代码如下: - #include <Voice.h>
- //#include <SoftwareSerial.h> //ruan chuankou
- #define SUM 5 //SUM识别关键词的个数,最大不超过50个
- uint8 nAsrStatus=0;
- //SoftwareSerial mySerial(10, 11); // RX, TX
- char sRecog[SUM][80] = {"qian jin", "hou tui","zuo zhuan", "you zhuan","ting zhi"};//每个关键词拼音字母个数不超过79个,用户可以自行修改
- int E1 = 5; //M1 Speed Control
- int E2 = 6; //M2 Speed Control
- int M1 = 4; //M1 Direction Control
- int M2 = 7; //M1 Direction Control
-
- void stop(void) //Stop
- {
- digitalWrite(E1,0);
- digitalWrite(E2,0);
- }
-
- void advance(char a,char b) //Move forward
- {
- analogWrite (E1,a); //PWM Speed Control
- digitalWrite(M1,HIGH);
- analogWrite (E2,b);
- digitalWrite(M2,HIGH);
- }
-
- void back_off (char a,char b) //Move backward
- {
- analogWrite (E1,a);
- digitalWrite(M1,LOW);
- analogWrite (E2,b);
- digitalWrite(M2,LOW);
- }
-
- void turn_L (char a,char b) //Turn Left
- {
- analogWrite (E1,a);
- digitalWrite(M1,LOW);
- analogWrite (E2,b);
- digitalWrite(M2,HIGH);
- }
-
- void turn_R (char a,char b) //Turn Right
- {
- analogWrite (E1,a);
- digitalWrite(M1,HIGH);
- analogWrite (E2,b);
- digitalWrite(M2,LOW);
- }
-
- void finally (unsigned char n)
- {
- switch(n) //n为数组中对应关键词的序列号,例如数组sRecog中的第一个关键词为“kai deng”则对应的序列号为0;
-
- {
- case 0:
- Serial.println( "qian jin");
- Serial.println( " ");
- advance (255,255);
- break;
- case 1:
- Serial.println( "hou tui");
- back_off (255,255);
- break;
- case 2:
- Serial.println( "zuo zhuan");
- turn_L (100,100);
- break;
- case 3:
- Serial.println( "you zhuan");
- turn_R (100,100);
- break;
- case 4:
- Serial.println( "ting zhi");
- stop();
- break;
- default:
- Serial.println( "error");
- Serial.println( " ");
- break;
- }
- }
-
- void ExtInt0Handler ()
- {
- Voice.ProcessInt0(); //芯片送出中断信号
- }
-
- void setup(void)
- {
- int i;
- for(i=4;i<=7;i++)
- pinMode(i, OUTPUT);
- Serial.begin(19200); //Set Baud Rate
- Voice.Initialise(MIC,VoiceRecognitionV1);//Initialise mode MIC or MONO,default is MIC
- //VoiceRecognitionV1 is VoiceRecognitionV1.0 shield
- //VoiceRecognitionV2 is VoiceRecognitionV2.1 module
- 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:
- {
- nAsrRes =Voice. LD_GetResult();//一次ASR识别流程结束,去取ASR识别结果
- finally(nAsrRes);
- nAsrStatus = LD_ASR_NONE;
- break;
- }
- case LD_ASR_FOUNDZERO:
- default:
- {
-
- nAsrStatus = LD_ASR_NONE;
- break;
- }
- }// switch
- delay(500);
- }// while
- }
复制代码
步骤三:功能实现。
下载程序到板卡之上,进行测试,当我们发出“前进”语音,小车将会调用 advance()函数,此时小车前进,其他运动时同样的道理。拔下USB线,插上锂电池,语言识别小车照样可以按照我们设定的指令工作。
第三部分:语音识别与MP3模块相结合。
语音控制完成了,总感觉少点什么是吧。要是小车能回应我们的话就好了。ok,那就动手吧。
步骤一:硬件搭建。
拿出我们的mp3播放模块。DFRduino Player module 。见见它的真面目吧。
很好,就是它了。介绍商城中都有,自己看罗。值得注意的是,在使用该模块的时候,最好在后背贴上胶带,以防止短路。说一下接线。mp3模块有一个串口排针接口,提供了5V,GND,RX,TX,OUT五个针脚,如下图:
将除了OUT以外的四个接在语音识别模块的mp3接线口。如下图:
其中,5V对应5V,GND对应GND,RX接在TX,TX对应RX。 实物图如下:
这里,我们还接上了一个小喇叭。在商城中也可以找到。 步骤二:程序编写。 线路搭建好以后,我们要进行程序编写了。同样是在之前的程序基础上,加上MP3播放的代码。当然,我们需要一个sd卡,在里面放入你想要播放的语音(故事,音乐,指令......都可以,你也可以实现设定对话,这样就可以跟我们的机器人聊天罗。)注意一下,我们使用的是串口通信,所以要将语音识别模块上UART和I2C选择按钮拨到UART那边哦。 贴一下关键代码。 - void finally (unsigned char n)
- {
- switch(n) //n为数组中对应关键词的序列号,例如数组sRecog中的第一个关键词为“kai deng”则对应的序列号为0;
-
- {
- case 0:
- Serial.println( "qian jin");
- Serial.println("\\qian");
- advance (255,255);
- break;
- case 1:
- Serial.println( "hou tui");
- Serial.println("\\hou");
- back_off (255,255);
- break;
- case 2:
- Serial.println( "zuo zhuan");
- Serial.println("\\zuo");
- turn_L (100,100);
- break;
- case 3:
- Serial.println( "you zhuan");
- Serial.println("\\you");
- turn_R (100,100);
- break;
- case 4:
- Serial.println( "ting zhi");
- Serial.println("\\zhi");
- stop();
- break;
- case 5:
- Serial.println( "chang ge");
- Serial.println("\\bo");
- Serial.println("\\2");
- break;
- case 6:
- Serial.println( "zan ting bo");
- Serial.println("\\:p");
- break;
- case 7:
- Serial.println( "ji xu bo");
- Serial.println("\\:s");
- break;
- case 8:
- Serial.println( "xia yi shou");
- Serial.println("\\:n");
- break;
- case 9:
- Serial.println( "shang yi shou");
- Serial.println("\\:u");
- break;
- default:
- Serial.println( "error");
- Serial.println( " ");
- break;
- }
- }
复制代码
步骤三:功能实现。
解释一下上面的关键代码。在case 0里面加入了 Serial.println("\\qian"), 这行代码是要求mp3播放SD卡中名字是【qian】的一段语音。同样的,case 1中多了一行Serial.println("\\hou")的代码,是要求mp3播放名字是【hou】的语音, Serial.println("\\:p")是暂停播放,Serial.println("\\:s")是继续播放,Serial.println("\\:n")是播放下一首......这些指令在商城中都有详细的介绍。 下载程序,就可以实现比较完整的语音控制小车啦。当我们发出“前进”指令,mp3会播放“执行命令前进”,其他的也是同样的道理。值得一提的是,我们给小车添加了播放音乐的功能。小车可以识别“播放音乐”,“暂停播放”,“继续播放”,“上一首”,“下一首”等多个指令。 这样的语音控制的小车有没有什么可以改进的地方呢,我们下次再说罗~~留点悬念呀,(*^__^*) 嘻嘻……
|