Built-in project · Arduino Uno R3

RFID door on an Arduino Uno

An MFRC522 reader and four cards. Tap one: two are on the list and light the green lamp, the other two light the red. The whole build, an Arduino Uno and 5 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 25 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $33. On Mokxi they're free.

Step by step, with the wiring and the common mistakes: Arduino RC522 RFID Reader: Wiring and Code

The circuit runs here once the page has loaded.

What you'll learn

  • Reading RFID cards over SPI
  • What a card UID is
  • Checking an ID against an allow list
  • Why the MFRC522 uses 3.3V
  • Giving feedback with two LEDs
  • Difficulty: Intermediate
  • Time: About 25 minutes
  • Board: Arduino Uno R3
  • Parts: 7

How it works

An MFRC522 reader talks to the Uno over SPI: SCK on 13, MISO on 12, MOSI on 11, SDA (chip select) on 10 and RST on 9. It runs on 3.3V. When a card comes near, the reader gets the card's UID, its unique ID.

The sketch prints the UID in hex and compares it with a list of two allowed cards. A match lights the green LED on pin 7, anything else lights the red LED on pin 6. Either one stays on for 1.5 seconds. A card left on the reader is not read again until you take it away and tap it again.

Parts list

7 parts, plus the jumper wires. They retail for about $33; on Mokxi they're free.

Kits that can build it

These 3 starter kits have every part in the circuit. Each kit's page lists what else it can build.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
RFID reader, MFRC522 pin GNDArduino Uno R3 pin GND
RFID reader, MFRC522 pin SCKArduino Uno R3 pin 13
RFID reader, MFRC522 pin MISOArduino Uno R3 pin 12
RFID reader, MFRC522 pin MOSIArduino Uno R3 pin 11
RFID reader, MFRC522 pin SDAArduino Uno R3 pin 10
RFID reader, MFRC522 pin RSTArduino Uno R3 pin 9
Resistor, 220 Ω (1) pin 1Arduino Uno R3 pin 7
Resistor, 220 Ω (2) pin 1Arduino Uno R3 pin 6
RFID reader, MFRC522 pin 3.3VArduino Uno R3 pin 3V3
LED, green pin CArduino Uno R3 pin GND
LED, red pin CArduino Uno R3 pin GND
LED, green pin AResistor, 220 Ω (1) pin 2
LED, red pin AResistor, 220 Ω (2) pin 2

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// RFID door: two of the four cards open it, the other two do not.
//
// Tap a card beside the reader to lay it on the antenna. The sketch reads its
// UID, looks it up in the list below, and lights the green LED for a card on
// the list or the red one for a card that is not. Every UID is printed, so a
// new card is added by tapping it, copying its UID from the serial monitor
// into ALLOWED, and running again.
//
// PICC_HaltA() at the end puts the card to sleep: it stays quiet until it
// leaves the field. That is why a card left on the reader opens the door once
// and not once a loop. Tap it off and on again to read it again.

#include <SPI.h>
#include <MFRC522.h>

MFRC522 reader(10, 9); // SDA (chip select) on 10, RST on 9

const int GREEN_LED = 7;
const int RED_LED = 6;

// The cards that open the door: the white card and the blue key fob.
const byte ALLOWED[][4] = {
    {0xC3, 0x5A, 0x1E, 0x94},
    {0x7B, 0x02, 0xD4, 0x19},
};
const int ALLOWED_COUNT = sizeof(ALLOWED) / sizeof(ALLOWED[0]);

bool onTheList()
{
    if (reader.uid.size != 4) {
        return false; // the seven-byte sticker is never on it
    }
    for (int card = 0; card < ALLOWED_COUNT; card++) {
        bool same = true;
        for (int i = 0; i < 4; i++) {
            if (reader.uid.uidByte[i] != ALLOWED[card][i]) {
                same = false;
            }
        }
        if (same) {
            return true;
        }
    }
    return false;
}

void setup()
{
    Serial.begin(9600);
    pinMode(GREEN_LED, OUTPUT);
    pinMode(RED_LED, OUTPUT);
    SPI.begin();
    reader.PCD_Init();
    reader.PCD_DumpVersionToSerial();
    Serial.println("Tap a card on the reader.");
}

