from machine import Pin, I2C, Timer
from ssd1306 import SSD1306_I2C
import time
# 初始化 I2C 和 SSD1306 顯示器
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
oled = SSD1306_I2C(128, 64, i2c)
# 設定 Membrane Keypad 的行和列引腳
rows = [Pin(13, Pin.OUT), Pin(12, Pin.OUT), Pin(14, Pin.OUT), Pin(27, Pin.OUT)]
cols = [Pin(26, Pin.IN, Pin.PULL_DOWN), Pin(25, Pin.IN, Pin.PULL_DOWN), Pin(33, Pin.IN, Pin.PULL_DOWN), Pin(32, Pin.IN, Pin.PULL_DOWN)]
led = Pin(23, Pin.OUT)
# 定義鍵盤按鍵佈局
keys = [
["1", "2", "3", "A"],
["4", "5", "6", "B"],
["7", "8", "9", "C"],
["*", "0", "#", "D"]
]
room_id = ""
key_pressed = None
state = "start"
last_time_update = time.time()
# 洗衣和烘衣時間設定(秒)
wash_time = 20
dry_time = 0 # 初始為 0,等待計算
extra_time_per_coin = 20
base_dry_time = 20 # 烘衣模式的起始時間:20 秒
coins_inserted = 0 # 用來記錄硬幣數量
# 閒置計時器
idle_time = 0 # 記錄閒置時間
idle_threshold = 5 # 閒置時間大於這個閾值才會鳴叫
# 顯示初始的內容
oled.fill(0)
oled.text("Room ID:", 0, 0)
oled.text(room_id, 0, 16)
oled.show()
# 定義掃描鍵盤的函數
def scan_keypad():
for row_num, row_pin in enumerate(rows):
row_pin.on()
for col_num, col_pin in enumerate(cols):
if col_pin.value() == 1:
row_pin.off()
return keys[row_num][col_num]
row_pin.off()
return None
# 更新顯示的函數
def update_display():
oled.fill(0)
# 永遠顯示 room_id 在頂部
oled.text("Room ID:", 0, 0)
oled.text(room_id, 65, 0)
if state == "start":
oled.text("Press * to next", 0, 56)
if state == "choose_mode":
oled.text("Select Mode:", 0, 16)
oled.text("1: Wash", 0, 32)
oled.text("2: Dry", 0, 48)
elif state == "insert_coins":
oled.text("Drying Mode", 0, 16)
oled.text(f"Time: {dry_time} sec", 0, 30)
oled.text(f"Coin: {coins_inserted}", 0, 44)
oled.text("Press * to next", 0, 56)
elif state == "wait_start":
if selected_mode == "washing":
oled.text("Washing...", 0, 16)
oled.text(f"Time: {wash_time} sec", 0, 32)
oled.text("Press * to start", 0, 48)
elif selected_mode == "drying":
oled.text("Drying Mode", 0, 16)
oled.text(f"Time: {dry_time} sec", 0, 30)
oled.text(f"Coin: {coins_inserted}", 0, 44)
oled.text("Press * to start", 0, 56)
elif state == "washing":
oled.text("Washing...", 0, 16)
oled.text(f"Time: {wash_time} sec", 0, 32)
elif state == "drying":
oled.text("Drying...", 0, 16)
oled.text(f"Time: {dry_time} sec", 0, 32)
if state == "finish":
oled.text("It's time to", 0, 16)
oled.text("get clothes~", 0, 32)
oled.text("Press # to start again", 0, 56)
oled.show()
# 主定時器回調函數,用於處理鍵盤輸入和倒計時邏輯
# 主定時器回調函數,用於處理鍵盤輸入和倒計時邏輯
def key_timer_callback(timer):
global key_pressed, room_id, state, wash_time, dry_time, last_time_update, selected_mode, coins_inserted, idle_time
key = scan_keypad()
if key and key != key_pressed:
key_pressed = key
# 處理鍵盤輸入的邏輯
if state == "start":
if key in "0123456789ABCD":
room_id += key
update_display()
elif key == "*":
state = "choose_mode"
update_display()
elif key == "#":
room_id = ""
update_display()
elif state == "choose_mode":
if key == "1":
selected_mode = "washing"
state = "wait_start"
update_display()
elif key == "2":
selected_mode = "drying"
state = "insert_coins"
dry_time = base_dry_time # 初始時間設定為 40 秒
coins_inserted = 0 # 重置硬幣數量
update_display()
elif state == "insert_coins":
if key in "0123456789": # 允許按下數字鍵來輸入硬幣數量
coins_inserted = int(key) # 將輸入轉換為硬幣數
dry_time = base_dry_time + coins_inserted * extra_time_per_coin # 以 40 秒為基準,增加每個硬幣的時間
update_display()
elif key == "*":
state = "wait_start" # 進入等待開始狀態
update_display()
elif state == "wait_start" and key == "*":
state = selected_mode # 開始計時
update_display()
elif state == "finish":
if key == "#":
# 確保 selected_mode 已經初始化
if selected_mode == "washing":
wash_time = 20 # 重設洗衣時間
elif selected_mode == "drying":
dry_time = 20
room_id = ""
state = 'start' # 回到選擇的模式並開始倒計時
update_display() # 更新顯示
idle_time = 0 # 重置閒置時間
print(idle_time)
led.off()
elif not key:
key_pressed = None
# 處理倒計時,每秒更新一次
current_time = time.time()
if current_time - last_time_update >= 1:
last_time_update = current_time
if state == "washing" and wash_time > 0:
wash_time -= 1
idle_time = 0 # 重置閒置時間
update_display()
elif state == "drying" and dry_time > 0:
dry_time -= 1
idle_time = 0 # 重置閒置時間
update_display()
if (state == "washing" and wash_time == 0) or (state == "drying" and dry_time == 0):
state = "finish"
update_display()
if state == "finish":
idle_time += 1
print(idle_time)
if idle_time >= 3:
if idle_time % 2 == 1: # 基數秒
led.on()
else: # 偶數秒
led.off()
# 創建定時器並設置每100ms檢查一次按鍵和倒計時
key_timer = Timer(0)
key_timer.init(period=100, mode=Timer.PERIODIC, callback=key_timer_callback)
# 主循環
while True:
pass # 可以加入其他非阻塞的邏輯