注釈

こんにちは、SunFounder Raspberry Pi & Python & ESP32 Enthusiasts Communityへようこそ!Raspberry Pi、Python、ESP32について、仲間と一緒により深く学びましょう。

なぜ参加するのか?

  • 専門家によるサポート:購入後の問題や技術的な課題に対して、コミュニティやチームのサポートを受けられます。

  • 学びと共有:スキル向上のためのヒントやチュートリアルを交換しましょう。

  • 限定プレビュー:新製品の発表や先行情報をいち早く手に入れることができます。

  • 特別割引:最新製品に対する独占的な割引をお楽しみいただけます。

  • お祭りプロモーションやプレゼント:プレゼントや季節限定プロモーションに参加できます。

👉 一緒に探索し、創造していきませんか? [こちら] をクリックして今すぐ参加しましょう!

7.6 信号機コントローラの作成

このプロジェクトでは、Raspberry Pi Pico 2、3つのLED(赤、黄、緑)、および4桁の7セグメントディスプレイを使用して 信号機コントローラ を作成します。このシステムは、実際の信号機の動作をシミュレートし、各信号の残り時間を7セグメントディスプレイに表示します。

必要なもの

このプロジェクトには以下のコンポーネントが必要です。

セットで購入するのが便利です。こちらからご確認ください:

名前

キット内アイテム

リンク

Newton Lab Kit

450+

Newton Lab Kit

また、個別に購入する場合は以下のリンクをご参照ください。

SN

コンポーネント

数量

リンク

1

Raspberry Pi Pico 2

1

購入

2

Micro USBケーブル

1

3

ブレッドボード

1

購入

4

ジャンパーワイヤー

数本

購入

5

抵抗器

7(220Ω)

購入

6

4桁7セグメント表示

1

7

74HC595

1

購入

8

LED

3

購入

コンポーネントの理解

  • LED:信号機を表します。これらを制御して、標準的な信号機の動作をシミュレートします。

  • 4桁の7セグメントディスプレイ:各信号のカウントダウンタイマーを表示します。

  • 74HC595シフトレジスタ:ピン数を節約しながら、複数の出力(ディスプレイのセグメントや桁)を制御できます。

回路図

sch_traffic_light

配線図

wiring_traffic_light

コードを書く

このプロジェクトでは、次のことを行うMicroPythonスクリプトを書きます:

  • 信号機の動作を制御する。

  • 7セグメントディスプレイにカウントダウンタイマーを表示する。

  • シフトレジスタを使ってディスプレイを制御する。

注釈

  • 7.6_traffic_light.pynewton-lab-kit/micropython から開くか、コードをThonnyにコピーして「実行」ボタンを押すか、F5キーを押して実行してください。

  • 正しいインタープリター(MicroPython(Raspberry Pi Pico))が選択されていることを確認してください。COMxx。

import machine
import utime
from machine import Timer

# LEDのピンを初期化
led_pins = [7, 8, 9]  # 緑、黄、赤のLEDをGP7、GP8、GP9に接続
leds = [machine.Pin(pin, machine.Pin.OUT) for pin in led_pins]

# 各信号の色の持続時間(秒)を定義 [緑、黄、赤]
light_time = [30, 5, 30]  # [緑、黄、赤]

# 各桁の2進数コード(0~9)
SEGMENT_CODES = [
    0x3F,  # 0
    0x06,  # 1
    0x5B,  # 2
    0x4F,  # 3
    0x66,  # 4
    0x6D,  # 5
    0x7D,  # 6
    0x07,  # 7
    0x7F,  # 8
    0x6F   # 9
]

# 74HC595の制御ピンを初期化
SDI = machine.Pin(18, machine.Pin.OUT)   # シリアルデータ入力(DS)
RCLK = machine.Pin(19, machine.Pin.OUT)  # レジスタクロック(STCP)
SRCLK = machine.Pin(20, machine.Pin.OUT) # シフトレジスタクロック(SHCP)

# 桁選択ピン(共通カソード)
digit_pins = [
    machine.Pin(10, machine.Pin.OUT),  # 桁1
    machine.Pin(11, machine.Pin.OUT),  # 桁2
    machine.Pin(12, machine.Pin.OUT),  # 桁3
    machine.Pin(13, machine.Pin.OUT)   # 桁4
]

# 74HC595にデータを送信する関数
def shift_out(data):
    RCLK.low()
    for bit in range(7, -1, -1):
        SRCLK.low()
        bit_val = (data >> bit) & 0x01
        SDI.value(bit_val)
        SRCLK.high()
    RCLK.high()

# 特定の位置に桁を表示する関数
def display_digit(position, digit):
    # すべての桁を消灯
    for dp in digit_pins:
        dp.high()
    # セグメントデータを送信
    shift_out(SEGMENT_CODES[digit])
    # 選択された桁をアクティブ化(共通カソードはアクティブロー)
    digit_pins[position].low()
    # 桁が見えるように小さな遅延を追加
    utime.sleep_ms(5)
    # 桁を消灯
    digit_pins[position].high()

