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 with Wemos D1 mini — SPI wiring and UID check

Wire an RC522 RFID reader to a Wemos D1 mini on D5–D8 with RST on D0, read card UIDs with the MFRC522 library and check them against an allowed card.

Arduino C++Verified — core esp8266 3.1.2, MFRC522 1.4.12, 3 Nov 2026Compile-only

Community draft — report a mistake

An RC522 reader on a D1 mini is the core of a Wi-Fi attendance register or a door lock that logs who came in. It talks SPI, and the ESP8266’s hardware SPI is fixed to D5, D6 and D7, with D8 as chip select and D0 for reset.

That uses six of the D1 mini’s eleven pins, so it is worth planning: D1/D2 stay free for an OLED or LCD, and nothing touches the boot pins D3 and D4. The sketch prints each card’s UID and checks it against one allowed card — paste your own UID into ALLOWED_UID.

Wiring

Wemos D1 miniOnly the pins used are shown · 3.3 V logicRC522 RFID reader (MFRC522, 13.56 MHz)D0D5D6D7D83V3GNDSDASCKMOSIMISOIRQ (not connected)GNDRST3.3V
Every connection
Wemos D1 miniRC522 RFID reader (MFRC522, 13.56 MHz)WireNotes
3V33.3VredNever 5V — the RC522 is a 3.3 V part.
GNDGNDblack
D5SCKyellowD5 = GPIO14, hardware SPI clock.
D6MISOgreenD6 = GPIO12.
D7MOSIblueD7 = GPIO13.
D8SDApurpleThe RC522’s SDA is its SPI chip select. D8 = GPIO15, the hardware CS.
D0RSTorangeD0 = GPIO16: a plain output is all RST needs.

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

  • The ESP8266’s hardware SPI is fixed to D5 (SCK), D6 (MISO), D7 (MOSI), and SPI.begin() takes no pin arguments on this core. The RC522 uses six of the D1 mini’s eleven GPIOs; D1/D2 are left for an I2C display.
  • Chip select on D8 (GPIO15) is safe: the board pulls it low for booting, and the RC522’s SDA input doesn’t fight that. Don’t add a pull-up to D8 — the board won’t boot.
  • RST goes on D0, which has no interrupt or PWM but is perfect for a simple output. That keeps D3/D4 (boot pins) out of the circuit. If you later want deep sleep, D0 is needed for the RST jumper — move the RC522 RST to D3 then.
  • IRQ is not connected; the library polls the reader.
  • A UID is not a password: most cheap 13.56 MHz cards can be cloned. Fine for attendance or a hobby lock, not for anything that needs real security.

Code

rc522-d1mini.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// RC522 RFID reader on a Wemos D1 mini (ESP8266), hardware SPI.
// 3.3V → 3V3, GND → GND, SCK → D5, MISO → D6, MOSI → D7, SDA (chip select) → D8, RST → D0.
// Prints each card's UID and checks it against one allowed card.
#include <SPI.h>
#include <MFRC522.h>

const uint8_t SS_PIN = D8;   // GPIO15: hardware CS, pulled low on the board so it boots fine
const uint8_t RST_PIN = D0;  // GPIO16: a plain output is all RST needs, keeps D1-D4 free
MFRC522 rfid(SS_PIN, RST_PIN);

const char* ALLOWED_UID = "DE AD BE EF";  // replace with your card's UID as printed below

void setup() {
  Serial.begin(115200);
  Serial.println();
  SPI.begin();  // ESP8266 HSPI: SCK = D5, MISO = D6, MOSI = D7
  rfid.PCD_Init();
  byte v = rfid.PCD_ReadRegister(MFRC522::VersionReg);
  if (v == 0x00 || v == 0xFF) {
    Serial.println("RC522 not answering - check 3.3V, SDA on D8 and the SPI wires");
  } else {
    Serial.printf("RC522 ready (version 0x%02X) - tap a card\n", v);
  }
}

void loop() {
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) {
    delay(50);
    return;
  }
  char uid[32] = "";
  for (byte i = 0; i < rfid.uid.size && i < 10; i++) {
    char b[4];
    snprintf(b, sizeof b, i ? " %02X" : "%02X", rfid.uid.uidByte[i]);
    strcat(uid, b);
  }
  MFRC522::PICC_Type type = rfid.PICC_GetType(rfid.uid.sak);
  Serial.printf("UID %s  (", uid);
  Serial.print(rfid.PICC_GetTypeName(type));  // a flash string (F("...")), so print it on its own
  Serial.printf(")  %s\n", strcmp(uid, ALLOWED_UID) == 0 ? "ALLOWED" : "denied");
  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
}

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

Expected serial output

Serial Monitor · 115200Output
RC522 ready (version 0x92) - tap a card
UID 93 4A 1C 0E  (MIFARE 1KB)  denied
UID DE AD BE EF  (MIFARE 1KB)  ALLOWED

Common errors

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

Check 3.3V power, SDA on D8, and that MISO/MOSI are not swapped. Full fix.

Version 0x12 or 0x88 and some cards don’t read

Clone chips report odd versions but usually work. Hold the card flat and close — the antenna range is only 2–3 cm.

Board won’t boot with the reader connected

Something is pulling D8 high at reset. Use a plain RC522 module without extra pull-ups on SDA, or move CS to D1/D2 and pass that pin to the constructor.

↑↓ to move · Enter to open