RFID Türschloss mit Arduino & RC522 bauen

Du willst deine Werkstatt, dein Büro oder den Serverraum nur mit einem RFID-Chip öffnen – ganz ohne Schlüssel, Code-Tastatur oder Bluetooth-App? In diesem Tutorial baust du ein komplettes RFID-Türschloss mit Arduino UNO und RC522-Modul. Wir starten einfacher Lesen der Karten-UID über den seriellen Monitor, bauen eine autorisierte Zutrittskontrolle mit Master-Chip und erweitern das System schließlich um ein OLED-Display mit Admin-Modus zum Anlernen neuer Karten. SPI-Grundlagen, Relais-Beschaltung mit Freilaufdiode und die Speicherung autorisierter Tags im EEPROM – alles in einem Guide.

Warum ein RFID-Türschloss selbst bauen?

Fertige RFID-Zutrittssysteme gibt es für 50–200 €. Aber sie haben fast immer einen Haken: geschlossene Firmware, keine Erweiterbarkeit und null Lerneffekt. Mit einem Arduino UNO R3 und einem günstigen RC522 RFID-Modul baust du dir ein vollständig offenes, anpassbares System – für unter 25 € Gesamtkosten.

Das selbstgebaute Türschloss kann:

  • Türen mit einem RFID-Tag oder einer Mifare-Karte öffnen
  • Neue Chips per Admin-Modus anlernen, ohne den Arduino neu flashen zu müssen
  • Autorisierte und nicht-autorisierte Zutrittsversuche auf einem OLED-Display anzeigen
  • Über ein Relais jeden handelsüblichen elektrischen Türöffner (12 V) ansteuern
  • Bis zu 50 verschiedene RFID-Tags im EEPROM speichern

💡 Was du am Ende kannst: RFID-Technologie auf 13,56 MHz verstehen, SPI-Kommunikation zwischen Arduino und RC522 beherrschen, Relais mit Transistorschaltung und Freilaufdiode korrekt betreiben und autorisierte UIDs persistent im EEPROM ablegen. Das sind Grundlagen, die du für Dutzende weitere Projekte brauchst – von Warenwirtschaft bis Smart-Home.

So funktioniert RFID mit dem RC522-Modul

Die Technologie hinter 13,56 MHz

RFID steht für Radio-Frequency Identification. Das RC522-Modul arbeitet auf dem weltweit lizenzfreien ISM-Band bei 13,56 MHz und ist kompatibel mit MIFARE Classic 1K/4K sowie MIFARE Ultralight Tags. Die Kommunikation zwischen Leser und Tag erfolgt nach ISO/IEC 14443 Type A – dem gleichen Standard, der auch in Reisepässen und kontaktlosen Bankkarten steckt.

Der physikalische Ablauf in Zeitlupe:

  1. Das RC522 erzeugt ein elektromagnetisches Wechselfeld über seine integrierte Antennenspule
  2. Nähert sich ein passiver RFID-Tag, induziert dieses Feld eine Spannung in der Tag-Spule – der Tag „erwacht"
  3. Der Tag moduliert seine Lastimpedanz (Load Modulation), um Daten an den Leser zurückzusenden
  4. Das RC522 demoduliert das Antwortsignal und extrahiert die UID (Unique Identifier) – eine 4 oder 7 Byte lange, einmalig vergebene Seriennummer
  5. Diese UID wird über den SPI-Bus an den Arduino übermittelt

🔍 MIFARE Classic 1K – was steckt drin? Ein MIFARE Classic 1K Tag enthält 1 KB EEPROM-Speicher, aufgeteilt in 16 Sektoren zu je 4 Blöcken (je 16 Byte). Sektor 0, Block 0 enthält die herstellerseitig vergebene, nicht überschreibbare UID. Für unser Türschloss nutzen wir ausschließlich diese UID – das ist sicherer als beschreibbare Sektoren, da die UID nicht geklont werden kann (ohne spezielle „Magic Tags" der ersten Generation, die es allerdings kaum noch gibt).

SPI-Kommunikation: Was passiert auf den Pins?

Das RC522 kommuniziert mit dem Arduino über SPI (Serial Peripheral Interface) – ein synchrones, vollduplex-fähiges Busprotokoll mit vier Leitungen:

SPI-Leitung Richtung Bedeutung
MOSI (Master Out, Slave In) Arduino → RC522 Daten vom Mikrocontroller zum RFID-Chip
MISO (Master In, Slave Out) RC522 → Arduino Daten vom RFID-Chip zurück zum Arduino
SCK (Serial Clock) Arduino → RC522 Taktleitung – jede Datenübertragung ist an diesen Takt gebunden
SS (Slave Select, auch NSS/SDA) Arduino → RC522 Chip-Select – LOW aktiv. Erst wenn dieser Pin auf LOW gezogen wird, hört das RC522 auf den Bus

Der Arduino UNO agiert als SPI-Master, das RC522 als SPI-Slave. Die MFRC522-Bibliothek von Miguel Balboa abstrahiert die SPI-Befehle: Statt einzelner Register-Zugriffe rufst du einfach mfrc522.PICC_IsNewCardPresent() auf. Intern sendet die Bibliothek über SPI den Befehl 0x26 (REQA – Request Answer To Request) und wartet auf die Antwort (ATQA) des Tags. Erst danach folgt der Anti-Kollisions-Algorithmus, der bei mehreren Tags im Feld genau einen selektiert und dessen UID ausliest.

Bauteile – alles auf einen Blick

🛒 Einkaufsliste

Arduino UNO R3

Das Gehirn des Projekts. ATmega328P mit 32 KB Flash, 2 KB RAM, 1 KB EEPROM. Der integrierte EEPROM-Speicher reicht für ca. 50 RFID-Tags à 4 Byte UID – perfekt für unser Vorhaben. SPI-Pins sind fest auf D10–D13 verdrahtet.

RFID RC522 Kit

13,56 MHz RFID-Reader/Writer mit SPI-Schnittstelle. Wird mit zwei RFID-Tags (Schlüsselanhänger + Karte) geliefert. Betriebsspannung 3,3 V – nicht an 5 V anschließen, sonst ist das Modul sofort defekt!

1-Kanal-Relais KY-019 (5 V)

Schaltet den Türöffner. Das Relaismodul enthält bereits einen Optokoppler und eine Freilaufdiode – du kannst es direkt an einen Arduino-Pin anschließen. Schaltleistung: bis 250 V AC / 10 A oder 30 V DC / 10 A.

OLED-Display 128×64 SSD1306 (I2C)

Kompaktes 0,96"-Display für Statusmeldungen: „Zugang gewährt", „Zugang verweigert" und Admin-Menü. I2C-Schnittstelle – nur 4 Kabel, kein Gelöt.

Kleinteile & Verbrauchsmaterial

Breadboard (400 Kontakte), Jumper-Wire-Set, ein JST-XH Stecker Set für saubere, steckbare Relais- und Stromanschlüsse, sowie ein 12-V-Netzteil passend zu deinem Türöffner.

⚠️ Lebenswichtiger RC522-Hinweis: Das RC522 läuft auf 3,3 V Logik, aber der Arduino UNO gibt 5 V auf seinen digitalen Pins aus. In der Praxis toleriert das RC522 5 V auf MOSI, SCK und SS meistens – das ist aber nicht spezifikationskonform. Für den Dauerbetrieb empfehlen wir einen Logic-Level-Shifter (3,3 V ↔ 5 V) an MOSI, SCK und SS. MISO kommt vom RC522 und liefert 3,3 V – der Arduino erkennt das zuverlässig als HIGH. Die MFRC522-Bibliotheksdokumentation bestätigt, dass 5 V Eingangsspannung auf Dauer den Chip beschädigen kann.

Schaltplan: So verdrahtest du alles

Der Aufbau besteht aus drei Teilschaltungen: (1) RC522 per SPI an Arduino, (2) OLED-Display per I2C, (3) Relais-Modul am Digital-Pin. Die folgende Tabelle zeigt jede einzelne Verbindung:

RC522 → Arduino UNO (SPI)

RC522 Pin Arduino UNO Pin Anmerkung
VCC 3.3 V Nicht 5 V! Siehe Warnung oben
RST D9 Reset-Leitung (konfigurierbar)
GND GND Gemeinsame Masse
MISO D12 SPI Master-In-Slave-Out
MOSI D11 SPI Master-Out-Slave-In
SCK D13 SPI Serial Clock
SDA (SS) D10 SPI Slave Select (Chip Select)

OLED Display SSD1306 → Arduino UNO (I2C)

OLED Pin Arduino UNO Pin
VCC 3.3 V oder 5 V (modulabhängig)
GND GND
SDA A4
SCL A5

Relais KY-019 → Arduino UNO

Relais Pin Arduino UNO Pin Anmerkung
VCC 5 V Spannungsversorgung für Relaisspule
GND GND Gemeinsame Masse
SIG D7 Steuersignal – HIGH = Relais geschaltet
NO + COM In Reihe mit Türöffner NO (Normally Open) schließt bei aktivem Relais

⚡ Relais & Freilaufdiode – warum ist das wichtig? Wenn ein Relais abschaltet, kollabiert das Magnetfeld der Spule und induziert einen Spannungsimpuls von mehreren hundert Volt (Lenzsche Regel). Ohne Freilaufdiode würde dieser Impuls den Arduino-Ausgangspin zerstören. Das KY-019-Modul hat bereits eine integrierte Freilaufdiode auf der Platine – du musst nichts zusätzlich einbauen. Die Diode leitet den Spannungsimpuls in einer geschlossenen Schleife ab („Freilaufkreis") und schützt so die Ausgangsstufe. Bei nackten Relais-Modulen ohne integrierte Diode müsstest du eine 1N4007 oder 1N4148 antiparallel zur Spule schalten.

Code-Stufe 1: RFID-Tag auslesen über Serial Monitor

Der sanfte Einstieg: Wir bringen das RC522 zum Laufen und geben jede erkannte Kartennummer im seriellen Monitor aus. Das ist die Basis für alles weitere – hier testest du, ob SPI-Kommunikation, Verkabelung und Bibliothek funktionieren.

Bibliotheken installieren

Öffne die Arduino IDE, gehe auf Werkzeuge → Bibliotheken verwalten und installiere:

  • MFRC522 von GithubCommunity (Miguel Balboa)
/*
 * Stufe 1 – RFID-Tag UID über Serial Monitor auslesen
 * Verkabelung: RC522 SPI → Arduino D9(RST), D10(SS), D11(MOSI), D12(MISO), D13(SCK)
 */

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

#define RST_PIN   9
#define SS_PIN    10

MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(9600);
  while (!Serial);

  SPI.begin();                    // SPI-Bus initialisieren
  mfrc522.PCD_Init();            // RC522 initialisieren
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);

  Serial.println(F("=== RFID Reader bereit ==="));
  Serial.println(F("Halte einen Tag oder eine Karte an den Leser..."));
  mfrc522.PCD_DumpVersionToSerial();  // Firmware-Version ausgeben
}

