在 2014年 3月曾寫過一篇「Raspberry Pi 筆記(十五):超音波測距離Raspberry」,將 Pi 連接超音波模組,測試一下實際的距離與感應測得的數據差多少,實測的結果誤差不到1公分。
最近繼續研究 Pi 跟 Arduino,也發現另有一個超音波測距的模組,HC-SR04,我改用 Arduino 來連接這個模組,也寫程式測試一下兩者得到的結果是否相同。
HC-SR04 技術規格:
• HC-SR04測距模組連接線路
• 音速 c = 331.5 + 0.607 * t (其中 t 為攝氏溫度)。
例: 攝氏20度時的音速約為: 331.5 + 0.607*20 = 343.64 公尺/秒
• 音速公尺/秒 換算成 公分/微秒:343.64 * 100 / 1000000 = 0.034364 公分/微秒,亦即
音速每公分需要29.1 微秒: 1 / 0.034364 = 29.1 微秒/公分
超音波發射的距離為來回,因此單程距離 = 時間差 / 2 再除以 29.1 微秒 / 公分,同樣的如果要換算成英吋,只要將 29.1 再乘以 2.54 即可。來看看程式的內容:
有關 HC-SR04的實作,用 1602 LCD 顯示測得的數據,可參考我的另一篇文章:Arduino筆記(96):HC-SR04與VL53L0X(GY-530)的測距比較
最近繼續研究 Pi 跟 Arduino,也發現另有一個超音波測距的模組,HC-SR04,我改用 Arduino 來連接這個模組,也寫程式測試一下兩者得到的結果是否相同。
[超音波測距 HC-SR04]
模組工作原理:- 採用I/O觸發測距,給至少為 10us 的高電位信號
- 模組自動發送 8 個 40KHZ 的方波,自動檢測是否有信號返回
- 有信號返回,通過 I/O 輸出一高電位,高電位持續的時間就是超聲波從發射到返回的時間
- 測試距離 = (高電位時間 x 聲速 (343.2 米/秒)) / 2
HC-SR04 技術規格:
- 電源:DC5V/2mA
- 輸出電位( 1/ 0):5V/ 0V
- 精度:3mm
- 距離範圍:2 ~ 450cm
- 有效的角度:<15℃
- 觸發輸入信號:10uS TTL pulse
- ECHO輸出信號: Input TTL lever signal and the range in proportion
- 接線方式:VCC、trig (控制端)、echo (接收端)、GND
[材料]
- Arduino Uno x 1
- HC-SR04測距模組 x1
- 連接線 x 4條
[接線圖]
• HC-SR04測距模組連接線路
HC-SR04 測距模組 | Arduino |
---|---|
1 - VCC | VCC |
2 - Trig – Trigger | Pin 12 |
3 - Echo | Pin 11 |
4 - GND | GND |
[程式一]
以下先不呼叫函式,直接以音波在空氣中傳遞的大約速度,算出來回測得的時間,乘以空氣中傳遞聲音的速度,算出距離。程式中有一行 cm = (duration/2) / 29.1,各位會不會覺得奇怪,為什麼要除以 29.1 ? 那是因為在攝氏零度之海平面音速約為331.5公尺/秒,每升高1攝氏度,音速就增加0.607公尺/秒,可以列出一個公式:• 音速 c = 331.5 + 0.607 * t (其中 t 為攝氏溫度)。
例: 攝氏20度時的音速約為: 331.5 + 0.607*20 = 343.64 公尺/秒
• 音速公尺/秒 換算成 公分/微秒:343.64 * 100 / 1000000 = 0.034364 公分/微秒,亦即
音速每公分需要29.1 微秒: 1 / 0.034364 = 29.1 微秒/公分
超音波發射的距離為來回,因此單程距離 = 時間差 / 2 再除以 29.1 微秒 / 公分,同樣的如果要換算成英吋,只要將 29.1 再乘以 2.54 即可。來看看程式的內容:
int trigPin = 12; //Trig Pin int echoPin = 11; //Echo Pin long duration, cm, inches; void setup() { Serial.begin (9600); // Serial Port begin pinMode(trigPin, OUTPUT); // 定義輸入及輸出 pinMode(echoPin, INPUT); } void loop() { digitalWrite(trigPin, LOW); delayMicroseconds(5); digitalWrite(trigPin, HIGH); // 給 Trig 高電位,持續 10微秒 delayMicroseconds(10); digitalWrite(trigPin, LOW); pinMode(echoPin, INPUT); // 讀取 echo 的電位 duration = pulseIn(echoPin, HIGH); // 收到高電位時的時間 cm = (duration/2) / 29.1; // 將時間換算成距離 cm 或 inch inches = (duration/2) / 74; Serial.print("Distance : "); Serial.print(inches); Serial.print("in, "); Serial.print(cm); Serial.print("cm"); Serial.println(); delay(250); }2020/11/23補充:執行上述程式時,從串列埠看到的測試值都是整數,如果要計算值要顯示小數點,可以將上述程式中「long duration, cm, inches;」改成「float duration, cm, inches;」。
有關 HC-SR04的實作,用 1602 LCD 顯示測得的數據,可參考我的另一篇文章:Arduino筆記(96):HC-SR04與VL53L0X(GY-530)的測距比較
[程式二]
網友將上述計算等方式,寫成一個函式,比較著名的是 NewPing,可以到 這裡 下載最新的函式庫,放到 Arduino 的預設 Libraries目錄,即可呼叫該函式,程式如下:#include <NewPing.h> #define TRIG_PIN 12 // trigger Pin #define ECHO_PIN 11 // Echo Pin #define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm. NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE); // 設定 NewPing 物件,並給與最遠測試距離 void setup() { Serial.begin(115200); // 開啟串列埠顯示 ping 的距離值 } void loop() { delay(50); // 等待 50 毫秒,需大於前程式說明的 29 秒 unsigned int uS = sonar.ping(); // 送出 ping,並取得微秒 microseconds(uS) 時間 Serial.print("Ping: "); Serial.print(sonar.convert_cm(uS)); // 換算時間為公分,如顯示 0,表示超出距離範圍 Serial.println("cm"); }
[測試結果]
測試的結果還蠻正確的,跟規格提供的誤差值3mm差不多。接下來就要將 HC-SR04接到小車上去,看看遇到障礙物時,是否能自動轉彎或倒退。[參考資料]
- Tim Eckel / Arduino New Ping:NewPing Arduino Library for Arduino
- Arduino Forum:NewPing Library Project Homepage
- Random Nerd Tutorials:Complete Guide for Ultrasonic Sensor HC-SR04
- 維基百科:音速
大大辛苦了,不過程式二的第四行
回覆刪除NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
其中TRIGGER_PIN應為TRIG_PIN
你好, 是的應該為TRIG_PIN才對,謝謝告知。
刪除請問大大,程式一中間的duration是甚麼?
回覆刪除直徑
刪除L298N驅動模組,採用ST公司的L298N晶片,可以直接驅動兩顆3-30V直流馬達,並提供了5V輸出介面,可以給5V微控制器電路系統供電,支援3.3V MCU控制,可以方便的控制直流馬達速度和方向,也可以控制1顆2相步進馬達。
刪除感謝您分享,初學者請教一下程式一的執行順序:
回覆刪除digitalWrite(trigPin, HIGH); // 給 Trig 高電位,持續 10微秒
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
=> trigPin在此時已寫入Low了, 那接著下方的duration是不是應該只收到low的訊號了呢?
pinMode(echoPin, INPUT); // 讀取 echo 的電位
duration = pulseIn(echoPin, HIGH); // 收到高電位時的時間
謝謝您
很久沒看Arduino的程式了,再去查一下pulseIn()這個函數的用法:前一個指令將TrigPin設為低電位,如有信號返回,EchoPin引脚會輸出高電位,函數是要偵測高電位,也就是計算從低電壓到接收訊號時高電位持續的時間,就是超聲波從發射到返回的時間。使用pulseIn()函數獲取到測距的結果,並計算出距與被測物的實際距離。
刪除請問如何讓超音波測距結合步進馬達呢
回覆刪除想做可以在15cm內正轉3圈否則不會動
若正轉3圈後障礙物的距離超出15cm則會反轉3圈回原點結束動作
我是新手,還有很多不足的地方,麻煩大大了!
請問大大,我是用bDesigner,測出來的數字單位是cm嗎?
回覆刪除123
刪除想請問一下 上面的code 把 tripin pull high 10ms, 那後來的 echopin的時間是否要先 -10呢?(收到的是10ms前的high)
回覆刪除就是改成這樣.(理論上pinMode(echoPin, INPUT); 應該也是要時間.所以應該在while迴圈錢設?)
pinMode(echoPin, INPUT); // 讀取 echo 的電位
duration = pulseIn(echoPin, HIGH); // 收到高電位時的時間
duration -=10;
作者已經移除這則留言。
回覆刪除網誌管理員已經移除這則留言。
回覆刪除網誌管理員已經移除這則留言。
回覆刪除張貼留言