from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import time
# 設定硬體
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled = SSD1306_I2C(128, 64, i2c)
button_a = Pin(5, Pin.IN, Pin.PULL_UP)
button_b = Pin(25, Pin.IN, Pin.PULL_UP)
led = Pin(14, Pin.OUT)
led.value(0)
# 初始參數
current_mode = 0 # 0: 秒, 1: 分鐘, 2: 小時
time_values = [0, 0, 0] # [秒, 分鐘, 小時]
countdown_running = False
last_press_a = 0 # A鍵上次按下的時間戳
last_press_b = 0 # B鍵上次按下的時間戳
debounce_time = 200 # 防彈跳時間(毫秒)已增加至200毫秒
waiting_confirmation = False # 是否在等待按下B鍵繼續
led_blinking = False # LED是否閃爍中
fast_increase = False # 按住A快速增加的標記
countdown_ended = False # 新增標誌,記錄是否倒計時結束
led_state = False # 初始化LED的狀態,預設為False(關閉)
# 更新OLED顯示
def update_display():
oled.fill(0)
oled.text("Timer:", 0, 0)
oled.text(f"{time_values[2]:02}:{time_values[1]:02}:{time_values[0]:02}", 0, 20)
if not countdown_running:
oled.text("Mode: " + ["Sec", "Min", "Hour"][current_mode], 0, 40)
if waiting_confirmation:
oled.text("Press B to start", 0, 55)
oled.show()
# 增加時間
def increase_time():
global time_values, current_mode
if not countdown_running:
time_values[current_mode] += 1
if time_values[0] > 59:
time_values[0] = 0
if time_values[1] > 59:
time_values[1] = 0
if time_values[2] > 23:
time_values[2] = 0
update_display()
# 按住A快速增加秒數
def check_button_a():
global last_press_a, fast_increase
if not button_a.value(): # 按鈕A被按住
current_time = time.ticks_ms()
if fast_increase or time.ticks_diff(current_time, last_press_a) > debounce_time:
last_press_a = current_time
increase_time()
fast_increase = True
else:
fast_increase = False
'''
# 修改:檢測短按和長按
def check_button_a():
global last_press_a, fast_increase
current_time = time.ticks_ms()
max_long_press_duration = 1000 # 長按閾值(毫秒)
if not button_a.value(): # 按鈕A被按下
if last_press_a == 0: # 按鈕第一次按下時記錄時間
last_press_a = current_time
elif time.ticks_diff(current_time, last_press_a) > max_long_press_duration:
# 持續按住超過閾值,視為長按
fast_increase = True
last_press_a = current_time # 重置時間,持續快速增加
increase_time()
else:
if last_press_a != 0: # 按鈕放開
press_duration = time.ticks_diff(current_time, last_press_a)
last_press_a = 0 # 重置按下時間
if press_duration < max_long_press_duration:
# 如果是短按,僅執行一次增加
increase_time()
fast_increase = False
'''
# 切換模式或啟動倒數
def switch_mode(pin):
global current_mode, countdown_running, last_press_b, waiting_confirmation
current_time = time.ticks_ms()
if time.ticks_diff(current_time, last_press_b) > debounce_time: # 防彈跳
last_press_b = current_time
if countdown_running: # 如果在倒計時中
reset_timer() # 按下B重置計時
elif waiting_confirmation: # 如果在等待確認
start_countdown() # 按下B啟動倒計時
else: # 否則切換模式
current_mode = (current_mode + 1) % 3
if current_mode == 2: # 當切換到小時數
waiting_confirmation = True # 進入確認階段
update_display() # 更新顯示
# 倒計時
def start_countdown():
global countdown_running, waiting_confirmation, time_values
countdown_running = True
waiting_confirmation = False
total_seconds = time_values[2] * 3600 + time_values[1] * 60 + time_values[0]
while total_seconds > 0:
minutes, seconds = divmod(total_seconds, 60)
hours, minutes = divmod(minutes, 60)
time_values[2], time_values[1], time_values[0] = hours, minutes, seconds
update_display()
time.sleep(1)
total_seconds -= 1
# 如果倒計時結束後時間顯示還是大於0,就設為00:00:00
time_values = [0, 0, 0]
update_display() # 更新顯示時間為00:00:00
timer_end() # 呼叫倒計時結束處理函數
# 倒計時結束
def timer_end():
global countdown_running, led_blinking, led_last_toggle_time, countdown_ended
countdown_running = False
countdown_ended = True # 標記倒計時結束
led_blinking = True
led_last_toggle_time = time.ticks_ms() # 記錄LED閃爍時間
oled.fill(0) # 清除顯示
oled.text("Time's up.", 0, 40)
oled.text("Press B to end", 0, 55)
oled.show()
def update_display():
if countdown_ended: # 如果倒計時結束,停止更新顯示
return
oled.fill(0)
oled.text("Timer:", 0, 0)
oled.text(f"{time_values[2]:02}:{time_values[1]:02}:{time_values[0]:02}", 0, 20)
if not countdown_running:
oled.text("Mode: " + ["Sec", "Min", "Hour"][current_mode], 0, 40)
if waiting_confirmation:
oled.text("Press B to start", 0, 55)
oled.show()
# 重置鬧鐘
def reset_timer():
global time_values, countdown_running, waiting_confirmation, current_mode
time_values = [0, 0, 0] # 重置時間值
countdown_running = False
waiting_confirmation = False
current_mode = 0 # 回到 "Sec" 模式
led.value(0) # 確保LED熄滅
update_display() # 更新顯示
#初始畫面
update_display()
oled.text("Press A to start", 0, 40)
oled.show()
# 中斷處理
button_b.irq(trigger=Pin.IRQ_FALLING, handler=switch_mode)
# 主迴圈
while True:
if not countdown_ended: # 如果倒計時尚未結束
check_button_a()
# LED閃爍邏輯
if led_blinking:
current_time = time.ticks_ms()
if time.ticks_diff(current_time, led_last_toggle_time) >= 500:
led_last_toggle_time = current_time
led_state = not led_state # 切換LED狀態
led.value(led_state)
if countdown_ended: # 如果倒計時結束
if not button_b.value(): # 如果按下B鍵
countdown_ended = False # 重置結束狀態
led_blinking = False # 停止LED閃爍
led.value(0) # 確保LED熄滅
reset_timer() # 重置計時器