void loop() {
  // Suche nach neuen Karten – kein Tag in Reichweite?
  if (!mfrc522.PICC_IsNewCardPresent()) return;

  // UID auslesen – Anti-Kollision nicht erfolgreich?
  if (!mfrc522.PICC_ReadCardSerial()) return;

  // UID hexadezimal ausgeben
  Serial.print(F("Tag erkannt! UID: "));
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    if (mfrc522.uid.uidByte[i] < 0x10) Serial.print(F("0"));
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    Serial.print(F(" "));
  }
  Serial.println();

  // Kartentyp bestimmen und ausgeben
  Serial.print(F("Kartentyp: "));
  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  Serial.println(mfrc522.PICC_GetTypeName(piccType));

  // Kommunikation mit Tag beenden (in Standby versetzen)
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

Nach dem Upload öffnest du den seriellen Monitor (Strg+Umschalt+M) auf 9600 Baud. Hältst du jetzt einen der mitgelieferten Tags ans RC522, erscheint die UID – z. B. F3 9A 6C 1B. Notier dir diese UID – du brauchst sie für die nächste Stufe.

✅ Was dieser Code kann: SPI-Bus-Init, Tag-Erkennung mit Anti-Kollision, UID-Ausgabe und Kartentyperkennung. Wenn das läuft, funktioniert deine Hardware einwandfrei.

