注釈

こんにちは、SunFounder Raspberry Pi & Arduino & ESP32 Enthusiast Community on Facebookへようこそ!他の愛好家と一緒に、Raspberry Pi、Arduino、ESP32の世界により深く入り込みましょう。

参加する理由

  • 専門家サポート: 購入後の問題や技術的な課題を、コミュニティと私たちのチームの助けを借りて解決します。

  • 学習と共有: ヒントやチュートリアルを交換して、スキルを向上させましょう。

  • 限定プレビュー: 新製品の発表や先行プレビューに早期アクセスできます。

  • 特別割引: 最新製品を特別割引でお楽しみいただけます。

  • 季節限定キャンペーンとプレゼント: プレゼント企画やホリデーキャンペーンに参加しましょう。

👉 一緒に発見し、創造する準備はできましたか? [こちら] をクリックして、今すぐ参加しましょう!

4.9 信号機シミュレーション

はじめに

このプロジェクトでは、LED と 4 桁の 7 セグメントディスプレイを使用して、実際の信号機システムをシミュレーションします。LED は赤・黄・緑の信号灯を表し、7 セグメントディスプレイは各信号の残り時間をカウントダウン表示します。GPIO 制御、タイミング処理、7 セグメントディスプレイの使い方を、教育用途や試作環境で楽しく学べる内容になっています。


必要なもの

このプロジェクトで必要なコンポーネントは以下のとおりです。

COMPONENT INTRODUCTION

PURCHASE LINK

ブレッドボード

購入

ジャンパーワイヤー

購入

抵抗器

購入

LED

購入

4桁7セグメントディスプレイ

-

74HC595

購入

Fusion HAT+

-

Raspberry Pi

-


回路図

以下は、信号機シミュレーションプロジェクトの回路図です。

../_images/4.1.9_sch.png

配線図

コンポーネントの組み立ては、以下の配線図を参照してください。

../_images/4.1.9_bb.png

サンプルの実行

このチュートリアルで使用するすべてのサンプルコードは ai-lab-kit ディレクトリに含まれています。 以下の手順に従ってサンプルを実行してください。

cd ~/ai-lab-kit/python/
sudo python3 4.9_TrafficLight.py

コード

以下は、信号機シミュレーションで使用する Python スクリプトです。

#!/usr/bin/env python3

from fusion_hat.pin import Pin, Mode
import threading

# Setup GPIO pins for 74HC595 shift register
SDI = Pin(17,mode=Mode.OUT)   # Serial Data Input
RCLK = Pin(4,mode=Mode.OUT)  # Register Clock
SRCLK = Pin(27,mode=Mode.OUT) # Shift Register Clock

# Define GPIO pins for digit selection on the 7-segment display
placePin = [Pin(pin,mode=Mode.OUT) for pin in (23, 24, 25, 12)]

# Segment codes for numbers 0-9 on 7-segment display
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# Setup GPIO pins for traffic light LEDs
ledPinR = Pin(5,mode=Mode.OUT) # Red LED
ledPinG = Pin(6,mode=Mode.OUT)  # Green LED
ledPinY = Pin(13,mode=Mode.OUT)  # Yellow LED

# Duration settings for traffic lights
greenLight = 30
yellowLight = 5
redLight = 60

# Traffic light color names
lightColor = ("Red", "Green", "Yellow")

# Initialize state variables
colorState = 0
counter = 60
timer1 = None

def setup():
   """ Initialize the traffic light system and start the timer. """
   global timer1
   timer1 = threading.Timer(1.0, timer)
   timer1.start()

def clearDisplay():
   """ Clear the 7-segment display. """
   for _ in range(8):
      SDI.high()
      SRCLK.high()
      SRCLK.low()
   RCLK.high()
   RCLK.low()

def hc595_shift(data):
   """ Shift data to the 74HC595 shift register for digit display. """
   for i in range(8):
      SDI.value(0x80 & (data << i))
      SRCLK.high()
      SRCLK.low()
   RCLK.high()
   RCLK.low()

def pickDigit(digit):
   """ Select a specific digit to display on the 7-segment display. """
   for pin in placePin:
      pin.low()
   placePin[digit].high()

def timer():
   """ Handle the timing for traffic light changes. """
   global counter, colorState, timer1
   timer1 = threading.Timer(1.0, timer)
   timer1.start()
   counter -= 1
   if counter == 0:
      counter = [greenLight, yellowLight, redLight][colorState]
      colorState = (colorState + 1) % 3
   print(f"counter : {counter}    color: {lightColor[colorState]}")

