JH7UBCブログ

アマチュア無線 電子工作 家庭菜園など趣味のブログです

Raspberry Pi Pico MicroPython HC-SR04 距離の測定

2021-12-13 12:35:36 | Raspberry Pi Pico
 Raspberry Pi Picoで、超音波センサーHC-SR04を使って距離を測定するプログラムをMicroPythonで組んでみます。

 MicroPythonでのプログラムは、既にmicro:bitで実験済みです。記事はこちら。測定原理はその記事を参照してください。なお、今回は、Pico内蔵の温度センサーから温度を読み取り、音速を計算します。

回路図です。表示はOLEDを使い、I2Cは、id=0,sda=Pin(16),scl=Pin(17)とします。HC-SR04のTRIGはGPIO14に、ECHOはGPIO15に接続します。HC-SR04からのECHO出力は、5Vなので、抵抗で分圧してPicoに入力します。



 TRIGに加えるパルスは、10us以上となっていますので、
 trigger=Pin(14,Pin.OUT)  とし、
 trigger.value(1)
 utime.sleep_us(2)
 rtigger.value(0)
 で、triggerパルスをCH-SR04に出力します。この時のパルスの波形です。

 約20us幅のパルスが発生しました。(パルス幅は若干広くなったり狭くなったり、ゆらぎます。)utime.sleep_us()を省略するとパルス幅は、10us以下になってしまいます。

 HC-SR04から帰ってくるECHOパルスを測定してみました。


 echoパルスの立ち上がりの時刻t1と立下りの時刻t2をutime.ticks_us()で、us単位で測定し、t=t2-t1からechoパルスの幅(us)を計算することができます。

 tは、HC-SR04から発せられた超音波が戻ってくるまでの時間で、距離の2倍を音が進む時間です。従って、音速をVs(m/s)、HC-SR04と物体の距離をL(m)とするとL(m)=Vs(m/s)×t(s)/2で計算できます。
距離をL(cm)、t(us)とすると、L(cm)=(Vs(m/s)×100×t(us)/1000000)/2=Vs(m/s)×t(us)/20000で計算することができます。なお、音速は温度によって変わり、Vs(m/s)=331.5+0.6×temp(℃)で計算できます。

 スクリプトです。
-----------------------------------------------------------------------------------------------
from machine import ADC,Pin,I2C
import utime
import ssd1306

trigger=Pin(14,Pin.OUT)
echo=Pin(15,Pin.IN)

i2c=I2C(0,sda=Pin(16),scl=Pin(17),freq=400000)
oled=ssd1306.SSD1306_I2C(128,64,i2c)
oled.text("RP2 HC-SR04 TEST",0,8)
oled.text("TEMP:      C",18,24)
oled.text("L(cm):",18,40)
oled.show()

trigger.value(0)#Triggerの初期値0

coeff=3.3/65535
a=ADC(4)

def mesurement():
     global temp,L
     #Trigger pulse >10us
     trigger.value(1)
     utime.sleep_us(2)
     trigger.value(0)
    #反射時間の測定
     while echo.value()==0:
         t1=utime.ticks_us()
     while echo.value()==1:
         t2=utime.ticks_us()
     t=t2-t1

    #気温の測定(pico内部の温度計を利用)
     v=a.read_u16()*coeff
     temp=round((34-(v-0.706)/0.001721),1)
    #距離の計算
     vs=331.5+0.6*temp#音速の計算
     L=round((vs*t/20000),1)#L(cm)

def display():
     global temp,L
     oled.fill_rect(72,24,32,8,0)
     oled.show()
     oled.text(str(temp),72,24)
     oled.show()
     if L < 2000:
         oled.fill_rect(72,40,56,8,0)
         oled.show()
         oled.text(str(L),72,40,)
         oled.show()

while True:
     mesurement()
     display()
     utime.sleep(1)

-----------------------------------------------------------------------------------------------
 Picoの内蔵温度計の値はADC(4)の電圧として読み取れます。その値を温度に変換する式は
 27-(v-0.706)/0.001721 ですが、実際より低い値になってしまいますので、便宜的に27を34に変更しました。
 1secごとに距離を測定して、OLEDに表示します。

 ブレッドボードです。


 温度の値は1℃以内で細かく変動します。

 実際に物体との距離を測定してみました。距離の表示も1cm以内で細かく変動します。

測定値です。
距離(cm) 測定値(cm)
 10    10.3
 20    20.6
 30    30.1
 40    39.9
 50    49.9
 60    59.4
 70    69.5
 80    79.0
 90    88.8
100    98.9

 micro:bitの時より、かなり精度が良くなっています。1m以内なら±5mm程度の誤差で測定ができそうです。