Code-Stufe 2: Autorisierter Zugang mit Master-Chip

Jetzt wird es praktisch: Wir hinterlegen eine Whitelist autorisierter UIDs direkt im Code. Nur diese Tags aktivieren das Relais für 3 Sekunden. Ein „Master-Tag" ist fest eingetragen – alle weiteren kannst du später im EEPROM speichern.

/*
 * Stufe 2 – RFID-Zutrittskontrolle mit Relais & Master-Chip
 * Autorisierte UIDs im Flash gespeichert (PROGMEM).
 * Relais: D7, aktiviert für 3000 ms nach gültigem Tag.
 */

#include <SPI.h>
#include <MFRC522.h>
#include <avr/pgmspace.h>

#define RST_PIN   9
#define SS_PIN    10
#define RELAY_PIN 7

MFRC522 mfrc522(SS_PIN, RST_PIN);

// --- AUTORISIERTE UIDs (HIER DEINE EIGENEN EINTRAGEN!) ---
// Format: {Länge, Byte0, Byte1, Byte2, Byte3}
const byte authorizedUIDs[][5] PROGMEM = {
  {4, 0xF3, 0x9A, 0x6C, 0x1B},  // Master-Tag (ersetzen mit deiner UID!)
  {4, 0xA1, 0xB2, 0xC3, 0xD4},  // Beispiel-Tag 2
};
const byte authorizedCount = sizeof(authorizedUIDs) / sizeof(authorizedUIDs[0]);

void setup() {
  Serial.begin(9600);
  while (!Serial);

  SPI.begin();
  mfrc522.PCD_Init();
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);

  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);  // Relais initial aus

  Serial.println(F("=== RFID Zutrittskontrolle bereit ==="));
  Serial.print(F("Autorisierte Tags: "));
  Serial.println(authorizedCount);
}

bool isAuthorized() {
  for (byte i = 0; i < authorizedCount; i++) {
    // UID-Länge prüfen
    if (pgm_read_byte(&authorizedUIDs[i][0]) != mfrc522.uid.size) continue;

    bool match = true;
    for (byte j = 0; j < mfrc522.uid.size; j++) {
      if (pgm_read_byte(&authorizedUIDs[i][j + 1]) != mfrc522.uid.uidByte[j]) {
        match = false;
        break;
      }
    }
    if (match) return true;
  }
  return false;
}

void unlockDoor() {
  Serial.println(F("✅ ZUGANG GEWÄHRT – Tür wird entriegelt"));
  digitalWrite(RELAY_PIN, HIGH);
  delay(3000);
  digitalWrite(RELAY_PIN, LOW);
  Serial.println(F("🔒 Tür wieder verriegelt"));
}

void loop() {
  if (!mfrc522.PICC_IsNewCardPresent()) return;
  if (!mfrc522.PICC_ReadCardSerial()) return;

  Serial.print(F("Tag UID: "));
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    if (mfrc522.uid.uidByte[i] < 0x10) Serial.print(F("0"));
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    Serial.print(F(" "));
  }

  if (isAuthorized()) {
    unlockDoor();
  } else {
    Serial.println(F(" X ZUGANG VERWEIGERT – Unbekannter Tag"));
    delay(1000);  // Anti-Brute-Force: 1 Sekunde Sperre nach Fehlversuch
  }

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

🔐 PROGMEM – UIDs sicher im Flash statt im RAM: Die autorisierten UIDs sind mit PROGMEM im Programm-Flash (32 KB) abgelegt, nicht im knappen SRAM (2 KB). Der Zugriff erfolgt über pgm_read_byte(). So hast du genug Platz für bis zu 100 Tags bei nur ~500 Byte Flash-Verbrauch, während das RAM für Bibliotheken und Laufzeitvariablen frei bleibt. Der delay(1000) nach Fehlversuchen ist eine einfache, aber effektive Brute-Force-Bremse – ohne sie könnte ein Angreifer hunderte Tags pro Sekunde durchprobieren.