void loop()
{
    if (!reader.PICC_IsNewCardPresent() || !reader.PICC_ReadCardSerial()) {
        return;
    }
    Serial.print("UID:");
    for (byte i = 0; i < reader.uid.size; i++) {
        Serial.print(reader.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(reader.uid.uidByte[i], HEX);
    }
    Serial.println();

    int led = onTheList() ? GREEN_LED : RED_LED;
    Serial.println(led == GREEN_LED ? "Welcome in." : "Not this card.");
    reader.PICC_HaltA();

    digitalWrite(led, HIGH);
    delay(1500);
    digitalWrite(led, LOW);
}

Code walkthrough

The key functions of the sketch, and what each one does.

onTheList sketch.ino

Compares the card in the reader with each entry in ALLOWED. A UID that is not four bytes long is refused right away. Otherwise it checks the four bytes one at a time, and returns true only if all four match a stored card.

bool onTheList()
{
    if (reader.uid.size != 4) {
        return false; // the seven-byte sticker is never on it
    }
    for (int card = 0; card < ALLOWED_COUNT; card++) {
        bool same = true;
        for (int i = 0; i < 4; i++) {
            if (reader.uid.uidByte[i] != ALLOWED[card][i]) {
                same = false;
            }
        }
        if (same) {
            return true;
        }
    }
    return false;
}

setup sketch.ino

Starts serial, makes the two LED pins outputs, starts SPI and the reader, and prints the reader's version to serial. This also tells you if the wiring is right. Then it asks you to tap a card.

void setup()
{
    Serial.begin(9600);
    pinMode(GREEN_LED, OUTPUT);
    pinMode(RED_LED, OUTPUT);
    SPI.begin();
    reader.PCD_Init();
    reader.PCD_DumpVersionToSerial();
    Serial.println("Tap a card on the reader.");
}

loop sketch.ino

Returns quickly unless a new card is present and its serial can be read. It prints the UID, then picks the green or red LED with onTheList(), and prints a message. PICC_HaltA() puts the card to sleep. The chosen LED stays on for 1500 ms.

void loop()
{
    if (!reader.PICC_IsNewCardPresent() || !reader.PICC_ReadCardSerial()) {
        return;
    }
    Serial.print("UID:");
    for (byte i = 0; i < reader.uid.size; i++) {
        Serial.print(reader.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(reader.uid.uidByte[i], HEX);
    }
    Serial.println();

    int led = onTheList() ? GREEN_LED : RED_LED;
    Serial.println(led == GREEN_LED ? "Welcome in." : "Not this card.");
    reader.PICC_HaltA();

    digitalWrite(led, HIGH);
    delay(1500);
    digitalWrite(led, LOW);
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • No version or UID ever prints. This project
    Check the SPI wires: SCK 13, MISO 12, MOSI 11, SDA 10, RST 9. Power the reader from 3.3V and join its GND.
  • Your own card shows red. This project
    It is not in ALLOWED. Tap it, copy the UID from the serial monitor into the list, and run again.
  • The reader is damaged or behaves oddly on 5 V power. RFID reader
    The MFRC522 runs on 3.3 V only. Power it from the 3.3 V pin, never 5 V. Ideally divide 5 V signals from an Uno down for SCK, MOSI and SS.
  • No card is detected. RFID reader
    Check SDA (SS), RST, SCK, MOSI and MISO against your board's SPI pins and the constructor in your code. It reads 13.56 MHz cards only, not 125 kHz key fobs.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
  • A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
    Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground.
  • The LED does not light, or it lights once and then dies. LED
    LEDs have polarity. The longer leg (anode) goes toward the positive side. Always add a series resistor, about 220 ohms to 1 k ohm on a 5 V pin.
  • A blue or white LED stays dark on 3.3 V. LED
    Blue and white LEDs drop about 3 V, so 3.3 V leaves almost nothing for the resistor. Use a 5 V supply, or a smaller resistor and a red or green LED.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.