【PR】この記事には広告が含まれています。

Raspberry Piと超音波距離センサーHC-SR04を使って距離を計測する方法について解説します。

以下がHC-SR04です。 秋月電子通商では300円で購入できます。

超音波が物体に当たって跳ね返ってくるまでの時間を使って、非接触で距離を測定できます。

測定できる距離は約2〜450cmです。

あらかじめピンヘッダーが取り付けられているため、はんだ付けをしなくてもブレッドボードに直接差し込んで使うことができます。
超音波距離センサーとラズパイを接続するためのパーツ
①ブレッドボード

ブレッドボードを使用すると、センサーやジャンパワイヤのピンを穴に差すだけで簡単に接続ができます。はんだ付けをする必要がなく、やり直しもできるため、とても便利です。
②ジャンパワイヤ

ジャンパワイヤは片端がオス(ブレッドボード用)、もう片端がメス(Raspberry Pi GPIOピン用)のタイプを4本、両端がオスのタイプを1本用意します。

ブレッドボードとジャンパワイヤの接続はピンを差し込むだけで簡単にできます。
③抵抗(1kΩ)×3

GPIOに5Vを入力するとラズベリーパイが壊れてしまうので、抵抗を使って電圧を下げます。1kΩ(=1000Ω)の抵抗のカラーコードは、「茶黒赤金」です。
ラズベリーパイと超音波距離センサーを接続する

まず、超音波センサHC-SR04のピンについて解説します。
①「VCC」 5V 電源
②「trig」 トリガー・・・ラズパイからの信号を受けると、超音波を送信します。GPIO27に接続します。
③「echo」 エコー・・・超音波を送信してから受信するまで、ECHO端子はHighになります。Highになっている時間の半分を音速で割った数値が距離になります。GPIO18に接続します。
④「gnd」 グランド

注意点は抵抗を使って電圧を下げることです。ラズベリーパイのGPIOピンは3.3Vまでしか対応していませんが、HC-SR04のEcho信号は5Vで出力されます。このままラズパイに接続すると、GPIOが壊れてしまう恐れがあります。
そこで「分圧回路(ぶんあつかいろ)」という仕組みを使って、5Vの信号を安全な3.3Vに下げる必要があります。

分圧とは複数の抵抗を直列につなぎ、その間の電圧を取り出す方法です。電圧が抵抗の比率で分かれるイメージです。今回は1kΩの抵抗を1本、1kΩを2本直列につないだものを使い、合計で3kΩの分圧回路を作っています。
この構成で、上から1kΩ(全体の1/3)の位置で電圧を取り出すことで、5Vの信号を約3.3Vに下げることができます。

もし2kΩの抵抗を1本持っていれば、それを使っても同じ結果が得られます。
1kΩを2本使っても、2kΩを1本使っても、合計の比率が1:2になっていれば、分圧の電圧は変わりません。
チェックポイント
比率が同じなら、他の抵抗でも問題ありません。「1:2の比率」であれば、出てくる電圧も同じです。ただし、抵抗値が小さすぎると電流が多く流れるので、ラズパイのGPIOに負担がかかります。目安としては、合計1kΩ以上にすると安全です。
超音波距離センサーを動かすためのプログラム

以下のコードはRaspberry Piと超音波距離センサーHC-SR04を使って、1秒ごとに距離を測定し、その値を画面に表示するものです。
from gpiozero import DistanceSensor
import time
import warnings
warnings.filterwarnings("ignore")
sensor = DistanceSensor(echo=18, trigger=27)
while True:
distance_cm = sensor.distance * 100
print(f"Distance: {distance_cm:.1f} cm")
time.sleep(1)

warnings.filterwarnings("ignore")
は、警告メッセージを非表示にするための設定です。gpiozeroを使うときに精度に関する警告が出ますが、ここではそれを気にせず進めたいので、表示しないようにしています。
sensor = DistanceSensor(echo=18, trigger=27)
の部分では、センサーを初期化しています。超音波センサーは「音を出す端子(トリガー)」と「反射を受け取る端子(エコー)」の2つのピンを使います。このコードでは、ラズベリーパイのGPIO27をトリガーに、GPIO18をエコーに接続しているという設定です。
while True:
の部分からは、無限ループになります。ここでは繰り返し距離を測って表示し続けます。
ループの中にある distance_cm = sensor.distance * 100
という行では、距離を取得しています。sensor.distance
はメートル単位の小数で返ってくるので、それを100倍してセンチメートルに直しています。
プログラムを実行すると、距離の測定が繰り返し行われて結果が表示されます。測定を中止するには「ctrl」キーを押しながら、「C」を押します。

活用方法
距離センサーとサーボモーターを組合わせることで、たとえば何かが近づいたときに開閉動作をする機械的な仕組みを再現できます。以下は自動でフタが開閉するごみ箱を作った例です。
よく使われるサーボモーターのSG90は、フタが重いゴミ箱には力不足なことがあります。そんなときは、よりパワーのあるSG92RやMG92Bに変更すると安定して動作します。
サーボモーターの固定には、強力タイプの両面テープを使用しました。
ラズパイと各部品は、以下のように接続します。

サーボモーターの使い方の詳細は以下の記事で解説しています。
≫【ラズベリーパイ入門】サーボモーターSG90を制御する方法
以下のコードは、距離センサーとサーボモーターを使って、物体が近づいたときにサーボを動かすプログラムです。センサー式ゴミ箱はこのコードをベースに作成しました。
from gpiozero import DistanceSensor
from gpiozero import Servo
import time
import warnings
warnings.filterwarnings("ignore")
sensor = DistanceSensor(echo=12, trigger=27)
servo = Servo(18, min_pulse_width=0.5/1000, max_pulse_width=2.4/1000)
def move_servo(angle, hold_time=0.5):
if angle < -90 or angle > 90:
raise ValueError("Angle must be between -90 and 90")
servo.value = angle / 90.0
time.sleep(hold_time)
servo.detach()
move_servo(90)
while True:
distance_cm = sensor.distance * 100
print(f"Distance: {distance_cm:.1f} cm")
if distance_cm < 5:
move_servo(-90)
move_servo(90)
time.sleep(0.5)
まずサーボを90度の初期位置に動かします。その後は無限ループに入り、0.5秒ごとに距離センサーで前方の距離を測定します。もし5cm未満の距離に物体がある場合には、サーボを-90度に動かし、そのあとすぐに90度へ戻します。
電子工作の初心者です。
こちらのブログの内容、いつも参考にさせて頂いております。
そぞらさんの著書を傍らに置いて勉強しております!!
電子工作でときおり見かける「分圧回路」ですが、初心者には敷居が高く、
基板よりも自分の頭から煙が出そうな勢いです(笑)
分圧回路について、噛み砕いた解説などしていただけたら嬉しいです。
ご検討いただければ幸いです。
返信が大変遅くなり、申し訳ございません。
「分圧回路」は理解が難しいところですね。
自分も改めて勉強し直して、記事を書き直しました。
このたびはリクエストいただきありがとうございました。