Code-Stufe 3: OLED-Display + Admin-Modus zum Anlernen neuer Chips

Die finale Ausbaustufe: Ein OLED-Display zeigt Statusmeldungen, und ein Admin-Modus erlaubt das Anlernen neuer RFID-Tags ohne den Code ändern zu müssen. Neue UIDs werden im EEPROM gespeichert und überstehen einen Neustart. Der Master-Tag (definiert in MASTER_UID) aktiviert den Admin-Modus, wenn er 3 Sekunden lang an den Leser gehalten wird.

Zusätzliche Bibliothek installieren

  • Adafruit SSD1306 von Adafruit
  • Adafruit GFX Library von Adafruit
/*
 * Stufe 3 – RFID-Türschloss mit OLED-Display & Admin-Modus
 * Master-Tag 3s halten → Admin-Modus → neue Tags anlernen
 * Autorisierte Tags werden im EEPROM gespeichert.
 */

#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>

#define RST_PIN       9
#define SS_PIN        10
#define RELAY_PIN     7
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 64
#define OLED_ADDR     0x3C
#define EEPROM_START  0       // Startadresse im EEPROM
#define MAX_TAGS      50      // Maximale Anzahl speicherbarer Tags
#define UID_SIZE      4       // 4-Byte UIDs

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
MFRC522 mfrc522(SS_PIN, RST_PIN);

// Master-UID (3 Sekunden halten → Admin-Modus)
const byte MASTER_UID[] = {0xF3, 0x9A, 0x6C, 0x1B};  // DEINE UID!

byte tagCount = 0;              // Anzahl gespeicherter Tags
byte storedUIDs[MAX_TAGS][UID_SIZE];

// --- OLED-Helfer ---
void displayMessage(const char* line1, const char* line2) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);

  display.setCursor(0, 10);
  display.println(line1);

  display.setCursor(0, 35);
  display.setTextSize(1);
  display.println(line2);

  display.display();
}

void displayWelcome() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 15);
  display.println(F("RFID Tuerschloss"));
  display.setCursor(20, 40);
  display.println(F("Bereit..."));
  display.display();
}

// --- EEPROM: Tags laden & speichern ---
void loadTagsFromEEPROM() {
  tagCount = EEPROM.read(EEPROM_START);
  if (tagCount > MAX_TAGS) tagCount = 0;  // Ungültige Daten abfangen

  for (byte i = 0; i < tagCount; i++) {
    int addr = EEPROM_START + 1 + (i * UID_SIZE);
    for (byte j = 0; j < UID_SIZE; j++) {
      storedUIDs[i][j] = EEPROM.read(addr + j);
    }
  }
  Serial.print(F("Tags aus EEPROM geladen: "));
  Serial.println(tagCount);
}

bool saveTagToEEPROM(byte uid[]) {
  if (tagCount >= MAX_TAGS) return false;

  int addr = EEPROM_START + 1 + (tagCount * UID_SIZE);
  for (byte j = 0; j < UID_SIZE; j++) {
    EEPROM.update(addr + j, uid[j]);
  }
  tagCount++;
  EEPROM.update(EEPROM_START, tagCount);
  return true;
}

// --- UID-Vergleich ---
bool uidMatches(byte* a, byte* b) {
  for (byte i = 0; i < UID_SIZE; i++) {
    if (a[i] != b[i]) return false;
  }
  return true;
}

