測距離
用聲音的來回時間換算距離。 · ⏱ 約 35 分鐘
你會學到三件事
- 超音波感測器怎麼運作:送一聲、量它多久回來
pulseIn 量一個脈衝有多長
- 為什麼這一課非得寫成一個函式不可
開始之前
接線:HC-SR04 的 Trig 接 9 號腳、Echo 接 10 號腳、
VCC 接 5V、GND 接 GND。
🟢 先把編輯器打開,跟著下面一起做:跟著做
一、原理
① Trig 送出一個 10 微秒的高電位 → 感測器發出一串超音波
② 聲音撞到東西彈回來
③ Echo 這支腳變高,持續的時間 = 聲音來回花的時間
聲音在空氣中大約 340 公尺/秒,也就是 0.034 公分/微秒。
所以:
來回距離 = 時間 × 0.034
單程距離 = 時間 × 0.034 ÷ 2 = 時間 ÷ 58
⚠️ 那個「除以 2」不能忘:量到的是來回,而你要的是單程。
忘了的話所有距離都會是兩倍,而它看起來只是「不太準」。
二、送出那一聲
照著打上這一段,它會送出一次超音波:
1digitalWrite(9, LOW);2delayMicroseconds(2);3digitalWrite(9, HIGH);4delayMicroseconds(10);5digitalWrite(9, LOW);
規格書要求:一個乾淨的 10 微秒高電位。
前面那個 LOW + 2 微秒是「先確保它是低的」——
不然上一次留下的殘留會讓這一次的脈衝長度不對。
積木盤上這五行收成了一顆,寫著「送出超音波觸發脈衝到腳位 …」
——⚠️ 而底下算距離那一段用的是「呼叫函式 …(…)」。
delayMicroseconds 和 delay 是同一件事,單位差一千倍
(1 毫秒 = 1000 微秒)。
三、量它多久回來
pulseIn 會等那一聲回來,回傳的是微秒:
1long t = pulseIn(10, HIGH);
pulseIn(腳, HIGH) 的意思是「等這支腳變高,然後量它高了多久」,
回傳的單位是微秒。
⚠️ pulseIn 會卡住整支程式,直到它量到(或超時)。
所以在它等待的那段時間,你的板子什麼都做不了。這是它的代價。
⚠️ 用 long 不用 int:int 在 Uno 上只裝得下 32767,
而 pulseIn 的值輕易就超過。溢位不會報錯,只會給你一個負數。
四、🔴 為什麼要寫成函式
上面那六行,每量一次距離就要全部再寫一次。
而「測距」在一支程式裡通常要用好幾次——判斷障礙、記錄、顯示。
所以它應該是一個名字:
1long distance() {2 digitalWrite(9, LOW);3 delayMicroseconds(2);4 digitalWrite(9, HIGH);5 delayMicroseconds(10);6 digitalWrite(9, LOW);7 long t = pulseIn(10, HIGH);8 return t / 58;9}
之後就只要寫 distance()。
函式不是「進階語法」——它是你第一次覺得
「這六行我不想再寫一遍」的時候,自然會想要的東西。
完成的樣子
這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。
1long distance() {2 digitalWrite(9, LOW);3 delayMicroseconds(2);4 digitalWrite(9, HIGH);5 delayMicroseconds(10);6 digitalWrite(9, LOW);7 long t = pulseIn(10, HIGH);8 return t / 58;9}10 11void setup() {12 Serial.begin(9600);13 pinMode(9, OUTPUT);14 pinMode(10, INPUT);15}16 17void loop() {18 Serial.println(distance());19 delay(200);20}
換你了
加一顆蜂鳴器:越近叫得越急。
提示:delay 的長度用 distance() 算出來——
近的時候 delay 短,遠的時候 delay 長。(倒車雷達就是這樣做的。)
到編輯器做這一題:練習:加一顆蜂鳴器,越近叫得越急
做一個
用超音波量你桌上某個東西的長度,再拿尺量一次,把兩個數字都用序列埠印出來。
🔴 這一題的答案不在程式裡,在兩個數字差多少。
⚠️ 量五次,你會發現它們不一樣。感測器的讀值本來就會跳,那要怎麼辦?
取平均?取中位數?丟掉最大最小?跟旁邊的人討論一下你們各選了哪一種。
到編輯器做這一題:做一個:拿它去量一個真的東西
這一課你做了什麼
- 你用一個脈衝的長度換算出了距離
- 你用
pulseIn 量了那個脈衝
- 你把六行包成一個函式,因為你不想再寫一遍
如果卡住了
| 你看到 |
多半是因為 |
| 距離都是 0 |
Echo 腳接錯,或感測器沒供電 |
| 距離是實際的兩倍 |
忘了除以 2(也就是除以 58 寫成除以 29) |
| 出現負數 |
用了 int。要用 long |
| 程式偶爾卡住不動 |
pulseIn 沒量到就會等到超時。那是正常的 |
| 讀數跳來跳去 |
超音波會被斜面和軟布吸走。多量幾次取中位數 |
在編輯器打開這一課 →