目的
我們希望自動控制的四軸飛行器能夠固定在指定的高度上,那我們就需要感測器來偵測目前飛行高度。本篇內容僅專注於超音波感測器。
材料
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 超音波距離檢測 效率改進