Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

RC522 RFID reader with ESP32 — SPI wiring and card UID code

Connect an RC522 RFID module to an ESP32 DevKit V1 over VSPI at 3.3 V and read card UIDs with the MFRC522 library.

Arduino C++Verified — core esp32 3.3.12, MFRC522 1.4.12, 3 Nov 2026Compile-only

Community draft — report a mistake

The RC522 reads 13.56 MHz MIFARE cards and tags — the blue cards that ship with most kits — and is the core of attendance and door-lock projects.

The ESP32 is a natural fit because both are 3.3 V: wire the four SPI lines plus RST and power, and the MFRC522 library does the rest. The sketch prints each card’s UID and type.

Wiring

ESP32 DevKit V1Only the pins used are shown · 3.3 V logicRC522 RFID reader (MFRC522, 13.56 MHz)GNDD23D22D19D18D43V3SDASCKMOSIMISOIRQ (not connected)GNDRST3.3V
Every connection
ESP32 DevKit V1RC522 RFID reader (MFRC522, 13.56 MHz)WireNotes
3V33.3VredThe RC522 is 3.3 V-only — never 5 V.
GNDGNDblack
D18SCKyellow
D19MISOblue
D23MOSIgreen
D4SDApurpleChip select (SS). The label “SDA” is historical — it is not I2C.
D22RSTorange

3.3 V only part, 3.3 V board. Power the RC522 from 3.3 V — never 5 V. The MFRC522 chip’s pins are not rated for 5 V either: many people wire it straight to an Uno and it works for a while, but for a build that lasts, drop the Uno’s SCK, MOSI, SDA (SS) and RST signals to 3.3 V with a level shifter or dividers. ESP32 and Pico connect directly.

Board quirks

  • Both sides run at 3.3 V, so unlike on an Uno there is no level shifting at all.
  • SCK/MISO/MOSI are the ESP32’s VSPI pins (18/19/23). Chip select is on GPIO4 rather than GPIO5 because GPIO5 is a boot-strapping pin.
  • IRQ is not needed — the library polls for cards.

Code

rc522-esp32.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// RC522 (MFRC522) RFID reader on an ESP32 DevKit V1 over SPI (VSPI).
// 3.3V → 3V3 (never 5 V), GND → GND, SCK → D18, MISO → D19, MOSI → D23, SDA(SS) → D4, RST → D22.
#include <SPI.h>
#include <MFRC522.h>

constexpr uint8_t SS_PIN = 4;
constexpr uint8_t RST_PIN = 22;

MFRC522 rfid(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(115200);
  SPI.begin(18, 19, 23, SS_PIN);  // SCK, MISO, MOSI, SS
  rfid.PCD_Init();
  byte v = rfid.PCD_ReadRegister(MFRC522::VersionReg);
  if (v == 0x00 || v == 0xFF) {
    Serial.println("RC522 not answering — check 3V3, SPI wiring and the SS/RST pins");
  } else {
    Serial.printf("RC522 ready (firmware 0x%02X). Tap a card…\n", v);
  }
}

void loop() {
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
  Serial.print("Card UID:");
  for (byte i = 0; i < rfid.uid.size; i++) Serial.printf(" %02X", rfid.uid.uidByte[i]);
  Serial.printf("  (%s)\n", rfid.PICC_GetTypeName(rfid.PICC_GetType(rfid.uid.sak)));
  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
}

Library: MFRC522 (GithubCommunity) — compiled with MFRC522 1.4.12.

Expected serial output

Serial Monitor · 115200Output
RC522 ready (firmware 0x92). Tap a card…
Card UID: 4A 3F 9C 2B  (MIFARE 1KB)
Card UID: 04 6E 21 A2 4F 61 80  (MIFARE Ultralight or Ultralight C)

Common errors

“RC522 not answering” (firmware 0x00 or 0xFF)

SPI wiring or chip select. Check SDA is on GPIO4 and RST on GPIO22, and that the module has 3.3 V.

Cards read only when touching the antenna

Normal range is 2–4 cm. Keep metal away from the antenna and the wires short.

↑↓ to move · Enter to open