手自两档避障小车(可蓝牙控制,可防火预警!)---新手求照顾
本帖最后由 刘梓靖 于 2016-1-15 22:55 编辑新手熬夜自制的,望大神们多多指教!谢谢。。(勿喷)
一、材料
1、arduino uno r3 控制板
2、超声波传感器
3、蓝牙模块HC05
4、舵机
5、L298N驱动模块
6、RGB LED指示灯
7、有源蜂鸣器
8、火焰传感器
9、小车底盘
10、12V电源
11、小面包板:1个
12、小车轮胎:2个
13、电阻:10KΩ(1个);220Ω
14、杜邦线:若干
二、原理
避障主要的是通过超声波测量前方障碍物到小车的距离,通过arduino控制系统控制电机驱动模块,进而控制电机正反转实现自动避障。
1、超声波测距原理
这次我们采用超声波测距模,其工作原理是给TRIG端至少10微妙的高电平的信号,模块自动检测是否有信号返回,有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速)/2。
2、电机驱动模块
电机驱动模块我们使用的是L298N,其逻辑功能为当ENA为高电平时,不够IN1、In2为高还是低电平OUT1、OUT2都是低电平,则不能够驱动,只有当ENA为低电平时IN1、IN2才开始工作。同理ENB也是一样,驱动模块的逻辑关系为IN1=OUT1、IN2=OUT2、IN3=OUT3、IN4=OUT4。
3、蓝牙模块
此次实验我们主要采用HC-05蓝牙模块,自身的TXD接到arduino的RXD端口,自身的RXD接到arduino的TXD端口,用Android配套的串口蓝牙与蓝牙模块配对,通过控制串口蓝牙 发出指令当蓝牙模块受到指令后,执行解码动作,从而控制小车的行动。
4、报警装置
小车在正常行走当中,执行程序命令小车亮绿灯,当遇到障碍时小车闪蓝灯,同时当小车遇到火焰时,火焰传感器触发,启动蜂鸣器的报警。
三、图片
蓝牙连接图
底盘组装图
实物图(有点乱,自己整理下吧)
四、代码(
①蓝牙控制
char getstr;
int in1=12;
int in2=11;
int in3=10;
int in4=9;
//上面定义了板上的4个控制端,12一组,34一组
int TrigPin = 5;
int EchoPin = 6;
float cm;
int i=0,j=1;//记录测量次数,每5次取一下平均值
float cmsum;//计算5次总值
float cmeve;//计算5次平均值\
void _mRun(int pin1,int pin2)//电机右转,电机到底是右转还是左转取决于电机端的接线和控制脚的顺序
{
digitalWrite(pin1,HIGH);
digitalWrite(pin2,LOW);
}
void _mBack(int pin1,int pin2)//同上
{
digitalWrite(pin1,LOW);
digitalWrite(pin2,HIGH);
}
void _mStop(int pin1,int pin2)//紧急制动,实际就是将电机两个端短接了
{
digitalWrite(pin1,HIGH);
digitalWrite(pin2,HIGH);
}
void setup()
{
Serial.begin(9600);
pinMode(in1,OUTPUT);
pinMode(in2,OUTPUT);
pinMode(in3,OUTPUT);
pinMode(in4,OUTPUT);
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
//下面程序开始时让控制端都为高电平,电机保持不动。
digitalWrite(in1,HIGH);
digitalWrite(in2,HIGH);
digitalWrite(in3,HIGH);
digitalWrite(in4,HIGH);
}
void loop()
{
int j = 1;
getstr=Serial.read();
delayMicroseconds(60);
digitalWrite(TrigPin, HIGH);
delayMicroseconds(60);
digitalWrite(TrigPin, LOW);
cm = pulseIn(EchoPin, HIGH) / 58.0; //将回波时间换算成cm
cm = (int(cm * 100.0)) / 100.0; //保留两位小数
b
if (i==5){//连接测5次,计算平均值,如果小于10厘米则紧急停车
i=0;
cmeve=cmsum/5;
cmsum=0;
if (cmeve<25 and cmeve>0)
{
Serial.println(cmeve);
_mStop(in1,in2);
_mStop(in3,in4);
}
}
else {
i=i+1;
cmsum=cmsum+cm;
}
if(getstr=='f')
{
Serial.println("go forward!");
_mStop(in1,in2);
_mStop(in3,in4);
_mRun(in1,in2);
_mRun(in3,in4);
}
else if(getstr=='b'){
Serial.println("go back!");
_mStop(in1,in2);
_mStop(in3,in4);
_mBack(in1,in2);
_mBack(in3,in4);
}
else if(getstr=='l' and j==1){
Serial.println("go left!");
_mStop(in1,in2);
_mStop(in3,in4);
_mRun2(in1,in2);
j--;
}
else if(getstr=='r' and j==1){
Serial.println("go right!");
_mStop(in1,in2);
_mStop(in3,in4);
_mRun2(in3,in4);
j--;
}
else if(getstr=='s'){
Serial.println("Stop!");
_mStop(in1,in2);
_mStop(in3,in4);
}
}
void _mRun2(int pin1,int pin2)//电机右转,电机到底是右转还是左转取决于电机端的接线和控制脚的顺序
{
digitalWrite(pin1,HIGH);
digitalWrite(pin2,LOW);
delay(500);
digitalWrite(pin1,LOW);
}
void _mBack2(int pin1,int pin2)//同上
{
digitalWrite(pin1,LOW);
digitalWrite(pin2,HIGH);
delay(500);
digitalWrite(pin1,LOW);
}
②自动避障
//超声波智能避障车程序(ARDUINO)
// L = 左
// R = 右
// F = 前
// B = 後
#include <Servo.h>
int pinLB=12; // 定義15腳位
int pinLF=11; // 定義14腳位
int pinRB=10; // 定義16腳位
int pinRF=9; // 定義17腳位
int inputPin = 5;// 定義超音波信號發射腳位
int outputPin =6;//定義超音波信號接收腳位
int Fspeedd = 0; // 前速
int Rspeedd = 0; // 右速
int Lspeedd = 0; // 左速
int directionn = 0; // 前=8 後=2 左=4 右=6
Servo myservo; // 設 myservo
int delay_time = 250; // 伺服馬達轉向後的穩定時間
int Fgo = 8; // 前進
int Rgo = 6; // 右轉
int Lgo = 4; // 左轉
int Bgo = 2; // 倒車
void setup()
{
Serial.begin(9600); // 定義馬達輸出腳位
pinMode(pinLB,OUTPUT); // 腳位 8 (PWM)
pinMode(pinLF,OUTPUT); // 腳位 9 (PWM)
pinMode(pinRB,OUTPUT); // 腳位 10 (PWM)
pinMode(pinRF,OUTPUT); // 腳位 11 (PWM)
pinMode(inputPin, INPUT); // 定義超音波輸入腳位
pinMode(outputPin, OUTPUT);// 定義超音波輸出腳位
myservo.attach(7); // 定義伺服馬達輸出第10腳位(PWM)
}
void advance(int a) // 前進
{
digitalWrite(pinRB,HIGH);// 使馬達(右後)動作
digitalWrite(pinRF,LOW);
digitalWrite(pinLB,HIGH);// 使馬達(左後)動作
digitalWrite(pinLF,LOW);
analogWrite(pinRB,150);
analogWrite(pinRF,150);
analogWrite(pinLB,250);
analogWrite(pinLF,250);
delay(a * 100);
}
void right(int b) //右轉(單輪)
{
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,HIGH);
digitalWrite(pinRB,LOW); //使馬達(右後)動作
digitalWrite(pinRF,HIGH);
analogWrite(pinRB,0);
analogWrite(pinRF,200);
delay(b * 100);
}
void left(int c) //左轉(單輪)
{
digitalWrite(pinRB,HIGH);
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,LOW); //使馬達(左後)動作
digitalWrite(pinLF,HIGH);
analogWrite(pinLB,0);
analogWrite(pinLF,200);
delay(c * 100);
}
void turnR(int d) //右轉(雙輪)
{
digitalWrite(pinRB,LOW);//使馬達(右後)動作
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,LOW);//使馬達(左前)動作
delay(d * 100);
}
void turnL(int e) //左轉(雙輪)
{
digitalWrite(pinRB,HIGH);
digitalWrite(pinRF,LOW); //使馬達(右前)動作
digitalWrite(pinLB,LOW); //使馬達(左後)動作
digitalWrite(pinLF,HIGH);
delay(e * 100);
}
void stopp(int f) //停止
{
digitalWrite(pinRB,HIGH);
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,HIGH);
delay(f * 100);
}
void back(int g) //後退
{
digitalWrite(pinRB,LOW);//使馬達(右後)動作
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,LOW);//使馬達(左後)動作
digitalWrite(pinLF,HIGH);
delay(g * 100);
}
void detection() //測量3個角度(0.90.179)
{
int delay_time = 250; // 伺服馬達轉向後的穩定時間
ask_pin_F(); // 讀取前方距離
if(Fspeedd < 20) // 假如前方距離小於10公分
{
stopp(1); // 清除輸出資料
back(2); // 後退 0.2秒
}
if(Fspeedd < 35) // 假如前方距離小於25公分
{
stopp(1); // 清除輸出資料
ask_pin_L(); // 讀取左方距離
delay(delay_time); // 等待伺服馬達穩定
ask_pin_R(); // 讀取右方距離
delay(delay_time); // 等待伺服馬達穩定
if(Lspeedd > Rspeedd) //假如 左邊距離大於右邊距離
{
directionn = Rgo; //向右走
}
if(Lspeedd <= Rspeedd) //假如 左邊距離小於或等於右邊距離
{
directionn = Lgo; //向左走
}
if (Lspeedd < 20 && Rspeedd < 20) //假如 左邊距離和右邊距離皆小於10公分
{
directionn = Bgo; //向後走
}
}
else //加如前方不小於(大於)25公分
{
directionn = Fgo; //向前走
}
}
void ask_pin_F() // 量出前方距離
{
myservo.write(90);
digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs
delayMicroseconds(2);
digitalWrite(outputPin, HIGH);// 讓超聲波發射高電壓10μs,這裡至少是10μs
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓
float Fdistance = pulseIn(inputPin, HIGH);// 讀差相差時間
Fdistance= Fdistance/5.8/10; // 將時間轉為距離距离(單位:公分)
Serial.print("F distance:"); //輸出距離(單位:公分)
Serial.println(Fdistance); //顯示距離
Fspeedd = Fdistance; // 將距離 讀入Fspeedd(前速)
}
void ask_pin_L() // 量出左邊距離
{
myservo.write(5);
delay(delay_time);
digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs
delayMicroseconds(2);
digitalWrite(outputPin, HIGH);// 讓超聲波發射高電壓10μs,這裡至少是10μs
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓
float Ldistance = pulseIn(inputPin, HIGH);// 讀差相差時間
Ldistance= Ldistance/5.8/10; // 將時間轉為距離距离(單位:公分)
Serial.print("L distance:"); //輸出距離(單位:公分)
Serial.println(Ldistance); //顯示距離
Lspeedd = Ldistance; // 將距離 讀入Lspeedd(左速)
}
void ask_pin_R() // 量出右邊距離
{
myservo.write(177);
delay(delay_time);
digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs
delayMicroseconds(2);
digitalWrite(outputPin, HIGH);// 讓超聲波發射高電壓10μs,這裡至少是10μs
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓
float Rdistance = pulseIn(inputPin, HIGH);// 讀差相差時間
Rdistance= Rdistance/5.8/10; // 將時間轉為距離距离(單位:公分)
Serial.print("R distance:"); //輸出距離(單位:公分)
Serial.println(Rdistance); //顯示距離
Rspeedd = Rdistance; // 將距離 讀入Rspeedd(右速)
}
void loop()
{
myservo.write(90);//讓伺服馬達回歸 預備位置 準備下一次的測量
detection(); //測量角度 並且判斷要往哪一方向移動
if(directionn == 2)//假如directionn(方向) = 2(倒車)
{
back(8); //倒退(車)
turnL(2); //些微向左方移動(防止卡在死巷裡)
Serial.print(" Reverse "); //顯示方向(倒退)
}
if(directionn == 6) //假如directionn(方向) = 6(右轉)
{
back(1);
right(6); // 右轉
Serial.print(" Right "); //顯示方向(左轉)
}
if(directionn == 4) //假如directionn(方向) = 4(左轉)
{
back(1);
left(6); // 左轉
Serial.print(" Left "); //顯示方向(右轉)
}
if(directionn == 8) //假如directionn(方向) = 8(前進)
{
advance(1); // 正常前進
Serial.print(" Advance "); //顯示方向(前進)
Serial.print(" ");
}
}
③手自两档带火焰报警避障
#include <Servo.h>
char getstr;
int pinLB=12;
int pinLF=11;
int pinRB=10;
int pinRF=9;
//上面定义了板上的4个控制端,12一组,34一组
int Inputpin = 5;
int Outputpin = 6;
Servo myservo;
int delay_time = 250; // 伺服馬達轉向後的穩定時間
int Fspeedd = 0; // 前速
int Rspeedd = 0; // 右速
int Lspeedd = 0; // 左速
int directionn = 0;
float cm;
int i=0,j;//记录测量次数,每5次取一下平均值
float cmsum;//计算5次总值
float cmeve;//计算5次平均值
int Fgo = 8; // 前進
int Rgo = 6; // 右轉
int Lgo = 4; // 左轉
int Bgo = 2; // 倒車
void _mRun(int pinLB,int pinLF)//电机右转,电机到底是右转还是左转取决于电机端的接线和控制脚的顺序
{
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,LOW);
}
void _mBack(int pinLB,int pinLF)//同上
{
digitalWrite(pinLB,LOW);
digitalWrite(pinLF,HIGH);
}
void _mStop(int pinLB,int pinLF)//紧急制动,实际就是将电机两个端短接了
{
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,HIGH);
}
void setup()
{
Serial.begin(9600);
pinMode(pinLB,OUTPUT);
pinMode(pinLF,OUTPUT);
pinMode(pinRB,OUTPUT);
pinMode(pinRF,OUTPUT);
pinMode(Inputpin, OUTPUT);
pinMode(Outputpin, INPUT);
//下面程序开始时让控制端都为高电平,电机保持不动。
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,HIGH);
digitalWrite(pinRB,HIGH);
digitalWrite(pinRF,HIGH);
myservo.attach(7);
}
void advance(int a) // 前進
{
digitalWrite(pinRB,HIGH);// 使馬達(右後)動作
digitalWrite(pinRF,LOW);
digitalWrite(pinLB,HIGH);// 使馬達(左後)動作
digitalWrite(pinLF,LOW);
delay(a * 100);
}
void right(int b) //右轉(單輪)
{
digitalWrite(pinRB,LOW); //使馬達(右後)動作
digitalWrite(pinRF,HIGH);
analogWrite(pinRB,0);
analogWrite(pinRF,200);
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,HIGH);
delay(b * 100);
}
void left(int c) //左轉(單輪)
{
digitalWrite(pinRB,HIGH);
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,LOW); //使馬達(左後)動作
digitalWrite(pinLF,HIGH);
analogWrite(pinLB,0);
analogWrite(pinLF,200);
delay(c * 100);
}
void turnR(int d) //右轉(雙輪)
{
digitalWrite(pinRB,LOW);//使馬達(右後)動作
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,LOW);//使馬達(左前)動作
delay(d * 100);
}
void turnL(int e) //左轉(雙輪)
{
digitalWrite(pinRB,HIGH);
digitalWrite(pinRF,LOW); //使馬達(右前)動作
digitalWrite(pinLB,LOW); //使馬達(左後)動作
digitalWrite(pinLF,HIGH);
delay(e * 100);
}
void stopp(int f) //停止
{
digitalWrite(pinRB,HIGH);
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,HIGH);
digitalWrite(pinLF,HIGH);
delay(f * 100);
}
void back(int g) //後退
{
digitalWrite(pinRB,LOW);//使馬達(右後)動作
digitalWrite(pinRF,HIGH);
digitalWrite(pinLB,LOW);//使馬達(左後)動作
digitalWrite(pinLF,HIGH);
delay(g * 100);
}
void detection() //測量3個角度(0.90.179)
{
int delay_time = 250; // 伺服馬達轉向後的穩定時間
ask_pin_F(); // 讀取前方距離
if(Fspeedd < 20) // 假如前方距離小於10公分
{
stopp(1); // 清除輸出資料
back(2); // 後退 0.2秒
}
if(Fspeedd < 35) // 假如前方距離小於25公分
{
stopp(1); // 清除輸出資料
ask_pin_L(); // 讀取左方距離
delay(delay_time); // 等待伺服馬達穩定
ask_pin_R(); // 讀取右方距離
delay(delay_time); // 等待伺服馬達穩定
if(Lspeedd > Rspeedd) //假如 左邊距離大於右邊距離
{
directionn = Lgo; //向右走
}
if(Lspeedd <= Rspeedd) //假如 左邊距離小於或等於右邊距離
{
directionn = Rgo; //向左走
}
if (Lspeedd < 20 && Rspeedd < 20) //假如 左邊距離和右邊距離皆小於10公分
{
directionn = Bgo; //向後走
}
}
else //加如前方不小於(大於)25公分
{
directionn = Fgo; //向前走
}
}
void ask_pin_F() // 量出前方距離
{
myservo.write(90);
digitalWrite(Inputpin, LOW); // 讓超聲波發射低電壓2μs
delayMicroseconds(2);
digitalWrite(Inputpin, HIGH);// 讓超聲波發射高電壓10μs,這裡至少是10μs
delayMicroseconds(10);
digitalWrite(Inputpin, LOW); // 維持超聲波發射低電壓
float Fdistance = pulseIn(Outputpin, HIGH);// 讀差相差時間
Fdistance= Fdistance/5.8/10; // 將時間轉為距離距离(單位:公分)
Serial.print("F distance:"); //輸出距離(單位:公分)
Serial.println(Fdistance); //顯示距離
Fspeedd = Fdistance; // 將距離 讀入Fspeedd(前速)
}
void ask_pin_L() // 量出左邊距離
{
myservo.write(5);
delay(delay_time);
digitalWrite(Inputpin, LOW); // 讓超聲波發射低電壓2μs
delayMicroseconds(2);
digitalWrite(Inputpin, HIGH);// 讓超聲波發射高電壓10μs,這裡至少是10μs
delayMicroseconds(10);
digitalWrite(Inputpin, LOW); // 維持超聲波發射低電壓
float Ldistance = pulseIn(Outputpin, HIGH);// 讀差相差時間
Ldistance= Ldistance/5.8/10; // 將時間轉為距離距离(單位:公分)
Serial.print("L distance:"); //輸出距離(單位:公分)
Serial.println(Ldistance); //顯示距離
Lspeedd = Ldistance; // 將距離 讀入Lspeedd(左速)
}
void ask_pin_R() // 量出右邊距離
{
myservo.write(177);
delay(delay_time);
digitalWrite(Inputpin, LOW); // 讓超聲波發射低電壓2μs
delayMicroseconds(2);
digitalWrite(Inputpin, HIGH);// 讓超聲波發射高電壓10μs,這裡至少是10μs
delayMicroseconds(10);
digitalWrite(Inputpin, LOW); // 維持超聲波發射低電壓
float Rdistance = pulseIn(Outputpin, HIGH);// 讀差相差時間
Rdistance= Rdistance/5.8/10; // 將時間轉為距離距离(單位:公分)
Serial.print("R distance:"); //輸出距離(單位:公分)
Serial.println(Rdistance); //顯示距離
Rspeedd = Rdistance; // 將距離 讀入Rspeedd(右速)
}
void loop()
{
int j=1;
getstr=Serial.read();
delayMicroseconds(60);
digitalWrite(Inputpin, HIGH);
delayMicroseconds(60);
digitalWrite(Inputpin, LOW);
cm = pulseIn(Outputpin, HIGH) / 58.0; //将回波时间换算成cm
cm = (int(cm * 100.0)) / 100.0; //保留两位小数
if (i==5){//连接测5次,计算平均值,如果小于10厘米则紧急停车
i=0;
cmeve=cmsum/5;
cmsum=0;
if (cmeve<20 and cmeve>0) {
Serial.println(cmeve);
_mStop(pinLB,pinLF);
_mStop(pinRB,pinRF);
}
}
else {
i=i+1;
cmsum=cmsum+cm;
}
myservo.write(90);
if(getstr=='z')
while(1)
{
myservo.write(90);//讓伺服馬達回歸 預備位置 準備下一次的測量
detection(); //測量角度 並且判斷要往哪一方向移動
if(directionn == 2)//假如directionn(方向) = 2(倒車)
{
back(8); //倒退(車)
turnL(2); //些微向左方移動(防止卡在死巷裡)
Serial.print(" Reverse "); //顯示方向(倒退)
}
if(directionn == 6) //假如directionn(方向) = 6(右轉)
{
back(1);
right(6); // 右轉
Serial.print(" Right "); //顯示方向(左轉)
}
if(directionn == 4) //假如directionn(方向) = 4(左轉)
{
back(1);
left(6); // 左轉
Serial.print(" Left "); //顯示方向(右轉)
}
if(directionn == 8) //假如directionn(方向) = 8(前進)
{
advance(1); // 正常前進
Serial.print(" Advance "); //顯示方向(前進)
Serial.print(" ");
}
getstr=Serial.read();
if(getstr=='z') break;
}
if(getstr=='f')
{
Serial.println("go forward!");
_mStop(pinLB,pinLF);
_mStop(pinRB,pinRF);
_mRun(pinLB,pinLF);
_mRun(pinRB,pinRF);
}
else if(getstr=='b'){
Serial.println("go back!");
_mStop(pinLB,pinLF);
_mStop(pinRB,pinRF);
_mBack(pinLB,pinLF);
_mBack(pinRB,pinRF);
}
else if(getstr=='l' and j==1){
Serial.println("go left!");
_mStop(pinLB,pinLF);
_mStop(pinRB,pinRF);
_mRun2(pinRB,pinRF);
j--;
}
else if(getstr=='r' and j==1){
Serial.println("go right!");
_mStop(pinLB,pinLF);
_mStop(pinRB,pinRF);
_mRun2(pinLB,pinLF);
j--;
}
else if(getstr=='s'){
Serial.println("Stop!");
_mStop(pinLB,pinLF);
_mStop(pinRB,pinRF);
}
}
void _mRun2(int pin1,int pin2)//电机右转,电机到底是右转还是左转取决于电机端的接线和控制脚的顺序
{
digitalWrite(pin1,HIGH);
digitalWrite(pin2,LOW);
delay(500);
digitalWrite(pin1,LOW);
}
新手第一次,请各位大神多多指教!
恩恩,挺不错的啦!同是新手,以后多多交流哈! 有没有详细连线图:lol 拍个视频跑一下 求 详细连线图:P 请问手自两档是如何切换的呀? 学习了。。。。
页:
[1]