ラズベリーパイは基板上に「GPIO」と呼ばれる、ラズベリーパイで作成したプログラムから信号の入力・信号の出力が行えるピンが存在します。
信号の入力とは「スイッチのON/OFF」「温度計で室温の計測」といった、ラズベリーパイの外の情報を入力(インプット)してプログラム上で使用することです。
対して、信号の出力とは「LEDを点灯させる」「モータを回す」といった、ラズベリーパイで制御した結果を外に出力(アウトプット)することです。
この記事では、ラズベリーパイのプログラム(Python)から超音波センサで距離を測定して赤色バーLEDを点灯させる方法を解説します。
超音波センサで距離を測定する方法は以下のページで解説しておりますので、宜しければご覧ください。
【ラズパイ電子工作】超音波センサで距離を読み取る方法(HC-SR04)目次
1. 完成イメージ(超音波センサに応じて赤色バーLEDを点灯)
この記事で完成するものは以下のようになります。
超音波センサでiPhoneまでの距離を測定して、距離に応じて赤色バーLEDを点灯させます。今回は超音波センサで5~15cmの距離を測定します。
2. 使用する部品
今回使用する部品は以下の通りです。
『Raspberry Pi 3 Model B+』を使用します。※2020年7月時点で最新はRaspberry Pi 4になります。
LEDや抵抗といった各種部品や(後述する)ジャンパ線などを穴に差し込み、部品間を電気的に接続する板(ボード)です。
電子工作をする上で必須の部品です。
ブレッドボートに差し込み、電子部品の間を電気的に接続します。
↑の写真では両側が「ピン」になっており、ブレッドボートの穴に差し込んで使用します。
HC-SR04は、超音波が反射する時間を利用して非接触で距離を測定するモジュールです。
「トリガー」ピンの状態をHighにすると超音波パルスが送信され、物体に反射して戻ってきた信号を受信します。超音波パルスを『送信した時間』と『戻ってきた信号を受信した時間』の差分を求めることで距離を測定します。
ラズパイのGPIOにて「トリガー」ピンを出力、「エコー」ピンを入力に割付けて使用します。
HC-SR04の主要なスペックは以下のようになります。
測定範囲 | :2~400cm |
電源電圧 | :DC5.0V |
動作電流 | :15mA |
動作周波数 | :40kHz |
トリガー信号 | :10μs |
今回は「バーLED」であるOXS10201-Rを使用します。赤色のLEDが10ヶ横一列に配列され、各LEDのアノード・カソードは独立しています。(コモンラインは無し)
外形図、内部配線は以下のようになります。
LEDなどの電子部品は適した電圧と電流値が決められており、既定の範囲を超えると壊れてしまう恐れがあります。
抵抗器は電流の流れを妨げ、電子部品に流れる電流を抑える役割を担います。
今回は『赤色バーLEDに220Ω』『超音波センサに1kΩ』の抵抗器を使用します。
電子工作をするため、これまで解説した部品の他にもスイッチやセンサなど、色々な部品が必要になってきます。個々で購入するには手間がかかるため、最初はセット品を購入することをおススメします。
私は以下のセット品を購入しました!
また、これからラズベリーパイを購入する場合、ラズベリーパイ本体を含めたセット品を購入することをおススメします。
ラズベリーパイ本体を収めるケースや、OSをインストールするためmicroSDカードなど必要なものを個々に購入する手間を省くことができます。
3. 回路図・配線の様子
ラズベリーパイのプログラム(Python)から超音波センサで距離を測定して赤色バーLEDを点灯させる回路を解説します。
回路図は以下のようになります。
超音波センサHC-SR04には以下の4ヶのピンがあります。
- VCC:DC5.0V電源(一番左側)
- Trig:トリガー信号
- Echo:エコー信号
- GND:グランド(一番右側)
ラズベリーパイとHC-SR04を以下のように接続します。
HC-SR04 | ラズベリーパイ | ジャンパ線 |
---|---|---|
VCC | :5V | :赤色 |
Trig | :GPIO 6番ポート | :青色 |
Echo | :GPIO 25番ポート※抵抗経由 | :黄色 |
GND | :GND | :黒色 |
Trigに接続するGPIO 6番ポートはラズベリーパイからトリガーを出力するため出力モードとして使用します。
対して、Echoに接続するGPIO 25番ポートはHC-SR04から”受信した”信号をラズベリーパイが入力するため入力モードとして使用します。
HC-SR04の動作電圧は5Vに対して、ラズベリーパイのGPIOは3.3Vになります。Echoをラズベリーパイがそのまま受けると、GPIOが破損する恐れがあります。そこで、抵抗器を用いて分圧します。
赤色バーLEDの各アノード(プラス側)にGPIOを個別に配線します。各LEDを右からA~Jとすると、各LEDとGPIOの関係は以下のように配線します。
LED区別 | GPIO | ジャンパ線色 |
---|---|---|
LED_A(一番左側) | GPIO 27番ポート | 白色 |
LED_B | GPIO 22番ポート | 青色 |
LED_C | GPIO 5番ポート | 黄色 |
LED_D | GPIO 13番ポート | オレンジ色 |
LED_E | GPIO 26番ポート | 白色 |
LED_F | GPIO 18番ポート | 青色 |
LED_G | GPIO 23番ポート | 黄色 |
LED_H | GPIO 24番ポート | オレンジ色 |
LED_I | GPIO 16番ポート | 白色 |
LED_J(一番右側) | GPIO 21番ポート | 青色 |
各LEDのカソード(マイナス側)には抵抗器(220Ω)を介してGNDに接続します。(黒色のジャンパ線)
配線の様子です。こんな感じになりました。
↑では、フラットケーブルでGPIOの全ピンをブレッドボードに接続しています。回路図と実際の配線は異なる部分がありますがご了承ください。
※電気的には「回路図」と同じ意味です。
4. プログラム(Python)
超音波センサで距離を測定して赤色バーLEDを点灯させるプログラム(Python)は以下のようになります。
#必要なモジュールをインポート
import RPi.GPIO as GPIO #GPIO用のモジュールをインポート
import time #時間制御用のモジュールをインポート
import sys #sysモジュールをインポート
#ポート番号の定義
Trig = 6 #変数"Trig"に6を代入
Echo = 25 #変数"Echo"に25を代入
Bar_led = [
27, 22, 5, 13, 26, 18, 23, 24, 16, 21] #変数"Bar_led"にリストを代入
#GPIOの設定
GPIO.setmode(GPIO.BCM) #GPIOのモードを"GPIO.BCM"に設定
GPIO.setup(Trig, GPIO.OUT) #GPIO6を出力モードに設定
GPIO.setup(Echo, GPIO.IN) #GPIO25を入力モードに設定
GPIO.setup(Bar_led, GPIO.OUT) #GPIO(10ヶ)を出力モードに設定
#HC-SR04で距離を測定する関数
def read_distance():
GPIO.output(Trig, GPIO.HIGH) #GPIO6の出力をHigh(3.3V)にする
time.sleep(0.00001) #10μ秒間待つ
GPIO.output(Trig, GPIO.LOW) #GPIO6の出力をLow(0V)にする
while GPIO.input(Echo) == GPIO.LOW: #GPIO25がLowの時間
sig_off = time.time()
while GPIO.input(Echo) == GPIO.HIGH: #GPIO25がHighの時間
sig_on = time.time()
duration = sig_on - sig_off #GPIO25がHighしている時間を演算
distance = duration * 34000 / 2 #距離を求める(cm)
return distance
#数値からバーLEDを点灯させる関数
def barled_lighting(level):
for i in range(0, level): #点灯させるGPIO(左側)
GPIO.output(Bar_led[i], GPIO.HIGH) #GPIO点灯
for i in range(level, 9): #消灯させるGPIO(右側)
j = i + 1
GPIO.output(Bar_led[j], GPIO.LOW) #GPIO消灯
#連続して値を超音波センサの状態を読み取る
while True:
try:
cm = read_distance() #HC-SR04で距離を測定する
if cm > 5 and cm < 16: #距離が5〜15cmの場合
bright = int(cm) - 5 #距離を0〜10に変換
barled_lighting(bright) #バーLEDを表示
time.sleep(0.1) #0.1秒間待つ
except KeyboardInterrupt: #Ctrl+Cキーが押された
GPIO.cleanup() #GPIOをクリーンアップ
sys.exit() #プログラム終了
超音波センサHC-SR04の「トリガー」ピンにGPIOからHighに出力して、「エコー」ピンに信号が戻ってきた時間を計測して距離を求めます。
測定した距離が5~16cmの範囲内であれば赤色バーLEDを点灯させます。
#必要なモジュールをインポート
import RPi.GPIO as GPIO #GPIO用のモジュールをインポート
import time #時間制御用のモジュールをインポート
import sys #sysモジュールをインポート
2~4行目で今回必要な「モジュール」を宣言します。
#ポート番号の定義
Trig = 6 #変数"Trig"に6を代入
Echo = 25 #変数"Echo"に25を代入
Bar_led = [
27, 22, 5, 13, 26, 18, 23, 24, 16, 21] #変数"Bar_led"にリストを代入
変数”Trig”と”Echo”と”Bar_led”に数値を代入します。この数値はGPIOのポート番号として扱い、後からポート番号を変更する場合はこの数値を変更します。
今回は『GPIO 27番ポートをトリガー』『GPIO 18番ポートをエコー』『GPIO 27番ポート他を赤色バーLED』として使用します。
#GPIOの設定
GPIO.setmode(GPIO.BCM) #GPIOのモードを"GPIO.BCM"に設定
GPIO.setup(Trig, GPIO.OUT) #GPIO6を出力モードに設定
GPIO.setup(Echo, GPIO.IN) #GPIO25を入力モードに設定
GPIO.setup(Bar_led, GPIO.OUT) #GPIO(10ヶ)を出力モードに設定
GPIOの設定を行います。
GPIO.setmode(GPIO.BCM)
は、GPIOをポート番号で扱う方法に設定します。
GPIO.setup(Trig, GPIO.OUT)
は、GPIO 6番ポートを出力モードに設定します。
GPIO.setup(Echo, GPIO.IN)
は、GPIO 25番ポートを入力モードに設定します。
GPIO.setup(Bar_led, GPIO.OUT)
は、GPIO 27番ポート他(リストBar_ledに代入されている数値)を出力モードに設定します。
#HC-SR04で距離を測定する関数
def read_distance():
GPIO.output(Trig, GPIO.HIGH) #GPIO6の出力をHigh(3.3V)にする
time.sleep(0.00001) #10μ秒間待つ
GPIO.output(Trig, GPIO.LOW) #GPIO6の出力をLow(0V)にする
while GPIO.input(Echo) == GPIO.LOW: #GPIO25がLowの時間
sig_off = time.time()
while GPIO.input(Echo) == GPIO.HIGH: #GPIO25がHighの時間
sig_on = time.time()
duration = sig_on - sig_off #GPIO25がHighしている時間を演算
distance = duration * 34000 / 2 #距離を求める(cm)
return distance
HC-SR04にて距離を測定する関数を作成します。
まずHC-SR04の「トリガー」ピンに対して、10μ秒間信号をHighにします。(20~22行目)
次に「エコー」ピンの状態を監視して、LowからHighになるまでの時間を測定します。(24~27行目)
最後に距離を求める演算を行い、変数”distance”を戻り値に返します。
distance = duration * 34000 / 2
は、測定した時間を音速で掛けて半分にしています。音速とは約340m/秒であるため、cmに直すと34000となります。
#数値からバーLEDを点灯させる関数
def barled_lighting(level):
for i in range(0, level): #点灯させるGPIO(左側)
GPIO.output(Bar_led[i], GPIO.HIGH) #GPIO点灯
for i in range(level, 9): #消灯させるGPIO(右側)
j = i + 1
GPIO.output(Bar_led[j], GPIO.LOW) #GPIO消灯
関数barled_lighting(level)
は、引数level
の数値を元に赤色バーLEDの点灯する数を制御します。
例えば、変数level
の値が4の場合、for文を用いてリストBar_led
の添え字(インデックス)が0~4となります。
リストBar_led
の0~4の要素は27,22,5,13,26のため、GPIO.output(Bar_led[i], GPIO.HIGH)
にてGPIO 27,22,5,13,26番ポートの電圧をHigh(3.3V)にします。これらのGPIOは赤色バーLEDの左側から接続されており、High(3.3V)になったLEDはここで点灯します。
GPIO.output(Bar_led[j], GPIO.LOW)
は、赤色バーLEDの残り(右側)のGPIOの電圧をLow(0V)にします。
#連続して値を超音波センサの状態を読み取る
while True:
try:
cm = read_distance() #HC-SR04で距離を測定する
if cm > 5 and cm < 16: #距離が5〜15cmの場合
bright = int(cm) - 5 #距離を0〜10に変換
barled_lighting(bright) #バーLEDを表示
time.sleep(0.1) #0.1秒間待つ
except KeyboardInterrupt: #Ctrl+Cキーが押された
GPIO.cleanup() #GPIOをクリーンアップ
sys.exit() #プログラム終了
「while文」は条件を指定して、その条件が真の時に繰り返し処理を行うものです。
while 条件式:
繰り返し処理を行うコード
↑の「条件式」にTrue
を指定することにより、条件式は常に真となりwhile文は無限に繰り返します。
ただし、このままではプログラム実行中に無限ループから抜け出す方法がありません。そこでwhile文の中にある「try文」と「except文」を使用します。
このtry-except文を用いることにより、while文の処理は以下のようになります。
while True:
try:
繰り返し処理を行うコード
except KeyboardInterrupt: #Ctrl+Cキーが押された
GPIO.cleanup() #GPIOをクリーンアップ
sys.exit() #プログラム終了
except KeyboardInterrupt:
は、キーボードのCtrl + cキーが押された時にwhile文の繰り返し処理から抜けて上記のプログラム終了の処理を行います。
Ctrl + cキーが押されていないとき、try:文の中の処理を繰り返し行います。(以下で解説)
while文の中の「繰り返し処理を行うコード」は以下の通りです。つまり、Ctrl + cキーが押されるまで以下の処理を繰り返します。
cm = read_distance() #HC-SR04で距離を測定する
if cm > 5 and cm < 16: #距離が5〜15cmの場合
bright = int(cm) - 5 #距離を0〜10に変換
barled_lighting(bright) #バーLEDを表示
time.sleep(0.1) #0.1秒間待つ
cm = read_distance()
は、HC-SR04で測定した距離を変数”cm”に代入します。
今回はHC-SR04で測定した距離が5~15cmの場合に赤色バーLEDを制御するため、if cm > 5 and cm < 16:
にて範囲外の値が入力された場合は除外する処理を行います。
測定した距離が5~15cmの場合、bright = int(cm) - 5
にて赤色バーLEDを点灯させる個数に変換して、barled_lighting(bright)
で関数に渡します。
time.sleep(0.1)
は何もせずに0.1秒間待ちます。
5. おわりに
ラズベリーパイのプログラム(Python)から超音波センサで距離を測定して赤色バーLEDを点灯させる方法を解説しました。
まだまだラズベリーパイ初心者の私ですが、以下の参考書が大変参考にさせて頂いております。
2冊とも初学者にも易しい内容になっており、ゼロからラズベリーパイを始める方にもオススメできる参考書です。