RFID Kit RC522 with Reader, Chip and Card for Arduino and Raspberry Pi Microcontrollers

Today it's about RFID, i.e. radio frequency identification. This makes it possible to identify the relevant transponder, or tag, contactlessly. The transponder has a microchip, but no power supply of its own. It is designed as a card or key ring. The reader builds up a high-frequency electromagnetic field. If a transponder comes into this field, it takes energy from this field for its own power supply. After the microchip has enough voltage, it starts a program and sends its hard-coded identification number. The transponder does not create its own electromagnetic field for data transmission, but influences the field of the reader. This recognizes this influence and can receive the data.

The system in today's offer works at 13.56 MHz. The microchip in the cards and key fobs can not only send its 4-byte identification number. It also has a memory that can store 1024 bytes. This data can be sent from the reader to the card and read from there again. The control of the reader uses the SPI (Serial Peripheral Interface) bus to communicate with the microcontroller.

We want to implement a simple access system as a sample project. Next to the RFID reader from today's offer we need a microcontroller for control. We use the Nano V3.0 We also need one RGB LED or three LEDs with a series resistor for display, a relay, for example, to operate a door opener and a button to completely delete the stored data if necessary.

The wiring is a little more extensive in this project, because four lines are required for the SPI bus alone.

 


The SPI connections are on the Nano V3.0 D12 for MOSI (Master Out, Slave In), D11 for MISO (Master In, Slave Out), D10 for ChipSelect SDA (Select Data Access) and D13 for the SCK (Serial Clock). The connection D9 is connected to RST (reset) to reset the reader. And finally, GND and 3.3V. The reader may only be operated with 3.3V!

The RGB-LED module has an RGB-LED with series resistors so that the anodes can be connected directly to the outputs of the Nano Microcontroller. The RGB-LED has a common cathode that is connected to GND. Since the green LED in particular is much brighter than the other, the LEDs should be controlled with PWM (Pulse Width Modulation). Not all connections of the Nano V3.0 are PWM capable. We connect the red LED to D3, the green LED to D5 and the blue LED to D6. D4 cannot be used for PWM.

The relay needs a supply voltage of 5V. We connect GND to GND and Vcc to 5V on the Nano Microcontroller. We use D7 on the Nano V3.0 for control.
With the button we switch a connection between D8 and GND. The program is designed in such a way that if D8 is on GND when starting, the internal EEPROM of the Nano V3.0 is deleted. This process should be carried out once during the initial start-up to ensure that the situation is clear.

For the program we need the library for the MFRC522 reader. We can install these via the library management. We enter MRFC522 as the search term.

 


The other libraries for the SPI bus (SPI.h) and for controlling the EEPROM (EEPROM.h) are already installed in the Arduino IDE. So we can enter the sketch and compile it.

sketch:

#include <SPI.h> //Bibliothek für SPI-Bus
#include <MFRC522.h> //Bibliothek für MFRC522 RFID Chip
#include <EEPROM.h> //Bibliothek für den internen EEPROM

#define SS_PIN 10 //Chipselect Pin
#define RST_PIN 9 //Reset Pin

#define LED_RED 3 //Anode rote LED
#define LED_GREEN 5 //Anode grüne LED
#define LED_BLUE 6 //Anode blaue LED

#define RELAIS 7 //Ansteuerung Relais
#define ERASE 8 //Taster zum Löschen

//Status Zustände
#define ST_WAIT 0 //Wartezustand alle LED aus
#define ST_MASTER 1 //Warten auf neuen Master LED blau
#define ST_ADD 2 //Unbekannte Karte hinzufügen LED gelb
#define ST_DEL 3 //Bekannte Karte löschen LED cyan
#define ST_ALLOW 4 //Zutritt erlaubt LED grün
#define ST_DENY 5 //Zutritt verweigert LED rot
#define ST_MASTERDEL 6 //Master löschen LED pink

