IOT

How to interface PN532 NFC RFID Module with Arduino

If you’re familiar with electronics, you’ve probably heard of RFID (radio-frequency identification) and NFC (near-field communication) (near-field-communication). The PN532 module is an RFID-NFC module that communicates via I2C, SPI, and HSU protocols.

In this tutorial, we will use the UART, I2C, and SPI modes to connect the PN532 NFC RFID Module to the Arduino Board. Later we will display the UID numbers of the NFC card on a 0.96″ OLED Display.

The PN532 is a common NFC RFID module for facilitating mobile payments and serving as a tool for other smartphone communications. It’s incorporated in modules that make it simple to pair with your Arduino creations.

Hardware Components

  • Arduino UNO R3
  • PN532 NFC Module
  • 0.96 inch OLED Display
  • Male to Female jumper wire

Software Apps

Arduino IDE

What is NFC?

Near Field Communication (NFC) is a technology standard that uses Radio Frequency Identification (RFID) to wirelessly communicate data across short distances. Consumers all over the world benefit from NFC technology because it makes it easier to perform purchases, share digital content, and link electronic devices with a single touch. Hundreds of millions of contactless cards and readers are already in use around the world.

PN532 NFC RFID Module

PN532 NFC Module is a highly integrated radio transmission module for Near Field Communication at 13.56MHz. NFC (Near Field Communication) protocol designed for smartphones and similar devices, can read and write cards and tags, interact with NFC phones, and enable communication from device to device.

NXP’s PN532 NFC controller is based on the 80C51 microcontroller and supports contactless communication at a frequency of 13.56 MHz. Furthermore, the MIFARE Classic 1K/MIFARE Classic 4K card support allows higher transfer speeds in both directions of up to 424 kbit/s. It has a 40-kilobyte ROM and a one-kilobyte RAM. It’s used to make ISO14443 cards look real. The ISO/IEC 14443 set of standards defines the parameters for international interchangeable identity cards and objects.

Features:

  • 80C51 microcontroller core with 40 KB ROM and 1 KB RAM
  • Highly integrated demodulator and decoder
  • Integrated RF level detector
  • Supports ISO/IEC 14443A/MIFARE
  • Supports ISO/IEC 14443B (Reader/Writer mode only)
  • Up to 50mm of operating distance in Reader/Writer mode for communication to ISO/IEC 14443A/MIFARE, ISO/IEC 14443B, or FeliCa cards
  • Up to 50mm of operating distance in NFCIP-1 depending on antenna size, tuning, and power supply
  • Approximately 100mm of operating distance in ISO/IEC 14443A/MIFARE or FeliCa card emulation mode
  • Possibility to communicate on the RF interface above 424 kbit/s using external analog components
  • Dedicated host interrupts
  • Low power modes
    • Hard-Power-Down mode
    • Soft-Power-Down mode
  • Programmable timers
  • Crystal oscillator
  • 2.7 to 5.5 V power supply operating range

Selection of the communication mode

One of the biggest benefits of the PN532 NFC module is that it can connect with Arduino using a variety of protocols, including UART, I2C, and SPI. These various protocols take advantage of the microcontroller’s unique pins and libraries.

PN532 NFC RFID Module Pinout

As mentioned above, this module supports HSU, SPI, and I2C communication protocols. The module uses separate pins for SPI protocol, but the pins used for I2C and HSU communication protocols are the same. The names of the I2C pins are on the front of the module and the names of the HSU pins are on the back of the module. HSU is the default protocol of the module. You can change the communication protocol of the module to one of the I2C, SPI, or HSU using DIP switches on the module.

This Module has 16 pins. The pins of each protocol are as follows:

I2C protocol:

  • VCC: Module power supply – 5V
  • GND: Ground
  • SDA: Data pin
  • SCL: Clock pin

SPI protocol:

  • VCC: Module power supply – 3-5V
  • GND: Ground
  • SCK: Clock pin
  • MISO: Output data pin
  • MOSI: Input data pin
  • SS: Slave select
  • IRQ: Interrupt pin
  • RSTO: Reset pin

HSU protocol:

  • VCC: Module power supply – 5V
  • GND: Ground
  • TXD: Transmit data pin
  • RXD: Receive data pin

You can see the pinout of this module in the image below.

Main applications of NFC

  • Mobile payments; Apple Pay NFC, Google Wallet
  • Tap-to-Pair; Pairing Bluetooth devices just by tapping, instead of manual entering
  • Embedding digital experience in physical products; NFC’s small form factor allows for it to be embedded into physical products, enabling a unique experience when interacted
  • Security
  • Password replacement
  • Product Authentication

Interfacing PN532 with Arduino in UART Mode

Let’s start by reading the NFC data using a high-speed UART or serial communication. Connect the PN532 to the Arduino in the following manner. On the rear of the module, the GND, VCC, Tx, and Rx pins are labeled.

