MicroPython的午睡(30) ラズパイPico、HC-SR04超音波センサを接続

Joseph Halfmoon

前回Raspberry Pi  PicoのPIOを使ってパルス幅測定ができるようになりました。今回はその応用、HC-SR04超音波センサで距離の測定を行ってみたいと思います。距離に比例するパルス幅(時間)が返ってくるセンサです。細かいことを言わなければ測ったパルス幅を距離に換算するだけ。

※「MicroPython的午睡」投稿順 Indexはこちら

(末尾に「精度とかとりあえず考えない版」のMicroPythonスクリプト全文を掲げました。)

HC-SR04超音波センサは、「電子工作業界」定番の超音波センサじゃないかと思います。ネット検索すれば、Arduinoなどでの応用例が多数みつかるでしょう。念のため、秋月電子通商殿のへのリンクを貼り付けておきます。そちらからデータシートを見ることもできます。

超音波距離センサー HC-SR04

制御そのものは非常に簡単です。

  1. Trig端子に1発、トリガ信号を与える(10uSパルス幅)
  2. Echo端子に距離に比例した時間幅のパルスが出力される。

ちょいと面倒なのが、5V電源、5VIO電圧であることです。Arduino Unoなど5VのIO電圧のマイコンであれば直結可能ですが、3.3V IO電圧のラズパイPicoに直結するのはマズイでしょう。そういえば以前にも3.3Vのマイコンに接続したことがあったな、ということで過去投稿を調べるとありました。

部品屋根性(31) HC-SR04 超音波センサ、3.3V信号接続

これみると、元々Groveコネクタ形式のI2Cの電圧変換用に作った治具を流用してWio Terminal(3.3VIO)と接続しているのね。お道具箱を調べて治具を見つけ出し、接続をいたしました。回路的にはこんな感じ。

RPiPico HC-SR04 schemetic後でもう少し「ストレートフォワードな?」レベル変換治具作りたい気もするけれど、有りものでやるのが楽なので、今回はこれでよし、と。

前回パルス幅測定プログラムの改造点

前回パルス幅測定用に作ったプロトタイプの入力(GP0端子)に、Echo端子からの信号を突っ込んでやればパルスの時間幅は測れる筈です。いくつか直したところは、以下のとおり(スクリプト全文は末尾に。)

  1. Trig端子に10μsくらいのHighパルスを1発入れた後、Echo信号の幅を測る
  2. パルス幅カウントの上限を変数とした
  3. 測定したパルス幅を「定数」で割ってcm単位の距離に換算した

Highパルスは、何も時間制御せずにTrig端子をMicroPythonのステートメントで操作しているだけです。デフォルト状態でラズパイPico上のMicroPythonは、1ステートメントを10μs以下くらいで処理しているようなので、それに期待しました。波形みるとほぼほぼ期待通りでした。

Echo信号の時間幅は、前回とPIOクロックを変更していないので2us単位の整数で返ります。センサ的な測定上限は400cmということで、カウント値の上限には12000くらいの数字を入れないとならないのです。しかし、どうせ手元で実験するときには30cmの物差しの範囲くらいで対象物をずらして距離を確認しているので30cmくらい測れればいいや、という値をセットしてあります。

また距離に換算するにあたっても、精度出すなら温度とか補正しないといけないのですが何もやっていません。それに超音波センサは、結構、対象物の材質や形状、外部の音響環境などの影響を受けやすいです。実用上はそういう配慮がいろいろ必要になる筈ですが、これまた何もやっていません。末尾のスクリプトはあくまで原理を実験するだけのものであります。

実際にセンサを駆動して得た波形を以下に掲げます。黄色がTrig信号、青がEcho信号です。

RPiPico HC-SR04 waveformそして、末尾のプログラムで行った実験結果の一部がこちら。物差しに沿って金属製の平たい缶の位置をずらしてみました。ま、だいたい15cm付近から4cm付近まで近づけたときの様子。細かいことを言わなければ、だいたい合っている感じ。

DATA=0x00000243 Dist=15.3[cm]
DATA=0x0000025f Dist=14.4[cm]
DATA=0x00000264 Dist=14.2[cm]
DATA=0x00000295 Dist=12.5[cm]
DATA=0x000002cc Dist=10.6[cm]
DATA=0x000002ec Dist=9.5[cm]
DATA=0x000002f9 Dist=9.1[cm]
DATA=0x00000346 Dist=6.4[cm]
DATA=0x0000035f Dist=5.6[cm]
DATA=0x00000378 Dist=4.7[cm]
DATA=0x00000386 Dist=4.2[cm]

PIOでパルス幅測定ができてしまえば後は楽。

MicroPython的午睡(30) ラズパイPico、PIOでパルス幅測定 へ戻る

MicroPython的午睡(31) ラズパイPico、PWMの周波数カウント機能を使う へ進む

HC-SR04超音波センサで距離を測るプロトタイプ
from rp2 import PIO, asm_pio
from machine import Pin, Timer
import time

countMax = 1024

@asm_pio()
def measureX():
    pull(block)
    mov(x, osr)
    wait(0, gpio, 0)
    wait(1, gpio, 0)
    label("highloop")    
    jmp(pin, "count")
    jmp(0, "exitloop")
    label("count")
    jmp(x_dec, "highloop")
    label("exitloop")
    mov(isr, x)    
    push(block)

sm0 = rp2.StateMachine(0, measureX, freq=1000000, in_base=Pin(0))
trig = Pin(1, Pin.OUT)
trig.value(0)

while True:
    trig.value(1)
    trig.value(0)
    sm0.active(1)
    sm0.put(countMax)
    dat = sm0.get()
    sm0.active(0)
    dist = (countMax - dat) / 29
    print("DATA=0x{0:08x} Dist={1:3.1f}[cm]".format(dat, dist))   
    time.sleep_ms(500)