Overview
The PN532 V3 is the most capable NFC module in the hobby ecosystem. Built around NXP's PN532 controller with a large onboard antenna loop, it reads and writes 13.56 MHz tags — MIFARE Classic 1K/4K cards and fobs, NTAG21x stickers, and other ISO14443A media — at a range of several centimeters, and it can even talk to smartphones over peer-to-peer NFC or emulate a card itself.
Its party trick is speaking three interfaces from one board: I2C, SPI, and high-speed UART. Two tiny DIP switches (S1, S2) select the mode, so the same module drops into an I2C-only Arduino build, an SPI Pico project, or a UART link to a Pi. Most people run I2C — two wires, address 0x24 internally handled by the libraries — which is what the wiring below defaults to wherever possible.
Typical builds: door access with a whitelist of card UIDs, attendance and check-in systems, NFC-triggered scenes in home automation, tabletop-game pieces that identify themselves, and writing URL tags that phones open on tap. Everything runs at 3.3V logic internally with 5V-tolerant regulation on VCC, so it wires directly to every board in this guide.
At a Glance
Specifications
| Parameter | Value |
| Chipset | NXP PN532 NFC controller |
| Operating Frequency | 13.56 MHz |
| Supported Tags | MIFARE Classic 1K/4K, MIFARE Ultralight, NTAG213/215/216, ISO14443A |
| Modes | Reader/writer, card emulation, peer-to-peer |
| Interfaces | I2C (default addr 0x24), SPI, HSU UART (115200 baud) |
| Mode Select | S1/S2 DIP: UART = 0/0, I2C = 1/0, SPI = 0/1 |
| Supply Voltage | 3.3V - 5V DC (onboard regulation) |
| Current Draw | ~50 mA active RF, ~20 mA idle |
| Read Range | 3-7 cm depending on tag size |
| Board Size | 42.7 x 40.4 mm |
| Extras | IRQ and RSTO pins on the SPI header |
Pinout Diagram
The top header carries the SPI bus (SCK, MISO, MOSI, SS) plus VCC, GND, IRQ, and RSTO. The left header is the I2C/UART side: GND, VCC, SDA/TXD, SCL/RXD — the same two signal pins serve as I2C or UART depending on the S1/S2 switches. Set the switches before power-up: I2C = S1 ON, S2 OFF; SPI = S1 OFF, S2 ON; UART = both OFF.
Wiring Guide
Arduino Wiring (I2C mode: S1=ON, S2=OFF)
| PN532 Pin | Arduino Pin | Details |
|---|---|---|
| VCC | 5V | |
| GND | GND | |
| SDA/TXD | A4 (SDA) | I2C data |
| SCL/RXD | A5 (SCL) | I2C clock |
ESP32 Wiring (I2C mode: S1=ON, S2=OFF)
| PN532 Pin | ESP32 Pin | Details |
|---|---|---|
| VCC | 3V3 | |
| GND | GND | |
| SDA/TXD | GPIO 21 | I2C data |
| SCL/RXD | GPIO 22 | I2C clock |
Raspberry Pi Wiring (I2C mode: S1=ON, S2=OFF)
| PN532 Pin | Pi Pin | Details |
|---|---|---|
| VCC | Pin 1 (3.3V) | |
| GND | Pin 6 (GND) | |
| SDA/TXD | Pin 3 (GPIO 2) | I2C1 SDA |
| SCL/RXD | Pin 5 (GPIO 3) | I2C1 SCL |
Raspberry Pi Pico Wiring (SPI mode: S1=OFF, S2=ON)
The most solid MicroPython driver for the PN532 uses SPI, so the Pico wiring uses the top header.
| PN532 Pin | Pico Pin | Details |
|---|---|---|
| VCC / GND | 3V3(OUT) / GND | |
| SCK | GP2 (SPI0 SCK) | |
| MISO | GP4 (SPI0 RX) | |
| MOSI | GP3 (SPI0 TX) | |
| SS | GP5 | Chip select |
Code Examples
Each example initializes the module, reports its firmware version, then polls for cards and prints each tag's UID — the foundation of any access-control or check-in project.
Arduino
// PN532 NFC Module V3 - Arduino Example (I2C mode)
// SDA->A4, SCL->A5, VCC->5V | S1=ON, S2=OFF
// Library: "Adafruit PN532" (Library Manager)
#include <Wire.h>
#include <Adafruit_PN532.h>
Adafruit_PN532 nfc(-1, -1, &Wire); // I2C, no IRQ/RSTO pins needed
void setup() {
Serial.begin(115200);
nfc.begin();
uint32_t version = nfc.getFirmwareVersion();
if (!version) {
Serial.println("Didn't find PN53x board - check S1/S2 and wiring");
while (1);
}
Serial.print("Found PN5");
Serial.println((version >> 24) & 0xFF, HEX);
nfc.SAMConfig(); // enable reader mode
Serial.println("Tap a card or tag...");
}
void loop() {
uint8_t uid[7];
uint8_t uidLength;
if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 500)) {
Serial.print("Card UID: ");
for (uint8_t i = 0; i < uidLength; i++) {
if (uid[i] < 0x10) Serial.print("0");
Serial.print(uid[i], HEX);
if (i < uidLength - 1) Serial.print(":");
}
Serial.println();
delay(1000); // debounce same-card reads
}
}
ESP32 (Arduino IDE)
// PN532 NFC Module V3 - ESP32 Example (I2C mode)
// SDA->GPIO 21, SCL->GPIO 22, VCC->3V3 | S1=ON, S2=OFF
// Library: "Adafruit PN532"
#include <Wire.h>
#include <Adafruit_PN532.h>
Adafruit_PN532 nfc(-1, -1, &Wire);
// Example whitelist: replace with your own card UID
const uint8_t DOOR_CARD[4] = {0xDE, 0xAD, 0xBE, 0xEF};
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
nfc.begin();
if (!nfc.getFirmwareVersion()) {
Serial.println("PN532 not found - check S1/S2 switches");
while (1) delay(10);
}
nfc.SAMConfig();
Serial.println("Tap a card or tag...");
}
void loop() {
uint8_t uid[7];
uint8_t len;
if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &len, 500)) {
Serial.print("UID: ");
for (uint8_t i = 0; i < len; i++) {
Serial.printf("%02X", uid[i]);
if (i < len - 1) Serial.print(":");
}
bool match = (len == 4) && !memcmp(uid, DOOR_CARD, 4);
Serial.println(match ? " -> ACCESS GRANTED" : " -> unknown card");
delay(1000);
}
}
Raspberry Pi (Python)
#!/usr/bin/env python3
# PN532 NFC Module V3 - Raspberry Pi Example (I2C mode)
# SDA->GPIO2, SCL->GPIO3, VCC->3.3V | S1=ON, S2=OFF
# Install: pip3 install adafruit-circuitpython-pn532
import time
import board
import busio
from adafruit_pn532.i2c import PN532_I2C
i2c = busio.I2C(board.SCL, board.SDA)
pn532 = PN532_I2C(i2c, debug=False)
ic, ver, rev, support = pn532.firmware_version
print("Found PN532 firmware {}.{}".format(ver, rev))
pn532.SAM_configuration()
print("Tap a card or tag...")
seen = None
try:
while True:
uid = pn532.read_passive_target(timeout=0.5)
if uid is not None:
uid_str = ":".join("{:02X}".format(b) for b in uid)
if uid_str != seen:
print("Card UID:", uid_str)
seen = uid_str
else:
seen = None
time.sleep(0.1)
except KeyboardInterrupt:
print("Stopped by user")
Raspberry Pi Pico (MicroPython, SPI)
# PN532 NFC Module V3 - Pico MicroPython Example (SPI mode)
# SCK->GP2, MOSI->GP3, MISO->GP4, SS->GP5 | S1=OFF, S2=ON
# Driver: copy NFC_PN532.py (micropython PN532 SPI driver) to the Pico
# from https://github.com/Carglglz/NFC_PN532 (save as NFC_PN532.py)
from machine import Pin, SPI
import NFC_PN532 as nfc_mod
import time
spi = SPI(0, baudrate=1000000,
sck=Pin(2), mosi=Pin(3), miso=Pin(4))
cs = Pin(5, Pin.OUT, value=1)
nfc = nfc_mod.PN532(spi, cs)
ic, ver, rev, support = nfc.get_firmware_version()
print("Found PN532 firmware {}.{}".format(ver, rev))
nfc.SAM_configuration()
print("Tap a card or tag...")
while True:
uid = nfc.read_passive_target(timeout=500)
if uid:
print("Card UID:", ":".join("{:02X}".format(b) for b in uid))
time.sleep(1)
time.sleep(0.1)