Arduino RFID Tutorial: Complete RC522 Guide with Code & Projects

Published  May 18, 2022   0
Arduino RC522 RFID Reader Module Project

This comprehensive Arduino RFID tutorial teaches you how to interface RFID (Radio Frequency Identification) technology with Arduino microcontrollers using the popular RC522 RFID module. Arduino RFID systems are revolutionizing DIY electronics projects, enabling makers to build professional-grade access control systems, inventory tracking solutions, and security applications. Whether you're creating an Arduino RFID door lock, attendance system, or product identification project, this guide provides complete wiring diagrams, code examples, and practical implementations to get your Arduino RFID project running successfully.

What will you learn?

This tutorial covers complete RC522 module interfacing, including wiring diagrams, pinout configurations, and SPI communication setup. Learn Arduino RFID programming with hands-on code examples for reading and writing RFID tags, plus authentication protocols. Build practical Arduino RFID projects like LED control systems and access control applications. Explore real-world Arduino RFID implementations, including door locks, attendance systems, and inventory tracking solutions. Perfect for beginners and experienced makers looking to integrate RFID technology into their Arduino projects. This article was updated in May 2025, to ensure the code still works for all versions of Arduino, you can follow the same procedure for Arduino Uno, Arduino Nano and the latest Arduino UNO R4 modules as well. 

How Arduino RFID Systems Work

Arduino RFID technology works by using electromagnetic waves in the radio frequency spectrum for wireless communication and data transfer between RFID tags and readers. From supermarket anti-theft systems to automatic toll payment like FastTag, RFID applications are everywhere around us. With Arduino RFID projects, you can replicate these commercial applications at home - building everything from simple LED control systems to complex access control solutions. The RC522 RFID reader module makes Arduino RFID integration straightforward, supporting reading, writing, and authentication operations that we'll explore in this tutorial. After mastering these Arduino RFID fundamentals, you'll be ready to tackle advanced projects like our Arduino RFID door lock system.

The RFID system is comprised of two components: the RFID reader and the tags. They are also called PCD (Proximity Coupling Device) and PICC (Proximity Integrated Circuit Card). The RFID reader consists of an antenna to emit high-frequency EM waves and a reader/writer. MFRC522 from NXP is an example of such an integrated circuit. Since we are using high-frequency waves in the megahertz range, the size of the antenna can be small.

RFID Reader Module Working

The RFID tag can be either passive or active. Active tags are powered by batteries while the passive RFID tags are powered by energy from the reader’s interrogating EM waves. The tags are available in different forms or shapes like cards, tags, key forbs, or stickers. Whatever the shape, the RFID tag will consist of an antenna and the RFID chip, which will store all the data. When triggered by an electromagnetic interrogation pulse from a nearby RFID reader, the tag will transmit data back to the reader. The reader will then analyze this data to identify the tag. Unlike a barcode or a QR code, the tag does not need to be within the reader’s line of sight. This makes it easier to process and can be used for tracking objects in a closed space.

Arduino RFID RC522 Module Pinout and Pin Configuration

The RC522 module has a total of 8 pins. This module supports various communication protocols, and each pin has a different function for each communication protocol. The pinout of an RFID Reader module is as follows:

Arduino RFID RC522 module pinout diagram

SDA SCL I2C Communication pins. DATA and CLOCK.

SS SCK MOSI MISO SPI communication pins. Slave Select, Clock, MOSI, and MISO.

RX TX UART Communication pins.

IRQ  Interrupt signal from the module to indicate RFID tag detection.

GND Ground pin that needs to be connected to the GND pin on the Arduino.

RST Reset pin for the module

VCC Supply pin for the module. The supply voltage can be anywhere from 2.5V to 3.3V and must be connected to the 3.3V pin on the Arduino.

RFID Reader Module Description

