RFID-модуль RC522 — электронный замок (2) (Arduino)

Радиочастотная идентификация (RFID) — это технология бесконтактной идентификации объектов при помощи радиочастотного канала связи. Иными словами, это способ опознания объектов, при котором радиосигналы записывают или считывают информацию, хранящуюся на RFID-метках (ещё их называют трансподерами).

RFID относится к беспроводной системе, состоящей из двух компонентов: метки и считывателя. Считыватель – это устройство, которое имеет одну или несколько антенн, которые излучают радиоволны и принимают сигналы обратно от RFID-метки.

RFID-метки могут хранить различную информацию от одного серийного номера до нескольких страниц данных.

В Arduino в качестве считывателя используют популярный модуль RFID-RC522. Модуль выполнен на микросхеме MFRC522 фирмы NXP, которая обеспечивает работу с метками HF (на частоте 13,56 МГц). В комплекте с модулем RFID-RC522 идут две метки, одна в виде карты, другая в виде брелока.

На основе RFID-модуля RC522 можно сделать простой электронный замок который будет управлять работой например электромагнитного замка или другим исполнительным механизмом.

Индикация RFID-меток происходит путем считывания ID UID (уникальный индефикационный номер). Таким образом UID позволяет отличить две с виду идентичные метки. UID как правило состоит из 4х байт, свободно считывается.

Ранее в http://rcl-radio.ru/?p=50041 был описан пример создания электронного замка при помощи RFID-модуля RC522, в нем необходимо было заранее в скетч записать несколько номеров UID RFID-меток, которые так же необходимо было заранее считать с RFID-меток. В этой статье будет рассмотрен пример электронного замка с возможностью занесения и стирания UID RFID-меток без предварительной их записи их в скетч.

Как и ранее в http://rcl-radio.ru/?p=50041 в скетч необходимо записать UID RFID-мету, но только одну, назовем ее мастер-метка. При помощи одной мастер-метки программно в процессе работы электронного замка можно добавить в память до 50 UID RFID-меток, а так же, то же программно удалить из памяти ненужную UID RFID-метку. Так как необходимы определенные действия в памятью (EEPROM), то для визуализации работы с памятью необходим дисплей, а так же 2 кнопки. Дисплей и две кнопки необходимы для добавления и стирания UID RFID-меток, поэтому они могут располагаются в недоступной для общего доступа части электронного замка. В доступной части расположен считыватель меток и два светодиода отображающие режим работы электронного замка.

Схема электронного замка

В памяти микроконтроллера содержаться несколько UID RFID-меток, при поднесении UID RFID-мети к считывателю ID UID метки считывается и сравнивается с содержимым памяти, если есть совпадение, то на 3 секунды загорается светодиод «open» (на выходе D4 появляется лог 1), звучит звуковой сигнал и на дисплее появляться надпись «OPEN». Если совпадение не обнаружено, то на 3 секунды загорается светодиод «closed» (на выходе D4 лог 0), звучит звуковой сигнал (но более короткий) и на дисплее появляться надпись «ERROR».

Для добавления UID RFID-меток в память (EEPROM) необходимо нажать и удерживать кнопку UP/SAVE и поднести мастер-метку, далее на дисплее появится надпись «OK» и произойдет переход в меню добавления UID RFID-меток. Кнопками UP или DW выберите любой свободный (все нули) адрес памяти и поднесите RFID-метку  ID адрес которой необходимо записать. Далее адрес RFID-метки появится на экране дисплея. Для выхода из меню необходимо подождать 20 секунд не нажимая ни одной кнопки.

Чтобы мастер-метка могла открывать электронный замок ее ID UID так же необходимо занести в память.

Для стирания UID RFID-метки необходимо нажать и удерживать кнопку DW/CLEAR и поднести мастер-метку, далее на дисплее появится надпись «OK» и произойдет переход в меню стирания UID RFID-меток. Кнопками UP или DW выберите любой ID метки и поднесите мастер-метку для стирания ID UID.

Для выхода из меню необходимо подождать 20 секунд не нажимая ни одной кнопки.

Номер UID мастер-метки и других меток доступны в мониторе порта:

В примере использовалась плата разработчика на базе микроконтроллера LGT8F328 (LGT8F328P-LQFP32 MiniEVB) — http://rcl-radio.ru/?p=129966.

Скетч

