Электрический замок с RFID - dimaatmelodromru/techdoc GitHub Wiki

Система доступа в помещение по коду и карточкам

Данная схема реализует доступ в помещение по коду или карточкам. В нормальном состоянии замок закрыт и на экране это написано. Если к картридеру прикладывается правильная карта или вводится верный код, то звучит звуковой сигнал, и открывается замок. Новые карточки или новый код можно зарегистрировать через компьютер.

Технические характеристики RFID MFRC522

  • Напряжение питания: 3.3V;
  • Потребляемый ток :13-26mA;
  • Рабочая частота: 13.56MHz;
  • Дальность считывания: 0 - 60 мм;
  • Интерфейс: SPI, I2C;
  • Скорость передачи: максимальная 10МБит/с;
  • Размер: 30мм х 30мм.

Технические характеристики RFID PN532

  • Микросхема: PN532;
  • Логика: КМОП, 3.3В;
  • Напряжение питания: 3.3-5В;
  • Максимальный потребляемый ток: 150 мА;
  • Потребляемый ток в режиме ожидания: 100 мА;
  • Потребляемый ток в режиме считывания: 120 мА;
  • Потребляемый ток в режиме записи: 120 мА;
  • Дальность считывания: 5 - 7 см;
  • Антенна: встроенная, на плате;
  • Размеры: 42.7 х 40.4 мм.

Пример готового проекта:

Нам понадобятся:

  1. Экран LCD1602
  2. RFID- MFRC522 или PN532
  3. Клавиатура 4х4
  4. Arduino UNO
  5. Buzzer
  6. Electromagnetic lock
  7. Соединительные провода

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 IDE для платы Arduino UNO

Программирование новой карты доступа и кода

Подлключите 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);}

Результаты

Неверный код:

Неверная карта:

Правильный код:

Правильная карта:

⚠️ **GitHub.com Fallback** ⚠️