歩行者用信号機をシミュレーション

身近なロジックのひとつに「押しボタン式信号機」がある。ラズパイ+LED+ボタン+Pythonで試してみよう。間違ったロジックをつくると交通事故になっちゃうぞ。

ラズパイGPIOの配線図

このサンプルでは「押しボタン」の入力にGPIO12を、「LED」の出力にGPIO20(青色)、GPIO21(赤色)を使っていますが、他の空いているGPIOを使っても構いません。

ラズパイのGPIO制御はRaspberryPi OS のファイルを操作します

例えば、GPIO21が出力モード[out]の時、ファイルに[1]を書き込むとLEDを点灯し、[0]を書き込むとLEDを消灯できます。またGPIO21が入力モード[in]の時は、ファイルを読み込むことで値[0][1]を取得することができます。

図.RaspberryPi OS のファイル操作(=デバイス制御)

ラズパイのターミナルを使って 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 )

チャレンジ: 終わった人は、赤・青・黄の車用信号機を作ってみようか。


歩行者用信号機をシミュレーション」への1件のフィードバック

コメントを残す