from machine import I2C, Pin, Timer
import time
from pico_i2c_lcd import I2cLcd

# 初始化 I2C 通信
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)

# 初始化 LCD 顯示器
lcd = I2cLcd(i2c, 0x27, 2, 16)

# 定義每個 LED 的顏色和腳位
led1 = {'r': Pin(3, Pin.OUT), 'y': Pin(4, Pin.OUT), 'g': Pin(5, Pin.OUT)}
led2 = {'r': Pin(10, Pin.OUT), 'y': Pin(11, Pin.OUT), 'g': Pin(12, Pin.OUT)}

# 定義按鈕的腳位
btn_mode = Pin(21, Pin.IN, Pin.PULL_DOWN)
btn_flip = Pin(16, Pin.IN, Pin.PULL_DOWN)

# 定義交通燈模式
MODES = {0: "Flash Red", 1: "Flash Yellow", 2: "Alt Flash R-Y", 3: "Alt Flash Y-R", 4: "Seq", 5: "Manual"}

# 設置當前模式
mode = 0
manual_flip = False  # 標誌手動控制的方向
flipping = False  # 標誌是否正在進行方向切換
step = 0  # 初始化常规交通灯序列的步骤

# 去抖動延遲
debounce = 200  # 毫秒

# 初始化時間記錄
last_mode_time = 0
last_flip_time = 0

# 初始化閃爍狀態
flash = False

# 關閉所有LED燈
def all_off():
    for color in led1:
        led1[color].value(0)
        led2[color].value(0)

# 更新 LCD 顯示
def update_lcd():
    lcd.clear()
    lcd.putstr(f"Mode: {mode}")
    if mode == 5:
        lcd.move_to(0, 1)
        lcd.putstr("Dir: B St. Go" if manual_flip else "Dir: A St. Go")

# 控制交通燈狀態的函數
def ctrl_lights(timer):
    global mode, flash, manual_flip, step
    flash = not flash  # 切換閃爍狀態

    all_off()  # 先關閉所有燈

    if mode == 0:  # 閃爍紅燈
        led1['r'].value(flash)
        led2['r'].value(flash)
    elif mode == 1:  # 閃爍黃燈
        led1['y'].value(flash)
        led2['y'].value(flash)
    elif mode == 2:  # 交替閃爍紅黃
        led1['r'].value(flash)
        led2['y'].value(flash)
    elif mode == 3:  # 交替閃爍黃紅
        led1['y'].value(flash)
        led2['r'].value(flash)
    elif mode == 4:  # 常規交通燈序列
        if step == 0:  # 第一步:第一組紅燈,第二組綠燈 (R/G)
            led1['r'].value(1)
            led2['g'].value(1)
        elif step == 1:  # 第二步:第一組紅燈,第二組黃燈 (R/Y)
            led1['r'].value(1)
            led2['y'].value(1)
        elif step == 2:  # 第三步:第一組綠燈,第二組紅燈 (G/R)
            led1['g'].value(1)
            led2['r'].value(1)
        elif step == 3:  # 第四步:第一組黃燈,第二組紅燈 (Y/R)
            led1['y'].value(1)
            led2['r'].value(1)
        step = (step + 1) % 4

    elif mode == 5:  # 手動控制方向切換
        if manual_flip:  # 第一組綠燈, 第二組紅燈
            led1['g'].value(1)
            led2['r'].value(1)
        else:  # 第一組紅燈, 第二組綠燈
            led1['r'].value(1)
            led2['g'].value(1)

# 處理模式切換的函數
def mode_btn(pin):
    global mode, last_mode_time, step
    if time.ticks_ms() - last_mode_time > debounce:
        mode = (mode + 1) % len(MODES)
        last_mode_time = time.ticks_ms()
        update_lcd()
        step = 0

# 處理方向切換的函數
def flip_btn(pin):
    global manual_flip, last_flip_time, flipping
    if time.ticks_ms() - last_flip_time > debounce and not flipping:
        flipping = True

        def transition():
            global flipping, manual_flip

            if manual_flip:  # 目前是第一組綠燈, 第二組紅燈
                led1['g'].value(0)  # 綠燈熄滅
                led1['y'].value(1)  # 黃燈亮
                led2['r'].value(1)  # 第二組保持紅燈
                time.sleep(1)  # 保持黃燈一段時間(1秒)
                led1['y'].value(0)  # 黃燈熄滅
                led1['r'].value(1)  # 黃燈變紅燈
                led2['r'].value(0)  # 第二組的紅燈熄滅
                led2['g'].value(1)  # 第二組的紅燈變為綠燈
            else:  # 目前是第一組紅燈, 第二組綠燈
                led2['g'].value(0)  # 綠燈熄滅
                led2['y'].value(1)  # 黃燈亮
                led1['r'].value(1)  # 第一組保持紅燈
                time.sleep(1)  # 保持黃燈一段時間(1秒)
                led2['y'].value(0)  # 黃燈熄滅
                led2['r'].value(1)  # 黃燈變紅燈
                led1['r'].value(0)  # 第一組的紅燈熄滅
                led1['g'].value(1)  # 第一組的紅燈變為綠燈

            manual_flip = not manual_flip
            flipping = False
            update_lcd()  # 在手動控制完成後更新 LCD 顯示

        transition()
        last_flip_time = time.ticks_ms()

# 添加按鍵事件檢測
btn_mode.irq(trigger=Pin.IRQ_RISING, handler=mode_btn)
btn_flip.irq(trigger=Pin.IRQ_RISING, handler=flip_btn)

# 主程序
if __name__ == "__main__":
    update_lcd()

    # 創建定時器來執行控制交通燈狀態的函數
    timer = Timer(-1)
    timer.init(period=500, mode=Timer.PERIODIC, callback=ctrl_lights)

    try:
        while True:
            pass
    except KeyboardInterrupt:
        pass






















Loading
pi-pico-w