distance在函数 int_Arduino智能小车——超声波避障
Arduino智能小車(chē)——超聲波避障
Arduino智能小車(chē)系列教程時(shí)空門(mén):
Arduino智能小車(chē)——拼裝篇 點(diǎn)擊跳轉(zhuǎn)
Arduino智能小車(chē)——測(cè)試篇 點(diǎn)擊跳轉(zhuǎn)
Arduino智能小車(chē)——調(diào)速篇 點(diǎn)擊跳轉(zhuǎn)
Arduino智能小車(chē)——超聲波避障 點(diǎn)擊跳轉(zhuǎn)
Arduino智能小車(chē)——藍(lán)牙小車(chē) 點(diǎn)擊跳轉(zhuǎn)
Arduino智能小車(chē)——循跡篇 點(diǎn)擊跳轉(zhuǎn)
Arduino智能小車(chē)——小車(chē)測(cè)速 點(diǎn)擊跳轉(zhuǎn)
文章目錄
經(jīng)過(guò)前幾篇的測(cè)試大家應(yīng)該對(duì)小車(chē)有一定的認(rèn)識(shí)了,在實(shí)際的操作過(guò)程中經(jīng)常會(huì)由于操作不當(dāng)各種碰壁吧?那這次我們將給小車(chē)裝上一只“眼睛”,讓小車(chē)看到障礙,躲避障礙。
準(zhǔn)備材料
超聲波模塊HC-SR04
在這里簡(jiǎn)單說(shuō)下超聲波測(cè)距的原理,相信大家也都知道。超聲波發(fā)射裝置發(fā)出超聲波,它的根據(jù)是接收器接到超聲波時(shí)的時(shí)間差,與雷達(dá)測(cè)距原理相似。 超聲波發(fā)射器向某一方向發(fā)射超聲波,在發(fā)射時(shí)刻的同時(shí)開(kāi)始計(jì)時(shí),超聲波在空氣中傳播,途中碰到障礙物就立即返回來(lái),超聲波接收器收到反射波就立即停止計(jì)時(shí)。
采用Trig引腳觸發(fā),給至少10us的高電平脈沖信號(hào)
模塊自動(dòng)發(fā)送8個(gè)40kHz的方波,自動(dòng)檢測(cè)是否有信號(hào)返回
有信號(hào)返回,通過(guò)Echo引腳輸出一個(gè)高電平脈沖,高電平脈沖持續(xù)的時(shí)間就是超聲波從發(fā)射到反射返回的時(shí)間。距離=(高電平脈沖時(shí)間*340)/2。(聲音在空氣中傳播速度為340m/s)
主要技術(shù)參數(shù)
工作電壓
DC5V
靜態(tài)電流
<2mA
輸出電平
0-5V
感應(yīng)角度
≤15度
探測(cè)距離
2cm-450cm
最高精度
0.3cm
舵機(jī)
在這里推薦9G舵機(jī)SG90,或者其他類(lèi)似的舵機(jī),這種舵機(jī)體積比較小,扭矩雖然不是大, 但是足夠帶動(dòng)簡(jiǎn)易云臺(tái),很方便在小車(chē)上使用,大家購(gòu)買(mǎi)時(shí)注意舵機(jī)的轉(zhuǎn)動(dòng)角度,有55度的,180度的等等,大家可以根據(jù)需要購(gòu)買(mǎi)。
舵機(jī)固定架
舵機(jī)固定架的購(gòu)買(mǎi)一定要配合舵機(jī),所以大家購(gòu)買(mǎi)的時(shí)候注意尺寸哦!!~
舵機(jī)安裝
舵機(jī)在安裝之前大家一定要記得校準(zhǔn),為什么要校準(zhǔn)那,這個(gè)跟舵機(jī)的工作原理有關(guān)。控制信號(hào)由接收機(jī)的通道進(jìn)入信號(hào)調(diào)制芯片,獲得直流偏置電壓。它內(nèi)部有一個(gè)基準(zhǔn)電路,產(chǎn)生周期為20ms,寬度為1.5ms的基準(zhǔn)信號(hào),將獲得的直流偏置電壓與電位器的電壓比較,獲得電壓差輸出。最后,電壓差的正負(fù)輸出到電機(jī)驅(qū)動(dòng)芯片決定電機(jī)的正反轉(zhuǎn)。當(dāng)電機(jī)轉(zhuǎn)速一定時(shí),通過(guò)級(jí)聯(lián)減速齒輪帶動(dòng)電位器旋轉(zhuǎn),使得電壓差為0,電機(jī)停止轉(zhuǎn)動(dòng)。
舵機(jī)的控制一般需要一個(gè)20ms左右的時(shí)基脈沖,該脈沖的高電平部分一般為0.5ms-2.5ms范圍內(nèi)的角度控制脈沖部分,總間隔為2ms。以180度角度伺服為例,那么對(duì)應(yīng)的控制關(guān)系是這樣的:
高電平時(shí)間
對(duì)應(yīng)位置
0.5ms
0度
1.0ms
45度
1.5ms
90度
2.0ms
135度
2.5ms
180度
也就是說(shuō)當(dāng)對(duì)舵機(jī)輸入相同控制信號(hào)時(shí),舵機(jī)會(huì)運(yùn)動(dòng)到固定位置,他的動(dòng)作不是做圓周運(yùn)動(dòng),而是在運(yùn)動(dòng)范圍內(nèi),每一個(gè)位置對(duì)應(yīng)一個(gè)控制信號(hào)。
因此我們需要在將舵機(jī)安裝在固定架上之前,需要先將舵機(jī)初始化好,舵機(jī)一般為三根線:棕色——GND,紅色——VCC,橙色——控制信號(hào)。因此我們將棕色線接到GND,紅色線接到“+5V”引腳,橙色線接到“9”引腳,初始化程序如下:
`#include //加入含有舵機(jī)控制庫(kù)的頭文件
#define PIN_SERVO 9 //舵機(jī)信號(hào)控制引腳
Servo myservo;
void setup()
{
myservo.attach(PIN_SERVO); //舵機(jī)初始化
}
void loop()
{
myservo.write(90); //PWM輸出
}`
* 1
* 2
* 3
* 4
* 5
* 6
* 7
* 8
* 9
* 10
* 11
* 12
* 13
* 14
在舵機(jī)初始化好之后將其安裝在固定架上,然后裝配在小車(chē)上,此時(shí)保證超聲波模塊超前。
超聲波接線
估計(jì)不少朋友早已經(jīng)發(fā)現(xiàn)板子上的“+5V”和“GND”引腳已經(jīng)不夠用了,這個(gè)時(shí)候你們可以向我這樣焊一個(gè)擴(kuò)展板出來(lái),上面固定兩排排針,一排用來(lái)擴(kuò)展“+5V”,一邊用來(lái)擴(kuò)展“GND”引腳。
超聲波模塊有四個(gè)引腳,“VCC”接到Arduino UNO開(kāi)發(fā)板的“+5V”引腳,“GND”接到開(kāi)發(fā)板“GND”引腳,“Trig”引腳接到開(kāi)發(fā)板“8”引腳,“Echo”引腳接到開(kāi)發(fā)板“7”引腳。
線太亂了,真的沒(méi)辦法整理,我自己都沒(méi)眼看。
代碼測(cè)試
`#include #define STOP 0
#define FORWARD 1
#define BACKWARD 2
#define TURNLEFT 3
#define TURNRIGHT 4
int leftMotor1 = 16;
int leftMotor2 = 17;
int rightMotor1 = 18;
int rightMotor2 = 19;
int leftPWM = 5;
int rightPWM = 6;
Servo myServo; //舵機(jī)
int inputPin=7; // 定義超聲波信號(hào)接收接口
int outputPin=8; // 定義超聲波信號(hào)發(fā)出接口
void setup() {
// put your setup code here, to run once:
//串口初始化
Serial.begin(9600);
//舵機(jī)引腳初始化
myServo.attach(9);
//測(cè)速引腳初始化
pinMode(leftMotor1, OUTPUT);
pinMode(leftMotor2, OUTPUT);
pinMode(rightMotor1, OUTPUT);
pinMode(rightMotor2, OUTPUT);
pinMode(leftPWM, OUTPUT);
pinMode(rightPWM, OUTPUT);
//超聲波控制引腳初始化
pinMode(inputPin, INPUT);
pinMode(outputPin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
avoidance();
}
void motorRun(int cmd,int value)
{
analogWrite(leftPWM, value); //設(shè)置PWM輸出,即設(shè)置速度
analogWrite(rightPWM, value);
switch(cmd){
case FORWARD:
Serial.println("FORWARD"); //輸出狀態(tài)
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
break;
case BACKWARD:
Serial.println("BACKWARD"); //輸出狀態(tài)
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
break;
case TURNLEFT:
Serial.println("TURN LEFT"); //輸出狀態(tài)
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
break;
case TURNRIGHT:
Serial.println("TURN RIGHT"); //輸出狀態(tài)
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
break;
default:
Serial.println("STOP"); //輸出狀態(tài)
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, LOW);
}
}
void avoidance()
{
int pos;
int dis[3];//距離
motorRun(FORWARD,200);
myServo.write(90);
dis[1]=getDistance(); //中間
if(dis[1]<30)
{
motorRun(STOP,0);
for (pos = 90; pos <= 150; pos += 1)
{
myServo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
dis[2]=getDistance(); //左邊
for (pos = 150; pos >= 30; pos -= 1)
{
myServo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
if(pos==90)
dis[1]=getDistance(); //中間
}
dis[0]=getDistance(); //右邊
for (pos = 30; pos <= 90; pos += 1)
{
myServo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
if(dis[0]=50)
{
//如果距離小于50厘米返回?cái)?shù)據(jù)
return 50;
}//如果距離小于50厘米小燈熄滅
else
return distance;
}`
* 1
* 2
* 3
* 4
* 5
* 6
* 7
* 8
* 9
* 10
* 11
* 12
* 13
* 14
* 15
* 16
* 17
* 18
* 19
* 20
* 21
* 22
* 23
* 24
* 25
* 26
* 27
* 28
* 29
* 30
* 31
* 32
* 33
* 34
* 35
* 36
* 37
* 38
* 39
* 40
* 41
* 42
* 43
* 44
* 45
* 46
* 47
* 48
* 49
* 50
* 51
* 52
* 53
* 54
* 55
* 56
* 57
* 58
* 59
* 60
* 61
* 62
* 63
* 64
* 65
* 66
* 67
* 68
* 69
* 70
* 71
* 72
* 73
* 74
* 75
* 76
* 77
* 78
* 79
* 80
* 81
* 82
* 83
* 84
* 85
* 86
* 87
* 88
* 89
* 90
* 91
* 92
* 93
* 94
* 95
* 96
* 97
* 98
* 99
* 100
* 101
* 102
* 103
* 104
* 105
* 106
* 107
* 108
* 109
* 110
* 111
* 112
* 113
* 114
* 115
* 116
* 117
* 118
* 119
* 120
* 121
* 122
* 123
* 124
* 125
* 126
* 127
* 128
* 129
* 130
* 131
* 132
* 133
* 134
* 135
* 136
* 137
* 138
* 139
* 140
* 141
* 142
* 143
* 144
* 145
* 146
* 147
代碼詳解
“Trig”引腳控制超聲波發(fā)出聲波,對(duì)應(yīng)int outputPin=8;
“Echo”引腳反應(yīng)接收到返回聲波,對(duì)應(yīng)int inputPin=7;
`int inputPin=7; // 定義超聲波信號(hào)接收接口
int outputPin=8; // 定義超聲波信號(hào)發(fā)出接口`
* 1
* 2
int getDistance()函數(shù)解析
超聲波發(fā)出引腳“Trig”為高時(shí)對(duì)外發(fā)出超聲波,為保證發(fā)出10μs聲波,因此在發(fā)送之前需要將該引腳拉低,并給他一定反應(yīng)時(shí)間。
`digitalWrite(outputPin, LOW); // 使發(fā)出發(fā)出超聲波信號(hào)接口低電平2μs
delayMicroseconds(2);`
* 1
* 2
之后發(fā)送10μs超聲波
`digitalWrite(outputPin, HIGH); // 使發(fā)出發(fā)出超聲波信號(hào)接口高電平10μs,這里是至少10μs`
* 1
聲波發(fā)送之后禁止其繼續(xù)發(fā)送,同時(shí)開(kāi)始檢測(cè)是否反射回來(lái)的聲波
`digitalWrite(outputPin, LOW); // 保持發(fā)出超聲波信號(hào)接口低電平
int distance = pulseIn(inputPin, HIGH); // 讀出脈沖時(shí)間`
* 1
* 2
pulseIn()單位為微秒,聲速344m/s,所以距離cm=344_100/1000000_pulseIn()/2約等于pulseIn()/58.0distance= distance/58; // 將脈沖時(shí)間轉(zhuǎn)化為距離(單位:厘米)
超聲波模塊工作受物體表面反射程度影響,并且在傳播過(guò)程中信號(hào)強(qiáng)度容易衰減,因此該模塊適用的檢測(cè)距離有限,一般在50cm以內(nèi)相對(duì)正確,而且我們?cè)诒苷蠒r(shí)不需要檢測(cè)太遠(yuǎn)的距離,因此超過(guò)50cm以上的都按50cm計(jì)算
`if (distance >=50)
{
//如果距離小于50厘米返回?cái)?shù)據(jù)
return 50;
}//如果距離小于50厘米小燈熄滅
else
return distance;`
* 1
* 2
* 3
* 4
* 5
* 6
* 7
void avoidance()函數(shù)解析
小車(chē)前進(jìn)過(guò)程中只檢測(cè)前方距離障礙的距離,并且控制舵機(jī),保持超聲波模塊位于正前方。
`motorRun(FORWARD,200);
myServo.write(90);
dis[1]=getDistance(); //中間`
* 1
* 2
* 3
當(dāng)檢測(cè)到小車(chē)前方距離障礙距離小于30cm時(shí)停車(chē),檢測(cè)兩邊距離。
`motorRun(STOP,0);`
* 1
控制舵機(jī)每次運(yùn)動(dòng)一個(gè)周期后都返回正前方位置。由于舵機(jī)運(yùn)動(dòng)需要一定的時(shí)間,因此在每轉(zhuǎn)過(guò)一個(gè)角度的時(shí)候都延時(shí)delay(15),供其運(yùn)動(dòng)。
`for (pos = 90; pos <= 150; pos += 1)
{
myServo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}`
* 1
* 2
* 3
* 4
* 5
當(dāng)運(yùn)動(dòng)到最左邊時(shí)檢測(cè)小車(chē)左邊距離障礙的距離
`dis[2]=getDistance(); //左邊`
* 1
向右邊運(yùn)動(dòng),檢測(cè)右邊距離
`for (pos = 150; pos >= 30; pos -= 1)
{
myServo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
if(pos==90)
dis[1]=getDistance(); //中間
}
dis[0]=getDistance(); //右邊`
* 1
* 2
* 3
* 4
* 5
* 6
* 7
* 8
將前邊、左邊、右邊距離障礙的距離都檢測(cè)結(jié)束之后,舵機(jī)回到最初位置。
`for (pos = 30; pos <= 90; pos += 1)
{
myServo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}`
* 1
* 2
* 3
* 4
* 5
注意事項(xiàng)
1.舵機(jī)使用時(shí)要防止其堵轉(zhuǎn),因?yàn)辄c(diǎn)擊堵轉(zhuǎn)時(shí)電流會(huì)增大,很容易燒壞舵機(jī)。
2.舵機(jī)的紅色電源線接入電壓一般要大于等于其工作電壓,供電不足會(huì)導(dǎo)致舵機(jī)不停自傳。
3.Arduino 《Servo.h》庫(kù)里提供的write()函數(shù)輸出的PWM即為舵機(jī)專(zhuān)用的20ms為周期的PWM波,如果使用其他開(kāi)發(fā)板或者函數(shù)的話,請(qǐng)務(wù)必保證輸出方波周期為20ms,否則舵機(jī)不會(huì)受控制
總結(jié)
這一篇講解了舵機(jī)和超聲波模塊的使用方法,舵機(jī)在大家以后的開(kāi)發(fā)生涯中應(yīng)該會(huì)經(jīng)常用到,因此舵機(jī)的使用規(guī)則(控制周期為20ms)請(qǐng)大家一定要記清楚,在舵機(jī)不受控制的時(shí)候建議大家可以購(gòu)買(mǎi)一個(gè)舵機(jī)測(cè)試儀來(lái)測(cè)試舵機(jī)。
總結(jié)
以上是生活随笔為你收集整理的distance在函数 int_Arduino智能小车——超声波避障的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: time库是python中处理时间的标准
- 下一篇: python单元测试工具_Python的