The RC522 module consists of an MFRC522 RFID chip from NXP. It is clocked at 27.12MHz by the onboard crystal oscillator in the 49S package. The board also consists of the required EMI filter circuit and matching circuit. It also consists of a PCB antenna for communicating and energizing the RFID tags.

The Schematic diagram for the RC522 module is given below. The circuit consists of bare minimum components. As we know the main component is the MFRC522 chip. The remaining components form the EMI filter along with the matching circuit for the antenna.

RFID Reader Module Circuit

Commonly Asked Questions about RFID Reader

What is an RFID used for?

RFID tags are a type of tracking system that uses radio frequency to search, identify, track, and communicate with items and people.

What Arduino boards are compatible with RFID modules?

Most Arduino boards are compatible with RFID modules like RC522. Arduino Uno, Nano, Pro Mini, Mega, ESP32/ESP8266 nd even the Raspberry Pi and Pi Pico boards all work perfectly with  RFID modules. The RC522 operates at 3.3V but has 5V-tolerant pins, making it compatible with both 3.3V and 5V Arduino boards. Ensure your Arduino has SPI pins (MOSI, MISO, SCK, SS) for proper Arduino RFID communication.

How to power Arduino RFID projects?

Arduino RFID systems can be powered through USB (5V), an external power adapter (7-12V), or battery packs. The RC522 module requires 3.3V, so connect it to the Arduino's 3.3V pin, not 5V. For portable Arduino RFID projects, use 9V batteries or rechargeable Li-ion battery packs with voltage regulators. Power consumption is typically 50- 100mA for basic Arduino RFID setups.

What's the range of Arduino RFID systems?

Arduino RFID reading range depends on the module and tag type. RC522 modules typically read RFID tags within 2-5cm range for standard cards and key fobs. Larger RFID tags can extend this to 8-10cm. The range is limited by the 13.56MHz frequency and power output. For longer-range Arduino RFID applications, consider UHF RFID modules that can read tags up to several meters away.

Can Arduino RFID work without the internet?

Yes, Arduino RFID systems work completely offline without internet connection. RFID technology uses radio frequency communication between the reader and tags, requiring no network connectivity. Your Arduino RFID projects can store authorized tag IDs locally in the Arduino's memory or SD card. Internet is only needed if you want to log data to cloud servers or enable remote monitoring of your Arduino RFID system.

How to make RFID door lock using Arduino?

Make an RFID door lock using Arduino by combining our basic RFID Arduino setup with a relay module and an electric lock. Our comprehensive Arduino RFID door lock tutorial provides complete wiring diagrams and code for building a secure access control system.

Can Wi-Fi interfere with RFID?

Interference from other radio-frequency (RF) emitting devices (RFI), such as other RFID readers and Wi-Fi access points, can negatively impact RFID system performance.

How to connect RFID to Arduino?

Connect your RFID Arduino setup by wiring the RC522 module's VCC to Arduino's 3.3V pin, GND to GND, RST to pin 9, SS to pin 10, MOSI to pin 11, MISO to pin 12, and SCK to pin 13. This RFID Arduino connection uses SPI communication for reliable data transfer.

How to store data in RFID tag Arduino?

Store data in RFID tags using Arduino by authenticating the tag, then writing data to specific memory blocks using the MIFARE_Write() function. Our RFID Arduino code examples show how to write custom data to blocks 1 and 2 of the tag's 1KB memory.

How to find RFID tag number using Arduino?

Find RFID tag numbers with Arduino by reading the UID (Unique Identifier) using mfrc522.uid.uidByte[] array. Each RFID Arduino setup can read and display the 4-byte UID in hexadecimal format through the serial monitor.

How to make RFID reader using Arduino?

Make an RFID reader using Arduino by connecting the RC522 module, installing the MFRC522 library, and uploading our provided RFID Arduino code. This creates a functional RFID Arduino reader capable of reading cards and key fobs.

RC522 RFID Reader Module

