35  NFC Tag Programming

In 60 Seconds

NFC tag programming lets you write URLs, text, and custom data to passive NFC tags using Android, Python, or Arduino platforms. This chapter provides hands-on code examples for reading and writing NDEF records across three development environments, plus guidance on selecting the right tag type for your application.

Sammy the Sensor found a blank NFC sticker and asked Max the Microcontroller, “Can we make this DO something?” Max grinned and said, “Absolutely! Think of this sticker like a tiny blank book. We can write a website address on it, and when anyone taps their phone on the sticker, it opens that website – like magic!” Bella the Battery added, “The best part? The sticker does not need a battery. The phone gives it energy just by being close, like warming your hands near a campfire.” Lila the LED chimed in, “We can even write messages, phone numbers, or Wi-Fi passwords. It is like leaving invisible sticky notes that only phones can read!”

35.1 Learning Objectives

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

  • Implement NFC tag writing across Android (Java), Python (PN532/nfcpy), and Arduino (I2C) platforms using NDEF URI and Text records
  • Construct multi-record NDEF messages that combine URI, Text, and MIME payloads for interoperable data exchange
  • Evaluate NFC tag types (Type 1 through 5) by comparing memory capacity, security features, and cost to select the best fit for a given IoT application
  • Diagnose NFC communication failures by systematically isolating hardware wiring, interface mode, antenna coupling, and NDEF formatting issues
  • Design an NFC tag deployment including tag selection, NDEF data structure, cost analysis, and maintenance strategy for a real-world scenario

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

35.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:

Comparisons:

Hands-On:

35.3 Programming NFC Tags

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

35.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");
}

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

Hardware:

  • Raspberry Pi
  • PN532 NFC module
  • NFC tags
PN532 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})

35.3.3 Example 3: Arduino NFC (PN532)

NFC tag type selection flowchart guiding users through memory, security, and cost requirements to choose between Type 1 Topaz, Type 2 NTAG, Type 3 FeliCa, Type 4 DESFire, and Type 5 ICODE tags
Figure 35.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.
Arduino + 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);
}

35.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
Type 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

NDEF message overhead impacts usable tag storage. Each NDEF record adds header bytes:

\[ \text{Overhead}_{\text{NDEF}} = 3 \text{ bytes (MB/ME/CF/SR/IL/TNF)} + L_{\text{type}} + L_{\text{ID}} + L_{\text{payload length field}} \]

NTAG213 example (144 bytes total): Reserved (10 bytes) + lock bits (4 bytes) = 130 bytes available. URI record “https://example.com/product/12345” (32 chars): - NDEF header: 3 bytes + 1 (type) + 1 (length) = 5 bytes - URI prefix byte: 1 byte (0x03 for “https://”) - URL payload: 24 bytes (after prefix compression) - Total: 5 + 1 + 24 = 30 bytes used, 100 bytes remaining for additional records (QR code, contact info, etc.)

35.5 Knowledge Check

35.6 Common Debugging Tips

Troubleshooting 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

35.7 Worked Example: NFC Tag Procurement for a 200-Room Hotel

A hotel chain deploys NFC tags throughout a 200-room property for guest services: Wi-Fi login, room service menus, local area guides, and feedback collection. Each room gets 3 tags (nightstand, desk, bathroom), plus 20 tags in common areas. Total: 620 tags.

Tag Type Selection:

Application Data Size Security Needed Recommended Tag Unit Cost
Wi-Fi credentials (SSID + password) ~90 bytes Password protect (prevent overwrites) NTAG213 (144 bytes) $0.15
Room service menu URL ~45 bytes None (public content) NTAG213 (144 bytes) $0.15
Guest feedback URL + room ID ~60 bytes None NTAG213 (144 bytes) $0.15
Common area guides (URL + text + icon) ~200 bytes Password protect NTAG215 (504 bytes) $0.35

Cost Breakdown:

Item Quantity Unit Cost Total
NTAG213 stickers (30mm round, white) 600 $0.15 $90
NTAG215 stickers (common areas) 20 $0.35 $7
NFC programming station (ACR122U USB reader) 1 $35 $35
Protective epoxy overlay (waterproof for bathroom) 200 $0.10 $20
Staff time: programming + placement (8 hours x $25/hr) 1 $200 $200
Total deployment $352

Alternative: QR Codes

Item Total
620 printed QR code stickers $45
Acrylic holders $310
Total $355

Nearly identical cost, but NFC advantages justify the investment:

  • Guest experience: Tap is faster than opening camera and scanning
  • Durability: NFC stickers embedded under desk surface last 5+ years; QR codes fade and scratch within 12-18 months
  • Analytics: NFC reads are logged with timestamps (track which amenities guests use most)
  • Reprogrammability: Change the Wi-Fi password across all 200 rooms by updating 600 tags with a handheld reader in 2 hours, vs. reprinting and replacing 600 QR stickers

Key insight: NTAG213 at $0.15/tag covers 90% of IoT applications. Only upgrade to NTAG215 ($0.35) for larger payloads or NTAG216 ($0.50) for 888 bytes. Never use DESFire ($2-5) unless you need on-tag cryptographic authentication (payments, secure access).

Concept Relationships

Builds on:

Programming Platforms Covered:

  • Android - NfcAdapter API for mobile apps (Java/Kotlin)
  • Python - nfcpy library with PN532 module (Raspberry Pi, desktop)
  • Arduino - I2C-based PN532 library (embedded systems)

Key Concepts:

  • NDEF message construction (TLV containers, record headers)
  • URI prefix compression (saving space on small tags)
  • Tag type selection (Type 2 NTAG for most IoT applications)
  • Write verification (read-back after write to prevent corruption)

Extends to:

See Also

Development Libraries:

Hardware Modules:

Tag Suppliers:

Common Pitfalls

Attempting to write to a read-only or locked NFC tag fails silently on some hardware. Fix: always read the tag’s capability container (CC) to check the write access condition before attempting a write operation.

NDEF URI records use a prefix byte to abbreviate common URL prefixes (0x01 = http://www., 0x03 = https://). Using the wrong prefix or 0x00 (no abbreviation) causes some readers to misinterpret the URL. Fix: consult the NFC Forum URI record specification and use the correct prefix byte for the URL scheme being encoded.

NFC Type 1 tags (Topaz) have only 96 bytes; Type 2 (NTAG213) has 144 bytes. Large payloads won’t fit. Fix: calculate the total NDEF message size before choosing a tag type and select a tag with at least 20% headroom beyond the maximum expected payload.

35.8 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

35.9 What’s Next

Next Chapter Description
NFC Simulation Lab Interactive Wokwi simulation for NDEF parsing, tag type identification, and anti-collision protocols
NFC Real-World Applications Payments, smart home automation, and product authentication case studies
NFC Security and Comparisons Security best practices and NFC vs RFID vs BLE vs QR code decision framework