#include <SPI.h>
#include <MFRC522.h>           // http://rcl-radio.ru/wp-content/uploads/2024/08/rfid-master.zip
#include <EEPROM.h>
#include <Wire.h> 
#include <U8glib.h>            // https://github.com/olikraus/u8glib/

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);
 
int x;
int uid[4];
int master_kart[4]{129,71,80,131}; 
int set,eeprom; 
unsigned long times,times_open,tim; 
bool open_,tim1; 

 
MFRC522 mfrc522(10,9); //(SS_PIN, RST_PIN)   
 
void setup() {
  Serial.begin(9600); 
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);  
  if(EEPROM.read(500)!=0){for(int i=0;i<501;i++){EEPROM.update(i,0);}}              
  SPI.begin();              
  mfrc522.PCD_Init();      
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(7,OUTPUT);// zummer
  digitalWrite(7,HIGH);
}
 
void loop() {
// Чтение UID //////////////////////////////////////////////////////////////////////////////////
  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()){delay(100);x=0; 
  
   for (int i = 0; i < 4; i++) {
      uid[i] = mfrc522.uid.uidByte[i];
      if(uid[i]==master_kart[i]){
        x++;
      }}}
      else{cl();}
////////////////////////////////////////////////////////////////////////////////////////////////
      
//set ==0 read, set == 1 SAVE, set == 2 clear
   if(x==4 && digitalRead(2)==LOW && uid[0]!=0 && set==0){set=1;ok();times=millis();cl();delay(2000);}
   if(x==4 && digitalRead(3)==LOW && uid[0]!=0 && set==0){set=2;ok();times=millis();cl();delay(2000);}

   
  if(set>0){
    if(digitalRead(2)==LOW){eeprom++;if(eeprom>49){eeprom=49;}times=millis();delay(200);}
    if(digitalRead(3)==LOW){eeprom--;if(eeprom<0){eeprom=0;}times=millis();delay(200);}
    }  
////////////////////////////////////////////////////////////////////////////////////////////////  
  if(uid[0]!=0 && uid[1]!=0 && uid[2]!=0 && uid[3]!=0){
  Serial.print("UID: "); 
  for(int i1=0;i1<4;i1++){Serial.print(uid[i1]);Serial.print(" ");}Serial.println();}
////////////////////////////////////////////////////////////////////////////////////////////////

  u8g.firstPage();  
   do {
///////////////////////////////////////////////////////////////////////////// 
  if(set==1){
    u8g.setFont(u8g_font_profont17r);u8g.drawStr(0,12,"SAVE UID");
    u8g.setFont(u8g_font_profont12r);
    u8g.drawLine(0, 17, 128, 17);
    u8g.drawStr(0,45,"UID:");
    u8g.drawStr(0,30,"Number:");u8g.setPrintPos(50, 30);u8g.print(eeprom);

    if(uid[0]!=0 && uid[1]!=0 && uid[2]!=0 && uid[3]!=0){
      EEPROM.update(0+eeprom*4,uid[0]);
      EEPROM.update(1+eeprom*4,uid[1]);
      EEPROM.update(2+eeprom*4,uid[2]);
      EEPROM.update(3+eeprom*4,uid[3]);
      }
      
    u8g.setPrintPos(30, 45);u8g.print(EEPROM.read(0+eeprom*4));
    u8g.setPrintPos(55, 45);u8g.print(EEPROM.read(1+eeprom*4));
    u8g.setPrintPos(80, 45);u8g.print(EEPROM.read(2+eeprom*4));
    u8g.setPrintPos(105, 45);u8g.print(EEPROM.read(3+eeprom*4));
    }
////////////////////////////////////////////////////////////////////////////
  if(set==2){
    u8g.setFont(u8g_font_profont17r);u8g.drawStr(0,12,"CLEAR UID");
    u8g.setFont(u8g_font_profont12r);
    u8g.drawLine(0, 17, 128, 17); 
    u8g.drawStr(0,45,"UID:");
    u8g.drawStr(0,30,"Number:");u8g.setPrintPos(50, 30);u8g.print(eeprom);

    if(uid[0]==master_kart[0]&&uid[1]==master_kart[1]&&uid[2]==master_kart[2]&&uid[3]==master_kart[3]){
      EEPROM.update(0+eeprom*4,0);
      EEPROM.update(1+eeprom*4,0);
      EEPROM.update(2+eeprom*4,0);
      EEPROM.update(3+eeprom*4,0);
      }

    u8g.setPrintPos(30, 45);u8g.print(EEPROM.read(0+eeprom*4));
    u8g.setPrintPos(55, 45);u8g.print(EEPROM.read(1+eeprom*4));
    u8g.setPrintPos(80, 45);u8g.print(EEPROM.read(2+eeprom*4));
    u8g.setPrintPos(105, 45);u8g.print(EEPROM.read(3+eeprom*4));
    }

//////////////////////////////////////////////////////////////////////////////  
  if(set==0){
  u8g.setFont(u8g_font_profont17r);   
  if(uid[0]!=0 && uid[1]!=0 && uid[2]!=0 && uid[3]!=0 && millis()-times_open>3000){
    for(int i=0;i<50;i++){
     if(
      uid[0]==EEPROM.read(0+i*4)&&
      uid[1]==EEPROM.read(1+i*4)&&
      uid[2]==EEPROM.read(2+i*4)&&
      uid[3]==EEPROM.read(3+i*4))
      {open_=1;times_open=millis();tim=millis();break;}else{open_=0;times_open=millis();tim1=1;}
      }
    }
  }//set=0
  
  if(tim1==1){tim1=0;digitalWrite(7,LOW);delay(100);digitalWrite(7,HIGH);}
  
  if(open_==1 && millis()-times_open<3000){u8g.drawStr(40,30,"OPEN");digitalWrite(4,HIGH);
  if(millis()-tim<200){digitalWrite(7,LOW);}
  if(millis()-tim>200){digitalWrite(7,HIGH);}
  if(millis()-tim>400){tim=millis();}
  } else{digitalWrite(4,LOW);digitalWrite(7,HIGH);}
   
  if(open_==0 && millis()-times_open<3000){u8g.drawStr(35,30,"ERROR");digitalWrite(5,HIGH);}
   else{digitalWrite(5,LOW);}
  
  } while( u8g.nextPage() );
 
 if(millis()-times>20000){set=0;eeprom=0;}
}

