本文是 AI 神經網路自走車 第二篇,分享如何使用 Raspberry pi pico (RP2040) 與 HC-SR04 超音波測距模組做底層的距離偵測。雖然最終會使用 camera 與 CNN 做 auto driving 的大腦,但加上距離資訊會更準確,就讓我們一起來學習吧!
目錄
準備硬體元件
這次製作需要準備的材料為:
Step 1:了解超音波測距原理
原理非常簡單,還記得小時候在山裡對著遠方山谷大喊嗎?我們利用從發出聲音與聽到回音的時間間隔,乘上聲速,並除以二就可以得到距離!
Step 2:了解 HC-SR04 模組工作原理
HC-SR04 只有 4 pin,分別是 VCC、GND、Trig、Echo。運作方式非常簡單,讓我們配著時序圖一起看:
- 向 Trig pin 送入一個至少 10us 長的方波
- 收到方波後模組被驅動,從音波發射端連續發出 8 個 40KHz 的方波
- 模組收到回音後,會將 Echo pin 輸出高電位,而後復位為低電位
- 測量 Echo pin 高電位的持續時間,即為超音波從發出到返回的時間
- 利用一開始提供的數學式,即可求得距離
Step 3:撰寫 Raspberry pi pico python 測試
了解原理後,就讓我們開始撰寫看看。首先將 pico 和 HC-SR04 模組相連,這邊只要是 GPIO pin 都可以使用,我們範例採用 GPIO 0 和 GPIO 1 來實作。
對照 pico 的 pinout 我們做以下連結
pico | HC-SR04 |
GPIO 0 | Trig |
GPIO 1 | Echo |
3V3 | VCC |
GND | GND |
模組的 VCC 和 GND 可以直接拉到 pico 身上的 3V3 和任一的 GND pin 座相連。
硬體接線完畢,我們開始看 code
from machine import Pin, time_pulse_us
import time
# 宣告 trig 和 echo pin
trig_pin = Pin(0, Pin.OUT)
echo_pin = Pin(1, Pin.IN)
# 對 trig pin 送 10us 長的方波
trig_pin.high()
time.sleep_us(10)
self.trig_pin.low()
# 透過內建函數 time_pulse_us,計算 echo pin 方波持續時間
# 第一個參數給定要測量的 pin
# 第二個參數給定 1 表示計算 high 持續時間
# 第三個參數給定 timeout 時間
echo_t = time_pulse_us(echo_pin, 1, timeout_us=58000)
# 依照官方文件描述
# 如果回傳 -2 表示等 echo pin 拉高超時
# 如果回傳 -1 表示 echo pin 拉高時間太長而超時
if echo_t == -2:
print('timeout to wait echo to be high.')
elif echo_t == -1:
print('timeout to measure echo pulse width')
else:
# 將 echo_t 轉換成距離,這邊單位為 cm
# 另,除以 29 約等於乘 0.034
distance = (echo_t / 2.0) / 29
print('distance is", distance)
這邊稍微解釋一下 code 中對 distance 的算法,因為與一開始講的不一樣。
我們同時將 us 轉成 s,m 轉成 cm,把
常數處理後,就會得到 0.034 這個數字,而 29 則是 0.034 的倒數
實際測試沒問題,我們將上述的 code refactor 成類別,以後呼叫比較方便!
Step 4:把 HC-SR04 模組的 code 包成類別
不多說,立刻看 code
from machine import Pin, time_pulse_us
import time
class HCSR04:
def __init__(self, trig_pin: int, echo_pin: int):
self.trig_pin = Pin(trig_pin, Pin.OUT)
self.echo_pin = Pin(echo_pin, Pin.IN)
self.trig_pin.low()
def get_distance_in_cm(self):
self._send_trig()
echo_t = self._receive_echo()
if echo_t >= 0:
return (echo_t / 2.0) / 29 # 1 / 29 = 0.034
# if timeout, return -1
return -1
def _send_trig(self):
# send trig high
self.trig_pin.high()
time.sleep_us(10)
# complete trig
self.trig_pin.low()
def _receive_echo(self):
echo_t = time_pulse_us(self.echo_pin, 1, 58000)
if echo_t == -2:
print('timeout to wait echo to be high.')
if echo_t == -1:
print('timeout to measure echo pulse width')
return echo_t
有了以上的包裝後,每一個 HCSR04 可以代表一個 sensor,使用上比較方便
sensor = HCSR04(0, 1)
distance = sensor.get_distance_in_cm()
print('distance is', distance)
有了基礎的距離偵測,我們就可以繼續往下邁進!如果覺得我文章內容對你有幫助的話,請在文章後面幫我按 5 個讚!讓我知道大家都喜歡什麼內容哦!
範例原始碼在此下載:github
AI 神經網路自走車
上一篇:用 Raspberry pi pico 做 PWM Motor Control
下一篇:如何用 Raspberry pi pico 做 I2C Slave? 使用 MicroPython 與 Raspberry pi