888  NFC Tag Programming

888.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Write URLs and Text to NFC Tags: Use Android Java, Python with PN532, and Arduino to write NDEF records
  • Read NFC Tag Data: Implement tag reading in mobile applications and embedded systems
  • Create NDEF Messages: Structure properly formatted NDEF messages for interoperability
  • Select Tag Types: Choose appropriate NFC tag types (Type 1-5) based on memory and feature requirements
  • Debug NFC Communication: Troubleshoot tag detection, read/write failures, and formatting issues

What is this chapter? Practical hands-on exercises for programming NFC tags using different platforms.

When to use: - When implementing NFC features in mobile apps - When building Arduino-based NFC readers - When working with Raspberry Pi and PN532 modules

Prerequisites: - NFC Fundamentals - Understanding of NDEF format - Basic programming knowledge (Java, Python, or C++) - Understanding of I2C communication

Recommended Path: 1. Study NFC Fundamentals 2. Work through programming exercises here 3. Continue to NFC Simulation Lab

888.2 Prerequisites

Before diving into this chapter, you should be familiar with:

  • NFC Fundamentals: Understanding NFC operating modes (peer-to-peer, read/write, card emulation), NDEF message structure, and tag types is essential for implementing hands-on NFC programming
  • Networking Basics: Basic knowledge of wireless communication protocols and data encoding helps contextualize how NFC data exchange works at 13.56 MHz
  • Programming fundamentals: Familiarity with Arduino/C++ or Python programming is necessary to implement the code examples for tag reading and writing

Deep Dives: - NFC Architecture - NDEF format and tag types - NFC Simulation Lab - Interactive Wokwi simulation - NFC Real-World Applications - Payments, smart home, authentication

Comparisons: - NFC Security and Comparisons - NFC vs RFID vs BLE vs QR codes - Bluetooth Applications - Alternative pairing methods

Hands-On: - Simulations Hub - NFC tag simulators - Bluetooth Implementations - BLE pairing labs

888.3 Programming NFC Tags

Time: ~20 min | Level: Advanced | Unit: P08.C22.U01

888.3.1 Example 1: Write URL to NFC Tag (Android)

Java Code:

import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;

public void writeUrlToTag(Tag tag, String url) throws Exception {
    // Create NDEF message with URL
    NdefRecord uriRecord = NdefRecord.createUri(url);
    NdefMessage message = new NdefMessage(new NdefRecord[]{uriRecord});

    // Write to tag
    Ndef ndef = Ndef.get(tag);
    ndef.connect();
    ndef.writeNdefMessage(message);
    ndef.close();

    Log.d("NFC", "URL written: " + url);
}

Usage:

// In your Activity
@Override
protected void onNewIntent(Intent intent) {
    Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    writeUrlToTag(tag, "https://iotclass.example.com");
}

888.3.2 Example 2: Read NFC Tag (Python with PN532)

Hardware: - Raspberry Pi - PN532 NFC module - NFC tags

WarningPN532 Power and Interfaces

Most PN532 breakout boards are 3.3V logic. Verify your module’s voltage requirements before connecting it to 5V microcontrollers.

The ContactlessFrontend(...) connection string depends on how the PN532 is attached: - UART/USB-serial: tty:USB0:pn532 (example below) - Other adapters (I2C/SPI): use the interface supported by your hardware/driver setup

Install dependencies (Raspberry Pi):

python3 -m pip install nfcpy ndeflib

Python Code:

import nfc

# Connect to NFC reader
clf = nfc.ContactlessFrontend('tty:USB0:pn532')

def on_tag_discovered(tag):
    """Callback when tag is detected"""
    print(f"Tag detected: {tag}")

    # Read NDEF message
    if tag.ndef:
        for record in tag.ndef.records:
            print(f"Type: {record.type}")
            print(f"Data: {record.text if hasattr(record, 'text') else record.uri}")
    else:
        print("No NDEF data found")

    return True  # Keep tag connected

# Listen for tags
print("Waiting for NFC tag...")
clf.connect(rdwr={'on-connect': on_tag_discovered})

Write to Tag:

import ndef

# Create NDEF message
uri_record = ndef.UriRecord("https://iotclass.example.com")
text_record = ndef.TextRecord("Welcome to IoT Class!")

message = [uri_record, text_record]

# Write to tag
def write_tag(tag):
    if tag.ndef:
        tag.ndef.records = message
        print("Written successfully!")
    return False

clf.connect(rdwr={'on-connect': write_tag})

