FluxBench.AIShared project · read-only

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.