看到機器小車上大多會裝上一個超音波測距模組,看起來像是兩個眼睛,引發我的好奇,如何能利用超音波來測距離呢?於是網購買了幾個套件,利用上班空閒之餘來研究一下這幾個模組的特性。以下是超音波模組含溫度補償功能的US-100。
上一篇提到智能小車除了用鍵盤控制方向外,還可以透過距離偵測感應轉彎,避免碰撞前方物體,本篇就來瞭解超音波測距的一些功能及測試結果。
聲音的速度,在一般空氣中約為每秒340公尺,因來回時間要將距離除以二,才是單程的距離。實際的聲音速度決定於好幾個環境因素,其中一個是溫度,計算時,需將環境因素考慮在內,才能更精確計算距離。
我在網路上購買的是US-100這個型號,根據規格文件,這個模組最遠可測得2公分~4.5公尺, 輸入電壓大約 2.4V ~ 5.5V,其偵測廣度大約是15度。這個模組具有溫度感測,距離值已經溫度調校,無需再根據環境溫度對超音波聲速進行校正。
在這個模組背面有一個Jumper,來控制兩種模式:
US-100有五個pin腳,說明如下:
工作方式:
透過Trig接腳發出一個10us(10^-6 秒)以上的高電位,此時等待Echo高電平輸出,一旦有輸出就可以開始計時,此時模組會發送8個40khz的方波,並開始自動檢測是否有返回信號;當偵測到反射訊號時,此時Echo接腳變為低電位。計算持續高電位的時間,也就是這次測距的時間。如果加上迴圈,就可以一直偵測前方移動物體的距離。
• US-100超音波模組 x1
• 連接線 x4
• US-100 Trig/TX接Pin16(GPIO23),Echo/RX接Pin18(GPIO24)
上一篇提到智能小車除了用鍵盤控制方向外,還可以透過距離偵測感應轉彎,避免碰撞前方物體,本篇就來瞭解超音波測距的一些功能及測試結果。
[基礎知識:超音波測距]
超音波測距的方式是發射一個電波,當電波遇到物體反射回來,再被測距儀偵測到反射電波,利用來回時間與音波的速度算出距離,計算公式如下:
距離=(音波發射與接收時間差 * 聲音速度(340M/S))/2;
聲音的速度,在一般空氣中約為每秒340公尺,因來回時間要將距離除以二,才是單程的距離。實際的聲音速度決定於好幾個環境因素,其中一個是溫度,計算時,需將環境因素考慮在內,才能更精確計算距離。
我在網路上購買的是US-100這個型號,根據規格文件,這個模組最遠可測得2公分~4.5公尺, 輸入電壓大約 2.4V ~ 5.5V,其偵測廣度大約是15度。這個模組具有溫度感測,距離值已經溫度調校,無需再根據環境溫度對超音波聲速進行校正。
在這個模組背面有一個Jumper,來控制兩種模式:
- open:將Jumper拔起來,此時為GPIO 模式(電位觸發模式)
- short:將Jumper 套上,此時設定為UART串列通訊模式
US-100有五個pin腳,說明如下:
- VCC:接電源(範圍2.4V~5.5V)。
- Trig/TX:UART 模式下,接外部電路UART 的TX 端;為GPIO模式時,為訊號發送端 Trigger。
- Echo/RX:UART 模式下,接外部電路UART 的RX 端;為GPIO模式時,為訊號接收端 Echo 。
- GND:接地,沒有使用。
- GND:電路接地。
工作方式:
透過Trig接腳發出一個10us(10^-6 秒)以上的高電位,此時等待Echo高電平輸出,一旦有輸出就可以開始計時,此時模組會發送8個40khz的方波,並開始自動檢測是否有返回信號;當偵測到反射訊號時,此時Echo接腳變為低電位。計算持續高電位的時間,也就是這次測距的時間。如果加上迴圈,就可以一直偵測前方移動物體的距離。
[材料]
• Raspberry Pi 主板 x1• US-100超音波模組 x1
• 連接線 x4
[線路連接與電路圖](圖片以HC-SR04替代)
• US-100 VCC接pin2(+5V),GND接pin6(GND)• US-100 Trig/TX接Pin16(GPIO23),Echo/RX接Pin18(GPIO24)
[程式碼]
import RPi.GPIO as GPIO
import time
trigger_pin = 23
echo_pin = 24
GPIO.setmode(GPIO.BCM)
GPIO.setup(trigger_pin, GPIO.OUT)
GPIO.setup(echo_pin, GPIO.IN)
def send_trigger_pulse():
GPIO.output(trigger_pin, True)
time.sleep(0.001)
GPIO.output(trigger_pin, False)
def wait_for_echo(value, timeout):
count = timeout
while GPIO.input(echo_pin) != value and count > 0:
count = count - 1
def get_distance():
send_trigger_pulse()
wait_for_echo(True, 5000)
start = time.time()
wait_for_echo(False, 5000)
finish = time.time()
pulse_len = finish - start
distance_cm = pulse_len * 340 *100 /2
distance_in = distance_cm / 2.5
return (distance_cm, distance_in)
while True:
print("cm=%f\tinches=%f" % get_distance())
time.sleep(1)
[測試結果]
我在超音波偵測頭前放一把尺,然後在刻度位置放置一個物體,程式回報測得的數據跟尺的刻度非常接近,誤差不到一公分,以物體感應來說,算是相當準確。[參考資料]
- Arduino 超音波測距機設計與製作(作者:曹永忠、許智誠、蔡英德)
- Raspberry Pi Cookbook
5000是什麼意思
回覆刪除5000是等待timeout的時間,也就是等待不超過5秒鐘。
回覆刪除老師好:我用一個超音波測距做5次不同測量,python要如何把這5個數據傳送到另一個.py程式做進一步計算,學生愚鈍查很久沒找到,請求老師解惑,謝謝
回覆刪除你好, 因為要量測5次再交由另一個.py處理,建議寫成檔案的方式,再由另一個.py讀入檔案進行計算處理。Python 的檔案讀寫不複雜,你可以參考一下f=open(檔名, 模式)、f.readlines() 等指令。
刪除老師你好,小弟這邊有個問題,我打算做一個自動判斷是否已滿的垃圾桶,如果滿了會自動發信到特定信箱。
回覆刪除那方法是打算使用超音波感測器裝在垃圾桶8成的高度,如果連續10秒偵測到物體(如果不設延遲的秒數會導致每丟一次垃圾 超音波就偵測到一次,因而發信),就代表垃圾已經到達8成滿,可以寄信給特定信箱了。
小弟是新手希望老師能稍微解惑一下...
第一個問題是,我要如果要做到那個延遲10秒才判定是True(True表示垃圾桶已滿),可以怎麼做呢?? 偵測到的每一秒就count++一次,count=10就變成True嗎?
第二個問題是,樹莓派有那種判斷式為True就自動發信的function嗎??
如果可以的話希望老師能給新手一點指導
你好,
刪除第一個問題可以用Count解決,如你提的方法,自己判斷次數後,觸發Mail發送。
第二個問題是你在樹莓派使用什麼語言呢?如果是用Ptyhon, 有段Python發送郵件的程式可提供參考:https://docs.python.org/2/library/email-examples.html,其他語言可找一下相關的範例,應該很多。
是python沒錯,了解了,非常謝謝指導!
刪除您好 如果樹莓派 不管有沒有接上HC-SR04
回覆刪除執行程式碼 都會一直跑出距離是正常的嗎??
是的, 我程式沒有判斷讀取HC-SR04的邏輯,一直出現距離是正常的。改天來改一下程式,判斷讀取值再呈現比較好。
刪除作者已經移除這則留言。
刪除真的嗎~~期待您的新程式碼 因為最近剛好作業做到HC-SR04
刪除參考到您的想說怎麼會一直出現距離~
老師您好 請問如果超音波感測超過他可偵測距離後就不再繼續回傳數值,就算再給他感測近處的物體他也不回傳數值,請問要怎麼解決才好。
回覆刪除import RPi.GPIO as GPIO
回覆刪除import time
TRIG=23
ECHO=24
dir=0
limiDist=20
GPIO.setmode(GPIO.BCM)
GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)
GPIO.setup(2,GPIO.OUT)
GPIO.setup(3,GPIO.OUT)
GPIO.setup(4,GPIO.OUT)
GPIO.setup(13,GPIO.OUT)
GPIO.setup(19,GPIO.OUT)
GPIO.setup(26,GPIO.OUT)
def test_distance():
GPIO.output(TRIG,GPIO.HIGH)
time.sleep(0.07)
GPIO.output(TRIG,GPIO.LOW)
while GPIO.input(ECHO)==0:
start=time.time()
while GPIO.input(ECHO)==1:
end=time.time()
distance=(end-start)*17150
return distance
def forward():
GPIO.output(2,True)
GPIO.output(3,True)
GPIO.output(4,False)
GPIO.output(13,True)
GPIO.output(26,True)
GPIO.output(19,False)
def backward():
GPIO.output(2,True)
GPIO.output(3,False)
GPIO.output(4,True)
GPIO.output(13,True)
GPIO.output(26,False)
GPIO.output(19,True)
def turn():
GPIO.output(2,True)
GPIO.output(3,False)
GPIO.output(4,False)
GPIO.output(13,True)
GPIO.output(26,False)
GPIO.output(19,True)
def stop():
GPIO.output(2,True)
GPIO.output(3,False)
GPIO.output(4,False)
GPIO.output(13,True)
GPIO.output(19,False)
GPIO.output(26,False)
while True:
print("{:.1f}".format(test_distance()))
try:
dist=test_distance()
except Exception:
dist=400
if dist>limiDist:
if dir !=0:
stop()
dir=0
time.sleep(0.5)
forward()
elif dist<limiDist:
if dir !=0:
stop()
dir=1
time.sleep(0.5)
turn()
else:
if dir !=1:
stop()
dir=1
time.sleep(0.5)
turn()
time.sleep(1)
這是我的程式碼
請問 程式打進去了要怎麼執行
回覆刪除張貼留言