888.3.3 Example 3: Arduino NFC (PN532)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D'}}}%%
flowchart TD
    START([NFC Tag<br/>Selection]) --> Q1{Memory<br/>needed?}

    Q1 -->|<96 bytes| T1[Type 1<br/>TOPAZ, 96B]
    Q1 -->|96-888 bytes| Q2{Write<br/>protection?}
    Q1 -->|>888 bytes| Q3{Security<br/>level?}

    Q2 -->|Basic/None| T2[Type 2<br/>NTAG213/215/216]
    Q2 -->|Password| T2
    Q2 -->|Strong| Q3

    Q3 -->|AES Encryption| T4[Type 4<br/>DESFire, NTAG424]
    Q3 -->|Basic| T3[Type 3<br/>FeliCa]

    T1 --> USE1[Low-cost stickers<br/>Marketing tags]
    T2 --> USE2[Smart posters<br/>Device pairing<br/>Home automation]
    T3 --> USE3[Transit cards<br/>e-Wallets Japan]
    T4 --> USE4[Secure access<br/>Authentication<br/>Anti-counterfeiting]

    style START fill:#2C3E50,stroke:#16A085,stroke-width:3px,color:#fff
    style T1 fill:#7F8C8D,stroke:#2C3E50,stroke-width:2px,color:#fff
    style T2 fill:#16A085,stroke:#2C3E50,stroke-width:2px,color:#fff
    style T3 fill:#E67E22,stroke:#2C3E50,stroke-width:2px,color:#fff
    style T4 fill:#2C3E50,stroke:#16A085,stroke-width:2px,color:#fff

Figure 888.1: NFC tag type selection flowchart based on memory requirements, security needs, and application use case. Type 2 (NTAG) covers most IoT applications while Type 4 provides cryptographic security for authentication.
TipArduino + PN532 (I2C) Wiring Notes
  • Set your PN532 board to I2C mode (check the jumpers/switches on your module).
  • Connect VCC to 3.3V unless your module explicitly supports 5V logic.
PN532 Arduino Uno
VCC 3.3V
GND GND
SDA SDA (A4)
SCL SCL (A5)
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>

PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);

void setup() {
    Serial.begin(9600);
    nfc.begin();
    Serial.println("NFC Reader Ready!");
}

void loop() {
    if (nfc.tagPresent()) {
        NfcTag tag = nfc.read();

        Serial.println("Tag detected!");
        Serial.print("UID: ");
        Serial.println(tag.getUidString());

        // Read NDEF message
        if (tag.hasNdefMessage()) {
            NdefMessage message = tag.getNdefMessage();
            int recordCount = message.getRecordCount();

            for (int i = 0; i < recordCount; i++) {
                NdefRecord record = message.getRecord(i);

                // Print record type and payload
                Serial.print("Record ");
                Serial.print(i);
                Serial.print(": ");

                int payloadLength = record.getPayloadLength();
                byte payload[payloadLength];
                record.getPayload(payload);

                // Print as string (if text/URI)
                for (int j = 0; j < payloadLength; j++) {
                    Serial.print((char)payload[j]);
                }
                Serial.println();
            }
        }
    }

    delay(1000);
}

888.4 NFC Tag Types Reference

Understanding NFC Forum tag types helps you select the right tag for your application:

Type Example IC Memory Security Best For
Type 1 Topaz 96-2KB None Low-cost labels
Type 2 NTAG213/215/216 48-888B Password Smart posters, IoT
Type 3 FeliCa 1-9KB Crypto Transit cards (Japan)
Type 4 DESFire, NTAG424 32KB AES/3DES Payments, access
Type 5 ICODE SLIX 8KB Password Industrial RFID
NoteType 2 (NTAG) for Most IoT Applications

For most IoT projects, Type 2 tags (NTAG213/215/216) offer the best balance of: - Sufficient memory (144-888 bytes) - Low cost ($0.10-0.50 per tag) - Wide compatibility (all NFC phones) - Optional password protection

888.5 Common Debugging Tips

WarningTroubleshooting NFC Tag Issues

Tag Not Detected: - Verify tag is within 4cm of reader - Check I2C address (default 0x24 for PN532) - Ensure tag is NFC Forum compliant (not just RFID) - Try different tag orientation

Write Failures: - Check if tag is locked (read-only) - Verify password (if protected) - Ensure data fits in tag memory - Format tag before first write

NDEF Parsing Errors: - Validate TLV structure (Type 0x03) - Check for terminator TLV (0xFE) - Verify TNF and record type match

888.6 Summary

This chapter covered hands-on NFC tag programming:

  • Android NFC Programming: Using NdefMessage and NdefRecord classes to write URLs and text to tags via the NfcAdapter API
  • Python with PN532: Using nfcpy and ndeflib libraries on Raspberry Pi for tag reading and writing with proper connection string configuration
  • Arduino Implementation: I2C-based PN532 communication with NfcAdapter library for embedded NFC readers
  • Tag Type Selection: Choosing between Type 1-5 tags based on memory requirements, security needs, and cost constraints
  • Debugging Strategies: Troubleshooting common issues with tag detection, write failures, and NDEF parsing

888.7 What’s Next

The next chapter, NFC Simulation Lab, provides an interactive Wokwi simulation to practice NFC concepts including NDEF parsing, tag type identification, anti-collision protocols, and security demonstrations without requiring physical hardware.