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 Raspberry Pi Pico W — read card UIDs in MicroPython

Read RFID card and key-fob UIDs with an RC522 on Pico W SPI0 (GP16–GP20) in MicroPython, with a small included driver and an access-granted demo.

MicroPythonVerified — micropython (mpy-cross v1.29.0), 3 Nov 2026Compile-only

Community draft — report a mistake

The RC522 is the cheapest way to read RFID cards and key fobs, and it is a 3.3 V part — so on a Pico W every wire goes straight to a GPIO. It talks SPI, here on SPI0 (GP16–GP19) with RST on GP20.

MicroPython has no built-in RC522 driver, so the sketch includes a compact one. Tap a card and the script prints its UID; add your UID to the allowed list to try the access-control demo.

Wiring

Raspberry Pi Pico WOnly the pins used are shown · 3.3 V logicRC522 RFID reader (MFRC522, 13.56 MHz)GND3V3GP20GP19GP18GP17GP16SDASCKMOSIMISOIRQ (not connected)GNDRST3.3V
Every connection
Raspberry Pi Pico WRC522 RFID reader (MFRC522, 13.56 MHz)WireNotes
GP17SDAorangeChip select (SPI0 CSn), physical pin 22. “SDA” is just the RC522’s name for SS.
GP18SCKyellowSPI0 SCK, physical pin 24.
GP19MOSIgreenSPI0 TX, physical pin 25.
GP16MISOblueSPI0 RX, physical pin 21.
GNDGNDblack
GP20RSTpurplePhysical pin 26.
3V33.3Vred3V3 is pin 36. Never 5 V.

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 RC522 is 3.3 V only — a perfect match for the Pico. Every pin connects directly; leave IRQ unconnected.
  • Copy mfrc522.py (a 120-line driver written for FlashReady from the NXP datasheet, MIT) to the board. It reads the 4-byte UID of MIFARE Classic cards and fobs — what door locks and attendance systems use.
  • Put your card’s UID (printed when you tap it) into ALLOWED to see the “access granted” demo light the on-board LED.
  • A UID is not a secret: cheap writable cards can copy it. Fine for a hobby attendance register, not for a real door lock on its own.

Code

main.pyMicroPython
# RC522 RFID reader on a Raspberry Pi Pico W (MicroPython): print the UID of each card or key fob.
# Wiring (SPI0): 3.3V -> 3V3 (pin 36), GND -> GND, SCK -> GP18 (pin 24), MOSI -> GP19 (pin 25),
# MISO -> GP16 (pin 21), SDA (chip select) -> GP17 (pin 22), RST -> GP20 (pin 26). IRQ unconnected.
# Copy mfrc522.py to the board too.
from machine import Pin, SPI
import time
from mfrc522 import MFRC522, OK

ALLOWED = ["A1B2C3D4"]  # put your own card's UID here for the "access granted" demo

spi = SPI(0, baudrate=1_000_000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
reader = MFRC522(spi, cs=Pin(17), rst=Pin(20))
led = Pin("LED", Pin.OUT)

v = reader.version()
if v in (0x00, 0xFF):
    raise SystemExit("RC522 not answering (version 0x%02X) - check SPI wiring and 3.3 V" % v)
print("RC522 ready, version 0x%02X - hold a card near the reader" % v)

last_uid = None
last_seen = 0
while True:
    if reader.request() == OK:
        stat, uid = reader.uid()
        if stat == OK:
            tag = "".join("{:02X}".format(b) for b in uid)
            now = time.ticks_ms()
            if tag != last_uid or time.ticks_diff(now, last_seen) > 2000:
                ok = tag in ALLOWED
                print("Card UID {}  ->  {}".format(tag, "access granted" if ok else "unknown card"))
                led.value(ok)
                last_uid = tag
            last_seen = now
    elif last_uid and time.ticks_diff(time.ticks_ms(), last_seen) > 1000:
        led.off()
        last_uid = None
    time.sleep_ms(50)

Expected serial output

REPL / Thonny shellOutput
RC522 ready, version 0x92 - hold a card near the reader
Card UID 73A1C4E9  ->  unknown card
Card UID A1B2C3D4  ->  access granted

Common errors

RC522 not answering (version 0x00)

SPI wiring: SCK GP18, MOSI GP19, MISO GP16, SDA GP17. Also check 3.3 V and that RST is on GP20.

Version reads 0x12 or 0x88

A clone chip — usually still works. If cards are never seen, hold them flat and close (under 3 cm).

Phone NFC or metro card not detected

The RC522 reads ISO 14443A (MIFARE). Many transit and bank cards are other types or encrypted; phones emulate cards only in payment apps.

↑↓ to move · Enter to open