# RFID 和 4*4薄膜鍵盤 控制繼電器(依照兩組預設密碼)
## 程式碼
```c =
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // 引用I2C序列顯示器的程式庫
#include <SoftwareSerial.h>
#include <PN532_SWHSU.h>
#include <PN532.h>
SoftwareSerial SWSerial(4, 5); // RX, TX
PN532_SWHSU pn532swhsu(SWSerial);
PN532 nfc(pn532swhsu);
// 宣告繼電器控制腳位
const int relay1Pin = 2;
const int relay2Pin = 3;
int num = 0 ;
int num2 = 0 ;
// 宣告兩組RFID卡號
uint8_t uid1[] = {0xE7, 0x87, 0x45, 0xC9};
uint8_t uid2[] = {0x3, 0x7E, 0x76, 0xC};
#define KEY_ROWS 4 // 薄膜按鍵的列數
#define KEY_COLS 4 // 薄膜按鍵的行數
#define LCD_ROWS 2 // LCD顯示器的列數
#define LCD_COLS 16 // LCD顯示器的行數
// 設置按鍵模組
char keymap[KEY_ROWS][KEY_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[KEY_ROWS] = {13, 12, 11, 10};
byte colPins[KEY_COLS] = {9, 8, 7, 6};
Keypad keypad = Keypad(makeKeymap(keymap), rowPins, colPins, KEY_ROWS, KEY_COLS);
String passcode1 = "4321"; // 預設密碼
String passcode2 = "1234";
String inputCode = ""; // 暫存用戶的按鍵字串
bool acceptKey = true; // 代表是否接受用戶按鍵輸入的變數,預設為「接受」
String passcode3 = "A";
// LCD顯示器
LiquidCrystal_I2C lcd(0x27, 20, 4); // 設定模組位址0x27/0x3F,以及20行, 4列的顯示形式
void clearRow(byte n) {
byte last = LCD_COLS - n;
lcd.setCursor(n, 1); // 移動到第2行,"PIN:"之後
for (byte i = 0; i < last; i++) {
lcd.print(" ");
}
lcd.setCursor(n, 1);
}
// 顯示「歡迎光臨」後,重設LCD顯示文字和輸入狀態。
void resetLocker() {
lcd.clear();
lcd.print("Knock, knock...");
lcd.setCursor(0, 1); // 切換到第2行
lcd.print("PIN:");
lcd.cursor();
acceptKey = true;
inputCode = "";
}
// 比對用戶輸入的密碼
void checkPinCode() {
acceptKey = false; // 暫時不接受用戶按鍵輸入
clearRow(0); // 從第0個字元開始清除LCD畫面
lcd.noCursor();
lcd.setCursor(0, 0); // 切換到第1行
// 比對密碼
if (inputCode == passcode1) {
lcd.print("Welcome uesr1!");
digitalWrite(relay1Pin, HIGH); // 開啟繼電器1
delay(5000); // 繼電器持續開啟5秒
digitalWrite(relay1Pin, LOW); // 關閉繼電器1
delay(1000);
} else if(inputCode == passcode2){
lcd.print("Welcome uesr2!");
digitalWrite(relay2Pin, HIGH); // 開啟繼電器2
delay(5000); // 繼電器持續開啟5秒
digitalWrite(relay2Pin, LOW); // 關閉繼電器2
delay(1000);
} else if (inputCode == passcode3 ){
num=0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Read...");
lcd.noCursor();
lcd.setCursor(0, 1); // 切換到第2行
while(num<10||relay1Pin ==1 || relay2Pin == 1 ){
boolean success;
uint8_t uid[7]; // 宣告一個7個元素的陣列,用於存儲RFID卡號
uint8_t uidLength; // 存儲卡號長度
// 使用PN532模組讀取RFID卡號
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
if (success ) { // 成功讀取到卡片,進行判斷
// 匹配卡號1
if (memcmp(uid, uid1, 4) == 0) {
Serial.println("匹配到卡號1");
lcd.print("Welcome uesr1!");
digitalWrite(relay1Pin, HIGH); // 開啟繼電器1
delay(5000); // 繼電器持續開啟5秒
digitalWrite(relay1Pin, LOW); // 關閉繼電器1
delay(1000);
break;
}
// 匹配卡號2
else if (memcmp(uid, uid2, 4) == 0) {
Serial.println("匹配到卡號2");
lcd.print("Welcome uesr2!");
digitalWrite(relay2Pin, HIGH); // 開啟繼電器2
delay(5000); // 繼電器持續開啟5秒
digitalWrite(relay2Pin, LOW); // 關閉繼電器2
delay(1000);
break;
}
else {
Serial.println("未知的卡號");
lcd.clear();
lcd.print("***WRONG!!***");
num+=1;
num2 += 1 ;
}
delay(1000); // 延遲一段時間再進行下一次讀卡
}else{
Serial.println("未匹配到");
num += 1 ;
delay(1000);
}
}
resetLocker(); // 重設LCD顯示文字和輸入狀態
}else {
if (num2 != 4) {
lcd.clear();
lcd.print("***WRONG!!***");
delay(1000);
resetLocker();
num2 += 1 ;
}else {
lcd.clear();
lcd.print("Wait 30S");
delay(30000);
resetLocker();
num2=0;
}
}
delay(500);
resetLocker(); // 重設LCD顯示文字和輸入狀態
}
void setup() {
Serial.begin(115200);
Serial.println("Hello Maker!");
// 初始化繼電器腳位
pinMode(relay1Pin, OUTPUT);
pinMode(relay2Pin, OUTPUT);
lcd.init(); // 初始化lcd物件
lcd.backlight(); // 開啟背光
resetLocker();
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (!versiondata) {
Serial.println("沒有找到 PN532 模組");
while (1); // 程序停止
}
// 設置模組讀取ISO14443A類型的RFID卡片
nfc.SAMConfig();
Serial.println("等待 ISO14443A 卡片...");
}
void loop() {
char key = keypad.getKey();
// 若目前接受用戶輸入,而且有新的字元輸入…
if (acceptKey && key != NO_KEY) {
if (key == '*') { // 清除畫面
clearRow(4); // 從第4個字元開始清除
inputCode = "";
} else if (key == '#') { // 比對輸入密碼
checkPinCode();
} else {
inputCode += key; // 儲存用戶的按鍵字元
lcd.print('*');
}
}
}
```
## 接線表
| 繼電器1 IN | 繼電器2 IN | 繼電器 VCC | 繼電器 GND | RN532 GND |RN532 VCC | RN532 TXD | RN532 RXD |
|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|
| Arduino D2 | Arduino D3 | 5V | GND | GND|5V | Arduino D4 | Arduino D5|
| LCD1602 I2C 正極 | LCD1602 I2C 負極 | LCD1602 I2C SDA | LCD1602 I2C SCL | 4*4薄膜鍵盤 |
|:----------------:|:----------------:|:----------------:|:---------------:|:---------------------:|
| 5V | GND | Arduino A4 | Arduino A5 | Arduino D6-13|
## 函式庫
- [GitHub](https://github.com/elechouse/PN532)