The RC522 RFID module is based on the popular MFRC522 RFID reader chip from NXP. These modules are cheap and available from most online stores. MFRC522 is a highly integrated RFID reader/writer IC for contactless communication at 13.56 MHz. The MFRC522 reader supports ISO/IEC 14443 A/MIFARE and NTAG. The operating voltage of the RC522 module is 2.5V – 3.3V. Even though the maximum supply voltage is 3.3V the communication pins are 5V tolerant. So, we can connect the module directly to an Arduino without any Level-Shifters.

EC522 RFID Reader Module

The MFRC522 supports three different communication protocols:

  • SPI with Speed up to 10Mbit/s

  • I2C interface with speed up to 400kBd in Fast mode and up to 3400kBd in High-Speed mode

  • RS232 Serial UART with speed up to 1228.8kBd

Arduino RFID projects using RC522 typically include RFID cards and key fobs, each containing 1KB of memory for your Arduino RFID applications. We can not only read these tags but can also program these with the RC522 module. Here is the picture showing the tags along with the RC522 module.

RC522 RFID Reader Module with RFID Tag

Arduino RFID Wiring: RC522 Circuit Diagram and Connections

Setting up your Arduino RFID project requires proper wiring between the Arduino board and RC522 module.. For interfacing the RC522 RFID module with the Arduino, we will be using the SPI interface. Follow the circuit diagram and make the connections as per that.

Arduino RFID wiring circuit schematic

The VCC and GND pins of the module are connected to the 3.3V and GND pins of Arduino respectively. The Reset pin is connected to the D9 and SS, MOSI, MISO, and SCK pins are connected to the D10, D11, D12, and D13 pins of the Arduino respectively. The SS and RST pins are configurable and can be connected to any other digital pins on the Arduino.

RC522 RFID Arduino vs Other Modules

While RC522 is the most popular choice for RFID Arduino projects, several alternatives exist. The PN532 NFC RFID module offers NFC compatibility for smartphone integration, making it ideal for modern Arduino RFID applications. However, RC522 remains the best choice for beginners due to its affordability, extensive library support, and 13.56MHz frequency compatibility. For high-frequency Arduino RFID projects requiring longer range, consider UHF RFID modules, though they require more complex Arduino RFID programming.

ModuleFrequencyRangeBest For
RC52213.56MHz2-5cmBeginner RFID Arduino projects
PN53213.56MHz3-8cmNFC-enabled Arduino RFID systems
UHF RFID860-960MHz1-5mLong-range Arduino RFID applications

Arduino RFID Code: Complete Programming Guide for RC522

This Arduino RFID code demonstrates how to read and write data to RFID tags using the RC522 module.. As the connections are made, let’s look at the coding part. For that, we are going to use the MFRC522 Arduino Library by Miguel André Balboa. Since the library is not available in the Arduino library manager, download it from the MFRC522 GitHub repository and install it in the Arduino library folder. You can install it either through the Arduino IDE, by going to Sketch -> Include Library -> Add ZIP Library and selecting the downloaded .ZIP file, or by just simply extracting the Zip file into the Arduino library folder.

Download Arduino RFID Code from Github

Once the library is installed, we can test our setup with an example code. For that, open the DumpInfo example from the MFRC522 library. Here is the example code.

// Arduino RFID library initialization
#include <MFRC522.h>
// Arduino RFID pin definitions for RC522
#define RST_PIN 9
#define SS_PIN 10
MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
void setup() {
Serial.begin(115200);                       // Initialize serial communications with the PC
while (!Serial);                       // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
            SPI.begin();                             // Init SPI bus
            mfrc522.PCD_Init();              // Init MFRC522
            delay(4);                                             // Optional delay. Some board do need more time after init to be ready, see Readme
            mfrc522.PCD_DumpVersionToSerial();      // Show details of PCD - MFRC522 Card Reader details
            Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}
void loop() {
            // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
            if ( ! mfrc522.PICC_IsNewCardPresent()) {
                        return;
            }
            // Select one of the cards
            if ( ! mfrc522.PICC_ReadCardSerial()) {
                        return;
            }
            // Dump debug info about the card; PICC_HaltA() is automatically called
            mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

Once it’s compiled and uploaded to the Arduino, open the serial monitor and show any tag near the RC522 module. When the tag is in the vicinity, the reader will read all the data from the tag and will dump it into the serial monitor as shown below.

Arduino RFID Module Code

The data dump will contain all the details like Card UID, Card SAK, PICC type, and all the memory maps. The UID or Unique ID is Unique for each tag as the name suggests. If you get any communication failed error, that’s because our serial baud rate is too slow. Increase the baud rate to 115200 in the code and it will resolve the issue. Here in the data dump, we can see that the PICC type is MIFARE 1KB. That means the tag contains a MIFARE chip with a memory of 1KB.

Writing data to the RFID tag

Now that we have dumped the factory data from the tag, let’s see how we can write some data to the card. For that use the following code.

#include <SPI.h>      //include the SPI library
// Arduino RFID library initialization
#include <MFRC522.h>
// Arduino RFID pin definitions for RC522
#define RST_PIN 9  //reset pin, which can be changed to another digital pin if needed.
#define SS_PIN 10  //SS or the slave select pin, which can be changed to another digital pin if needed.
MFRC522 mfrc522(SS_PIN, RST_PIN);  // create a MFRC522 instant.
MFRC522::MIFARE_Key key;          //create a MIFARE_Key struct named 'key' to hold the card information
byte data1[14] = {"Circuit-Digest"};  //The first data that needs to be written to the tag.
byte data2[12] = {"Jobit-Joseph"};  //The second data that needs to be written to the tag.
byte readbackblock[18];  //Array for reading out a block.
void setup()
{
  Serial.begin(115200);        // Initialize serial communications with the PC
  SPI.begin();               // Init SPI bus
  mfrc522.PCD_Init();        // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
  Serial.println("Scan a MIFARE Classic card");
  for (byte i = 0; i < 6; i++)
  {
    key.keyByte[i] = 0xFF;  // Prepare the security key for the read and write operations.
  }
}
void loop()
{
  // Look for new cards if not found rerun the loop function
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  // read from the card if not found rerun the loop function
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  Serial.println("card detected. Writing data");
  writeBlock(1, data1); //write data1 to the block 1 of the tag
  writeBlock(2, data2); //write data2 to the block 2 of the tag
  Serial.println("reading data from the tag");
  readBlock(1, readbackblock);   //read block 1
  //print data
  Serial.print("read block 1: ");
  for (int j = 0 ; j < 14 ; j++)
  {
    Serial.write (readbackblock[j]);
  }
  Serial.println("");
  readBlock(2, readbackblock);  //read block 2
  //print data
  Serial.print("read block 2: ");
  for (int j = 0 ; j < 12 ; j++)
  {
    Serial.write (readbackblock[j]);
  }
  Serial.println("");
  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));//uncomment below line if want to see the entire memory dump.
}
//Write specific block
int writeBlock(int blockNumber, byte arrayAddress[])
{
  //check if the block number corresponds to data block or triler block, rtuen with error if it's trailer block.
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
  if (blockNumber > 2 && (blockNumber + 1) % 4 == 0) {
    Serial.print(blockNumber);
    Serial.println(" is a trailer block: Error");
    return 2;
  }
  //authentication
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Authentication failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" as error message
  }
  //writing data to the block
  status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);
  //status = mfrc522.MIFARE_Write(9, value1Block, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Data write failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.print("Data written to block ");
  Serial.println(blockNumber);
}
//Read specific block
int readBlock(int blockNumber, byte arrayAddress[])
{
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
  //authentication of the desired block for access
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Authentication failed : ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" as error message
  }
  //reading data from the block
  byte buffersize = 18;
  status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Data read failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.println("Data read successfully");
}

