之前我写了一篇《Arduino的智能语言输入实现》,讨论了Arduino与LU-ASR01之间通过串口通信实现Arduino的中文语音输入,不过那个通信是不完整的,因为LU-ASR01的串口只有一个发送端口TX,而没有接收端口RX。其实在真正的应用中,LU-ASR01通常也需要接收上位机的数据,例如为确保上位机已经收到LU-ASR01发送的数据,上位机需要返回一个已收到数据的应答,又例如上位机想让LU-ASR01发出某条语音消息或让LU-ASR01进行某个操作,都需要由上位机发送数据,然后由LU-ASR01接收数据后,进行相应的处理。
为解决LU-ASR01的串口没有接收端口RX这个问题,我们可以利用LU-ASR01的I/O端口(前文介绍过LU-ASR01共有8个I/O端口),取其中的2个端口挪作串口通信用,然后采用软串口通信的方式来实现Arduino与LU-ASR01之间的双向串口通信。
因为在网上查找不到一点LU-ASR01模块的软串口通信资料,只能通过不断地测试,因为手头连最基本检测工具示波器等都没有,只有一台电脑、一块Arduino板和一块LU-ASR01板,为检测软串口有没有发送数据,我甚至只能连接LED到串口,查看在串口发送数据时LED有没有闪烁。经历了数十次的失败,几乎已经绝望地想放弃了LU-ASR01的软串口通信实现,哈哈,最后当然成功啦,不然我就写不了这篇文章了。
闲话不说了,本次实验就是通过由LU-ASR01发送命令,Arduino收到该命令后,再返回发送该命令数据(即同样的数值)到LU-ASR01作为应答,最后LU-ASR01收到了Arduino发回的该命令数据,进行比较后(即判别发送的数据与接收到的数据是否相等),确认该命令发送成功了。
本次实验中,Arduino UNO仍然采用硬件串口通信,使用TX和RX端口,LU-ASR01则使用IO6端口作为发送数据的软TX,IO7端口作为接收数据的软RX。由Arduino提供5V电源给LU-ASR01(下图中的红黑2线),Arduino的TX连接到LU-ASR01的IO7端口(软RX),Arduino的RX连接到LU-ASR01的IO6端口(软TX),连接图如下:
LU-ASR01仍然采用“天问block”的图形化编程平台,下面是在“天问block”上的完整程序:
然后我们将下面的程序下载到Arduino UNO板,完整程序如下:
/*
Arduino与ASR01语音识别模块的串口通讯实验
为确保ASR01发送的数据能够接收到,采用应答方式,Arduino每接收到一个可识别的
命令后,都会将这个命令会送给ASR01
*/
// 定义引脚
const int LedPin = 13; // led连接的引脚,作为LED灯的正极
char Txbyte; //串口发送的字符数据
char Rxbyte; //串口读取的字符数据
//初始化
void setup() {
Serial.begin(9600); //设置串口波特率9600
pinMode(LedPin, OUTPUT); //设置LedPin
}
//主程序
void loop() {
if(Serial.available() > 0){ //当串口缓冲区有数据
Rxbyte=char(Serial.read());
if(Rxbyte==0x21) { //当Rxbyte为0x21则LedPin置高电平,即开灯
Serial.write(Rxbyte);
digitalWrite(LedPin, HIGH);
}
if(Rxbyte==0x22) { //当Rxbyte为0x22则LedPin置低电平,即关灯
Serial.write(Rxbyte);
digitalWrite(LedPin, LOW);
}
if(Rxbyte==0x20){ //当Rxbyte为0x20则Led灯闪3下
Serial.write(Rxbyte);
for(int i=0;i<3;i++){ //Led灯闪3下
digitalWrite(LedPin, HIGH);
delay(100);
digitalWrite(LedPin, LOW);
delay(100);
}
}
delay(2);
}
}
两边的程序下载完后,连接好4条联线,LU-ASR01首先会播报“我们正在进行实验,请呼唤我“不赦先生”唤醒我。我暂时休息了,有事请呼唤我:不赦先生”,然后我们呼叫“不赦先生”,则LU-ASR01回答“我在”后就通过软串口发送了一个字节的命令:0x20,Arduino收到0x20后,再次发送0x20到LU-ASR01;当LU-ASR01收到数据后,与之前发送的数据进行比较,如果相等,则播报:“阿杜已经收到命令了”,否则等待1秒钟,没有收到正确的数据0x20,则播报:“超时了,阿杜没有收到命令,请重新发”(这里说明下,为简化程序,程序中没有再次重新发送该数据)。接着可以测试“打开灯光”和“关闭灯光”。