能够通过超声波“摇头”避障,并且能用左右两路红外线感应处理“突发障碍”的智能小车
很多朋友制作了超声波避障智能小车,有的带有舵机的“摇头”功能,有的没有。不过可惜超声波测量平面物体相对比较准确,对于细长形的物体,经常无法形成有效的反射,因此测量不到,使得智能小车容易“卡”在桌子、凳子脚下或其他障碍物下面。 又由于超声波一般装在车头,对于左右两侧出现的“障碍”无法处理。所以我在小车底盘左右两侧加装了红外线感应,基本达到小车在房间了到处走,不会“卡死”的效果,也能够及时处理突然在车身左右出现的障碍物,行走时速度快,比较灵活。
本人使用某国内厂家的小车底盘,他们自己生产的HJduino控制板,拓展板(兼容Arduino),红外感测器,通用的超声波。我不是厂家的人,没必要在这里给他做广告,只是本人穷,在两百多块左右的价位选择这个厂家的东西还是比较合适的。
红外感应器的感测距离我自己可以调到6cm至7cm左右,但是这仪器“怕太阳光”。即使没有直接被阳光直射到,白天在室内也可能被太阳辐射热影响到红外信号,小车失灵。一般是晚上八点之后,小车的红外感应比较灵敏、准确。
从理论上说,在小车上多装几个超声波或者红外线是没有问题的。 我也计划过买一台小孩开的玩具车(可以坐人的那种)来改装成“自动行驶”避障车,但是由于时间、精力、财力等问题,目前实现不了。希望有朋友可以做出来。
个人拍的一些视频已经上传到优酷,有兴趣的朋友可以去看看。 智能小车超声波找出路2—在线播放—优酷网,视频高清在线观看 http://v.youku.com/v_show/id_XMjkzNzQzMjE5Mg==.html?spm=a2h3j.8428770.3416059.1 智能小车超声波避障1—在线播放—优酷网,视频高清在线观看 http://v.youku.com/v_show/id_XMjkzNzQyODc1Mg==.html?spm=a2h3j.8428770.3416059.1 智能小车超声波找出路3—在线播放—优酷网,视频高清在线观看 http://v.youku.com/v_show/id_XMjkzNzQzMjU2OA==.html?spm=a2h3j.8428770.3416059.1 智能小车从角落里出来—在线播放—优酷网,视频高清在线观看 http://v.youku.com/v_show/id_XMjkzNzQzMjUyOA==.html?spm=a2h3j.8428770.3416059.1 智能小车自主走出角落—在线播放—优酷网,视频高清在线观看 http://v.youku.com/v_show/id_XMjkzNzQyODc5Mg==.html?spm=a2h3j.8428770.3416059.1 智能小车超声波舵机避障4—在线播放—优酷网,视频高清在线观看 http://v.youku.com/v_show/id_XMjkzNzQzMTU2MA==.html?spm=a2h3j.8428770.3416059.1 智能小车超声波舵机避障3—在线播放—优酷网,视频高清在线观看 http://v.youku.com/v_show/id_XMjkzNzQzMTU1Mg==.html?spm=a2h3j.8428770.3416059.1 视频管理-全部视频 http://vm.tudou.com/video/list 视频管理-全部视频 http://vm.tudou.com/video/list 我的自频道-优酷视频 优酷用户1475903255365918 http://i.youku.com/i/UNTg2NjM1Njk2?spm=a2hww.20023042.uerCenter.5~5!2~A
我拍视频时是用手机随便拍的,没有分清是“1路”避障还是“3路”避障。个人感觉3路避障灵活些,不过我做的1路避障效果也还可以。
以下是源代码:
//ARDUINO 超声波(舵机)加红外线智能避障小车 L = 左 R = 右 F = 前 B = 后
#include <Servo.h> int pinLB=14; int pinLF=15; int pinRB=17; int pinRF=16;
int MotorRPWM=3; int MotorLPWM=5;
int inputPin = 9; // 超声波接收管脚号 int outputPin =8; // 超声波发射管脚号
const int SensorLeft = 12; //左红外传感器管脚号 const int SensorRight = 13; //右红外传感器管脚号 int SL; //左 int SR; //右
int Fspeedd = 0; // 前进速度 int Rspeedd = 0; // 右转速度 int Lspeedd = 0; // 左转速度 int directionn = 0; //方向 Servo myservo; // 设 myservo int delay_time = 250; // 舵机转向后稳定的时间
int Fgo = 1; // 前进 int Rgo = 5; // 右转 int Lgo = 3; // 左转 int Bgo = 7; // 后退
void setup() { Serial.begin(9600); //波特率 pinMode(pinLB,OUTPUT); //电机 pinMode(pinLF,OUTPUT); pinMode(pinRB,OUTPUT); pinMode(pinRF,OUTPUT); pinMode(MotorLPWM, OUTPUT); //PWM pinMode(MotorRPWM, OUTPUT);
pinMode(inputPin, INPUT); // 超声波接收 pinMode(outputPin, OUTPUT); //超声波发射
pinMode(SensorLeft, INPUT); //定义左红外传感器 pinMode(SensorRight, INPUT); //定义右红外传感器
myservo.attach(10); // 舵机 } void advance(int a) // 前进 { digitalWrite(pinRF,HIGH); digitalWrite(pinRB,LOW); analogWrite(MotorRPWM,150); digitalWrite(pinLF,HIGH); digitalWrite(pinLB,LOW); analogWrite(MotorLPWM,150); delay(a * 100); } void right(int b) //单轮 { digitalWrite(pinRB,LOW); digitalWrite(pinRF,HIGH); analogWrite(MotorRPWM,200); digitalWrite(pinLB,LOW); digitalWrite(pinLF,LOW); delay(b * 100); } void left(int c) //单轮 { digitalWrite(pinRB,LOW); digitalWrite(pinRF,LOW); digitalWrite(pinLB,LOW); digitalWrite(pinLF,HIGH); analogWrite(MotorLPWM,200); delay(c * 100); } void turnR(int d) //双轮右转 { digitalWrite(pinRB,HIGH); digitalWrite(pinRF,LOW); analogWrite(MotorRPWM,150); digitalWrite(pinLB,LOW); digitalWrite(pinLF,HIGH); analogWrite(MotorLPWM,150); delay(d * 100); } void turnL(int e) //双轮左转 { digitalWrite(pinRB,LOW); digitalWrite(pinRF,HIGH); analogWrite(MotorRPWM,150); digitalWrite(pinLB,HIGH); digitalWrite(pinLF,LOW); analogWrite(MotorLPWM,150); delay(e * 100); } void stopp(int f) //停止 { digitalWrite(pinRB,LOW); digitalWrite(pinRF,LOW); digitalWrite(pinLB,LOW); digitalWrite(pinLF,LOW); delay(f * 100); } void back(int g) //后退 { digitalWrite(pinRF,LOW); digitalWrite(pinRB,HIGH); analogWrite(MotorRPWM,150); digitalWrite(pinLF,LOW); digitalWrite(pinLB,HIGH); analogWrite(MotorLPWM,150); delay(g * 100); }
void detection() //测量3个方向 { int delay_time = 200; // 舵机转向后稳定的时间 ask_pin_F(); // 读取前方距离
if(Fspeedd < 30) // 假如前方距离小于30厘米 { stopp(5); ask_pin_L(); // 读取左边距离 delay(delay_time); // 等待舵机稳定 ask_pin_R(); // 读取右边距离 delay(delay_time); // 等待舵机稳定
if(Lspeedd > Rspeedd) //假如左边距离大于右边距离 { directionn = Lgo; //向左走 }
if(Lspeedd <=Rspeedd) //假如 左边距离小于或等于右边距离 { directionn = Rgo; //向右走 }
if (Lspeedd < 15&& Rspeedd < 15) //假如左边距离和右边距离均小于15厘米 { directionn = Bgo; //后退 } } else //假如前方距离不小于30厘米 { directionn = Fgo; //前进 } } void ask_pin_F() // 测量前方距离 { myservo.write(90); digitalWrite(outputPin,LOW); // 超声波发射低电平2μs delayMicroseconds(2); digitalWrite(outputPin,HIGH); // 超声波发射高电平10μs delayMicroseconds(10); digitalWrite(outputPin,LOW); // 维持超声波发射低电平 float Fdistance =pulseIn(inputPin, HIGH); //读取相差时间 Fdistance=Fdistance/5.8/10; //将时间转化为距离(单位:厘米) Fspeedd = Fdistance; // 将距离输入前进速度 } void ask_pin_L() // 测量左边距离 { myservo.write(5); delay(delay_time); digitalWrite(outputPin,LOW); delayMicroseconds(2); digitalWrite(outputPin,HIGH); delayMicroseconds(10); digitalWrite(outputPin,LOW); float Ldistance =pulseIn(inputPin, HIGH); Ldistance=Ldistance/5.8/10; Lspeedd = Ldistance; // 将距离输入左转速度 } void ask_pin_R() // 测量右边距离 { myservo.write(177); delay(delay_time); digitalWrite(outputPin,LOW); delayMicroseconds(2); digitalWrite(outputPin,HIGH); delayMicroseconds(10); digitalWrite(outputPin,LOW); float Rdistance =pulseIn(inputPin, HIGH); Rdistance=Rdistance/5.8/10; Rspeedd = Rdistance; // 将距离输入右转速度 }
void loop() { myservo.write(90); //让舵机回到预备位置,准备下一次的测量 detection(); //测量角度,并且判断向哪边移动
SL = digitalRead(SensorLeft); SR = digitalRead(SensorRight);
if(directionn == 7) //假如方向 = 7 后退 { back(8); turnL(2); //稍微左转,防止卡死 } if(directionn == 5) //假如方向 = 5 右转 { back(4); turnR(6); } if(directionn == 3) //假如方向 = 3 左转 { back(4); turnL(6); } if(directionn == 1) //假如方向= 1 前进 { advance(1); if (SL == HIGH & SR ==LOW) // 如果右边红外线感测到物体,单轮向左 { left(6); } else if (SR == HIGH & SL ==LOW) // 如果左边红外线感应到物体,向右 { right(6); } else if (SR == LOW & SL == LOW)// 如果两个红外线均感应到物体,后退 { back(4); } } }
|