RFID Door Lock
ESP32 DevKit (WROOM-32)·Arduino C++·Updated Jul 27, 2026·by FluxBench TeamIncludes Lab + Schematic
A tap-to-open door lock built on the classic miguelbalboa MFRC522 SPI RFID reader. Tapping the authorized card (UID 9A:2F:C4:1B - card A on the bench panel, and the built-in auto tag) retracts a servo deadbolt for 3 seconds, lights the green LED and shows WELCOME plus a running open count on the OLED. Any other card (try card B) is rejected with the red LED and a DENIED screen. The reader panel appears on the bench while the sketch runs.
sketch.ino
// RFID Door Lock - tap an RFID card on the MFRC522 reader to open a servo
// deadbolt. The classic miguelbalboa MFRC522 library reads the card's unique
// ID over SPI. The right card (9A:2F:C4:1B) opens the lock for 3 seconds and
// lights the green LED; any other card is rejected with the red LED.
// Use the reader panel on the bench: card A is authorized, card B is not.
#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Servo.h>
#define SS_PIN 5 // MFRC522 SDA/SS
#define RST_PIN 27 // MFRC522 reset
#define LED_OK 4 // green: access granted
#define LED_NO 2 // red: access denied
#define SERVO_PIN 26 // deadbolt servo
MFRC522 rfid(SS_PIN, RST_PIN);
Adafruit_SSD1306 display(128, 64, &Wire, -1);
Servo bolt;
byte masterUid[4] = {0x9A, 0x2F, 0xC4, 0x1B};
int opens = 0;
void showLocked() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("RFID DOOR LOCK");
display.setTextSize(3);
display.setCursor(0, 18);
display.print("LOCKED");
display.setTextSize(1);
display.setCursor(0, 52);
display.print("Tap your card...");
display.display();
}
void setup() {
Serial.begin(115200);
pinMode(LED_OK, OUTPUT);
pinMode(LED_NO, OUTPUT);
SPI.begin();
rfid.PCD_Init();
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
bolt.attach(SERVO_PIN);
bolt.write(0); // bolt extended = locked
showLocked();
Serial.println("RFID Door Lock ready - tap a card on the reader");
}
void loop() {
if (!rfid.PICC_IsNewCardPresent()) {
delay(60);
return;
}
if (!rfid.PICC_ReadCardSerial()) {
delay(60);
return;
}
char idbuf[16];
sprintf(idbuf, "%02X:%02X:%02X:%02X", rfid.uid.uidByte[0], rfid.uid.uidByte[1], rfid.uid.uidByte[2], rfid.uid.uidByte[3]);
bool ok = true;
for (int i = 0; i < 4; i++) {
if (rfid.uid.uidByte[i] != masterUid[i]) ok = false;
}
if (ok) {
opens = opens + 1;
Serial.print("ACCESS GRANTED to ");
Serial.print(idbuf);
Serial.print(" (opens: ");
Serial.print(opens);
Serial.println(")");
digitalWrite(LED_OK, HIGH);
bolt.write(90); // retract the deadbolt
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 0);
display.print("WELCOME");
display.setTextSize(1);
display.setCursor(0, 24);
display.print("Card ");
display.print(idbuf);
display.setCursor(0, 40);
display.print("Door OPEN 3 s");
display.setCursor(0, 52);
display.print("Opens: ");
display.print(opens);
display.display();
delay(3000);
bolt.write(0); // lock again
digitalWrite(LED_OK, LOW);
Serial.println("Door locked again");
} else {
Serial.print("ACCESS DENIED for ");
Serial.println(idbuf);
digitalWrite(LED_NO, HIGH);
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 8);
display.print("DENIED");
display.setTextSize(1);
display.setCursor(0, 32);
display.print("Card ");
display.print(idbuf);
display.setCursor(0, 44);
display.print("is not authorized");
display.display();
delay(1500);
digitalWrite(LED_NO, LOW);
}
showLocked();
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}Built with FluxBench.AI — the AI workbench for embedded projects.