// --- Admin-Modus: Warte auf neuen Tag zum Anlernen ---
void adminMode() {
  displayMessage("ADMIN MODUS", "Neuen Tag anlernen...");
  Serial.println(F("=== Admin-Modus: Neuen Tag anlegen ==="));
  delay(1000);

  unsigned long start = millis();
  while (millis() - start < 15000) {  // 15s Timeout
    if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {

      // Master-Tag erneut erkannt → Admin-Modus verlassen
      if (uidMatches(mfrc522.uid.uidByte, (byte*)MASTER_UID)) {
        displayMessage("ADMIN MODUS", "Beendet.");
        Serial.println(F("Admin-Modus beendet."));
        mfrc522.PICC_HaltA();
        delay(1500);
        return;
      }

      // Prüfen, ob Tag bereits gespeichert ist
      for (byte i = 0; i < tagCount; i++) {
        if (uidMatches(mfrc522.uid.uidByte, storedUIDs[i])) {
          displayMessage("Bereits", "gespeichert!");
          Serial.println(F("Tag bereits vorhanden."));
          mfrc522.PICC_HaltA();
          delay(1000);
          return;
        }
      }

      // Neuen Tag speichern
      for (byte j = 0; j < UID_SIZE; j++) {
        storedUIDs[tagCount][j] = mfrc522.uid.uidByte[j];
      }

      if (saveTagToEEPROM(mfrc522.uid.uidByte)) {
        displayMessage("Tag gespeichert!", "Anzahl: ");
        Serial.print(F("Neuer Tag gespeichert. Gesamt: "));
        Serial.println(tagCount);
      } else {
        displayMessage("FEHLER", "Speicher voll!");
      }

      mfrc522.PICC_HaltA();
      delay(2000);
      return;
    }
  }

  displayMessage("ADMIN MODUS", "Timeout – beendet");
  delay(1500);
}

// --- Tür öffnen ---
void unlockDoor() {
  displayMessage("ZUGANG GEWAEHRT", "Tuer offen...");
  digitalWrite(RELAY_PIN, HIGH);
  delay(3000);
  digitalWrite(RELAY_PIN, LOW);
  Serial.println(F("Tür entriegelt (3s)"));
}

void setup() {
  Serial.begin(9600);
  while (!Serial);

  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);

  SPI.begin();
  mfrc522.PCD_Init();
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);

  // OLED initialisieren
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(F("OLED nicht gefunden!"));
    while (1);
  }
  displayWelcome();

  // Tags aus EEPROM laden
  loadTagsFromEEPROM();

  Serial.println(F("=== RFID Türschloss mit OLED bereit ==="));
  Serial.print(F("Administrator-Tag UID: "));
  for (byte i = 0; i < UID_SIZE; i++) {
    if (MASTER_UID[i] < 0x10) Serial.print(F("0"));
    Serial.print(MASTER_UID[i], HEX);
    Serial.print(F(" "));
  }
  Serial.println();
}

void loop() {
  // Prüfen, ob ein Tag dauerhaft am Leser anliegt (Admin-Modus)
  if (mfrc522.PICC_IsNewCardPresent()) {
    unsigned long start = millis();
    while (millis() - start < 3000) {
      if (mfrc522.PICC_ReadCardSerial()) {
        if (uidMatches(mfrc522.uid.uidByte, (byte*)MASTER_UID)) {
          // Master-Tag wurde 3s gehalten → Admin-Modus
          Serial.println(F("Master-Tag erkannt (lang) → Admin-Modus"));
          mfrc522.PICC_HaltA();
          adminMode();
          displayWelcome();
          return;
        }
        mfrc522.PICC_HaltA();
      }
      delay(50);
    }
  }

  if (!mfrc522.PICC_IsNewCardPresent()) return;
  if (!mfrc522.PICC_ReadCardSerial()) return;

  // UID ausgeben
  Serial.print(F("Tag: "));
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    if (mfrc522.uid.uidByte[i] < 0x10) Serial.print(F("0"));
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    Serial.print(F(" "));
  }

  // Autorisierungsprüfung
  bool authorized = false;

  // Zuerst Master-UID prüfen
  if (uidMatches(mfrc522.uid.uidByte, (byte*)MASTER_UID)) {
    authorized = true;
  }

  // Dann EEPROM-Tags durchsuchen
  if (!authorized) {
    for (byte i = 0; i < tagCount; i++) {
      if (uidMatches(mfrc522.uid.uidByte, storedUIDs[i])) {
        authorized = true;
        break;
      }
    }
  }

  if (authorized) {
    Serial.println(F("→ ZUGANG GEWÄHRT"));
    unlockDoor();
    displayWelcome();
  } else {
    Serial.println(F("→ ZUGANG VERWEIGERT"));
    displayMessage("ZUGANG VERWEIGERT", "Unbekannter Tag!");
    delay(1500);
    displayWelcome();
  }

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}

