注釈
こんにちは、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+ |
また、個別に購入する場合は以下のリンクをご参照ください。
SN |
コンポーネント |
数量 |
リンク |
|---|---|---|---|
1 |
1 |
||
2 |
Micro USBケーブル |
1 |
|
3 |
1 |
||
4 |
数本 |
||
5 |
7(220Ω) |
||
6 |
1 |
||
7 |
1 |
||
8 |
3 |
コンポーネントの理解
LED:信号機を表します。これらを制御して、標準的な信号機の動作をシミュレートします。
4桁の7セグメントディスプレイ:各信号のカウントダウンタイマーを表示します。
74HC595シフトレジスタ:ピン数を節約しながら、複数の出力(ディスプレイのセグメントや桁)を制御できます。
回路図

この回路は、 5.3 4桁7セグメント表示器を使ったタイムカウンターの作成 をベースに、3つのLEDを追加したものです。
3つの赤、黄、緑のLEDはそれぞれGP7~GP9に接続されています。
配線図
コードを書く
このプロジェクトでは、次のことを行うMicroPythonスクリプトを書きます:
信号機の動作を制御する。
7セグメントディスプレイにカウントダウンタイマーを表示する。
シフトレジスタを使ってディスプレイを制御する。
注釈
7.6_traffic_light.pyをnewton-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からのカウントダウンが表示されます。 このサイクルは無限に繰り返されます。
コードの理解
インポートと初期化:
machine: ハードウェア関連の機能にアクセスするためのモジュール。utime: 時間に関連する関数を提供するモジュール。Timer: ハードウェアタイマーを作成するために使用される。
LEDの初期化:
赤、黄、緑のLEDのGPIOピンを定義し、それぞれを出力として初期化します。
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] # [緑、黄、赤]
ディスプレイ関数:
display_digit(digit): 特定の桁をディスプレイに表示。shift_out(data): シフトレジスタにデータを送信。display_number(num): 数字を桁ごとに分解し、マルチプレクシングを使用して表示。
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)
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)
メインの実行:
初期変数: 初期状態を緑に設定し、カウンタを初期化。
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やディスプレイなどのハードウェアを制御し、タイマーと割り込みを使ってリアルタイムのアプリケーションを作成する方法を示しています。
このプロジェクトを拡張し、新しい機能を追加したり、より大きなシステムに統合したりしてみてください。
