上回接寻迹功能后,这次来介绍超声波避障功能。
我们将超声波固定在舵机上,再通过对舵机的控制来实现超声波的转向。
超声波避障功能
示例代码
#include<Servo.h>
int inputPin = 8; // 定义超声波信号接收接口
int outputPin = 9; // 定义超声波信号发出接口
int STBY = 11; //控制电机驱动状态引脚
int PWMA = 3; //A电机速度控制
int AIN1 = 23; //A电机方向
int AIN2 = 22;
int PWMB = 5; //与上述A做对应即可
int BIN1 = 25;
int BIN2 = 24;
Servo myservo;//定义舵机变量名
void setup()
{
Serial.begin(9600);//设置串口波特率为9600
myservo.attach(10);//定义舵机接口10
pinMode(inputPin, INPUT);
pinMode(outputPin, OUTPUT);
pinMode(STBY, OUTPUT);
pinMode(PWMA, OUTPUT);
pinMode(AIN1, OUTPUT);
pinMode(AIN2, OUTPUT);
pinMode(PWMB, OUTPUT);
pinMode(BIN1, OUTPUT);
pinMode(BIN2, OUTPUT);
myservo.write(90); //初始化舵机方向
}
void loop()
{
myservo.write(90);
int distance=MTD(); //超声波测距
if(distance<50) //前方50cm处有障碍
{
move(1,0,1); //小车停下
move(2,0,1);
delay(1000);
myservo.write(0); //舵机左转
delay(500);
int qdistance=MTD(); //测距
if(qdistance<50) // 左边50cm处有障碍
{
move(1,0,1);
move(2,0,1);
delay(1000);
myservo.write(180); //舵机右转
delay(500);
int qqdistance=MTD(); //测距
if(qqdistance<20) //右边50cm处有障碍
{
move(1,0,1);
move(2,0,1);
move(1,128,1); //左电机向前,右电机向后,以实现掉头这一过程
move(2,128,0);
delay(2000); //延迟时间较长,以实现成功掉头
move(1,0,1);
move(2,0,1);
}
else //右边50cm无障碍
{
delay(1000);
move(1,100,1); //左电机向前,右电机向后,以实现右转
move(2,100,0);
delay(1000); //延迟时间短,以实现右转
move(1,0,1);
move(2,0,1);
}
}
else //左边50cm处无障碍
{
delay(1000);
move(1,100,0); //左电机向后,右电机向前,以实现左转
move(2,100,1);
delay(1000);
move(1,0,1);
move(2,0,1);
}
}
else //前方50cm处无障碍
{
move(1,128,1);
move(2,128,1);
}
delay(500);//刷新时间500ms,也就是0.5s
}
int MTD(){ //测距函数 可参考博客Arduino小车设计(三),里面有对此代码较为详细的说明
digitalWrite(outputPin, LOW); // 使发出发出超声波信号接口低电平2ms
delayMicroseconds(2);
digitalWrite(outputPin, HIGH); // 使发出发出超声波信号接口高电平10ms,这里是至少10μs
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // 保持发出超声波信号接口低电平
int distance = pulseIn(inputPin, HIGH); // 读出脉冲时间
distance = distance / 58; // 将脉冲时间转化为距离(单位:厘米)
return distance;
}
void move(int motor, int speed, int direction){ //可参考博客Arduino小车设计(三),里面有对此代码较为详细的说明
digitalWrite(STBY, HIGH); //disable standby
boolean inPin1 = HIGH;
boolean inPin2 = LOW;
if(direction == 1){
inPin1 = LOW;
inPin2 = HIGH;
}
if(motor == 1){
digitalWrite(AIN1, inPin1);
digitalWrite(AIN2, inPin2);
analogWrite(PWMA, speed);
}
else{
digitalWrite(BIN1, inPin1);
digitalWrite(BIN2, inPin2);
analogWrite(PWMB, speed);
}
}
示例代码也是根据所做的小车的具体情况,不断加以完善的。(找不到源码了,如果能做对照,真的会发现有很多不同的情况)。 虽说是完善后的,但是实际情况还是不能让人称心如意。 为什么这么说呢,如下图所示,博主做的是一个三蹦子==
小车是怎么控制方向的呢?是通过左右电机速度的不同来实现左右前后转动,而后面的小轮(白色)实际上起的是一个辅助左右,并没有相应的代码来控制。 如果没有实际操作过,你很难想象后面的小轮也有一定作用。 为什么这样说呢?如果一开始小车的功能是直走,而后面的小轮是朝右或朝左的,就很容易偏离方向。 你可能会说,如果一开始调整好了,那不就行了。但是在实际的操作过程中,如果发生了转弯的情况,小轮还是调整不过来,最后还是会导致小车的偏离。 我们也曾想过将速度调大的方法来让小轮强制转过来,可是只是一种想法。因为我们电池的电压实在有限(仅有6v),所以电机的速度最大也不是很给力。 下一个问题就是超声波的延迟问题,我们在测量当前方,左方和右方都有物体时,按照代码来说照理说应该掉头的。可是出现了几次正常流程,几次非正常的流程(即向右拐)。我们当时也比较疑惑,是不是延迟给的时间太少了。因为会不定时的出现,所以我们也没有根本的解决这个问题,我感觉这应该和超声波本身工作原理的延迟有关吧(猜的)。 超声波传感器是比较敏感的,前期设计时,杜邦线没有固定好,出现在超声波前方时,会让超声波测定前方有障碍物,所以一定要固定好杜邦线。
我的想法:
超声波避障整整做了一天。。。。。做着做着一天就没了,很多复杂的小问题,都是我们忽视的,导致小车并不是那么完美。一直不断不断的改善,才稍微像样。超声波避障给了我第一次在实例上的打击,也让我清楚地认识到,实践是检测一个事难度的最好方法,而不是靠想象。不要小瞧了任何东西,很多有成就的事都是有这些小东西组成的,你要尽全力完美地做好它。