PN532 Arduino UART
  • GND (Ground) <-> GND
  • Vcc (Power supply) <-> 5V
  • Tx (Clock) <-> D3
  • Rx (Data) <-> D2
Interfacing PN532 with Arduino in UART Mode

Source Code/Program

Since PN532 has multiple communication possibilities, the appropriate library must be used in each circumstance. The  PN532 Elechouse library is the most advanced library that supports all communication protocols. Extract all of the libraries from the zip folder and place them in the Arduino library folder.

In the case of a UART communication, the following libraries are used.

  1. PN532_HSU Library: Download
  2. PN532_SWHSU Library: Download

Copy the following code and upload it to the Arduino Board.

#include <SoftwareSerial.h>
#include <PN532_SWHSU.h>
#include <PN532.h>
SoftwareSerial SWSerial( 3, 2 ); // RX, TX

PN532_SWHSU pn532swhsu( SWSerial );
PN532 nfc( pn532swhsu );
String tagId = “None”, dispTag = “None”;
byte nuidPICC[4];

void setup(void)
{
Serial.begin(115200);
Serial.println(“Hello Maker!”);
// Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata)
{
Serial.print(“Didn’t Find PN53x Module”);
while (1); // Halt
}
// Got valid data, print it out!
Serial.print(“Found chip PN5”);
Serial.println((versiondata >> 24) & 0xFF, HEX);
Serial.print(“Firmware ver. “);
Serial.print((versiondata >> 16) & 0xFF, DEC);
Serial.print(‘.’);
Serial.println((versiondata >> 8) & 0xFF, DEC);
// Configure board to read RFID tags
nfc.SAMConfig();
//Serial.println(“Waiting for an ISO14443A Card …”);
}


void loop()
{
readNFC();
}


void readNFC()
{
boolean success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
if (success)
{
Serial.print(“UID Length: “);
Serial.print(uidLength, DEC);
Serial.println(” bytes”);
Serial.print(“UID Value: “);
for (uint8_t i = 0; i < uidLength; i++)
{
nuidPICC[i] = uid[i];
Serial.print(” “); Serial.print(uid[i], DEC);
}
Serial.println();
tagId = tagToString(nuidPICC);
dispTag = tagId;
Serial.print(F(“tagId is : “));
Serial.println(tagId);
Serial.println(“”);
delay(1000); // 1 second halt
}
else
{
// PN532 probably timed out waiting for a card
Serial.println(“Timed out! Waiting for a card…”);
}
}
String tagToString(byte id[4])
{
String tagId = “”;
for (byte i = 0; i < 4; i++)
{
if (i < 3) tagId += String(id[i]) + “.”;
else tagId += String(id[i]);
}
return tagId;
}

You can open the Serial Monitor after uploading the code and begin testing the module by bringing some NFC cards close to the PN532.

The chip could only read data with four bytes in the High-Speed UART mode. Reading 7 bytes of data from NFC cards fails the module.

Interfacing PN532 with Arduino in I2C Mode

Let’s read the NFC data using I2C mode now. Connect the PN532 to the Arduino in the following manner.

  • GND (Ground) <-> GND
  • VCC (Power supply) <-> 5V
  • SDA (Data) <-> A4
  • SCL (Clock) <-> A5

Source Code/Program

Download and place the PN532_I2C.h library in the library folder if you’re using I2C.

Copy the code below and paste it into the Arduino board.

#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
String tagId = “None”;
byte nuidPICC[4];

void setup(void)
{
Serial.begin(115200);
Serial.println(“System initialized”);
nfc.begin();
}


void loop()
{
readNFC();
}

void readNFC()
{
if (nfc.tagPresent())
{
NfcTag tag = nfc.read();
tag.print();
tagId = tag.getUidString();
}
delay(5000);
}

You can open the Serial Monitor after uploading the code and begin testing the module by bringing some NFC cards close to the PN532. The chip can read both 4 bytes and 7 bytes of data from different NFC tags in I2C mode.

Interfacing PN532 with Arduino in SPI Mode

Let’s read the NFC data using SPI mode now. There are far too many connections in SPI mode. As a result, connect the PN532 to Arduino as shown below.

PN532 Arduino SPI
  • VCC (Power supply) <-> 5V
  • RST (Reset) <-> 9
  • GND (Ground) <-> GND
  • MISO (Master Input Slave Output) <-> 11
  • MOSI (Master Output Slave Input) <-> 12
  • SCK (Serial Clock) <-> 13
  • SS (Slave select) <-> 10

Source Code/Program

Download and place the PN532_SPI.h library in the library folder if you’re using SPI.

Copy the code below and paste it into the Arduino board.

// for SPI Communication
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_SPI interface(SPI, 10); // create a PN532 SPI interface with the SPI CS terminal located at digital pin 10
NfcAdapter nfc = NfcAdapter(interface); // create an NFC adapter object
String tagId = “None”;

void setup(void)
{
Serial.begin(115200);
Serial.println(“System initialized”);
nfc.begin();
}

void loop()
{
readNFC();
}

void readNFC()
{
if (nfc.tagPresent())
{
NfcTag tag = nfc.read();
tag.print();
tagId = tag.getUidString();
}
delay(5000);
}

The 4 bytes and 7 bytes NFC Cards work well in this mode as well.

Making Portable NFC Scanner with OLED Display

We can make a portable NFC Scanner module using PN532 and Arduino Board. For displaying data we can add a 0.96″ I2C OLED Display to the below circuit.

PN532 Arduino I2C OLED

Connect the PN532 Module & OLED Display to Arduino as per the circuit diagram.

  • GND (Ground) <-> GND
  • VCC (Power supply) <-> 5V
  • SDA (Data) <-> A4
  • SCL (Clock) <-> A5

Source Code/Program

We will not utilize the above library for this portable NFC Reader. We’d rather use the most recent Adafruit PN532 library. The library is designed for Adafruit PN532 NFC/RFID breakout boards and only works in I2C or SPI mode with Arduino UNO/Nano boards.

Aside from that, we’ll require another library for compilation. Download the following libraries and use Library Manager to add them to the Arduino IDE:

1. Adafruit PN532 Library: Download

2. Adafruit GFX Library: https://github.com/adafruit/Adafruit-GFX-Library

3. SSD1306 OLED Library: Download

Copy the following code and upload it to your Arduino Board.

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_PN532.h>

#define PN532_IRQ (2)
#define PN532_RESET (3) // Not connected by default on the NFC Shield

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128×64, 0x3C for 128×32;

Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup(void)
{
Serial.begin(115200);
while (!Serial) delay(10); // for Leonardo/Micro/Zero
Serial.println(“Hello!”);

nfc.begin();

if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
{
Serial.println(F(“SSD1306 allocation failed”));
for (;;); // Don’t proceed, loop forever
}

uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata)
{
Serial.print(“Didn’t find PN53x board”);
while (1); // halt
}

// Got ok data, print it out!
Serial.print(“Found chip PN5”);
Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print(“Firmware ver. “);
Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print(‘.’); Serial.println((versiondata>>8) & 0xFF, DEC);

display.clearDisplay();
display.setCursor(0, 0); //oled display
display.setTextSize(1);
display.setTextColor(WHITE);
display.print(“Found chip PN5”);
display.print((versiondata >> 24) & 0xFF, HEX);

display.setCursor(0, 20); //oled display
display.setTextSize(1);
display.setTextColor(WHITE);
display.print(“Firmware ver. “);
display.print((versiondata >> 16) & 0xFF, DEC);
display.print(“.”);
display.print((versiondata >> 8) & 0xFF, DEC);

nfc.setPassiveActivationRetries(0xFF);

// configure board to read RFID tags
nfc.SAMConfig();

Serial.println(“Waiting for an ISO14443A card”);

display.setCursor(0, 40); //oled display
display.setTextSize(1);
display.setTextColor(WHITE);
display.print(“Waiting for NFC Card”);
display.display();

}

void loop(void)
{
boolean success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)


success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);

if (success) {
Serial.println(“Found a card!”);
Serial.print(“UID Length: “);
Serial.print(uidLength, DEC);
Serial.println(” bytes”);
Serial.print(“UID Value: “);

display.clearDisplay();
display.setCursor(10, 0); //oled display
display.setTextSize(1);
display.setTextColor(WHITE);
display.print(“UID Length:”);
display.print(uidLength, DEC);
display.print(” bytes”);

display.setCursor(35, 20); //oled display
display.setTextSize(1);
display.setTextColor(WHITE);
display.println(“UID Value: “);
display.setCursor(5, 35); //oled display


for (uint8_t i=0; i < uidLength; i++)
{

Serial.print(” 0x”);
Serial.print(uid[i], HEX);
display.print(” 0x”);
display.print(uid[i], HEX);
display.display();
}
Serial.println(“”);
// Wait 1 second before continuing
delay(1000);
}
else
{
// PN532 probably timed out waiting for a card
Serial.println(“Timed out waiting for a card”);
}
}

You can begin testing after the code has been successfully uploaded. The firmware version will be printed on the OLED Display, and the cards will be scanned.

Portable NFC Scanner

Bring some NFC cards close to the PN532 NFC Board now. Your bank card, a travel card, or even an NFC test card may be included in the NFC Card. The PN532 Module displays the byte length as well as the UID value on the OLED panel.

Depending on the type of NFC Card, the byte length maybe 4 bytes or 7 bytes.

If you don’t want to use the OLED Display for your project, you can use the Serial Monitor to display the UID value and byte length.

Conclusion

I hope all of you understand how to Interface PN532 NFC RFID Module with Arduino. We MATHA ELECTRONICS will be back soon with more informative blogs.

Leave a Reply

Your email address will not be published.