Documentation

PN532 NFC RFID Reader Writer Module V3 13.56MHz | ShillehTek Product Manual
Documentation / PN532 NFC RFID Reader Writer Module V3 13.56MHz | ShillehTek Product Manual

PN532 NFC RFID Reader Writer Module V3 13.56MHz | ShillehTek Product Manual

shillehtek

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

Controller
NXP PN532
Frequency
13.56 MHz (NFC)
Interfaces
I2C / SPI / UART (HSU)
Tag Support
MIFARE, NTAG, ISO14443A
Supply Voltage
3.3V - 5V
Read Range
~3-7 cm

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.

PN532 NFC RFID module V3 pinout diagram showing SPI header, I2C UART header, S1 S2 mode switches and board dimensions

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
Warning: Set S1/S2 with the power off. If the sketch reports "Didn't find PN53x board," the switches are in the wrong position 9 times out of 10.

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
Note: The Adafruit PN532 library compiles unchanged for ESP32 in the Arduino IDE — the same sketch as the Uno works with these pins.

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
Tip: Enable I2C in raspi-config, then i2cdetect -y 1 should show the module at 0x24 before you run the Python example.

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_arduino.ino
// 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_esp32.ino
// 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)

pn532_rpi.py
#!/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_pico.py
# 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)

Frequently Asked Questions

"Didn't find PN53x board" — what do I check?
In order: the S1/S2 switches match the interface your code uses (this is the cause in most cases); wiring — SDA/SCL not swapped; power — the module wants a solid 3.3V or 5V; and finally the bus itself (i2cdetect on the Pi should show 0x24). The switches are tiny — use tweezers and confirm the printed ON direction rather than guessing.
Which interface should I pick — I2C, SPI, or UART?
I2C for most projects: two wires, shares the bus with other sensors, and has the best library support on Arduino, ESP32, and Pi. SPI when you want the fastest polling or your MicroPython driver expects it (as on the Pico). UART when the host is far away or you're talking to it like a serial peripheral (libnfc on the Pi supports HSU too). Functionally all three expose the same features.
Can it read the RFID cards from my RC522 kit? What about 125 kHz fobs?
13.56 MHz media — MIFARE Classic cards and fobs, NTAG stickers — yes, the PN532 reads everything the RC522 does and more. What it cannot read is 125 kHz low-frequency tags (EM4100 and similar "proximity" fobs): different radio band entirely, which needs an RDM6300-class reader. Check the card: 13.56 MHz cards usually respond to a phone's NFC, 125 kHz ones don't.
Can my phone interact with it?
Yes, three ways. A phone can read NTAG tags you've written with the module; the PN532 can operate peer-to-peer with a phone; and in card-emulation mode the module can present itself as a tag to the phone. The Arduino/ESP32 libraries expose card emulation and P2P as examples — fun for check-in badges that phones scan.
How do I write data to a tag, not just read the UID?
For NTAG/Ultralight, use the ntag2xx_WritePage() calls (Adafruit library) or write_ntag2xx via the Python lib — 4-byte pages, no authentication. For MIFARE Classic, authenticate a sector with its key (factory default FF:FF:FF:FF:FF:FF) before reading or writing its blocks. Storing a URL as an NDEF record makes phones open it automatically on tap.
What actually determines read range?
Antenna size on both sides. Full-size cards read at 5-7 cm; small fobs and stickers manage 2-4 cm. Metal surfaces behind the module or the tag kill range — keep the antenna loop away from metal or use on-metal tags. Supply quality matters too: RF transmit draws current spikes, so weak wiring shows up as flaky long-range reads.
Is a card UID secure enough for a door lock?
Treat UID-only matching as convenience-grade: UIDs are readable by anyone and special "magic" cards can clone them. It's fine for a workshop drawer or clock-in system. For real security, use MIFARE sector authentication with your own keys, or better, NTAG 424 / DESFire-class tags with cryptographic authentication — and pair the reader with server-side checks.

Related Tutorials