宜昌老张

基于超声波传感器的MakeBlock金属智能车避障的实现

0
阅读(9806)

    实验使用上位机软件LabVIEW对以Arduino作为下位机的MakeBlock智能小车进行实时监控。采用URM37V3.2超声波测距传感器实时测量小车在行驶的过程中与前方障碍物的距离,Arduino将检测到的测距信息转换为实际的距离值。在Arduino中实现避障算法,当MakeBlock小车与障碍物的距离小于设定值时,小车实施避障方案,从而躲避障碍物。同时,Arduino将检测到的距离信息发送给上位机LabVIEW。

   这次实验的避障算法是在下位机Arduino中完成,而不是在远端的PC机完成避障算法。上位机的LabVIEW界面只是对小车的运行状态进行实时监视。如果想了解如何用远端的上位PC机来实现对智能车的无线避障遥控,可参见文章《基于LabVIEW测控的MakeBlock智能车避障控制》,网址:http://blog.chinaaet.com/detail/33644.html。MakeBlock智能车全景图如图1所示。

图1 MakeBlock金属智能车

MakeBlock金属智能车避障视频:

网址:http://player.youku.com/player.php/sid/XNjEyMTM1OTA0/v.swf

    在本文的实验中,XBee模块与Arduino之间通过串行接口(即Tx和Rx引脚)进行通信。本文使用点对点无线传输方式,通过串行接口向XBee模块写入命令数据,实现数据的发送;当XBee模块接收到数据时,通过读串行接口获得这些数据,实现数据的读取。对于Xbee模块的使用方法,可详见博客文章《美国DIGI公司的XBee模块无线通讯实验》,网址:

http://blog.chinaaet.com/detail/29230.html

图2  Xbee模块与Arduino控制器连接方法

图3  Xbee模块与PC机连接方法 


一、   硬件设计

   实验采用URM37V3.2超声波传感器作为外界环境信息的采集工具。下面,简要介绍一下与本次实验有关的URM37V3.2超声波传感器的一些知识。

   URM37V3.2超声波传感器是一种多功能的智能传感器,它可以测量4~500 cm的距离,并且有1cm的分辨率。能够测量较远的距离并且性能稳定。可通过脉宽输出的方式来测量数据,也可以使用R232串口通讯,有较好的可靠性。下图4是URM37V3.2超声波传感器的引脚定义。URM37V3.2超声波传感器与Arduino的连线图见图5。

图4  URM37V3.2超声波传感器引脚示意图

图5  URM37V3.2超声波传感器TTL方式串口接线图

    作为一种智能传感器,该传感器可以将信号采集、数字处理和信息传送融为一体。用户只需要使用单片机的TTL电平串口,向传感器发出四个字节的信息读取命令:0x22, 0x00, 0x00, 0x22。传感器接收命令后,会向单片机回送四个字节的测距信息:0x22, highbyte, lowbyte, sum。这四个字节里有两个字节就是16位被测距离信息。如果高位字节和低位字节都是 0xFF,这意味着测量无效,超出测量范围。反之,被测距离就等于高位字节乘以256再加上低位字节,实际距离的单位是厘米。


二、下位机程序设计

    为了获得距离信息,Arduino需要向URM37 V3.2测距传感器发送四个字节的测距指令,等待超声波测距传感器完成测距任务后,再接受它返回的四个字节的距离信息。并按上文的方法转换为实际的距离值。如果实测距离大于40cm,小车继续前进;反之,小车实施避障策略,及时左转,从而躲避障碍物。同时,Arduino控制器将距离信息通过无线传输模块Xbee发送给远程监控的上位机LabVIEW处理。这里发送给上位机处理的有关距离信息的数据前面带上了标识字符“10”,用于上位机判断哪个字节是有效字符串信息的第一个字节。发送给上位机的数据(字符串)格式是:10+距离数据高8位+距离数据低8位。

    下位机Arduino程序的流程图如图6所示。

图6 基于超声波传感器避障的程序流程图           

    Arduino程序:

int E_right =5;              //连接电机1的使能端口到数字接口5
int M_right =4;              //连接电机1的转向端口到数字接口4
int E_left = 6;              //连接电机2的使能端口到数字接口6
int M_left=7;                //连接电机2的转向端口到数字接口5
int velocity1=190;           //右电机速度
int velocity2=250;           //左电机速度
int USValue = 0;             //超声波实测距离变量
boolean flag=true;           //设置循环标识符并初始化为真
byte DMcmd[4] = {0x22, 0x00, 0x00, 0x22}; //距离命令数组

void advance()               //声明前进子函数
{
	digitalWrite(M_right,HIGH);      //右电机反转
	analogWrite(E_right, velocity1); //右电机速度调节
	digitalWrite(M_left,LOW);        //左电机正转
	analogWrite(E_left, velocity2);  //左电机速度调节
}
void back()                          //声明后退子函数

{
	digitalWrite(M_right,LOW);       //右电机正转
	analogWrite(E_right,velocity1);  //右电机速度调节
	digitalWrite(M_left,HIGH);       //左电机反转
	analogWrite(E_left,velocity2);   //左电机速度调节
}
void right()//声明右转子函数

{
	digitalWrite(M_right,LOW);        //右电机正转
	analogWrite(E_right,velocity1);   //右电机速度调节
	digitalWrite(M_left,LOW);         //左电机正转
	analogWrite(E_left,velocity2);    //左电机速度调节
}
void left()                           //声明左转子函数

{
	digitalWrite(M_right,HIGH);        //右电机反转
	analogWrite(E_right,velocity1);    //右电机速度调节
	digitalWrite(M_left,HIGH);         //左电机反转
	analogWrite(E_left,velocity2);     //左电机速度调节
}
void Stop()                            //声明停止子函数

{
	digitalWrite(E_right, LOW);        //右电机停
	digitalWrite(E_left, LOW);         //左电机停
}
void setup() 
{
  Serial.begin(9600);                  //串口波特率设置          
  pinMode(M_right, OUTPUT);           //设置输出引脚
  pinMode(E_right, OUTPUT);
  pinMode(M_left, OUTPUT);
  pinMode(E_left, OUTPUT);
  delay(20);                          //延时20ms
}
void loop( )
{
  for(int i=0;i<4;i++)
  {
    Serial.print(DMcmd[i],BYTE);     //发送四个字节的超声波测距命令
  }
  delay(75);                         //延时75ms
  while(flag)
  {
      if(Serial.available()>0)       //如果串口有缓存数据
      {
        byte header=Serial.read();   //从测距命令标识符0x22开始接收数据
        byte highbyte=Serial.read(); //距离数据高8位
        byte lowbyte=Serial.read();  //距离数据低8位
        byte sum=Serial.read();      //sum为校验和
         if(highbyte==255)   //如果高位数据位255,超出测量范围,数据无效
          {
            USValue=65525;  
          }
          else
          {
            USValue = highbyte*256+lowbyte; //计算实际距离值
            if (USValue <=40)
            {
              //如果距离小于40厘米小车左转500ms
              left();
              delay(500);
            }
             //相反的情况,小车前进
           else
              advance();
          }
         Serial.print(10,BYTE);        //上传距离信息的标识符
         Serial.print(highbyte,BYTE);  //上传距离数据高8位
         Serial.print(lowbyte,BYTE);   //上传距离数据低8位     
         flag=false;                   //标识符变为假,退出该循环
       }
    }
    delay(20);                         // 延时20ms
}

三、上位机LabVIEW程序设计

   编写LabVIEW程序,通过串口读取下位机发送的距离信息,将提取的信息实时显示在LabVIEW的前面板上,就可以实时观察小车的运行状态。LabVIEW只需要根据上文Arduino发送是信息数据格式提取相关的字符串信息即可。图7是LabVIEW程序的程序框图。

LabVIEW程序先读取一个标识字符,如果读取的是标识字符“10”,程序会继续读取2个字节的字符串。通过“字符串值字节数组函数”将其转换为一维数组后,通过“索引数组”得到距离数据高8位和距离数据低8位。LabVIEW将字节数据转换为十进制的实际距离值。16位的二进制距离信息到十进制实际距离的转换公式是:实际距离=256*距离数据高8位+距离数据低8位。

   图8是LabVIEW程序的前面板。在前面板上,可以实时观察到小车运行时是否遇到障碍物。由于超声波测距传感器相对实验的场地来说,有较大的测距范围。因此,在这里显示了小车运行时与前方障碍物的实测距离,并通过一定的微分取导算法,得出了小车运行时的近似速度值,以供参考。

图7 基于超声波的智能小车避障的LabVIEW程序框图

图8 基于超声波的智能小车避障的LabVIEW前面板

 LabVIEW和Arduino程序源文件请下载:http://yunpan.cn/QGn6HWbKMUSjp


四、系统调试

     在LabVIEW的前面板选择COM4(在实验中,XBee模块添加到计算机后,所获得的串口号COM4),并设置波特率为9600bps。接通智能小车电机及控制器供电电源。运行上位机LabVIEW程序,通过前面板来观察小车的运行状态,与小车实际避障情况比较。实验结果表明,LabVIEW前面板读到的信息与小车实际运行状况相符,并且装备超声波测距传感器的智能小车可以很好地躲避前方障碍物。 


五、总结

    本文采用超声波测距传感器检测小车与前方障碍物的实际距离,通过与预先设定的小车转向时机的值进行比较,在遇到障碍物时左转一定的角度,实现避障。实验中Arduino采集数据,实现避障算法,LabVIEW作为上位机监视小车的运行状态。