35 NFC Tag Programming
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:
- Study NFC Fundamentals
- Work through programming exercises here
- 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:
- 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
35.3 Programming NFC Tags
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
Install dependencies (Raspberry Pi):
python3 -m pip install nfcpy ndeflibPython 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)
#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 |
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
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).
Builds on:
- NFC Fundamentals - Understanding NDEF format and tag types before programming
- NFC Communication Fundamentals - Operating modes and architecture
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:
- NFC Simulation Lab - Interactive learning without hardware
- NFC Real-World Applications - Practical implementations
Development Libraries:
- Android NFC Developer Guide - Official Android documentation
- nfcpy Python Library - Python NFC library for PN532
- Adafruit PN532 Library - Arduino NFC library
Hardware Modules:
- PN532 NFC Module Guide - Wiring and setup
- ACR122U USB Reader - PC-based tag programming
Tag Suppliers:
- NFC Tag Comparison - NTAG213/215/216 selection guide
- On-Metal Tags - Tags for industrial environments
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 |