void ok(){
    u8g.firstPage();  
   do {
    u8g.setFont(u8g_font_profont17r); 
    u8g.drawStr(55,30,"OK");
  } while( u8g.nextPage() );
  }

void cl(){uid[0]=0;uid[1]=0;uid[2]=0;uid[3]=0;}  

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=10620#p10620


RFID-RC522 + LCD1602_I2C

Ниже показан скетч где вместо OLED дисплея применен LCD1602 с модулем I2C. Функционал электронного замка с использованием LCD1602 аналогичен первому варианту примера.

Скетч

#include <SPI.h>
#include <MFRC522.h>           // http://rcl-radio.ru/wp-content/uploads/2024/08/rfid-master.zip
#include <EEPROM.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1 

LiquidCrystal_I2C lcd(0x27,16,2);
 
int x;
int uid[4];
int master_kart[4]{129,71,80,131}; 
int set,eeprom; 
unsigned long times,times_open,tim; 
int open_,tim1; 

 
MFRC522 mfrc522(10,9); //(SS_PIN, RST_PIN)   
 
void setup() {
  Serial.begin(9600); 
  lcd.init();lcd.noBacklight();lcd.clear();
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);  
  if(EEPROM.read(500)!=0){for(int i=0;i<501;i++){EEPROM.update(i,0);}}              
  SPI.begin();              
  mfrc522.PCD_Init();      
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(7,OUTPUT);// zummer
  digitalWrite(7,HIGH);
}
 
void loop() {
// Чтение UID //////////////////////////////////////////////////////////////////////////////////
  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()){delay(200);x=0; 
   for (int i = 0; i < 4; i++) {uid[i] = mfrc522.uid.uidByte[i];if(uid[i]==master_kart[i]){x++;}}}
    else{cl();}
////////////////////////////////////////////////////////////////////////////////////////////////
      
//set ==0 read, set == 1 SAVE, set == 2 clear
   if(x==4 && digitalRead(2)==LOW && uid[0]!=0 && set==0){set=1;lcd.clear();ok();times=millis();cl();delay(2000);}
   if(x==4 && digitalRead(3)==LOW && uid[0]!=0 && set==0){set=2;lcd.clear();ok();times=millis();cl();delay(2000);}

  if(set>0){
    if(digitalRead(2)==LOW){lcd.clear();eeprom++;if(eeprom>49){eeprom=49;}times=millis();delay(200);}
    if(digitalRead(3)==LOW){lcd.clear();eeprom--;if(eeprom<0){eeprom=0;}times=millis();delay(200);}
    }  