//Instanz für Reader Interface
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class

uint32_t cardId; //letzte gelesene Karten ID
int16_t cardIndex; //Index der Karte im Speicher
uint32_t masterId; //ID der Masterkarte
uint32_t lastAction; //Zeitstempel der letzten Aktion
uint8_t status; //aktueller Status

//Details des RFID Lesers zur Info anzeigen
void ShowReaderDetails() {
// Get the MFRC522 software version
byte v = rfid.PCD_ReadRegister(rfid.VersionReg);
Serial.print(F("MFRC522 Software Version: 0x"));
Serial.print(v, HEX);
if (v == 0x91)
Serial.print(F(" = v1.0"));
else if (v == 0x92)
Serial.print(F(" = v2.0"));
else
Serial.print(F(" (unknown),probably a chinese clone?"));
Serial.println("");
// When 0x00 or 0xFF is returned, communication probably failed
if ((v == 0x00) || (v == 0xFF)) {
Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
Serial.println(F("SYSTEM HALTED: Check connections."));
while (true); // do not go further
}
}

//die Funktion liest die vier Bytes einer Karten ID und gibt
//sie als 32-Bit Integer zurück
uint32_t getId() {
uint32_t res = 0;
uint8_t tmp[4];
// Wurde eine neue Karte gelesen?
if ( ! rfid.PICC_IsNewCardPresent()) {
return 0; //nein return 0
}
  // read card id
  if (! rfid.PICC_ReadCardSerial ()) {
    return 0; // not successful return 0
  }
Serial.println(F("Scanned PICC's UID:"));
for ( uint8_t i = 0; i < 4; i++) { //
//byteorder umdrehen für 32-bit Integer
tmp[3-i] = rfid.uid.uidByte[i];
}
rfid.PICC_HaltA(); // Lesen beenden
res = *((unsigned long*)tmp);
Serial.print("Result: ");
Serial.println(res);
return res;
}

//Laesst eine bestimmte LED blinken
//led = Pinnummer, cnt = wie oft, val = Helligkeit
void blinkLED(uint8_t led, uint8_t cnt, uint8_t val) {
for (uint8_t i = 0; i<cnt; i++) {
analogWrite(led,val);
delay(200);
digitalWrite(led,0);
delay(200);
  }
}

//Schaltet alle LEDs aus
void allOff() {
analogWrite(LED_RED,0);
analogWrite(LED_GREEN,0);
analogWrite(LED_BLUE,0);
}

//Sucht eine bestimmte ID im EEPROM und gibt den Index
//zurück oder -1 wenn die ID nicht gefunden wurde
int16_t findId(uint32_t id) {
uint16_t max = (EEPROM.length() - 6) / 4;
uint16_t i = 0;
boolean found = false;
uint32_t data;
while ((i<max) && !found) {
EEPROM.get(i*4+6,data);
found = (data == id);
if (!found) i++;
}
Serial.println(found);
if (found) return i*4+6; else return -1;
}

//Sucht eine den nächsten freien Platz im EEPROM und gibt den Index
//zurück oder -1 wenn kein Platz mehr ist
int16_t findEmpty() {
uint16_t max = (EEPROM.length() - 6) / 4;
uint16_t i = 0;
boolean found = false;
uint32_t data;
while ((i<max) && !found) {
EEPROM.get(i*4+6,data);
found = (data == 0);
if (!found) i++;
}
if (found) return i*4+6; else return -1;
}

//Schaltet das Relais ein oder aus
void relais(boolean on) {
digitalWrite(RELAIS,!on); //wird ein anderes Relais benutzt,
//muss eventuell das NOT (!) entfallen
}

