身近なロジックのひとつに「押しボタン式信号機」がある。ラズパイ+LED+ボタン+Pythonで試してみよう。間違ったロジックをつくると交通事故になっちゃうぞ。
ラズパイGPIOの配線図
このサンプルでは「押しボタン」の入力にGPIO12を、「LED」の出力にGPIO20(青色)、GPIO21(赤色)を使っていますが、他の空いているGPIOを使っても構いません。
ラズパイのGPIO制御はRaspberryPi OS のファイルを操作します
例えば、GPIO21が出力モード[out]の時、ファイルに[1]を書き込むとLEDを点灯し、[0]を書き込むとLEDを消灯できます。またGPIO21が入力モード[in]の時は、ファイルを読み込むことで値[0][1]を取得することができます。
ラズパイのターミナルを使って RaspberryPi OS からLEDと押しボタンを操作してみます。
▼GPIOの利用を宣言する(lsでディレクトリが作成されたことを確認する)
$ cd /sys/class/gpio …GPIOディレクトリへ移動
$ echo 12 > export …GPIO12ピンを使うことを宣言
$ echo 20 > export … 〃 20
$ echo 21 > export … 〃 21
$ ls …ディレクトリできてるか。
▼値1をセットするとLEDが点灯する。値0なら消灯。
$ echo in > gpio12/direction …in:読み取り用
$ echo out > gpio20/direction …out:出力 3.3VをON/OFF
$ echo out > gpio21/direction …out:出力 3.3VをON/OFF
$ echo 1 > gpio20/value …点灯(青色)
$ echo 0 > gpio20/value …消灯
$ echo 1 > gpio21/value …点灯(赤色)
$ echo 0 > gpio21/value …消灯
▼ボタンのON/OFFを読む
$ echo high > gpio12/direction … 内部プルアップ電源をhighに設定
$ cat gpio12/value …押しボタンの値を読む
>> 0 …0ならOFF、1ならON
RaspberryPi OS のシェルスクリプトを自動化する
空の新しいファイルを作成して下記のコードを記述する。ファイル名は例えば「led.sh」とする。
#!/bin/bash
# GPIOを使う宣言
echo 12 > /sys/class/gpio/export
echo 20 > /sys/class/gpio/export
echo 21 > /sys/class/gpio/export
# GPIOを入力、出力のどちらを使うか宣言する
echo in > /sys/class/gpio/gpio12/direction
echo out > /sys/class/gpio/gpio20/direction
echo out > /sys/class/gpio/gpio21/direction
# GPIOに[1]を代入する
echo 1 > /sys/class/gpio/gpio20/value
echo 1 > /sys/class/gpio/gpio21/value
# 2秒待つ
sleep 2
# GPIOに[0]を代入する
echo 0 > /sys/class/gpio/gpio20/value
echo 0 > /sys/class/gpio/gpio21/value
# GPIO利用を終了する
echo 12 > /sys/class/gpio/unexport
echo 20 > /sys/class/gpio/unexport
echo 21 > /sys/class/gpio/unexport
# スクリプトを終了する
exit 0
シェルスクリプトを実行する
$ sudo bash led.sh
LEDを点滅させるシェルスクリプト(青点灯→青点滅→赤点灯)
点滅する for ループ 文だけ記載するので、上記「led.sh」を改造してみてください。
for (( i=0; i<10; i++ ))
do
echo 1 > /sys/class/gpio/gpio20/value
sleep 0.5
echo 0 > /sys/class/gpio/gpio20/value
sleep 0.5
done
押しボタンを検出するシェルスクリプト
新しい空のファイル「例えば、button.sh」に下記コードを記述して実行。
実行したら10秒以内に、押しボタンを押したり離したり試してください。
#!/bin/bash
echo 12 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio12/direction
echo high > /sys/class/gpio/gpio12/direction
for (( i=0; i<10; i++ ))
do
cat /sys/class/gpio/gpio12/value
sleep 1
done
echo 12 > /sys/class/gpio/unexport
exit 0
Python で歩行者用信号を完成させる
お待たせ。ラズパイのGPIOはファイル操作で制御することが分かったので、次はいよいよ Pythonで信号機のコードを記述します。新しい空のファイル「例えば、signal.py」に下記コードを記述。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO # RPi.GPIOモジュールを使用
import time
# 定数にピン番号をセット
gpio_sw = 12
gpio_led_blue = 20
gpio_led_red = 21
GPIO.setmode( GPIO.BCM ) #GPIOを番号で指定する
GPIO.setup( gpio_sw, GPIO.IN, pull_up_down=GPIO.PUD_UP ) #入力に設定
GPIO.setup( gpio_led_blue, GPIO.OUT) #出力に設定
GPIO.setup( gpio_led_red, GPIO.OUT) #出力に設定
while True:
GPIO.output( gpio_led_red, 1 ) #赤信号を点灯
GPIO.output( gpio_led_blue, 0 ) #青信号は消灯
intSW = 1
# スイッチが押されるまで待つ(赤信号のまま)
while intSW == 1:
intSW = GPIO.input( gpio_sw )
print( 'もうすぐ信号が変わります' )
time.sleep( 2 )
GPIO.output( gpio_led_red, 0 ) #赤を消灯
GPIO.output( gpio_led_blue, 1 ) #青を点灯
time.sleep( 3 )
# 8回繰り返す
for num in range( 8 ):
GPIO.output( gpio_led_blue, 1 )
time.sleep( 0.5 )
GPIO.output( gpio_led_blue, 0 )
time.sleep( 0.5 )
# ここに、赤が点灯して5秒間待つプログラムを追加したい
# GPIOを終了する
GPIO.cleanup( gpio_sw )
GPIO.cleanup( gpio_led_blue )
GPIO.cleanup( gpio_led_red )
チャレンジ: 終わった人は、赤・青・黄の車用信号機を作ってみようか。
地味に難しい。