def lightup():
   """ Update the traffic light LED based on the current state. """
   global colorState
   ledPinR.low()
   ledPinG.low()
   ledPinY.low()
   [ledPinR, ledPinG, ledPinY][colorState].high()

def display():
   """ Display the current counter value on the 7-segment display. """
   global counter

   for i in range(4):
      digit = counter // (10 ** (3 - i)) % 10
      if i == 0 and digit == 0:
            continue
      clearDisplay()
      pickDigit(i)
      hc595_shift(number[digit])

def loop():
   """ Main loop to continuously update display and lights. """
   while True:
      display()
      lightup()

def destroy():
   """ Clean up resources when the script is terminated. """
   global timer1
   timer1.cancel()
   ledPinR.low()
   ledPinG.low()
   ledPinY.low()

try:
   setup()
   loop()
except KeyboardInterrupt:
   destroy()

コードの解説

  1. 初期化:

    • シフトレジスタ、7 セグメントディスプレイ、および信号機用 LED の GPIO ピンを設定します。

    • 各信号の点灯時間を定義し、状態変数を初期化します。

  2. 7 セグメントディスプレイ用関数:

    • clearDisplay: ディスプレイ上のすべてのセグメントを消灯します。

    • hc595_shift: 表示セグメントを制御するために、シフトレジスタへデータを送信します。

    • pickDigit: 多重化表示のために、特定の桁を有効にします。

  3. タイマー関数:

    • カウントダウンを処理し、信号の状態を切り替えます。

  4. 信号機の制御:

    • 現在の状態に応じて LED を更新します。

  5. メインループ:

    • ディスプレイと LED を継続的に更新します。

  6. 終了処理:

    • スクリプト終了時に、すべてのリソースが適切に解放されるようにします。


トラブルシューティング

  1. 信号灯が動作しない :

    • 原因 : 配線ミス、または LED の故障。

    • 対処方法 :

      • LED が GPIO5(赤)、GPIO6(緑)、GPIO13(黄)に正しく接続されていることを確認してください。

      • 簡単な GPIO 制御スクリプトで各 LED を個別にテストしてください。

  2. 7 セグメントディスプレイにカウントダウンが表示されない:

    • 原因 : 配線ミス、またはシフトレジスタ設定の誤り。

    • 対処方法 :

      • シフトレジスタの SDIRCLKSRCLK ピンが、それぞれ GPIO17、GPIO4、GPIO27 に正しく接続されていることを確認してください。

      • 桁選択ピンが placePin の設定と一致していることを確認してください。

  3. カウントダウンタイマーが停止する:

    • 原因 : タイマースレッドが正しく再起動していません。

    • 対処方法 : timer() 関数内で timer1.start() が呼び出され、タイマースレッドが再開されていることを確認してください。

  4. 信号の点灯時間が正しくない :

    • 原因 : 時間設定値、または状態遷移の誤り。

    • 対処方法 :

      • redLightgreenLightyellowLight の値を確認してください。

      • timer() 関数内のロジックが、正しく状態を切り替えていることを確認してください。


拡張アイデア

  1. 歩行者用横断機能: 歩行者ボタンを追加し、信号サイクルを一時的に中断して安全に横断できるようにします。

    from fusion_hat import Pin
    pedestrian_button = Pin(22, Pin.IN, Pin.PULL_DOWN)
    
    def handle_pedestrian():
          global colorState, counter
          if colorState == 1:  # If Green Light
             counter = 5  # Shorten green light duration
    pedestrian_button.when_activated = handle_pedestrian
    
  2. 適応型タイミング制御 : リアルタイムの交通量に応じて、各信号の点灯時間を動的に調整します。

  3. イベントログ記録 : 信号状態の変化とタイムスタンプをファイルに保存して分析できるようにします。

    with open("traffic_log.txt", "a") as log_file:
          log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {lightColor[colorState]} light\n")
    

まとめ

このプロジェクトでは、信号機システムをシミュレーションすることで、GPIO 制御、シフトレジスタ、7 セグメントディスプレイの使い方を実践的に学ぶことができます。実際のアプリケーションを模した、楽しく教育的な電子工作プロジェクトです。さらに機能を追加して、よりインタラクティブなシステムへ発展させてみてください。