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
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.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Half breadboard
- 1 × RFID reader, MFRC522In Escape Box Kit.
- 2 × Resistor, 220 ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
- 1 × LED, greenIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
- 1 × LED, redIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
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 pin | Connects to |
|---|---|
| RFID reader, MFRC522 pin GND | Arduino Uno R3 pin GND |
| RFID reader, MFRC522 pin SCK | Arduino Uno R3 pin 13 |
| RFID reader, MFRC522 pin MISO | Arduino Uno R3 pin 12 |
| RFID reader, MFRC522 pin MOSI | Arduino Uno R3 pin 11 |
| RFID reader, MFRC522 pin SDA | Arduino Uno R3 pin 10 |
| RFID reader, MFRC522 pin RST | Arduino Uno R3 pin 9 |
| Resistor, 220 Ω (1) pin 1 | Arduino Uno R3 pin 7 |
| Resistor, 220 Ω (2) pin 1 | Arduino Uno R3 pin 6 |
| RFID reader, MFRC522 pin 3.3V | Arduino Uno R3 pin 3V3 |
| LED, green pin C | Arduino Uno R3 pin GND |
| LED, red pin C | Arduino Uno R3 pin GND |
| LED, green pin A | Resistor, 220 Ω (1) pin 2 |
| LED, red pin A | Resistor, 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.
// 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 inALLOWED. 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.