はじめに
Raspberry Pi Picoを使って超音波センサーHCSR04で対象物までの距離をを計測してみます。
超音波センサーHCSR04は、トリガー信号を出力した後に帰ってくるエコー信号を捉え、そのエコー信号のhighレベル時間からセンサーと対象物の距離を計測するというセンサーです。
今回は、エコー信号のhighレベル時間をRaspberry Pi PicoのGPIO割り込みを使って計算します。
HC-SR04 超音波距離センサーモジュール 距離測定モジュール トランスデューサI / Oトリガーセンサー UNO Mega2560/Raspberry Pi B/ロボット/ Arduino用 価格:980円 |
価格:807円 |
回路
超音波センサーのTrig信号をGPIO28、Echo信号をGPIO6に接続します。
センサー側は5Vで動作するのに対してRaspberry Pi Picoは3.3V動作なので、Raspberry Pi Picoに入力されるEcho信号ラインのGPIO6は分圧する形にします。分圧1:2となるようにEchoラインに5kΩ、EchoとGndラインに10kΩの抵抗を接続します。
センサーのVccには5V電源を接続し、Gndは接地します。
プロジェクトのディレクトリ作成
まず、作成するプロジェクトのディレクトリをつくっていきます。
ここでは、次のようなディレクトリ構成にしています。
C:¥prog¥pico¥DL
┗¥pico-sdk
┗¥ultrasonic_hcsr04
┗ \build
┗ ultrasonic_hcsr04.c
┗ CMakeLists.txt
┗ pico_sdk_import.cmake
pico-sdkディレクトリやpico_sdk_import.cmakeファイルに関しては、こちらの記事にまとめています。
SourceファイルとMakeファイルの作成
次にソースファイルとビルドファイルを準備します。
作成したプロジェクトディレクトリに移動します。(ここでは、ultrasonic_hcsr04ディレクトリ)
ultrasonic_hcsr04ディレクトリの中に実行するソースファイルultrasonic_hcsr04.cを作成します。
ultrasonic_hcsr04.cのファイルに次のようなプログラムを記述しました。
ultrasonic_hcsr04.cの中身は、次のようにしています。
main()関数にあるstdio_init_all()関数 は、printf()関数で結果を出力するために呼び出しています。printf()関数の出力は、Tera Termなどのソフトを使うことによって確認できます。
raspberry Pi Picoの28ピンをセンサーのトリガー信号用にGPIO出力として設定します。
また、6ピンをエコー信号用にGPIO入力設定にして、割り込みを使うため、gpio_set_irq_enabled_with_callback()関数で割り込み設定を行います。
この関数の仕様は、SDK Documentationに記載されています。
第一引数は、使用するGPIOピン番号、第二引数は、イベントマスク、第三引数は、割り込みの許可、禁止の設定(trueまたはfalse)、第四引数は、割り込み発生時のコールバック関数指定になります。
第二引数のイベントマスク値は、次のうちの何れかを使用します。
enum gpio_irq_level { GPIO_IRQ_LEVEL_LOW = 0x1u , GPIO_IRQ_LEVEL_HIGH = 0x2u , GPIO_IRQ_EDGE_FALL = 0x4u , GPIO_IRQ_EDGE_RISE = 0x8u }
また、第四引数のコールバック関数は、void型の戻り値をもち、割り込みが発生したGPIOピン番号とイベントマスク値を引数にもつ形で定義します。
メインループでは、12[us]のトリガー信号(仕様上は、10[us]以上の出力)を出力し100[ms]ウェイト後、エコー信号のhigh時間が格納されているdtimeをチェックしています。
ここでは、センサーと対象物間の距離が10[cm] 未満の場合、エコー信号のhighレベル時間を出力するようにしています。距離[cm]は、エコー信号のhighレベル時間[us] / 58 で計算できます。
出力後は、5秒待った後に再度トリガー信号を出力するという流れです。
超音波センサーは、トリガー信号を受信後、エコー信号を送出します。Raspberry Pi Pico側では、そのエコー信号の立上がりと立下りを割り込みで捉えます。
立上り時の時間と立下り時の時間を取得し、その差をabsolute_time_diff_us()関数を使って算出し、dtimeという変数に代入しています。このdtimeの値をメインループ側でチェックするというプログラムです。
プログラムができたら、続いて、CMakeLists.txtを作成します。
CMakeLists.txtには次のように記述しておきます。
cmake_minimum_required(VERSION 3.13)
include(pico_sdk_import.cmake)
project(ultrasonic_hcsr04_project C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
add_executable(ultrasonic_hcsr04
ultrasonic_hcsr04.c
)
target_link_libraries(ultrasonic_hcsr04 pico_stdlib hardware_gpio)
pico_enable_stdio_usb(ultrasonic_hcsr04 1)
pico_enable_stdio_uart(ultrasonic_hcsr04 1)
pico_add_extra_outputs(ultrasonic_hcsr04)
target_link_libraries(ultrasonic_hcsr04 pico_stdlib)
さらに、pico-sdk¥externalディレクトリの中にあるpico_sdk_import.cmakeというファイルをコピーして保存します。
ビルド
プログラムをビルドします。
このとき、パス設定をしていなければ、次のコマンドを実行します。
C:\prog\pico\DL\ultrasonic_hcsr04\build>setx PICO_SDK_PATH "..\..\pico-sdk"
実行ファイルを生成するため、cmakeを実行し、その後、nmakeを実行するとビルドが開始されます。
C:\prog\pico\DL\ultrasonic_hcsr04\build>cmake -G "NMake Makefiles" ..
C:\prog\pico\DL\ultrasonic_hcsr04\build>nmake
実行
ビルドが正常に終了するとbuildディレクトリの中にultrasonic_hcsr04.uf2ファイルが作成されるので、このファイルをRaspberry Pi Picoに書き込みます。
書き込みは、Raspberry Pi Picoのリセットボタンを押しながらRaspberry Pi PicoにつないだUSBケーブルをPCに接続します。この実験環境では、DドライブとしてRPI-RP2が認識されました。
このDドライブ内にultrasonic_hcsr04.uf2ファイルをドラッグアンドドロップで入れ込みます。
ドロップ後、プログラムが自動的に実行されます。
ここで、Tera Termなどのソフトでシリアル通信を確認するとセンサーと対象物までの距離が10[cm]未満となったときにエコー信号のhighレベル時間が出力されます。
壁に向かっておおよそ9[cm]の位置にセンサーを設置して実験した結果が上の写真です。
オシロのCH2がエコー信号になります。507[us]のhighレベルが出力されています。
それに対して、プログラム上のprintf()関数から出力された結果も507前後となっています。
距離を算出すると、507 / 58 = 8.74[cm] となります。
厳密にセンサー位置を決めているわけではないので、誤差の検証はできませんが、おおよその距離算出はできていると思います。
まとめ
このブログではRaspberry Pi Picoで超音波センサーHCSR04を使い、対象物の距離計測をしてみました。距離を確認するためには、センサーのエコー信号のhighレベル時間を取得する必要があり、その時間取得のためにGPIO割り込みを使いました。
プログラムを作成し、プログラムから得られたセンサーのエコー出力値と実際の対象物とセンサーの距離におおよその一致が得られました。
コメント