🎯 Was Stufe 3 alles kann: OLED-Statusanzeige mit Begrüßungsbildschirm, EEPROM-Persistenz für bis zu 50 Tags, Admin-Modus durch langes Halten des Master-Tags (3 s), visuelles Feedback bei Zugang oder Ablehnung, Timeout-basierte Sicherheit im Admin-Modus (15 s). Der Admin-Modus erkennt auch den Master-Tag erneut und beendet sich dann sauber – so kommst du jederzeit kontrolliert wieder raus.

Einbau & Montage – von der Breadboard-Schaltung zum fertigen Türschloss

1 Prototyp auf dem Breadboard

Baue die komplette Schaltung zunächst auf einem Breadboard auf. Halte die SPI-Verbindungen kurz (<15 cm), sonst drohen Signalreflexionen bei 4 MHz Takt. Das OLED-Display wird über I2C mit nur 4 Kabeln angeschlossen – praktisch kein Verdrahtungsaufwand.

2 Relais und Türöffner testen

Verbinde den COM- und NO-Anschluss (Normally Open) des KY-019 Relais in Reihe mit deinem elektrischen Türöffner (typischerweise 12 V DC oder AC). Das Relais fungiert als Schalter: Bei digitalWrite(RELAY_PIN, HIGH) wird der Stromkreis geschlossen. Teste zuerst mit einer 12-V-Lampe oder Summer statt direkt am Türöffner – so vermeidest du versehentliches Dauer-Entriegeln während der Entwicklung.

3 Gehäuse & Festeinbau

Für den Festeinbau empfehlen wir:

  • Arduino und Relais in ein ABS-Kunststoffgehäuse setzen – nicht leitend, leicht zu bohren
  • Das RC522-Modul hinter einer dünnen Kunststoff- oder Holzblende montieren (Metall schirmt das 13,56-MHz-Feld ab!)
  • Alle Anschlüsse mit dem JST-XH Stecker Set steckbar machen – dann kannst du das Modul jederzeit ohne Löten austauschen
  • Das OLED-Display sichtbar auf der Rauminnenseite platzieren

⚠️ Sicherheitshinweis zum Festeinbau: Ein selbstgebautes Türschloss ist ein Prototyp. Verwende es nie als einzige Zugangsmöglichkeit zu kritischen Räumen. Stelle sicher, dass der Türöffner auch mechanisch (von innen) betätigt werden kann – z. B. mit einem Panik-Notknopf oder klassischem Schlüssel als Backup. Bei Stromausfall muss der Raum weiterhin zugänglich sein. Denk auch an den Brandschutz: Ein Arduino, der im Fehlerfall das Relais dauerhaft auf HIGH hält, würde die Tür öffnen – das ist bei den meisten elektrischen Türöffnern der fail-safe-Modus und gewollt (Fluchtweg!).

Fehlerbehebung: Wenn's nicht auf Anhieb klappt