# 4桁ディスプレイに数字を表示する関数
def display_number(number):
    # 数字を桁ごとに分解
    digits = [
        (number // 1000) % 10,
        (number // 100) % 10,
        (number // 10) % 10,
        number % 10
    ]
    # 各桁を素早く表示
    for i in range(4):
        display_digit(i, digits[i])

# 現在の状態に基づいてLEDを更新する関数
def update_leds(state):
    # 状態: 0 = 緑、1 = 黄、2 = 赤
    for i in range(3):
        leds[i].value(0)
    leds[state].value(1)

# タイマー変数
counter = light_time[0]  # 緑の信号の時間から開始
current_state = 0  # 0 = 緑、1 = 黄、2 = 赤

# タイマー割り込みコールバック関数(信号機の状態とカウントを更新)
def timer_callback(t):
    global counter, current_state
    counter -= 1
    if counter <= 0:
        current_state = (current_state + 1) % 3  # 状態を循環
        counter = light_time[current_state]  # 新しい状態に対するカウンタをリセット
        update_leds(current_state)

# タイマーを初期化
timer = Timer(period=1000, mode=Timer.PERIODIC, callback=timer_callback)

# 初期LED状態
update_leds(current_state)

# メインループ
try:
    while True:
        display_number(counter)
except KeyboardInterrupt:
    timer.deinit()
    print("Program stopped.")

コードが実行されると、最初に緑のLEDが点灯し、ディスプレイに30からのカウントダウンが表示されます。 30秒後、黄色のLEDが点灯し、ディスプレイに5からのカウントダウンが表示されます。 その後、赤のLEDが点灯し、ディスプレイに30からのカウントダウンが表示されます。 このサイクルは無限に繰り返されます。

コードの理解

  1. インポートと初期化:

    • machine: ハードウェア関連の機能にアクセスするためのモジュール。

    • utime: 時間に関連する関数を提供するモジュール。

    • Timer: ハードウェアタイマーを作成するために使用される。

  2. LEDの初期化:

    赤、黄、緑のLEDのGPIOピンを定義し、それぞれを出力として初期化します。

    led_pins = [7, 8, 9]  # 緑、黄、赤のLEDはそれぞれGP7、GP8、GP9に接続
    leds = [machine.Pin(pin, machine.Pin.OUT) for pin in led_pins]
    
  3. 信号機のタイミング:

    各信号機状態の継続時間(秒単位)を指定します。

    light_time = [30, 5, 30]  # [緑、黄、赤]
    
  4. ディスプレイ関数:

    • display_digit(digit): 特定の桁をディスプレイに表示。

    • shift_out(data): シフトレジスタにデータを送信。

    • display_number(num): 数字を桁ごとに分解し、マルチプレクシングを使用して表示。

  5. update_leds(state) 関数:

    • 現在の信号機状態に基づいてLEDの状態を更新。

    • すべてのLEDを消灯した後、現在の状態に対応するLEDを点灯。

    def update_leds(state):
        # 状態: 0 = 緑、1 = 黄、2 = 赤
        for i in range(3):
            leds[i].value(0)
        leds[state].value(1)
    
  6. timer_callback(t) 関数:

    • タイマー割り込みコールバック関数。

    • カウンタを毎秒減算。

    • カウンタがゼロになると、次の信号機状態にサイクルし、カウンタをリセット。

    def timer_callback(t):
        global counter, current_state
        counter -= 1
        if counter <= 0:
            current_state = (current_state + 1) % 3  # 状態を循環
            counter = light_time[current_state]  # 新しい状態のためにカウンタをリセット
            update_leds(current_state)
    
  7. メインの実行:

    • 初期変数: 初期状態を緑に設定し、カウンタを初期化。

      counter = light_time[0]  # 緑の信号機の継続時間で開始
      current_state = 0  # 0 = 緑、1 = 黄、2 = 赤
      
    • タイマーの初期化: 1000ミリ秒(1秒)ごとにタイマーコールバックを呼び出す周期的タイマーを作成。

      timer = Timer(period=1000, mode=Timer.PERIODIC, callback=timer_callback)
      
    • 初期LED状態の設定: 最初に正しいLEDが点灯していることを確認。

      update_leds(current_state)
      
    • メインループ: 無限ループでカウントダウンタイマーを表示。キーボード割り込み(例:Ctrl+C)でタイマーを安全に停止し、終了。

      try:
          while True:
              display_number(counter)
      except KeyboardInterrupt:
          timer.deinit()
          print("Program stopped.")
      

さらに実験

  • タイミングの調整:

    light_time リストを変更して、各信号機の継続時間を調整します。

  • 歩行者信号の追加:

    ボタンや追加のLEDを実装して、歩行者信号をシミュレートします。

  • ディスプレイの改善:

    時間がほぼ終了した際にLEDを点滅させるなどの機能を追加します。

  • 実際の信号機のシミュレーション:

    左折信号や交差点の複数信号など、より複雑なシーケンスを追加します。

結論

あなたはRaspberry Pi Pico 2を使用して信号機制御システムを正常に構築しました!このプロジェクトは、マイクロコントローラーを使ってLEDやディスプレイなどのハードウェアを制御し、タイマーと割り込みを使ってリアルタイムのアプリケーションを作成する方法を示しています。

このプロジェクトを拡張し、新しい機能を追加したり、より大きなシステムに統合したりしてみてください。