//Zeigt die Farben des aktuellen Status auf den LEDs an
void statusColorOn() {
Serial.print("Status ");
Serial.println(status);
allOff();
switch (status) {
//nur blau
case ST_MASTER: analogWrite(LED_BLUE,255); break;
//grün und rot = gelb
case ST_ADD: analogWrite(LED_GREEN,30); analogWrite(LED_RED,255); break;
//blau und grün = cyan
case ST_DEL: analogWrite(LED_BLUE,255); analogWrite(LED_GREEN,70); break;
//nur grün
case ST_ALLOW: analogWrite(LED_GREEN,50); break;
//nur rot
case ST_DENY: analogWrite(LED_RED,255); break;
//blau und rot = magenta
case ST_MASTERDEL: analogWrite(LED_BLUE,255);analogWrite(LED_RED,255); break;
  }
}

//Eine Karte wurde gelesen und soll ausgewertet werden
void gotCard(uint32_t id){
switch (status) {
//Wartezustand Masterkarte öffnet sorfort die Tür
//wurde eine andere Karte im Speicher gefunden, kann sie mit der Masterkarte gelöscht werden
//wurde eine andere Karte nicht im Speicher gefunden, kann sie mit der Masterkarte hinzugefügt werden
  case ST_WAIT: if (id==masterId) {
      status = ST_ALLOW;
relais(true);
} else {
cardIndex = findId(id);
cardId = id;
if (cardIndex>=0) {
Serial.print("ID gefunden Index = ");
Serial.println(cardIndex);
status = ST_DEL;
} else {
Serial.println("ID nicht gefunden");
status = ST_ADD;
          }
        }
       break;
//Zustand ist warten auf eine neue Masterkarte. gelesene ID = MasterID
case ST_MASTER: masterId = id;
  EEPROM.write(1,197);
EEPROM.put(2,masterId);
Serial.print("Master ID = ");
Serial.println(masterId);
status = ST_WAIT;
break;
 //wurde die MasterId gelesen wird eine Karte die nicht im Speicher war gespeichert
//danach wird die Tür geöffnet
case ST_ADD: if (id == masterId) {
  int16_t ix = findEmpty();
if (ix>=0) {
Serial.print("Addiere ID ");
Serial.print(cardId);
Serial.print(" Index = ");
Serial.println(ix);
EEPROM.put(ix,cardId);
status = ST_ALLOW;
relais(true);
}
} else {
status = ST_DENY;
relais(false);
}
break;
//wurde die MasterId gelesen wird eine Karte die im Speicher war gelöscht
//danach wird der Zutritt verweigert
case ST_DEL: if ((id == masterId) && (cardIndex >= 0)) {
  Serial.print("Lösche ID ");
Serial.println(cardIndex);
EEPROM.put(cardIndex,long(0));
status = ST_DENY;
relais(false);
} else {
status = ST_ALLOW;
relais(true);
}
break;
//wurde die MaterID gelesen, wird die MasterID gelöscht
//es kann eine andere Karte als Master gespeichert werden
 case ST_MASTERDEL: if (id == masterId) {
  EEPROM.put(2,long(0));
EEPROM.write(1,0);
Serial.println("Lösche Master");
status = ST_MASTER;
relais(false);
}
break;

  }
  statusColorOn();
lastAction = millis(); 
}

//3 Sekunden seit der letzten Aktion sind vergangen
void handleTimeout() {
switch (status) {
  //ungültige Karte, Zutritt verweigern
case ST_ADD: status = ST_DENY;
    relais(false);
break;
  //gültige Karte, Zutritt erlauben
case ST_DEL: status = ST_ALLOW;
    relais(true);
break;
  //sonst immer Zutritt verweigern
default: status = ST_WAIT;
      relay (false);
  }
statusColorOn ();
lastAction = millis ();
}