Once the code is compiled and uploaded, open the serial monitor. Then scan a tag with the module. The module will write two data to the tag and will read back once it’s written. This data will be then printed to the serial monitor. See the screenshot below.

Arduino RFID code output serial monitor

Code Explanation

In the first lines, we have included the necessary libraries and defined the reset and SS pins. Since we are using the SPI protocol, we have included the SPI library and then the MFRC522 library for the RFID reader. The reset and SS pins can be connected to any other digital pin. The users may change it at their convenience.

#include <SPI.h>      //include the SPI library
// Arduino RFID library initialization
#include <MFRC522.h>
// Arduino RFID pin definitions for RC522
#define RST_PIN 9  //reset pin, which can be changed to another digital pin if needed.
#define SS_PIN 10  //SS or the slave select pin, which can be changed to another digital pin if needed.

Next, we have created the objects for the RFID reader library and declared the data that’s needed to be written. Also, declared an array to hold the data that was read from the tag.

MFRC522 mfrc522(SS_PIN, RST_PIN);  // create a MFRC522 instant.
MFRC522::MIFARE_Key key;          //create a MIFARE_Key struct named 'key' to hold the card information
byte data1[14] = {"Circuit-Digest"};  //The first data that needs to be written to the tag.
byte data2[12] = {"Jobit-Joseph"};  //The second data that needs to be written to the tag.
byte readbackblock[18];  //Array for reading out a block.

In the setup() function, we have initialized the serial communication, SPI, and the RFID reader library. We have also cleared the key array with blank data for reading and writing operations.

void setup()
{
  Serial.begin(115200);        // Initialize serial communications with the PC
  SPI.begin();               // Init SPI bus
  mfrc522.PCD_Init();        // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
  Serial.println("Scan a MIFARE Classic card");
  for (byte i = 0; i < 6; i++)
  {
    key.keyByte[i] = 0xFF;  // Prepare the security key for the read and write operations.
  }
}

The function we are using to write data to the tag is the writeblock function. When this function is called, it will check if the provided block number corresponds to the data block or the trailer block. The trailer block will hold the Access Bit which controls the read and write access to the reaming blocks. Block number 3 is the trailer block. If the provided block number does not correspond to a data block, the function will return an error message. If it’s a data block, the function will authenticate the tag with a security key and if the authentication is successful, the data will be written to the corresponding block.

int writeBlock(int blockNumber, byte arrayAddress[])
{
  //check if the block number corresponds to data block or triler block, rtuen with error if it's trailer block.
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
  if (blockNumber > 2 && (blockNumber + 1) % 4 == 0) {
    Serial.print(blockNumber);
    Serial.println(" is a trailer block: Error");
    return 2;
  }
  //authentication
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Authentication failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status))
    return 3;//return "3" as error message
  }
  //writing data to the block
  status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);
  //status = mfrc522.MIFARE_Write(9, value1Block, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Data write failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.print("Data written to block ");
  Serial.println(blockNumber);
}

For reading data from the tag, we are using the readBlock function. It is similar to the write function. Once the function is called, it will determine the trailer block for the sector and then it will authenticate. If the authentication is successful, the function will read the data from the tag.

int readBlock(int blockNumber, byte arrayAddress[])
{
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
  //authentication of the desired block for access
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Authentication failed : ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" as error message
  }
  //reading data from the block
  byte buffersize = 18;
  status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Data read failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.println("Data read successfully");
}

In the loop function, the microcontroller will check if a tag is present or not periodically. If a tag is present and readable, the function will write two data arrays to the tag, and then it will read back and printed to the serial monitor.

void loop()
{
  // Look for new cards if not found rerun the loop function
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  // read from the card if not found rerun the loop function
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  Serial.println("card detected. Writing data");
  writeBlock(1, data1); //write data1 to the block 1 of the tag
  writeBlock(2, data2); //write data2 to the block 2 of the tag
  Serial.println("reading data from the tag");
  readBlock(1, readbackblock);   //read block 1
  //print data
  Serial.print("read block 1: ");
  for (int j = 0 ; j < 14 ; j++)
  {
    Serial.write (readbackblock[j]);
  }
  Serial.println("");
  readBlock(2, readbackblock);  //read block 2
  //print data
  Serial.print("read block 2: ");
  for (int j = 0 ; j < 12 ; j++)
  {
    Serial.write (readbackblock[j]);
  }
  Serial.println("");
  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));//uncomment below line if want to see the entire memory dump.
}

Arduino RFID LED Control Project

For this, connect an LED to the Arduino pin D8 through a current limiting resistor as shown below.

Arduino RFID project LED control setup

Arduino Code to Turn On or Off LED with RFID

Now let’s look at the code. The code is pretty simple. The RFID reader will check for any tags in the vicinity and if a tag is found, the reader will read the Unique ID from the tag. And if the UID matches with the UID in the code, the Arduino will toggle the LED state.