Problem Mögliche Ursache Lösung
RC522 erkennt keine Tags SPI-Verkabelungsfehler oder 5 V statt 3,3 V Alle SPI-Pins prüfen (D9–D13), VCC auf 3,3 V messen, SPI.begin() vor PCD_Init() sicherstellen
„Firmware-Version: 0x00" RC522 antwortet nicht – kein SPI-Kontakt SS-Pin auf D10 prüfen. Im Code MFRC522(SS_PIN, RST_PIN) muss mit der Verdrahtung übereinstimmen
OLED bleibt schwarz I2C-Adresse falsch oder Kabel vertauscht I2C-Scanner-Sketch ausführen. Adresse prüfen (meist 0x3C, manchmal 0x3D). SDA=A4, SCL=A5
Relais klickt nicht SIG-Pin falsch, Modul defekt, 5 V fehlt 5 V am VCC des Relaismoduls messen. SIG mit D7 testweise auf HIGH setzen
EEPROM speichert nicht Adresskonflikt oder Schreibschutz EEPROM.update() statt EEPROM.write() verwenden (verlängert Lebensdauer). Maximale Schreibzyklen: ~100.000
Zufällige Fehlauslösungen RC522 zu empfindlich oder EMV-Störungen Antennengain reduzieren: PCD_SetAntennaGain(RxGain_18dB), SPI-Kabel kürzen, Ferritkern am USB-Kabel

Erweiterungsideen für dein Türschloss

Dein System läuft und du willst mehr? Hier sind fünf Ideen, um das Türschloss auszubauen:

🔌 ESP32 statt Arduino

Ein ESP32 bringt WiFi und Bluetooth gleich mit – du kannst das Türschloss dann per App oder Webinterface bedienen, Logs an einen MQTT-Broker schicken oder die Zutrittshistorie in einer Datenbank speichern. Der RC522 läuft am ESP32 nativ auf 3,3 V – kein Logic-Level-Shifter nötig.

⌨️ PIN-Code als Zweitfaktor

Kombiniere RFID mit einer 4×4-Matrix-Tastatur: Zugang nur, wenn sowohl der richtige Tag als auch die richtige PIN eingegeben wird. Zwei-Faktor-Zutrittskontrolle für höhere Sicherheitsanforderungen.

📊 Web-Dashboard mit Zugriffslog

Speichere jeden Zutrittsversuch mit Zeitstempel auf einer SD-Karte oder sende ihn an einen Raspberry Pi. Ein simples Web-Dashboard zeigt dir, wer wann den Raum betreten (oder es versucht) hat.

📱 NFC-Handy als Schlüssel

Das RC522 kann auch NFC-Tags lesen. Dein Android-Handy im Card-Emulation-Modus sendet eine konfigurierbare UID – kein separater Tag nötig. iOS limitiert die NFC-Emulation allerdings stark.

🔊 Akustisches Feedback

Ein Piezo-Buzzer gibt unterschiedliche Tonsignale: kurzer Doppelton bei Zugang, langer tiefer Ton bei Ablehnung. Besonders praktisch, wenn das Display nicht direkt sichtbar ist.

🛒 Alle Bauteile direkt bei makeroo

Du hast alle Komponenten für dieses Projekt im Überblick. Hier findest du sie direkt in unserem Shop – versandfertig aus Deutschland, mit schneller Lieferung und fairen Preisen:

Komplettpaket-Preis: unter 25 € – für ein vollwertiges RFID-Zutrittssystem mit Display, das du komplett selbst programmiert und erweitert hast. Keine Abos, keine Cloud, keine Limitierungen.

Fazit: Dein eigenes RFID-Türschloss – unabhängig, günstig & unendlich erweiterbar

Du hast in diesem Tutorial gelernt:

  • Wie ein 13,56-MHz-RFID-System auf physikalischer Ebene arbeitet
  • Wie SPI-Kommunikation zwischen Arduino und RC522 auf den vier Busleitungen funktioniert
  • Wie du ein Relais mit integrierter Freilaufdiode korrekt beschaltest und warum das wichtig ist
  • Wie du UIDs im EEPROM speicherst, um Tags dauerhaft zu autorisieren
  • Wie du einen Admin-Modus baust, der neue Tags anlernt – ohne USB-Kabel und IDE
  • Wie du mit einem OLED-Display nutzerfreundliches Feedback gibst

Das Ergebnis ist kein Spielzeug, sondern ein ernstzunehmendes Zutrittssystem – gebaut für unter 25 €, vollständig verstanden und jederzeit erweiterbar. Genau das, was Maker begeistert.

Du hast Fragen zum Aufbau oder brauchst Hilfe bei der Fehlersuche? Schreib uns einfach – wir helfen gern.

Zurück zum Blog