adafruit_pn532
Works with
Any board with I2C or SPI. The PN532 breakout board supports both interfaces — select with jumpers.
What it does
adafruit_pn532 drives the PN532 NFC/RFID controller chip, which can read and write NFC tags and cards. It works with MIFARE Classic (the most common access card format), MIFARE Ultralight, and NTAG2xx tags (the sticker-style NFC tags used with phones). You can read a tag's unique UID for identification, read data blocks for more detailed information, and write data to blank tags. Common use cases include access control, event attendance tracking, interactive art installations, NFC-triggered actions, and building prop replicas with embedded tags.
The library supports the PN532 over both I2C and SPI. SPI gives slightly faster communication; I2C uses fewer pins.
Installing the library
Copy all of the following to CIRCUITPY/lib/:
adafruit_pn532/(folder)adafruit_bus_device/(folder)
Quick start
import board
import busio
import adafruit_pn532.i2c
# I2C connection
i2c = busio.I2C(board.SCL, board.SDA)
pn532 = adafruit_pn532.i2c.PN532_I2C(i2c, debug=False)
# Configure the chip for reading passive NFC tags
pn532.SAM_configuration()
print("PN532 ready. Firmware version:", pn532.firmware_version)
print("Waiting for NFC tag...")
while True:
uid = pn532.read_passive_target(timeout=0.5)
if uid is not None:
print("Tag found! UID:", [hex(i) for i in uid])
# Read a block of data from a MIFARE Classic card
# (requires authentication first)
key_a = b"\xFF\xFF\xFF\xFF\xFF\xFF" # default factory key
authenticated = pn532.mifare_classic_authenticate_block(
uid, block_number=4, key_number=0x60, key=key_a
)
if authenticated:
data = pn532.mifare_classic_read_block(4)
print("Block 4 data:", data)
# Write to an NTAG2xx tag (no auth needed)
# pn532.ntag2xx_write_block(4, b"Hello World! ")
Key things you can do
| What you want | How to do it |
|---|---|
| Initialize over I2C | PN532_I2C(i2c) then pn532.SAM_configuration() |
| Initialize over SPI | PN532_SPI(spi, cs) then pn532.SAM_configuration() |
| Wait for and read a tag's UID | uid = pn532.read_passive_target(timeout=0.5) — returns bytes or None |
| Check firmware version | pn532.firmware_version |
| Authenticate a MIFARE Classic block | pn532.mifare_classic_authenticate_block(uid, block, key_number, key) |
| Read a MIFARE Classic block | pn532.mifare_classic_read_block(block_number) |
| Write a MIFARE Classic block | pn532.mifare_classic_write_block(block_number, data) — 16 bytes |
| Read an NTAG2xx page | pn532.ntag2xx_read_block(page) |
| Write an NTAG2xx page | pn532.ntag2xx_write_block(page, data) — 4 bytes |
| Compare UIDs | if uid == expected_uid: |
| Detect tag type from UID length | 4-byte UID = MIFARE Classic, 7-byte = MIFARE Ultralight/NTAG |
Reading the official docs
Full API reference: https://docs.circuitpython.org/projects/pn532/en/latest/
Projects using this library
- Adafruit PN532 NFC/RFID Controller — complete guide covering wiring, reading tags, writing data, and project ideas