Электрический замок с RFID - RobotDynOfficial/Documentation GitHub Wiki
Данная схема реализует доступ в помещение по коду или карточкам. В нормальном состоянии замок закрыт и на экране это написано. Если к картридеру прикладывается правильная карта или вводится верный код, то звучит звуковой сигнал, и открывается замок. Новые карточки или новый код можно зарегистрировать через компьютер.
- Напряжение питания: 3.3V;
- Потребляемый ток :13-26mA;
- Рабочая частота: 13.56MHz;
- Дальность считывания: 0 - 60 мм;
- Интерфейс: SPI, I2C;
- Скорость передачи: максимальная 10МБит/с;
- Размер: 30мм х 30мм.
- Микросхема: PN532;
- Логика: КМОП, 3.3В;
- Напряжение питания: 3.3-5В;
- Максимальный потребляемый ток: 150 мА;
- Потребляемый ток в режиме ожидания: 100 мА;
- Потребляемый ток в режиме считывания: 120 мА;
- Потребляемый ток в режиме записи: 120 мА;
- Дальность считывания: 5 - 7 см;
- Антенна: встроенная, на плате;
- Размеры: 42.7 х 40.4 мм.
- Экран LCD1602
- RFID- MFRC522 или PN532
- Клавиатура 4х4
- Arduino UNO
- Buzzer
- Electromagnetic lock
- Соединительные провода
Cоберем схему, используя данную таблицу:
Arduino | LCD1602 | Buzzer | keypad | Relay | PN532 | MFRC522 | lock |
---|---|---|---|---|---|---|---|
5V | 5V | VCC | VCC | VCC | 5V | 5V | |
vin | + | ||||||
GND | GND | GND | GND | GND | GND | GND | |
3 | in | ||||||
5 | S | ||||||
A4 | SCL | SCL | MISO | ||||
A5 | SDA | SDA | SDA | ||||
A0 | Out | ||||||
(-) to relay in OUT |
Для правильного включения э.м. замка в цепь, нужно параллельно замку поключить защитный диод.
В зависимости от используемых RFID считывателей установите соответствующие библиотеки:
PN532_I2C.h библиотека RFID PN532 I2C
NfcAdapter.h библиотека RFID
LiquidCrystal_I2C.h библиотека дисплея 1602
EEPROM.h библиотека памяти EEPROM
Wire.h библиотека шины I2C
MFRC522_I2C.h библиотека RFID MFRC522
Библиотеку "MFRC522_I2C.h" можно скачать по ссылке:
https://github.com/arozcan/MFRC522-I2C-Library
Подлключите Arduino к компьютеру, откройте монитор порта на скорости 115200 Бод, введите слово 'card', приложите новую карту к считывателю и напишите в монитор порта символ 's', если вам нужно удалить эту карту из памяти, напишите символ 'd'.
Для программирования нового кода доступа в мониторе порта введите "code 1234", где 1234 - это новый код.
#include <PN532_I2C.h> //библиотека RFID PN532 I2C
#include <NfcAdapter.h> //библиотека RFID
#include <LiquidCrystal_I2C.h> //библиотека дисплея 1602
#include <EEPROM.h> //библиотека памяти EEPROM
#include <Wire.h> //библиотека шины I2C
#include "MFRC522_I2C.h" //библиотека RFID MFRC522
#define useMFRC522
//#define usePN532
#define keybPin A0
#define beepPin 5
#define relayPin 3
#define timeOpen 6 //сколько секунд открыт замок
#define relayLogic 1 //состояние пина при открытом замке
#define beepLogic 1 //состояние пина при звучащей пищалке
#define lcdAddr 0x38 //I2C адрес дисплея
#define mfrcAddr 0x2A //I2C адрес считывателя MFRC522
int keybVals[16] = {325,1020,926,850,674,632,595,504,480,459,784,562,439,235,403,269}; //средние значения сигнала для клавиатуры
int nowCard;
int degKV;
byte cardSaved[10][4];
byte uid[4];byte uidLength;
byte codeT[4];
byte codeE[4];
unsigned long timeRst;
char key;
char keyOld;
byte entCode;
byte cLen;
LiquidCrystal_I2C lcd(lcdAddr,16,2);
#ifdef usePN532
PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);
#endif
#ifdef useMFRC522
MFRC522 mfrc522(mfrcAddr, 2);
#endif
void setup(){
Serial.begin(115200);
Wire.begin();
lcd.init();lcd.noBacklight();
pinMode(relayPin, OUTPUT);digitalWrite(relayPin, !relayLogic);
pinMode(beepPin, OUTPUT);digitalWrite(beepPin, !beepLogic);
pinMode(keybPin, INPUT);
#ifdef usePN532
//Проверка подключения RFID и его инициализация
Wire.beginTransmission(0x24);
if(!Wire.endTransmission()){
nfc.begin();
nfc.setPassiveActivationRetries(0x04);
nfc.SAMConfig();
}else{
Serial.println("RFID error");
while(1){}
}
#endif
#ifdef useMFRC522
//Проверка подключения RFID и его инициализация
Wire.beginTransmission(mfrcAddr);
if(!Wire.endTransmission()){
mfrc522.PCD_Init();
}else{
Serial.println("RFID error");
while(1){}
}
#endif
for(int n=0;n<10;n++){for(int k=0;k<4;k++){cardSaved[n][k] = EEPROM.read(k+4*n);}}
for(int n=0;n<4;n++){codeT[n] = EEPROM.read(n+50);}
degKV = 1024;
for(int n=0;n<16;n++){
for(int i=0;i<16;i++){
if(i != n){
if(abs(keybVals[n] - keybVals[i]) < degKV){degKV = abs(keybVals[n] - keybVals[i]);}
}
}
}
degKV--;
entCode = 0;
lcdClear();
lcd.backlight();
Serial.println("Std");
}
void loop(){
nowCard = isCard();
if(nowCard >= 0){
Serial.println("Open by card");
beep(700);
lcd.clear();lcd.setCursor(0,0);lcd.print(" OPEN ");
digitalWrite(relayPin, relayLogic);
delay(1000*timeOpen);
digitalWrite(relayPin, !relayLogic);
lcdClear();
}else if(nowCard == -2){
Serial.println("Wrong card");
beep(200);delay(300);beep(200);
while(isCard() != -1){delay(500);}
delay(500);
}
key = getKey();
if(key){
timeRst = millis() + 4000;
beep(70);
if(!entCode){
lcd.print("code: ");
cLen = 0;
}
lcd.print(key);
codeE[cLen] = key;
cLen++;
entCode = 1;
if(cLen >= 4){
if(codeE[0] == codeT[0] && codeE[1] == codeT[1] && codeE[2] == codeT[2] && codeE[3] == codeT[3]){
Serial.println("Open by code");
beep(700);
lcd.clear();lcd.setCursor(0,0);lcd.print(" OPEN ");
digitalWrite(relayPin, relayLogic);
delay(1000*timeOpen);
digitalWrite(relayPin, !relayLogic);
lcdClear();
}else{
lcd.setCursor(6,1);lcd.print("Error");
beep(200);delay(300);beep(200);
delay(1500);
timeRst = 0;
}
}
}
if(entCode == 1 && millis() > timeRst){
entCode = 0;
lcdClear();
}
if(Serial.available() > 0){
if(Serial.read() == 'c'){
delay(20);
byte sRead = Serial.read();
if(sRead == 'a'){
if(Serial.read() == 'r' && Serial.read() == 'd'){
Serial.print("attach card : ");
nowCard = isCard();
while(nowCard != -1){nowCard = isCard();}
#ifdef usePN532
while(!nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength)){}
#endif
#ifdef useMFRC522
while(!(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())){}
for(int i=0;i<4;i++){uid[i] = mfrc522.uid.uidByte[i];}
#endif
beep(500);
for(int n=0;n<4;n++){Serial.print(uid[n]);Serial.print(" ");}Serial.println("");
while(Serial.available() > 0){Serial.read();}
Serial.println("d - delete");
Serial.println("s - save");
while(Serial.available() <= 0){}
sRead = Serial.read();
if(sRead == 's'){
Serial.println("Saved");
if(EEPROM.read(100) > 9){EEPROM.write(100, 0);}
for(int k=0;k<4;k++){cardSaved[EEPROM.read(100)][k] = uid[k];EEPROM.write(k+4*EEPROM.read(100), uid[k]);}
EEPROM.write(100, EEPROM.read(100)+1);
}
if(sRead == 'd'){
Serial.println("Deleted");
for(int n=0;n<10;n++){
if(cardSaved[n][0] == uid[0] && cardSaved[n][1] == uid[1] && cardSaved[n][2] == uid[2] && cardSaved[n][3] == uid[3]){
for(int k=0;k<4;k++){cardSaved[n][k] = 0;EEPROM.write(k+4*n, 0);}
}
}
}
}
}else if(sRead == 'o'){
if(Serial.read() == 'd' && Serial.read() == 'e' && Serial.read() == ' '){
byte codeN[4];byte res = 1;
for(int n=0;n<4;n++){codeN[n] = Serial.read();if((codeN[n] < '0' || codeN[n] > '9') && (codeN[n] < 'A' || codeN[n] > 'D') && codeN[n] != '*' && codeN[n] != '#'){res = 0;}}
if(res){
Serial.println("Saved");
for(int n=0;n<4;n++){codeT[n] = codeN[n];EEPROM.write(n+50, codeN[n]);}
}else{
Serial.println("Error");
}
}
}
}
}
}
void lcdClear(){
lcd.clear();
lcd.setCursor(0,0);lcd.print(" CLOSED");
lcd.setCursor(0,1);
}
int isCard(){
#ifdef usePN532
if(nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength)){
for(int n=0;n<10;n++){
if(uid[0] == cardSaved[n][0]){
if(uid[1] == cardSaved[n][1]){
if(uid[2] == cardSaved[n][2]){
if(uid[3] == cardSaved[n][3]){return n;}
}
}
}
}
return -2;
}
#endif
#ifdef useMFRC522
if(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()){
for(int i=0;i<4;i++){uid[i] = mfrc522.uid.uidByte[i];}
for(int n=0;n<10;n++){
if(uid[0] == cardSaved[n][0]){
if(uid[1] == cardSaved[n][1]){
if(uid[2] == cardSaved[n][2]){
if(uid[3] == cardSaved[n][3]){return n;}
}
}
}
}
return -2;
}
#endif
return -1;
}
char getKey(){
int aReadK = analogRead(keybPin);
if(aReadK < 100){keyOld = 0;return 0;}
if(keyOld > 0){return 0;}
for(int i=0;i<16;i++){
if(aReadK > keybVals[i]-degKV/2 && aReadK < keybVals[i]+degKV/2){
if(i < 10){if(i+48 != keyOld){keyOld = i+48;return i+48;}else{return 0;}}else{
if(i == 10 && keyOld != 10){keyOld = 10;return 'A';}
if(i == 11 && keyOld != 11){keyOld = 11;return 'B';}
if(i == 12 && keyOld != 12){keyOld = 12;return 'C';}
if(i == 13 && keyOld != 13){keyOld = 13;return 'D';}
if(i == 14 && keyOld != 14){keyOld = 14;return '*';}
if(i == 15 && keyOld != 15){keyOld = 15;return '#';}
}
}
}
return 0;
}
void beep(int del){tone(beepPin, 230, del);}
Неверный код:
Неверная карта:
Правильный код:
Правильная карта: