SE322 /

Lab: RFID Access Control System

Prof. Anis Koubaa
Professor

Prof. Anis Koubaa

SE322: Internet of Things Applications
Spring 2025
College of Engineering, Alfaisal University

RFID Access Control System

📅 Duration: 2 hours
🎯 Objective:
Build an RFID access control system using Arduino and the MFRC522 RFID module to grant or deny access based on authorized card UIDs.

Introduction

This Arduino program reads an RFID tag using the MFRC522 module and determines whether access is granted or denied based on a list of pre-authorized UIDs. We'll examine the code structure, understand how it works, and implement a complete access control system.

Circuit Diagram

RFID Circuit Diagram

Circuit diagram showing the connections between Arduino and MFRC522 RFID reader.

Understanding the RFID Access Control System

1. Libraries and Setup

  • We need two essential libraries:
    • SPI.h - Allows communication between Arduino and RFID module using SPI protocol
    • MFRC522.h - Provides functions to interact with the MFRC522 RFID reader
  • Define the RFID module pins:
    • SS_PIN (Slave Select) connected to pin 10
    • RST_PIN (Reset) connected to pin 9
  • Create an instance of MFRC522 class
Libraries and Setup
#include 
#include 

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

2. Storing Authorized UIDs

  • Create an array to store pre-approved RFID card UIDs
  • Calculate the number of authorized UIDs automatically
Authorized UIDs
const String authorizedUIDs[] = { "BD31152B", "A1B2C3D4" };
const int numAuthorized = sizeof(authorizedUIDs) / sizeof(authorizedUIDs[0]);

3. The setup() Function

  • Initialize serial communication for debugging
  • Initialize SPI bus for RFID communication
  • Initialize the MFRC522 RFID reader
  • Print initialization message to serial monitor
Setup Function
void setup() {
    Serial.begin(9600);  // Start serial communication
    SPI.begin();         // Initialize SPI bus
    mfrc522.PCD_Init();  // Initialize the MFRC522 RFID reader
    
    Serial.println("RFID Access Control System Initialized");
    Serial.println("Please scan your card...");
}

4. The loop() Function

  • Check if a new RFID card is present
  • Read the card's UID if present
  • Check if the card is authorized
  • Wait before scanning again
Loop Function
void loop() {
    // Check if a new RFID card is present
    if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial()) {
        return; // Exit loop if no card is detected
    }
    
    // Read the UID of the card
    String scannedUID = getCardUID();
    
    Serial.print("Scanned UID: ");
    Serial.println(scannedUID);
    
    // Check if UID is authorized
    if (isAuthorized(scannedUID)) {
        Serial.println("Access Granted ✅");
    } else {
        Serial.println("Access Denied ❌");
    }
    
    delay(3000); // Wait 3 seconds before scanning again
}

5. The getCardUID() Function

This function reads the RFID card's UID and converts it to a readable string format.

getCardUID Function
String getCardUID() {
    String uid = "";  // Create an empty string to store the UID
    
    // Loop through all bytes of the UID
    for (byte i = 0; i < mfrc522.uid.size; i++) {
        uid += String(mfrc522.uid.uidByte[i], HEX); // Convert byte to HEX and append
    }
    
    uid.toUpperCase(); // Convert to uppercase for consistency
    return uid; // Return the UID string
}

6. The isAuthorized() Function

This function checks if the scanned UID matches any of the pre-authorized UIDs.

isAuthorized Function
bool isAuthorized(String uid) {
    for (int i = 0; i < numAuthorized; i++) {
        if (uid.equalsIgnoreCase(authorizedUIDs[i])) {
            return true; // Authorized UID found
        }
    }
    return false; // Not authorized
}

Deep Dive: Understanding getCardUID() Function

What is a UID in RFID?

  • Every RFID card has a Unique Identifier (UID)
  • The UID is a series of bytes (typically 4, 7, or 10 bytes)
  • The UID is stored in hexadecimal (HEX) format
  • Example of a 4-byte UID: BD 31 15 2B

Why Convert the UID to a String?

  • The RFID reader reads the UID as raw bytes
  • To compare it with predefined UIDs, we need to convert it to a readable format
  • Example:
    • Raw bytes: [0xBD, 0x31, 0x15, 0x2B]
    • Converted string: "BD31152B"

Breaking Down getCardUID() Step by Step

  • Step 1: Create an empty string
    String uid = "";
  • Step 2: Loop through each byte
    for (byte i = 0; i < mfrc522.uid.size; i++) {
  • Step 3: Convert each byte to HEX
    uid += String(mfrc522.uid.uidByte[i], HEX);
  • Step 4: Convert to uppercase
    uid.toUpperCase();
  • Step 5: Return the final UID string
    return uid;

Example in Action

Let's say we scanned a card with UID = BD 31 15 2B

Raw Data from RFID Reader:

mfrc522.uid.uidByte[0] = 0xBD
mfrc522.uid.uidByte[1] = 0x31
mfrc522.uid.uidByte[2] = 0x15
mfrc522.uid.uidByte[3] = 0x2B

Processing in getCardUID():

  • First loop iteration (i = 0): uid = "BD"
  • Second loop iteration (i = 1): uid = "BD31"
  • Third loop iteration (i = 2): uid = "BD3115"
  • Fourth loop iteration (i = 3): uid = "BD31152B"

Final Output:

Scanned UID: BD31152B

Why This Conversion Is Important

❌ Incorrect Comparison (Raw Bytes):

if (mfrc522.uid.uidByte == {0xBD, 0x31, 0x15, 0x2B}) { // Won't work

✅ Correct Comparison (String):

if (scannedUID.equalsIgnoreCase("BD31152B")) {

Complete RFID Access Control System Code

Complete RFID Access Control System
#include 
#include 

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

const String authorizedUIDs[] = { "BD31152B", "A1B2C3D4" };
const int numAuthorized = sizeof(authorizedUIDs) / sizeof(authorizedUIDs[0]);

void setup() {
    Serial.begin(9600);  // Start serial communication
    SPI.begin();         // Initialize SPI bus
    mfrc522.PCD_Init();  // Initialize the MFRC522 RFID reader
    
    Serial.println("RFID Access Control System Initialized");
    Serial.println("Please scan your card...");
}

void loop() {
    // Check if a new RFID card is present
    if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial()) {
        return; // Exit loop if no card is detected
    }
    
    // Read the UID of the card
    String scannedUID = getCardUID();
    
    Serial.print("Scanned UID: ");
    Serial.println(scannedUID);
    
    // Check if UID is authorized
    if (isAuthorized(scannedUID)) {
        Serial.println("Access Granted ✅");
    } else {
        Serial.println("Access Denied ❌");
    }
    
    delay(3000); // Wait 3 seconds before scanning again
}

// Function to read RFID UID and return it as a string
String getCardUID() {
    String uid = "";  // Create an empty string to store the UID
    
    // Loop through all bytes of the UID
    for (byte i = 0; i < mfrc522.uid.size; i++) {
        uid += String(mfrc522.uid.uidByte[i], HEX); // Convert byte to HEX and append
    }
    
    uid.toUpperCase(); // Convert to uppercase for consistency
    return uid; // Return the UID string
}

// Function to check if the UID is in the authorized list
bool isAuthorized(String uid) {
    for (int i = 0; i < numAuthorized; i++) {
        if (uid.equalsIgnoreCase(authorizedUIDs[i])) {
            return true; // Authorized UID found
        }
    }
    return false; // Not authorized
}

Example Output on the Serial Monitor

Authorized Card

RFID Access Control System Initialized
Please scan your card...
Scanned UID: BD31152B
Access Granted ✅

Unauthorized Card

Scanned UID: 5A7C3D1E
Access Denied ❌

Lab Exercise: Enhancing the RFID System

Task 1: Add Visual Indicators

  • Add a Green LED to indicate access granted
  • Add a Red LED to indicate access denied
  • Pin suggestions:
    • Green LED: Pin 7
    • Red LED: Pin 6

Task 2: Add Sound Notification

  • Add a buzzer that beeps:
    • One short beep for access granted
    • Three short beeps for access denied
  • Suggested pin: Buzzer on Pin 8

Task 3: Implement a Door Lock Simulation

  • Use a servo motor to simulate a door lock
  • When access is granted:
    • Rotate servo to "unlock" position
    • Wait 5 seconds
    • Rotate servo back to "lock" position
  • Suggested pin: Servo on Pin 5

Task 4: Dynamic Card Management

  • Allow adding new authorized cards through serial commands
  • Create a "master card" that when scanned, puts the system in "enrollment mode"
  • The next card scanned is added to the authorized list
  • Use EEPROM to store the list of authorized cards

Submission Requirements

  • Complete Arduino code with comments explaining each section
  • Circuit diagram showing all connections
  • Video demonstration of your working system
  • Brief report explaining:
    • How your implemented features work
    • Challenges faced and how you solved them
    • Potential real-world applications

Grading Criteria

  • Functionality (40%)
    • All features working as specified
    • Proper integration of components
  • Code Quality (30%)
    • Well-structured and commented code
    • Efficient implementation
  • Documentation (20%)
    • Clear circuit diagram
    • Complete submission requirements
  • Creativity (10%)
    • Additional features or improvements
    • Innovative solutions

Review Questions

Question 1

Explain the purpose of the MFRC522 library in the RFID access control system and list the key functions it provides.

Question 2

Why is it necessary to convert the RFID card's UID from raw bytes to a string format? What problems would arise if we tried to compare raw byte arrays directly?

Question 3

Modify the provided code to add a counter that keeps track of how many times each authorized card has been used. Display this information on the Serial Monitor each time a card is scanned.

Question 4

What are the common issues that might arise when working with RFID readers, and how would you troubleshoot them?

Question 5

Design a system that uses both the RFID reader and an LCD display. Explain how you would modify the code to show personalized messages for different authorized users.