////////////////////////////////////////////////////////////////////////////////////////////////  
  if(uid[0]!=0 && uid[1]!=0 && uid[2]!=0 && uid[3]!=0){
  Serial.print("UID: "); 
  for(int i1=0;i1<4;i1++){Serial.print(uid[i1]);Serial.print(" ");}Serial.println();}
////////////////////////////////////////////////////////////////////////////////////////////////
  if(set==1){
    lcd.backlight();
    lcd.setCursor(0, 0);lcd.print("SAVE  UID|NUM:");
    lcd.setCursor(14, 0);lcd.print(eeprom);
   
    if(uid[0]!=0 && uid[1]!=0 && uid[2]!=0 && uid[3]!=0){lcd.clear();
      EEPROM.update(0+eeprom*4,uid[0]);
      EEPROM.update(1+eeprom*4,uid[1]);
      EEPROM.update(2+eeprom*4,uid[2]);
      EEPROM.update(3+eeprom*4,uid[3]);
      }
      
    lcd.setCursor(0, 1);lcd.print(EEPROM.read(0+eeprom*4));lcd.print(".");
    lcd.setCursor(4, 1);lcd.print(EEPROM.read(1+eeprom*4));lcd.print(".");
    lcd.setCursor(8, 1);lcd.print(EEPROM.read(2+eeprom*4));lcd.print(".");
    lcd.setCursor(12, 1);lcd.print(EEPROM.read(3+eeprom*4));
    }
////////////////////////////////////////////////////////////////////////////
  if(set==2){
    lcd.backlight();
    lcd.setCursor(0, 0);lcd.print("CLEAR UID|NUM:");
    lcd.setCursor(14, 0);lcd.print(eeprom);

    if(uid[0]==master_kart[0]&&uid[1]==master_kart[1]&&uid[2]==master_kart[2]&&uid[3]==master_kart[3]){lcd.clear();
      EEPROM.update(0+eeprom*4,0);
      EEPROM.update(1+eeprom*4,0);
      EEPROM.update(2+eeprom*4,0);
      EEPROM.update(3+eeprom*4,0);
      }

    lcd.setCursor(0, 1);lcd.print(EEPROM.read(0+eeprom*4));lcd.print(".");
    lcd.setCursor(4, 1);lcd.print(EEPROM.read(1+eeprom*4));lcd.print(".");
    lcd.setCursor(8, 1);lcd.print(EEPROM.read(2+eeprom*4));lcd.print(".");
    lcd.setCursor(12, 1);lcd.print(EEPROM.read(3+eeprom*4));
    }
//////////////////////////////////////////////////////////////////////////////  
  if(set==0){
  if(uid[0]!=0 && uid[1]!=0 && uid[2]!=0 && uid[3]!=0){ for(int i=0;i<50;i++){
  if(uid[0]==EEPROM.read(0+i*4)&&uid[1]==EEPROM.read(1+i*4)&&uid[2]==EEPROM.read(2+i*4)&&uid[3]==EEPROM.read(3+i*4)){open_=1;break;}else{open_=2;}}}}//set=0
 
  if(open_==1){open_=0;lcd.backlight();lcd.setCursor(6, 0);lcd.print("OPEN");digitalWrite(4,HIGH);
  for(int n=0;n<8;n++){digitalWrite(7,LOW);delay(200);digitalWrite(7,HIGH);delay(200);}
  lcd.noBacklight();lcd.clear();digitalWrite(4,LOW);digitalWrite(7,HIGH);}
   
  if(open_==2){open_=0;lcd.backlight();lcd.setCursor(5, 0);lcd.print("ERROR");digitalWrite(5,HIGH);
  digitalWrite(7,LOW);delay(100);digitalWrite(7,HIGH);delay(3000);digitalWrite(5,LOW);lcd.noBacklight();lcd.clear();}
 
  if(millis()-times>10000){lcd.noBacklight();lcd.clear();set=0;eeprom=0;}
}

void ok(){ lcd.backlight();lcd.setCursor(0, 0);lcd.print("OK");}

void cl(){uid[0]=0;uid[1]=0;uid[2]=0;uid[3]=0;}  

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=10625#p10625

Добавить комментарий

Войти с помощью: