Community project

RFID Tag Reader

Photo of RFID Tag Reader
Generated with AI

Abubakar Iqbal

Published November 3, 2026

This project builds an RFID tag reader using an ESP32 microcontroller and a PN532 NFC module communicating over I2C. The reader detects NFC tags and cards within range, displays the unique identifier (UID) on the serial monitor, and provides visual feedback through green and red LEDs.

The guide includes a complete wiring diagram showing how to connect the PN532 module to the ESP32's I2C pins, a full parts list, step-by-step assembly instructions, and ready-to-upload firmware. By the end, the reader will scan your own NFC tags and report their UIDs, making it a foundation for access control, inventory tracking, or interactive projects.

Wiring diagram

Loading diagram…

Gather all the parts

QtyComponent
1

LED

green 5 mm

Standard 3mm/5mm through-hole LED. A current-limiting series resistor is added automatically.

1

LED

red 5 mm

Standard 3mm/5mm through-hole LED. A current-limiting series resistor is added automatically.

1

Resistor

220 Ω, 1/4 W

Through-hole resistor (current-limiting in series with an LED)

1

Resistor

220 Ω, 1/4 W

Through-hole resistor (current-limiting in series with an LED)

1

PN532 NFC Module (I2C Mode)

NXP PN532-based NFC/RFID reader-writer module supporting ISO 14443A/B, MIFARE, NTAG213, NTAG215, and NTAG216 tags. Supports three interface modes (I2C, SPI, HSU/UART) selected by on-board DIP switches. I2C mode: both DIP switches set to ON (SW1=ON, SW2=ON). I2C address 0x24. Operates at 3.3 V, compatible directly with ESP32 without level shifting. On-board pull-up resistors provided for I2C lines.

Assemble it in 7 steps

1. Set the PN532 reader to I²C mode

With the ESP32 unplugged, find the two small mode switches on your PN532 board. Set both switches to ON for I²C mode; this is the setting that lets the reader use the two data wires below.

  • Check the switch labels printed on the board; the PN532 reader’s manual calls this I²C mode.
  • Do not change these switches while the board is powered, because an accidental short can damage the reader.

2. Place the parts without power

Put the ESP32 DevKit v1, PN532 reader, two 220 Ω resistors, and the red and green LEDs on a breadboard. Keep the PN532 antenna facing upward and leave the ESP32 unplugged while making connections.

  • The LED’s long leg is the positive leg; the short leg and flat edge are the negative side.

3. Connect power to the NFC reader

Connect PN532 VCC to the ESP32 3V3 pin (power), and connect PN532 GND to an ESP32 GND pin (ground).

  • These wires give both boards the same voltage reference.
  • Do not connect PN532 VCC to 5 V; this project uses the ESP32’s 3.3 V pin, and swapped power wires can damage the reader.

4. Connect the two reader data wires

Connect PN532 SDA to ESP32 GPIO21 (data), and PN532 SCL to ESP32 GPIO22 (clock). Leave the optional PN532 IRQ and RSTO pins unconnected.

  • Follow the small SDA and SCL labels printed next to the PN532 header pins; a wire in the wrong breadboard row stops the reader from responding.

5. Add the green scan light

Connect ESP32 GPIO25 to one leg of green_resistor (signal), connect its other leg to the long leg of green_led (current limiting), then connect the short leg of green_led to ESP32 GND (ground).

  • The resistor can face either direction; it prevents too much current from damaging the LED.

6. Add the red warning light

Connect ESP32 GPIO26 to one leg of red_resistor (signal), connect its other leg to the long leg of red_led (current limiting), then connect the short leg of red_led to ESP32 GND (ground).

  • Keep each LED’s long leg in a separate breadboard row so the two lights cannot touch.

7. Test with your own NFC tag

Hold an NFC tag, card, or phone tag you own flat against the PN532 antenna. When it is detected, the green LED flashes and its ID is printed over USB.

  • The tag reads best within a few centimetres with its flat face parallel to the antenna.
  • Use this project only with tags and systems you own or are authorised to test.

Review all connections

1. Connections between "green_resistor" and "ESP32"

Functiongreen_resistorESP32
digitalP1 → green status-light signalGPIO 25
digitalP2 → LED ANODEEXT

2. Connections between "green_led" and "ESP32"

Functiongreen_ledESP32
groundGND → green LED ground returnGND

3. Connections between "red_resistor" and "ESP32"

Functionred_resistorESP32
digitalP1 → red status-light signalGPIO 26
digitalP2 → LED ANODEEXT

4. Connections between "red_led" and "ESP32"

Functionred_ledESP32
groundGND → red LED ground returnGND

5. Connections between "pn532_reader" and "ESP32"

Functionpn532_readerESP32
powerVCC → PN532 3.3 V power3V3
groundGND → common groundGND
i2cSDA → I2C dataGPIO 21
i2cSCL → I2C clockGPIO 22

Deploy the firmware

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_PN532.h>

constexpr uint8_t PN532_SDA_PIN = 21;
constexpr uint8_t PN532_SCL_PIN = 22;
constexpr uint8_t GREEN_LED_PIN = 25;
constexpr uint8_t RED_LED_PIN = 26;

// I2C mode does not need the optional IRQ or reset wires.
Adafruit_PN532 nfc(-1, -1, &Wire);

void flashLed(uint8_t pin, uint16_t durationMs) {
  digitalWrite(pin, HIGH);
  delay(durationMs);
  digitalWrite(pin, LOW);
}

void printUid(const uint8_t *uid, uint8_t uidLength) {
  Serial.print("NFC UID: ");
  for (uint8_t i = 0; i < uidLength; ++i) {
    if (uid[i] < 0x10) {
      Serial.print('0');
    }
    Serial.print(uid[i], HEX);
    if (i + 1 < uidLength) {
      Serial.print(':');
    }
  }
  Serial.println();
}

void setup() {
  Serial.begin(115200);
  pinMode(GREEN_LED_PIN, OUTPUT);
  pinMode(RED_LED_PIN, OUTPUT);
  digitalWrite(GREEN_LED_PIN, LOW);
  digitalWrite(RED_LED_PIN, LOW);

  Wire.begin(PN532_SDA_PIN, PN532_SCL_PIN);
  nfc.begin();

  uint32_t version = nfc.getFirmwareVersion();
  if (version == 0) {
    Serial.println("PN532 not found. Check power, SDA/SCL wires, and set both PN532 switches to I2C mode.");
    flashLed(RED_LED_PIN, 500);
    return;
  }

  nfc.SAMConfig();
  Serial.println("PN532 ready. Hold an NFC tag or card you own near the antenna.");
  flashLed(GREEN_LED_PIN, 120);
}

void loop() {
  uint8_t uid[7] = {0};
  uint8_t uidLength = 0;
  bool tagFound = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 100);

  if (!tagFound) {
    delay(20);
    return;
  }

  printUid(uid, uidLength);
  flashLed(GREEN_LED_PIN, 180);
  delay(250);
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace, diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik