Gitlab信号機を作る話 -信号を3つにするのとリファクタリング-

Gitlab信号機を作るにあたりまして当たり前ですが問題がありました。
それは…
LED4つなんですよね。信号機って3色(赤、黄色、緑)もしくは2色(赤、緑)なのでその辺りを再定義したいと思います。

信号を4色から3色にする

今のところ以下の様になっております

赤 : 試験失敗
緑 : 試験成功
青 : 試験中
黄色 : 試験準備中

はい、青を無くすして状態を再構成しました

赤 : 試験失敗
緑 : 試験成功
黄色 : 試験中
全点灯 : 試験準備中

これで3色で表現できますね。

今で各色に意味がついていたのでLED_Successとかしていましたが、成功のLEDと言う意味ではなくなるのでLED1などと表現を変えました。

GPIOピン配列の変更

青色が今までGPIO 27を使っていました。
今回これがなくなりますので利用ポートが歯抜けになるのはダサいです。
なので全部のGPIOピン配列も再定義します

合わせて、リセットボタン設置時に間違って差し込まない様に信号LEDとボタンは離して設置しました。
四角の色はケーブルの色にマッチさせます

抵抗追加と配線図の再描写

前回までの信号LEDでは共通した抵抗を使っておりました。
今回全灯が発生するためにと明るさをそれぞれ変更が可能な様に各信号LED毎に抵抗を入れました。
抵抗値はまだ適当です(10KΩだったかな…)
配線図を再描写します。(ファイルが飛んだので一から書きました)

Raspbery piのパーツが逆転しているのでGPIOが読みづらいですが、以下の配線をしております

GPIO 22 : LED1 (緑)
GPIO 27 : LED2 (黄色)
GPIO 17 : LED3 (赤)

ブレッドボード図

ブレッドボード図も変更しました

配線変更

前回まで無視していましたブレッドボード図のブレッドボードの番号と実物のブレッドボードの番号を合わせました

プログラムの変更とリファクタリング

プログラムを以下の様に変更しました

  • LED名称を変更
  • LED接続ピンが変更なったので修正
  • 試験準備中の場合全灯点灯状態にする
  • メソッドに切り分ける

出来上がりプログラム

#! /usr/bin/python3
import RPi.GPIO as GPIO
import paho.mqtt.client as mqtt
import json

host = '192.168.1.201'
port = 1883
topic = 'pipeline'

LED1 = 22  # 緑
LED2 = 27  # 黄色
LED3 = 17  # 赤

SW_Reset = 26  # リセットボタン

GPIO.setmode(GPIO.BCM)

GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)

GPIO.setup(SW_Reset, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# 全消灯にします
def reset_signal():
    GPIO.output(LED1, False)
    GPIO.output(LED2, False)
    GPIO.output(LED3, False)
# 指定ステータスの点灯状態にします
def set_signal(status):
    reset_signal()
    if status == 'pending':
        # 試験準備中は全点灯
        GPIO.output(LED1, True)
        GPIO.output(LED2, True)
        GPIO.output(LED3, True)
    elif status == 'running':
        # 試験中は黄色を点灯
        GPIO.output(LED2, True)
    elif status == 'success':
        # 試験成功は緑を点灯
        GPIO.output(LED1, True)
    elif status == 'fail':
        # 試験失敗は赤色を点灯
        GPIO.output(LED3, True)
# リセットボタン押下時のイベント
def reset_button_callback(channel):
    print("Button was pushed!")
    reset_signal()
# MQTT購読イベント
def on_message(client, userdata, msg):
    print(str(msg.payload, 'utf-8'))
    # MQTT購読メッセージを読み込みます
    message = json.loads(str(msg.payload, 'utf-8'))
    # LEDステータスを変更します
    set_signal(message['status'])
# メイン実行
def run():
    client = mqtt.Client()
    client.connect(host, port=port, keepalive=60)

    client.subscribe(topic)
    client.on_message = on_message

    client.loop_forever()


if __name__ == '__main__':
    try:
        GPIO.add_event_detect(SW_Reset, GPIO.RISING, callback=reset_button_callback, bouncetime=2000)
        run()
    finally:
        GPIO.cleanup(LED1)
        GPIO.cleanup(LED2)
        GPIO.cleanup(LED3)
        GPIO.cleanup(SW_Reset)

動作確認

はい、ちゃんとステータス通りに動くことを確認できました。

終いに

今回はほぼ新しいことはしていませんが整理はできました。

次回は… 信号機っぽいものにこれを組み込んでみたいと思います