distance在函数 int_Arduino智能小车——超声波避障
Arduino智能小車——超聲波避障
Arduino智能小車系列教程時空門:
Arduino智能小車——拼裝篇 點擊跳轉(zhuǎn)
Arduino智能小車——測試篇 點擊跳轉(zhuǎn)
Arduino智能小車——調(diào)速篇 點擊跳轉(zhuǎn)
Arduino智能小車——超聲波避障 點擊跳轉(zhuǎn)
Arduino智能小車——藍牙小車 點擊跳轉(zhuǎn)
Arduino智能小車——循跡篇 點擊跳轉(zhuǎn)
Arduino智能小車——小車測速 點擊跳轉(zhuǎn)
文章目錄
經(jīng)過前幾篇的測試大家應該對小車有一定的認識了,在實際的操作過程中經(jīng)常會由于操作不當各種碰壁吧?那這次我們將給小車裝上一只“眼睛”,讓小車看到障礙,躲避障礙。
準備材料
超聲波模塊HC-SR04
在這里簡單說下超聲波測距的原理,相信大家也都知道。超聲波發(fā)射裝置發(fā)出超聲波,它的根據(jù)是接收器接到超聲波時的時間差,與雷達測距原理相似。 超聲波發(fā)射器向某一方向發(fā)射超聲波,在發(fā)射時刻的同時開始計時,超聲波在空氣中傳播,途中碰到障礙物就立即返回來,超聲波接收器收到反射波就立即停止計時。
采用Trig引腳觸發(fā),給至少10us的高電平脈沖信號
模塊自動發(fā)送8個40kHz的方波,自動檢測是否有信號返回
有信號返回,通過Echo引腳輸出一個高電平脈沖,高電平脈沖持續(xù)的時間就是超聲波從發(fā)射到反射返回的時間。距離=(高電平脈沖時間*340)/2。(聲音在空氣中傳播速度為340m/s)
主要技術(shù)參數(shù)
工作電壓
DC5V
靜態(tài)電流
<2mA
輸出電平
0-5V
感應角度
≤15度
探測距離
2cm-450cm
最高精度
0.3cm
舵機
在這里推薦9G舵機SG90,或者其他類似的舵機,這種舵機體積比較小,扭矩雖然不是大, 但是足夠帶動簡易云臺,很方便在小車上使用,大家購買時注意舵機的轉(zhuǎn)動角度,有55度的,180度的等等,大家可以根據(jù)需要購買。
舵機固定架
舵機固定架的購買一定要配合舵機,所以大家購買的時候注意尺寸哦!!~
舵機安裝
舵機在安裝之前大家一定要記得校準,為什么要校準那,這個跟舵機的工作原理有關(guān)。控制信號由接收機的通道進入信號調(diào)制芯片,獲得直流偏置電壓。它內(nèi)部有一個基準電路,產(chǎn)生周期為20ms,寬度為1.5ms的基準信號,將獲得的直流偏置電壓與電位器的電壓比較,獲得電壓差輸出。最后,電壓差的正負輸出到電機驅(qū)動芯片決定電機的正反轉(zhuǎn)。當電機轉(zhuǎn)速一定時,通過級聯(lián)減速齒輪帶動電位器旋轉(zhuǎn),使得電壓差為0,電機停止轉(zhuǎn)動。
舵機的控制一般需要一個20ms左右的時基脈沖,該脈沖的高電平部分一般為0.5ms-2.5ms范圍內(nèi)的角度控制脈沖部分,總間隔為2ms。以180度角度伺服為例,那么對應的控制關(guān)系是這樣的:
高電平時間
對應位置
0.5ms
0度
1.0ms
45度
1.5ms
90度
2.0ms
135度
2.5ms
180度
也就是說當對舵機輸入相同控制信號時,舵機會運動到固定位置,他的動作不是做圓周運動,而是在運動范圍內(nèi),每一個位置對應一個控制信號。
因此我們需要在將舵機安裝在固定架上之前,需要先將舵機初始化好,舵機一般為三根線:棕色——GND,紅色——VCC,橙色——控制信號。因此我們將棕色線接到GND,紅色線接到“+5V”引腳,橙色線接到“9”引腳,初始化程序如下:
`#include //加入含有舵機控制庫的頭文件
#define PIN_SERVO 9 //舵機信號控制引腳
Servo myservo;
void setup()
{
myservo.attach(PIN_SERVO); //舵機初始化
}
void loop()
{
myservo.write(90); //PWM輸出
}`
* 1
* 2
* 3
* 4
* 5
* 6
* 7
* 8
* 9
* 10
* 11
* 12
* 13
* 14
在舵機初始化好之后將其安裝在固定架上,然后裝配在小車上,此時保證超聲波模塊超前。
超聲波接線
估計不少朋友早已經(jīng)發(fā)現(xiàn)板子上的“+5V”和“GND”引腳已經(jīng)不夠用了,這個時候你們可以向我這樣焊一個擴展板出來,上面固定兩排排針,一排用來擴展“+5V”,一邊用來擴展“GND”引腳。
超聲波模塊有四個引腳,“VCC”接到Arduino UNO開發(fā)板的“+5V”引腳,“GND”接到開發(fā)板“GND”引腳,“Trig”引腳接到開發(fā)板“8”引腳,“Echo”引腳接到開發(fā)板“7”引腳。
線太亂了,真的沒辦法整理,我自己都沒眼看。
代碼測試
`#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; //舵機
int inputPin=7; // 定義超聲波信號接收接口
int outputPin=8; // 定義超聲波信號發(fā)出接口
void setup() {
// put your setup code here, to run once:
//串口初始化
Serial.begin(9600);
//舵機引腳初始化
myServo.attach(9);
//測速引腳初始化
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厘米返回數(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ā)出聲波,對應int outputPin=8;
“Echo”引腳反應接收到返回聲波,對應int inputPin=7;
`int inputPin=7; // 定義超聲波信號接收接口
int outputPin=8; // 定義超聲波信號發(fā)出接口`
* 1
* 2
int getDistance()函數(shù)解析
超聲波發(fā)出引腳“Trig”為高時對外發(fā)出超聲波,為保證發(fā)出10μs聲波,因此在發(fā)送之前需要將該引腳拉低,并給他一定反應時間。
`digitalWrite(outputPin, LOW); // 使發(fā)出發(fā)出超聲波信號接口低電平2μs
delayMicroseconds(2);`
* 1
* 2
之后發(fā)送10μs超聲波
`digitalWrite(outputPin, HIGH); // 使發(fā)出發(fā)出超聲波信號接口高電平10μs,這里是至少10μs`
* 1
聲波發(fā)送之后禁止其繼續(xù)發(fā)送,同時開始檢測是否反射回來的聲波
`digitalWrite(outputPin, LOW); // 保持發(fā)出超聲波信號接口低電平
int distance = pulseIn(inputPin, HIGH); // 讀出脈沖時間`
* 1
* 2
pulseIn()單位為微秒,聲速344m/s,所以距離cm=344_100/1000000_pulseIn()/2約等于pulseIn()/58.0distance= distance/58; // 將脈沖時間轉(zhuǎn)化為距離(單位:厘米)
超聲波模塊工作受物體表面反射程度影響,并且在傳播過程中信號強度容易衰減,因此該模塊適用的檢測距離有限,一般在50cm以內(nèi)相對正確,而且我們在避障時不需要檢測太遠的距離,因此超過50cm以上的都按50cm計算
`if (distance >=50)
{
//如果距離小于50厘米返回數(shù)據(jù)
return 50;
}//如果距離小于50厘米小燈熄滅
else
return distance;`
* 1
* 2
* 3
* 4
* 5
* 6
* 7
void avoidance()函數(shù)解析
小車前進過程中只檢測前方距離障礙的距離,并且控制舵機,保持超聲波模塊位于正前方。
`motorRun(FORWARD,200);
myServo.write(90);
dis[1]=getDistance(); //中間`
* 1
* 2
* 3
當檢測到小車前方距離障礙距離小于30cm時停車,檢測兩邊距離。
`motorRun(STOP,0);`
* 1
控制舵機每次運動一個周期后都返回正前方位置。由于舵機運動需要一定的時間,因此在每轉(zhuǎn)過一個角度的時候都延時delay(15),供其運動。
`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
當運動到最左邊時檢測小車左邊距離障礙的距離
`dis[2]=getDistance(); //左邊`
* 1
向右邊運動,檢測右邊距離
`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
將前邊、左邊、右邊距離障礙的距離都檢測結(jié)束之后,舵機回到最初位置。
`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
注意事項
1.舵機使用時要防止其堵轉(zhuǎn),因為點擊堵轉(zhuǎn)時電流會增大,很容易燒壞舵機。
2.舵機的紅色電源線接入電壓一般要大于等于其工作電壓,供電不足會導致舵機不停自傳。
3.Arduino 《Servo.h》庫里提供的write()函數(shù)輸出的PWM即為舵機專用的20ms為周期的PWM波,如果使用其他開發(fā)板或者函數(shù)的話,請務必保證輸出方波周期為20ms,否則舵機不會受控制
總結(jié)
這一篇講解了舵機和超聲波模塊的使用方法,舵機在大家以后的開發(fā)生涯中應該會經(jīng)常用到,因此舵機的使用規(guī)則(控制周期為20ms)請大家一定要記清楚,在舵機不受控制的時候建議大家可以購買一個舵機測試儀來測試舵機。
總結(jié)
以上是生活随笔為你收集整理的distance在函数 int_Arduino智能小车——超声波避障的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: time库是python中处理时间的标准
- 下一篇: python单元测试工具_Python的