#include <SPI.h>
// Arduino RFID library initialization
#include <MFRC522.h>
// Arduino RFID pin definitions for RC522
#define SS_PIN 10
#define RST_PIN 9
#define LED 8
byte readCard[4];
String tag_UID = "39C3BB99";  // Replace this with the UID of your tag!!!
String tagID = "";
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
void setup()
{
  pinMode(LED, OUTPUT);// initialize digital pin LED_BUILTIN as an output.
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  Serial.begin(115200);        // Initialize serial communications with the PC
  SPI.begin(); // SPI bus
  mfrc522.PCD_Init(); // Initialise MFRC522
}
void loop()
{
  //Wait until new tag is available
  while (readID()
  {
    if (tagID == tag_UID)
    {
      digitalWrite(LED, !digitalRead(LED));  // Turn on or off the onboard led
    }
  }
}
  //Read new tag if available
  boolean readID()
  {
    //Check if a new tag is detected or not. If not return.
    if ( ! mfrc522.PICC_IsNewCardPresent())
    {
      return false;
    }
    //Check if a new tag is readable or not. If not return.
    if ( ! mfrc522.PICC_ReadCardSerial())
    {
      return false;
    }
    tagID = "";
    // Read the 4 byte UID
    for ( uint8_t i = 0; i < 4; i++)
    {
      //readCard[i] = mfrc522.uid.uidByte[i];
      tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Convert the UID to a single String
    }
    tagID.toUpperCase();
    mfrc522.PICC_HaltA(); // Stop reading
    return true;
  }

Code Explanation

At first, we have included all the necessary libraries, declared the global variables, and created an instance for the RFID library.

#include <SPI.h>
// Arduino RFID library initialization
#include <MFRC522.h>
// Arduino RFID pin definitions for RC522
#define SS_PIN 10
#define RST_PIN 9
#define LED 8
byte readCard[4];
String tag_UID = "39C3BB99";  // Replace this with the UID of your tag!!!
String tagID = "";
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance

Here the LED pin is connected to the Arduino pin D8. The tag_UID is unique for each tag and replace it with your own tag’s UID. You can get the UID by using the Dumpinfo example.

In the setup() function, we have initialized the pin D8 as an output and set its initial state to LOW. And then initialized the SPI bus and the MFRC522 instance.

void setup()
{
  pinMode(LED, OUTPUT);// initialize digital pin LED_BUILTIN as an output.
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  SPI.begin(); // SPI bus
  mfrc522.PCD_Init(); // Initialise MFRC522
}

The function readID is used to get the UID from the tags. This function will check if a tag is available or not and if a tag is available, it will read the UID from the tag. Then the UID is converted to a string and it’s stored in a variable called tagID. The readID function will return true if the reading was a success.

boolean readID()
  {
    //Check if a new tag is detected or not. If not return.
    if ( ! mfrc522.PICC_IsNewCardPresent()
    {
      return false;
    }
    //Check if a new tag is readable or not. If not return.
    if ( ! mfrc522.PICC_ReadCardSerial())
    {
      return false;
    }
    tagID = "";
    // Read the 4 byte UID
    for ( uint8_t i = 0; i < 4; i++)
    {
      //readCard[i] = mfrc522.uid.uidByte[i];
      tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Convert the UID to a single String
    }
    tagID.toUpperCase();
    mfrc522.PICC_HaltA(); // Stop reading
    return true;
  }

In the loop function, the Arduino will check for a valid tag reading periodically. If it receives a valid tag reading the read UID matches with the UID we have declared earlier, the LED state will be toggled.

void loop()
{
  //Wait until new tag is available
  while (readID())
  {
    if (tagID == tag_UID)
    {
      digitalWrite(LED, !digitalRead(LED));  // Turn on or off the onboard led
    }
  }
}

RFID Arduino Troubleshooting Guide

Common RFID Arduino issues and their solutions:

  • Communication Failed Error: Check your RFID Arduino wiring connections, especially SPI pins. Ensure RC522 VCC connects to Arduino's 3.3V, not 5V.
  • No Card Detected: Verify RFID Arduino power supply and tag proximity (2-5cm range). Some cards require specific orientation.
  • Authentication Failed: Reset your RFID Arduino setup and check if the tag is readable. Use default MIFARE keys (0xFF) for new tags.
  • Library Compilation Errors: Ensure MFRC522 library is properly installed for your Arduino RFID project. Download from official GitHub repository.

For advanced RFID Arduino troubleshooting, use a multimeter to verify 3.3V power supply and check SPI communication with an oscilloscope. If problems persist, try different RFID tags to isolate hardware issues. If you are still facing any problems, you can post them in the comment section below and we will try our best to answer them. Also, look for the  "Ask our community members" option at the bottom of the article to join and engage with our 100K+ readers. 

Advanced Arduino RFID Projects and Applications

These Arduino RFID projects showcase practical applications you can build at home. If you want to know more about those topics, links are given below.

IoT-based Event Management System

IoT-based Event Management System

This RFID Based IoT Enabled Event Management System not only monitors the entry log but with the help of IoT technology it can also send the Log and Entry data directly to a dedicated server that can handle all the authentication, authorization, and management making the whole process seamless.

RFID Based Attendance System

RFID Based Attendance System

In this RFID based Attendance System project, we will explain how we can count attendance automatically by using RFID cards. You can also find a step-by-step guide along with circuit and code to build your own attendance system.

Arduino RFID Door Lock

Arduino RFID Door Lock

Here in this project, we are using Arduino and relay to trigger the Electric Door Lock and RFID to authenticate, so your RFID tag will act as a key. If you place the wrong RFID card near the RFID reader a buzzer will beep to alert you about the wrong card.

This Arduino RFID tutorial covered everything from basic RC522 interfacing to advanced Arduino RFID projects. With these Arduino RFID techniques, you can create security systems, access control, and inventory management solutions.

Complete Project Code

LED Control
 
#include <SPI.h>
// Arduino RFID library initialization
#include <MFRC522.h>
// Arduino RFID pin definitions for RC522
#define SS_PIN 10
#define RST_PIN 9
#define LED 8
byte readCard[4];
String tag_UID = "39C3BB99";  // Replace this with the UID of your tag!!!
String tagID = "";
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
void setup()
{ 
  pinMode(LED, OUTPUT);// initialize digital pin LED_BUILTIN as an output.
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  SPI.begin(); // SPI bus
  mfrc522.PCD_Init(); // Initialise MFRC522
}
void loop()
{
  //Wait until new tag is available
  while (readID())
  {
    if (tagID == tag_UID)
    {
      digitalWrite(LED, !digitalRead(LED));  // Turn on or off the onboard led
    }
  }
}
  //Read new tag if available
boolean readID()
  {
    //Check if a new tag is detected or not. If not return.
    if ( ! mfrc522.PICC_IsNewCardPresent())
    {
      return false;
    }
    //Check if a new tag is readable or not. If not return.
    if ( ! mfrc522.PICC_ReadCardSerial())
    {
      return false;
    }
    tagID = "";
    // Read the 4 byte UID
    for ( uint8_t i = 0; i < 4; i++)
    {
      //readCard[i] = mfrc522.uid.uidByte[i];
      tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Convert the UID to a single String
    }
    tagID.toUpperCase();
    mfrc522.PICC_HaltA(); // Stop reading
    return true;
  }

Write:
#include <SPI.h>      //include the SPI library
// Arduino RFID library initialization
#include <MFRC522.h>
// Arduino RFID pin definitions for RC522
#define RST_PIN 9  //reset pin, which can be changed to another digital pin if needed.
#define SS_PIN 10  //SS or the slave select pin, which can be changed to another digital pin if needed.
MFRC522 mfrc522(SS_PIN, RST_PIN);  // create a MFRC522 instant.
MFRC522::MIFARE_Key key;          //create a MIFARE_Key struct named 'key' to hold the card information
byte data1[14] = {"Circuit-Digest"};  //The first data that needs to be written to the tag.
byte data2[12] = {"Jobit-Joseph"};  //The second data that needs to be written to the tag.
byte readbackblock[18];  //Array for reading out a block.
void setup()
{
  Serial.begin(115200);        // Initialize serial communications with the PC
  SPI.begin();               // Init SPI bus
  mfrc522.PCD_Init();        // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
  Serial.println("Scan a MIFARE Classic card");
  for (byte i = 0; i < 6; i++)
  {
    key.keyByte[i] = 0xFF;  // Prepare the security key for the read and write operations.
  }
}
void loop()
{
  // Look for new cards if not found rerun the loop function
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  // read from the card if not found rerun the loop function
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  Serial.println("card detected. Writing data");
  writeBlock(1, data1); //write data1 to the block 1 of the tag
  writeBlock(2, data2); //write data2 to the block 2 of the tag
  Serial.println("reading data from the tag");
  readBlock(1, readbackblock);   //read block 1
  //print data
  Serial.print("read block 1: ");
  for (int j = 0 ; j < 14 ; j++)
  {
    Serial.write (readbackblock[j]);
  }
  Serial.println("");
  readBlock(2, readbackblock);  //read block 2
  //print data
  Serial.print("read block 2: ");
  for (int j = 0 ; j < 12 ; j++)
  {
    Serial.write (readbackblock[j]);
  }
  Serial.println("");

  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));//uncomment below line if want to see the entire memory dump.
}
//Write specific block
int writeBlock(int blockNumber, byte arrayAddress[])
{
  //check if the block number corresponds to data block or triler block, rtuen with error if it's trailer block.
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
  if (blockNumber > 2 && (blockNumber + 1) % 4 == 0) {
    Serial.print(blockNumber);
    Serial.println(" is a trailer block: Error");
    return 2;
  }
  //authentication
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Authentication failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" as error message
  }

  //writing data to the block
  status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);
  //status = mfrc522.MIFARE_Write(9, value1Block, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Data write failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.print("Data written to block ");
  Serial.println(blockNumber);
}
//Read specific block
int readBlock(int blockNumber, byte arrayAddress[])
{
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector

  //authentication of the desired block for access
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));

  if (status != MFRC522::STATUS_OK) {
    Serial.print("Authentication failed : ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" as error message
  }

  //reading data from the block
  byte buffersize = 18;
  status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
  if (status != MFRC522::STATUS_OK) {
    Serial.print("Data read failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.println("Data read successfully");
}
Have any question realated to this Article?

Ask Our Community Members