#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
//定義行和列的引腳
int rowPins[4] = {13, 12, 14, 27};
int colPins[4] = {26, 25, 33, 32};
//按鍵映射表
const char keys[4][4] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
//蜂鳴器和 RGB LED 引腳
#define BUZZER_PIN 15
#define RED_PIN 2
#define GREEN_PIN 0
#define BLUE_PIN 4
//密碼變數
String password = "";
String guessPassword = "";
bool setPassword = true;
bool passwordSet = false;
//初始化列為高電位
void initializeColumns() {
for (int i = 0; i < 4; i++) {
pinMode(colPins[i], OUTPUT);
digitalWrite(colPins[i], HIGH);
}
}
void initializeRows() {
for (int i = 0; i < 4; i++) {
pinMode(rowPins[i], INPUT_PULLUP);
}
}
//設置 RGB LED 顏色 紅、綠、藍
void setRGBColor(int red, int green, int blue) {
analogWrite(RED_PIN, red);
analogWrite(GREEN_PIN, green);
analogWrite(BLUE_PIN, blue);
}
// 按鍵掃描函數
char scanKeys() {
for (int i = 0; i < 4; i++) {
digitalWrite(colPins[i], LOW); //將列設為低電位
for (int j = 0; j < 4; j++) {
if (digitalRead(rowPins[j]) == LOW) { //檢查該行是否被按下
digitalWrite(colPins[i], HIGH); //恢復列為高電位
return keys[j][i];
}
}
digitalWrite(colPins[i], HIGH); //恢復列為高電位
}
return '\0';
}
//蜂鳴器播放音效
void playTone(int frequency, int duration) {
tone(BUZZER_PIN, frequency, duration);
delay(duration + 50);
noTone(BUZZER_PIN);
}
void setup() {
//初始化 OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Initializing...");
display.display();
delay(1000);
initializeRows();
initializeColumns();
pinMode(BUZZER_PIN, OUTPUT);
//初始化 RGB LED
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println("Set Password");
display.display();
setRGBColor(255, 255, 0); //黃色 待機或設定密碼
}
void loop() {
static char lastKey = '\0';
char key = scanKeys();
if (key != '\0' && key != lastKey) {
lastKey = key;
if (key == '#') {
//按下 # 時,重設密碼
if (passwordSet) {
playTone(392, 150);
playTone(440, 150);
playTone(494, 150);
playTone(523, 400);
passwordSet = false;
setPassword = true;
password = ""; //清除已設置的密碼
guessPassword = ""; //清除猜測的密碼
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println("Resetting");
display.setCursor(0, 20);
display.println("Password");
display.display();
delay(1000);
display.clearDisplay();
display.setCursor(0, 0);
display.println("Set Password");
display.display();
setRGBColor(255, 255, 0); //黃色 (待機或設定密碼)
}
} else if (setPassword) {
//設置密碼模式
if (password.length() < 5) {
if (key == '*') {
if (password.length() > 0) password.remove(password.length() - 1);
} else {
password += key;
}
}
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println("Set Password");
display.setTextSize(2);
display.setCursor(0, 30);
display.println(password);
display.display();
if (password.length() == 5) {
setPassword = false;
passwordSet = true;
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println("Password Set!");
display.display();
playTone(523, 100);
playTone(587, 100);
playTone(659, 100);
playTone(784, 200);
delay(1000);
display.clearDisplay();
display.setCursor(0, 0);
display.println("Guess Password");
display.display();
guessPassword = "";
setRGBColor(255, 255, 0); //黃色 (待機或輸入中)
}
} else if (passwordSet) {
//驗證密碼模式
if (key == '*') {
if (guessPassword.length() > 0) guessPassword.remove(guessPassword.length() - 1);
} else {
guessPassword += key;
}
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println("Guess Password");
display.setTextSize(2);
display.setCursor(0, 30);
display.println(guessPassword);
display.display();
if (guessPassword.length() == password.length()) {
if (guessPassword == password) {
display.clearDisplay();
display.setTextSize(3);
display.setCursor(0, 0);
display.println("Correct!");
display.display();
setRGBColor(0, 255, 0); //綠色 密碼正確
playTone(784, 200);
playTone(659, 200);
playTone(784, 200);
playTone(880, 400);
} else {
display.clearDisplay();
display.setTextSize(3);
display.setCursor(0, 0);
display.println("Wrong!");
display.display();
setRGBColor(255, 0, 0); //紅色 密碼錯誤
playTone(440, 200);
playTone(349, 200);
playTone(330, 300);
}
guessPassword = "";
delay(1000);
setRGBColor(255, 255, 0); //黃色 待機或輸入中
}
}
} else if (key == '\0') {
lastKey = '\0'; //重置上一次按鍵記錄
}
delay(10);
}