from machine import Pin, I2C, PWM
import time
import ssd1306
# 設定 I2C
i2c = I2C(0, scl=Pin(22), sda=Pin(21)) # SCL接到GPIO 22, SDA接到GPIO 21
# OLED 顯示屏配置
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
# 初始化 OLED
oled.fill(0)
oled.text("Initializing...", 0, 0) # 顯示初始化文字
oled.show()
time.sleep(1)
# 顯示 Set Password
oled.fill(0)
oled.text("Set Password", 0, 0)
oled.show()
# 定義行和列的引腳
rows = [Pin(12, Pin.IN, Pin.PULL_UP), Pin(13, Pin.IN, Pin.PULL_UP), Pin(14, Pin.IN, Pin.PULL_UP), Pin(27, Pin.IN, Pin.PULL_UP)]
cols = [Pin(33, Pin.OUT), Pin(32, Pin.OUT), Pin(25, Pin.OUT), Pin(26, Pin.OUT)]
# 按鍵映射表
keys = [
['1', '2', '3', 'A'],
['4', '5', '6', 'B'],
['7', '8', '9', 'C'],
['*', '0', '#', 'D']
]
# 初始化列為高電位
for col in cols:
col.init(Pin.OUT)
col.value(1)
# 按鍵掃描函數
def scan_keys():
for i in range(4):
cols[i].value(0) # 將列設為低電位
for j in range(4):
if not rows[j].value(): # 檢查該行是否被按下
cols[i].value(1) # 恢復列為高電位
return keys[j][i]
cols[i].value(1) # 恢復列為高電位
return None
# 蜂鳴器設定
buzzer = PWM(Pin(15), freq=1, duty=0) # 預設關閉蜂鳴器
def play_tone(frequency, duration):
""" 播放蜂鳴器音效 """
buzzer.freq(frequency)
buzzer.duty(512) # 設定占空比
time.sleep(duration)
buzzer.duty(0) # 關閉蜂鳴器
time.sleep(0.05)
# 密碼設置
set_password = True
password = ""
guess_password = ""
last_key = None
password_set = False
while True:
key = scan_keys()
if key: # 如果有按鍵被按下
if key != last_key: # 只有當按鍵改變時才處理
last_key = key
if set_password:
if len(password) <= 5: # 限制密碼長度最多為5位
if key == '*': # 刪除最後一位
password = password[:-1]
else:
password += key
oled.fill(0)
oled.text("Set Password", 0, 0)
oled.text(password, 0, 20)
oled.show()
if len(password) == 5: # 密碼設置完成
set_password = False
password_set = True
oled.fill(0)
oled.text("Password Set!", 0, 0)
oled.show()
time.sleep(1) # 顯示 "Password Set!" 1秒
# 顯示 "Guess Password"
oled.fill(0)
oled.text("Guess Password", 0, 0)
oled.show()
# 重置猜測密碼和上次按鍵
guess_password = "" # 清空已輸入的猜測密碼
last_key = None # 重置上次的按鍵,避免錯誤的按鍵滯後
elif password_set:
# 顯示 "Guess the password"
oled.fill(0)
oled.text("Guess Password", 0, 0)
oled.text(guess_password, 0, 20)
oled.show()
if key == '*': # 刪除最後一位
guess_password = guess_password[:-1]
else:
guess_password += key
# 更新顯示,立即反映最新的密碼
oled.fill(0)
oled.text("Guess Password", 0, 0)
oled.text(guess_password, 0, 20)
oled.show()
# 當輸入的密碼長度與設置密碼長度相同時,檢查正確性
if len(guess_password) == len(password):
if guess_password == password:
oled.fill(0)
oled.text("Correct!", 0, 0)
oled.show()
# 播放成功音效
play_tone(523, 0.2) # C5
play_tone(659, 0.2) # E5
play_tone(784, 0.4) # G5
else:
oled.fill(0)
oled.text("Wrong!", 0, 0)
oled.show()
# 播放錯誤音效
for _ in range(3):
play_tone(440, 0.1) # A4
guess_password = "" # 重置輸入密碼
time.sleep(1)
elif not key:
last_key = None # 重置上一次按鍵記錄
time.sleep(0.01) # 主迴圈延遲時間縮短至0.01秒,避免過長的延遲