超音波センサーで距離測定してみた。(Raspberry Pi Pico)

つぶやき

HC-SR04超音波センサーを使用して距離を測定します。

Timer関数で作動させた。


TRIGピンを使って超音波を送信しECHOピンで反射音を受信し、かかった時間から距離を計算します。
2秒ごとにタイマーで自動測定します。

from machine import Timer, Pin  # タイマーとGPIOピン制御のためのモジュールをインポート
import time  # 時間制御のためのモジュールをインポート

# 使用するGPIOピン番号を定義
TRIG_PIN = 17  # 超音波センサーのTRIGピンをGPIO17に接続
ECHO_PIN = 16  # 超音波センサーのECHOピンをGPIO16に接続

# TRIGピンを出力に、ECHOピンを入力に設定
TRIG = Pin(TRIG_PIN, Pin.OUT)
ECHO = Pin(ECHO_PIN, Pin.IN)

def distance():
    """
    超音波センサー(HC-SR04)を使って距離を測定する関数。
    戻り値:
        測定に成功した場合: 距離(mm 単位)
        測定失敗(タイムアウト)の場合: -1 を返す
    """
    # TRIGピンに10マイクロ秒のパルスを送って測定を開始
    TRIG.low()  # 念のためLOWにしてからスタート
    time.sleep_us(2)
    TRIG.high()  # 10マイクロ秒だけHIGHにする
    time.sleep_us(10)
    TRIG.low()

    # ECHOピンがHIGHになるのを待つ(超音波の送信開始)
    timeout_start = time.ticks_us()  # タイムアウト用の開始時刻を記録
    while not ECHO.value():  # LOWのままの場合、待つ
        if time.ticks_diff(time.ticks_us(), timeout_start) > 30000:
            return -1  # 30ms以上応答がなければ失敗

    # ECHOがHIGHになった瞬間の時間を記録(超音波が戻ってくるのを測定)
    time1 = time.ticks_us()

    # ECHOピンが再びLOWになるのを待つ(超音波が戻ってきた)
    while ECHO.value():  # HIGHが続いている間は待つ
        if time.ticks_diff(time.ticks_us(), time1) > 30000:
            return -1  # パルスが長すぎる=失敗

    # LOWになった瞬間の時間を記録
    time2 = time.ticks_us()

    # パルスの継続時間を計算(エコーの往復時間)
    duration = time.ticks_diff(time2, time1)

    # 距離をミリメートル単位で計算
    # 音速 343,000 mm/s(343 m/s)を使用
    # 往復なので2で割る
    distance_mm = duration * 343 / 2 / 1000

    return distance_mm

def measure_distance(timer):
    """
    タイマー割り込みで定期的に呼び出される関数。
    現在の距離を測定して表示する。
    """
    dis = distance()  # 距離を測定
    if dis != -1:
        print("Distance: %.0f mm" % dis)  # 測定成功時に距離を表示
    else:
        print("Measurement failed")  # 測定失敗時のメッセージ

# タイマーを初期化して、2秒ごとにmeasure_distance()を呼び出す
timer = Timer()
timer.init(period=2000, mode=Timer.PERIODIC, callback=measure_distance)

sleep関数で作動させた。

sleep関数で作動させた。

import machine  # ハードウェア制御用のモジュール
import time     # 時間制御用のモジュール

# 超音波センサー用のGPIOピンを定義
TRIG = machine.Pin(17, machine.Pin.OUT)  # TRIGピン(出力):超音波の発信を制御
ECHO = machine.Pin(16, machine.Pin.IN)   # ECHOピン(入力):反射波の受信を検出

def distance():
    """
    HC-SR04超音波センサーを使って距離を測定する関数。
    戻り値:
        距離(mm単位のfloat値)、または
        タイムアウト時は -1 を返す。
    """

    # センサーをリセットするためにTRIGをLOWにする(少し待つ)
    TRIG.low()
    time.sleep_us(2)

    # TRIGピンを10マイクロ秒だけHIGHにして、超音波パルスを送信
    TRIG.high()
    time.sleep_us(10)
    TRIG.low()

    # タイムアウト測定の開始時間を記録
    timeout_start = time.ticks_us()

    # ECHOピンがHIGHになるのを待つ(反射波の受信開始)
    while not ECHO.value():
        # 30ms以上HIGHにならなければ失敗と判断
        if time.ticks_diff(time.ticks_us(), timeout_start) > 30000:
            return -1  # タイムアウト(反射波が来なかった)

    # ECHOがHIGHになった時刻を記録(パルスの開始)
    time1 = time.ticks_us()

    # ECHOが再びLOWになるのを待つ(反射波の終了)
    while ECHO.value():
        # 30ms以上HIGHが続く場合も失敗と判断
        if time.ticks_diff(time.ticks_us(), time1) > 30000:
            return -1  # タイムアウト(パルスが長すぎる)

    # ECHOがLOWになった時刻を記録(パルスの終了)
    time2 = time.ticks_us()

    # パルスの継続時間を計算(単位はマイクロ秒)
    duration = time.ticks_diff(time2, time1)

    # 距離をミリメートル単位に変換
    # 音速:340 m/s = 340,000 mm/s = 0.34 mm/µs
    # 往復なので2で割る
    return duration * 340 / 2 / 1000  # 単位:mm

# メインループ(1秒ごとに距離を測定)
while True:
    dis = distance()  # 距離を取得
    if dis != -1:
        print("Distance: %.0f mm" % dis)  # 測定成功時に距離を出力(整数で表示)
    else:
        print("Measurement failed (timeout)")  # 測定失敗時のメッセージ

    time.sleep_ms(1000)  # 1秒待機してから次の測定

短いプログラムにしてみた

from machine import Pin, time_pulse_us
import time

t, e = Pin(17, Pin.OUT), Pin(16, Pin.IN)

while True:
    t.off(); time.sleep_us(2)
    t.on(); time.sleep_us(10); t.off()
    d = time_pulse_us(e, 1, 30000)
    print(f"{d * 0.1715:.0f} mm" if d > 0 else "タイムアウト")
    time.sleep(1)
from machine import Pin, time_pulse_us
import time

# HC-SR04のピン設定
trigger = Pin(3, Pin.OUT)
echo = Pin(2, Pin.IN)

# ブザーピン(パッシブ or アクティブブザー)
buzzer = Pin(15, Pin.OUT)

def get_distance():
    trigger.low()
    time.sleep_us(2)
    trigger.high()
    time.sleep_us(10)
    trigger.low()
    duration = time_pulse_us(echo, 1, 30000)  # タイムアウト30ms
    distance = duration * 0.0343 / 2  # 音速で距離換算(cm)
    return distance

while True:
    try:
        distance = get_distance()
        print("Distance: {:.1f} cm".format(distance))
        
        if distance < 100:  # 100cm以内に近づいたとき
            interval = max(0.05, distance / 200)  # 距離に応じて間隔短縮(近いほど速い)
            buzzer.high()
            time.sleep(0.05)  # 短く鳴らす
            buzzer.low()
            time.sleep(interval)
        else:
            time.sleep(0.2)  # 対象が遠いときは鳴らさない

    except Exception as e:
        print("Error:", e)
        time.sleep(1)

参考にさせていただいたサイトです。

【Raspberry Pi Pico】ロボット制御入門③~I2C通信と障害物回避~【Python】
前回はライブラリの作成について学びました。 今回はセンサー入力を使って自動制御の一旦を体験して

コメント