Arduino 超音波距離檢測

目的

我們希望自動控制的四軸飛行器能夠固定在指定的高度上,那我們就需要感測器來偵測目前飛行高度。本篇內容僅專注於超音波感測器。

材料


HC-SR04 超音波距離感測器

量測距離最近2cm,最遠400cm,感應角度小於15度。
四軸飛行器的飛行高度也就是垂直距離,距離量測中常見的感測器又有光學(紅外線、LIDAR)與超音波(Ultrasonic)兩大類,兩者的測距原理都是發射器發射一段脈衝訊號出去,由接收器接收訊號回來,計算兩者時間差來反算距離。
光學感測器具有精準度高、速度快,且能夠量測遠距離物體的優點,不過比起超音波來說真的太貴了XD
而超音波是藉由空氣傳導,聲音傳播速率計算公式為 331+0.6T,其中T為攝氏溫度,由此可知聲速會因為空氣溫度變化而改變,除此之外也會因為反射物體的表面材質、物體大小、擺放角度而影響,例如吸音棉可能會量不到距離、測量物體太小無法反射超音波等。

方法

透過Arduino控制HC-SR04發送脈衝訊號,等待訊號返回利用時間差計算距離。

配置

HC-SR04 有四個接點,分別為VCC、TRIG、ECHO、GND,其中TRIG為發送器,ECHO為接收器,我們將TRIG接上D9、ECHO接上D8。

根據HC-SR04官方文件說明,其運作流程如下圖,我們對TRIG給一個10微秒的高電位脈衝,HC-SR04就會發送8個超音波出去,接著等待超音波反射回來並接收到後,ECHO會回傳一個脈衝,這個脈衝的長度隨著超音波距離增加而變長,我們只要將脈衝長度稍作換算就能得知物體距離。

完整程式碼如下:

 

#define TRIGPIN 9
#define ECHOPIN 8

//發送脈衝
float ping()
{
	digitalWrite(TRIGPIN, LOW);
	delayMicroseconds(2);
	digitalWrite(TRIGPIN, HIGH);
	delayMicroseconds(10);
	digitalWrite(TRIGPIN, LOW);

	return (float)pulseIn(ECHOPIN, HIGH)/29/2;
}

void setup() {
	Serial.begin(9600);
	pinMode(TRIGPIN, OUTPUT);
	pinMode(ECHOPIN, INPUT);
}

void loop() {

	float cm = ping();

	Serial.print(cm);
	Serial.print("cm\n");

	delay(200);
}

其中第13行:

 return (float)pulseIn(ECHOPIN, HIGH)/29/2;

我們利用pulseIn() 函數來取得脈衝持續時間,這個脈衝時間必須除以29,29為聲音每前進一公分所需要的微秒數(microseconds),若溫度為攝氏24度則聲速約為29微秒/公分,計算方法如下:

如果Arduino上有接其他溫度模組,就可以利用此公式來取得更準確的距離。

另外,由於是透過物體反射超音波來計算距離,實際上超音波走的距離是真正距離的兩倍,所以我們還要再將距離除以2,才是正確數值。

結果

若將手在HC-SR04之前前後移動,則數字將會有所變化。

改進

持續把玩了一陣子後會發現,HC-SR04在偵測遠距離物體時(超過一公尺),執行效率會變得很差,我們在loop()中放入pingTime來計算執行時間,程式碼如下:

void loop() {

	long startTime = millis();
	float cm = ping();
	long pingTime = millis() - startTime;

	Serial.print(pingTime);
	Serial.print("ms\t");
	Serial.print(cm);
	Serial.print("cm\n");

	delay(200);
}

其結果如下圖:

第一排數字為每次ping所執行的時間,我們會發現當距離越遠,所執行的時間就需要越久,這對處理效率來說是相當差的。如果HC-SR04只是裝在速度不快的避障車上,這些微的時間差影響不大,但是若要將HC-SR04裝在四軸飛行器上,這將會是個災難。

改善HC-SR04執行效率的方法,請參閱下一篇:Arduino 超音波距離檢測 效率改進


發表迴響