//Set up
void setup () {
  Serial.begin (9600);
//Pins als Output oder Input definieren
  pinMode (LED_RED, OUTPUT);
  pinMode (LED_GREEN, OUTPUT);
  pinMode (LED_BLUE, OUTPUT);
  pinMode (RELAIS, OUTPUT);
  pinMode (ERASE, INPUT_PULLUP);
//Relais abschalten
relais(false);
//LEDs der Reihe nach zum Test blinken lassen
  blinkLED (LED_RED, 3.255);
  blinkLED (LED_GREEN, 3.50);
  blinkLED (LED_BLUE, 3.255);
//SPI und RFID Leser starten
  SPI.begin ();
  rfid.PCD_Init ();
//Startmeldung und Info zum Reader ausgeben
  Serial.println ("Adventblog 13.12.2020");
  ShowReaderDetails ();
//Falls die Taste gedrückt wurde, den EEPROM loschen
  if (digitalRead (ERASE) == 0) {
  Serial.print("Lösche EEPROM" );
Serial.print(EEPROM.length());
Serial.println(" Bytes");
for (int i = 0 ; i < EEPROM.length() ; i++) {
EEPROM.write(i, 0);

    }
  }
 //die ersten 16 gespeicherten Karten anzeigen
for (uint16_t i = 0; i <16; i ++) {
  EEPROM.get (i * 4 + 6, cardId);
  Serial.print (i * 4 + 6);
  Serial.print ("=");
  Serial.println (cardId);
}

//haben wir eine Master Card ?
if (EEPROM.read (1) == 197) {
Serial.println("Wir haben eine Master Id");
EEPROM.get(2,masterId);
status = ST_MASTERDEL; //das Löschen der Masterkarte ermöglichen
statusColorOn();
} else {
Serial.println("Wir haben keine Master Id");
  masterId = 0;
status = ST_MASTER; //auf die ID einer Karte warten und
//diese als Master speichern
statusColorOn ();
  }
//Zeitstempel zurücksetzen
  lastAction = millis ();
}

void loop () {
  uint32_t tmpId;
tmpId = getId(); //KartenId abfragen
//Wurde eine Karte gelesen, so wird die Nummer ausgewertet
if (tmpId > 0) gotCard(tmpId);
  //Sind 3 Sekunden abgelaufen wir dein Timeout bearbeitet
//Ausnahme der Wartezustand und das Warten auf eine Masterkarte
//bei diesen Zuständen gibt es kein Timeout
  if ((status! = ST_WAIT) && (status! = ST_MASTER) && ((millis () - lastAction)> 3000)) handleTimeout ();
}

Download sketch

Functionality:

When starting for the first time, the delete button should be pressed so that the EEPROM is deleted. When starting, the three LEDs flash three times as a control. If no master card has yet been saved, the LED shows blue. A master card can now be set by holding this card in front of the reader. If the card has been read, the LED changes to green and the relay picks up. The read ID is saved as a master. After three seconds the LED goes out and the relay drops out.

If a master card was already saved when starting, it will be used. The LED shows magenta. In this state, the master card can be deleted by holding it in front of the reader. If the deletion was successful, the LED changes to blue and a new master card can be read.

The LED is off in the waiting state. If a card is read that has not yet been saved, the LED turns yellow. You now have three seconds to validate the unknown card with the master card. If this action is successful, the LED changes to green and the relay picks up. If the unknown card is not confirmed with the master card, the LED turns red and the relay does not pick up.

If a card is read that has already been saved, the LED goes to cyan. You now have three seconds to delete the saved card with the master card. If this action is successful, the LED changes to red and the relay does not pick up. If the saved card is not deleted with the master card, the LED turns green and the relay picks up.

After three seconds the green LED goes out again and the relay drops out. The same thing happens with the red LED.

Have fun with the replica.

Specials

2 comments

Andreas Wolter

Andreas Wolter

@Roberto Pinto: please check the datasheet: https://cdn.shopify.com/s/files/1/1509/1638/files/RFID_RC522_Set_mit_Reader_Chip_und_Card_13_56MHz_Datenblatt.pdf?2098853292011892896

I think it doesn’t support it.

roberto pinto

roberto pinto

does it work with DESFIRE cards?

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN