%% fig-alt: Decision tree for selecting NFC operating modes including Reader/Writer, Peer-to-Peer, and Card Emulation based on use case
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#E67E22'}}}%%
flowchart TD
START([NFC Mode<br/>Selection]) --> Q1{Interaction<br/>type?}
Q1 -->|Read tags| RW[/Reader/Writer Mode/]
Q1 -->|Exchange data| Q2{Both NFC<br/>enabled?}
Q1 -->|Act as card| CE[/Card Emulation/]
Q2 -->|Yes phones| P2P[/Peer-to-Peer Mode/]
Q2 -->|No one passive| RW
RW --> RW_USE["Access control<br/>Asset tracking<br/>Smart posters"]
P2P --> P2P_USE["File sharing<br/>Bluetooth pairing<br/>Wi-Fi handover"]
CE --> CE_USE["Mobile payments<br/>Transit cards<br/>Loyalty cards"]
RW --> RW_TAG{Tag type?}
RW_TAG -->|Simple UID| TYPE1["Type 1/2<br/>Low cost"]
RW_TAG -->|Secure data| TYPE4["Type 4<br/>NDEF + crypto"]
CE --> CE_SEC{Security<br/>level?}
CE_SEC -->|High HCE| SE["Secure Element<br/>TEE/eSE"]
CE_SEC -->|App-level| HCE["Host Card<br/>Emulation"]
style START fill:#2C3E50,color:#fff
style RW fill:#16A085,color:#fff,stroke:#2C3E50,stroke-width:3px
style P2P fill:#E67E22,color:#fff,stroke:#2C3E50,stroke-width:2px
style CE fill:#9B59B6,color:#fff,stroke:#2C3E50,stroke-width:3px
893 NFC Access Control Systems
893.1 Learning Objectives
By the end of this chapter, you will be able to:
- Build NFC Access Control: Implement door lock systems using ESP32 and PN532 modules
- Configure I2C Communication: Set up reliable NFC tag reading via I2C protocol
- Design Authorization Logic: Create authorized tag databases with UID matching
- Integrate Hardware Components: Wire servo locks, LEDs, and buzzers for feedback
- Implement Access Logging: Track access attempts with circular buffer storage
- Debug NFC Issues: Diagnose communication, range, and interference problems
This chapter guides you through building a complete NFC-based door lock system. When someone taps an authorized NFC tag (like an employee badge), the system:
- Reads the tagβs unique ID
- Checks if the ID is in the authorized list
- Unlocks the door (servo motor)
- Provides visual feedback (green LED = granted, red LED = denied)
- Logs the access attempt for security auditing
Think of it like the key card systems in hotels or offices, but one you build yourself!
Prerequisites: - NFC Fundamentals - Core NFC concepts and operating modes - NFC Architecture - Protocol stack and tag types
Continue Learning: - NFC Smart Home Automation - Python-based scene control - NFC Security and Comparisons - Payment security and technology selection - NFC Hands-On - Practical implementations
893.2 Prerequisites
Required Knowledge: - Understanding of NFC operating modes (Reader/Writer, Peer-to-Peer, Card Emulation) - Basic Arduino/ESP32 programming experience - Familiarity with I2C communication protocol
Required Hardware: - ESP32 Development Board - PN532 NFC Reader Module (I2C) - Servo motor (SG90) for lock mechanism - NFC tags (Type 2 recommended) - LED (Green for granted, Red for denied) - Buzzer (optional) - Jumper wires and breadboard
Estimated Time: 45 minutes
893.3 System Architecture
The NFC access control system follows a straightforward flow: tag detection, authorization check, and hardware response.
This decision tree helps select the appropriate NFC operating mode based on application requirements.
893.4 Hardware Wiring
Connect the ESP32 to the PN532 NFC module and output devices as shown:
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D'}}}%%
flowchart LR
subgraph ESP32["ESP32 Development Board"]
direction TB
P3V3[3.3V]
P5V[5V]
GND[GND]
G21[GPIO 21<br/>I2C SDA]
G22[GPIO 22<br/>I2C SCL]
G13[GPIO 13]
G25[GPIO 25]
G26[GPIO 26]
G27[GPIO 27]
end
subgraph NFC["PN532 NFC Module"]
NFC_VCC[VCC]
NFC_GND[GND]
NFC_SDA[SDA]
NFC_SCL[SCL]
end
subgraph Servo["Servo Motor SG90"]
S_SIG[Signal]
S_VCC[VCC]
S_GND[GND]
end
subgraph Output["Output Indicators"]
LED_G[Green LED<br/>+ 220Ξ©]
LED_R[Red LED<br/>+ 220Ξ©]
BUZ[Buzzer]
end
P3V3 --> NFC_VCC
GND --> NFC_GND
G21 <--> NFC_SDA
G22 <--> NFC_SCL
G13 --> S_SIG
P5V --> S_VCC
GND --> S_GND
G25 --> LED_G
G26 --> LED_R
G27 --> BUZ
style ESP32 fill:#2C3E50,stroke:#16A085,color:#fff
style NFC fill:#16A085,stroke:#2C3E50,color:#fff
style Servo fill:#E67E22,stroke:#2C3E50,color:#fff
style Output fill:#7F8C8D,stroke:#2C3E50,color:#fff
Wiring Summary Table:
| Component | Pin | ESP32 GPIO | Notes |
|---|---|---|---|
| PN532 VCC | VCC | 3.3V | Power supply |
| PN532 GND | GND | GND | Common ground |
| PN532 SDA | SDA | GPIO 21 | I2C data |
| PN532 SCL | SCL | GPIO 22 | I2C clock |
| Servo Signal | Orange | GPIO 13 | PWM control |
| Servo VCC | Red | 5V | Higher voltage for motor |
| Servo GND | Brown | GND | Common ground |
| Green LED | Anode | GPIO 25 | Via 220Ξ© resistor |
| Red LED | Anode | GPIO 26 | Via 220Ξ© resistor |
| Buzzer | + | GPIO 27 | Active buzzer |
893.5 Complete Implementation
The following code implements a fully functional NFC access control system:
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
#include <ESP32Servo.h>
// Pin definitions
#define SERVO_PIN 13
#define GREEN_LED 25
#define RED_LED 26
#define BUZZER 27
// NFC setup
PN532_I2C pn532i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532i2c);
// Servo for lock
Servo lockServo;
// Authorized UIDs (add your NFC tag UIDs here)
String authorizedUIDs[] = {
"04 A3 B2 C1 D4 5E 80", // Alice's badge
"08 F7 E2 9A 3B 1C 4D", // Bob's badge
"12 34 56 78 9A BC DE" // Admin card
};
const int numAuthorizedUIDs = 3;
// Lock states
const int LOCKED_ANGLE = 0;
const int UNLOCKED_ANGLE = 90;
bool isLocked = true;
// Access log (circular buffer)
struct AccessLog {
String uid;
String status;
unsigned long timestamp;
};
AccessLog accessHistory[10];
int accessLogIndex = 0;
void setup() {
Serial.begin(115200);
Serial.println("\n=== ESP32 NFC Access Control System ===");
// Initialize pins
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
pinMode(BUZZER, OUTPUT);
// Initial state: deny
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, HIGH);
// Initialize servo
lockServo.attach(SERVO_PIN);
lockServo.write(LOCKED_ANGLE);
// Initialize NFC
nfc.begin();
Serial.println("β NFC Reader initialized");
Serial.println("π± Ready to scan NFC tags...\n");
// Startup beep
beep(100);
}
void loop() {
// Check for NFC tag
if (nfc.tagPresent(1000)) { // 1 second timeout
NfcTag tag = nfc.read();
String uid = tag.getUidString();
Serial.println("\nββββββββββββββββββββββββββββββββ");
Serial.println("π± NFC Tag Detected");
Serial.print(" UID: ");
Serial.println(uid);
// Check authorization
if (isAuthorized(uid)) {
grantAccess(uid);
} else {
denyAccess(uid);
}
Serial.println("ββββββββββββββββββββββββββββββββ\n");
delay(2000); // Prevent multiple reads
}
delay(100);
}
bool isAuthorized(String uid) {
/**
* Check if UID is in authorized list
*/
for (int i = 0; i < numAuthorizedUIDs; i++) {
if (uid == authorizedUIDs[i]) {
return true;
}
}
return false;
}
void grantAccess(String uid) {
/**
* Grant access: unlock door, green LED, success beep
*/
Serial.println("β
ACCESS GRANTED");
// Visual feedback
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
// Unlock door
lockServo.write(UNLOCKED_ANGLE);
isLocked = false;
// Audio feedback
beep(50);
delay(100);
beep(50);
Serial.println("π Door unlocked");
Serial.println(" Relocking in 5 seconds...");
// Log access
logAccess(uid, "GRANTED");
// Keep door unlocked for 5 seconds
delay(5000);
// Re-lock door
lockServo.write(LOCKED_ANGLE);
isLocked = true;
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, HIGH);
Serial.println("π Door locked");
}
void denyAccess(String uid) {
/**
* Deny access: red LED, error beep
*/
Serial.println("β ACCESS DENIED");
Serial.println(" Unauthorized NFC tag");
// Visual feedback (red LED already on)
// Blink red LED
for (int i = 0; i < 3; i++) {
digitalWrite(RED_LED, LOW);
delay(100);
digitalWrite(RED_LED, HIGH);
delay(100);
}
// Audio feedback (long error beep)
beep(500);
// Log denied attempt
logAccess(uid, "DENIED");
}
void beep(int duration_ms) {
/**
* Sound buzzer for specified duration
*/
digitalWrite(BUZZER, HIGH);
delay(duration_ms);
digitalWrite(BUZZER, LOW);
}
void logAccess(String uid, String status) {
/**
* Record access attempt in circular buffer
*/
accessHistory[accessLogIndex].uid = uid;
accessHistory[accessLogIndex].status = status;
accessHistory[accessLogIndex].timestamp = millis();
accessLogIndex = (accessLogIndex + 1) % 10; // Circular buffer
// Print log entry
Serial.print("π Logged: ");
Serial.print(status);
Serial.print(" - ");
Serial.println(uid);
}
// Optional: Add command to print access history via Serial
void printAccessHistory() {
Serial.println("\n=== Access History (Last 10 attempts) ===");
for (int i = 0; i < 10; i++) {
if (accessHistory[i].uid != "") {
Serial.print(i + 1);
Serial.print(". ");
Serial.print(accessHistory[i].status);
Serial.print(" - ");
Serial.print(accessHistory[i].uid);
Serial.print(" @ ");
Serial.print(accessHistory[i].timestamp / 1000);
Serial.println("s");
}
}
Serial.println("=====================================\n");
}893.6 Expected Serial Output
When the system is running, youβll see output like this:
=== ESP32 NFC Access Control System ===
β NFC Reader initialized
π± Ready to scan NFC tags...
ββββββββββββββββββββββββββββββββ
π± NFC Tag Detected
UID: 04 A3 B2 C1 D4 5E 80
β
ACCESS GRANTED
π Door unlocked
Relocking in 5 seconds...
π Logged: GRANTED - 04 A3 B2 C1 D4 5E 80
π Door locked
ββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββ
π± NFC Tag Detected
UID: FF AA BB CC DD EE 11
β ACCESS DENIED
Unauthorized NFC tag
π Logged: DENIED - FF AA BB CC DD EE 11
ββββββββββββββββββββββββββββββββ
893.8 Troubleshooting
Common issues and solutions:
| Problem | Cause | Solution |
|---|---|---|
| NFC not initializing | I2C wiring issue | Check SDA/SCL connections, verify 3.3V power |
| Tag not detected | Range too far | Hold tag within 2-3cm of reader |
| Wrong UID format | Tag type mismatch | Use Type 2 tags (NTAG213/215/216) |
| Servo jittering | Power issue | Use separate 5V supply for servo |
| Intermittent reads | Interference | Keep away from metal surfaces |
893.9 Security Considerations
This basic implementation demonstrates NFC access control concepts. For production use, consider:
- Encrypted UIDs: Use tag types with encryption (NTAG 424 DNA)
- Challenge-Response: Implement mutual authentication between reader and tag
- Audit Logging: Store logs to external database with timestamps
- Anti-Passback: Prevent same tag from entering twice without exit
- Tamper Detection: Add sensors to detect physical attacks on reader
893.10 Summary
This chapter covered building an ESP32-based NFC access control system:
- Hardware Integration: Connecting PN532 NFC reader, servo motor, and feedback indicators
- I2C Communication: Configuring ESP32 for reliable tag reading
- Authorization Logic: Matching tag UIDs against an authorized list
- Access Logging: Recording all access attempts in a circular buffer
- User Feedback: Providing visual (LED) and audio (buzzer) confirmation
The system demonstrates the Reader/Writer operating mode of NFC, where the ESP32 acts as an NFC reader and passive tags provide identification.
893.11 Whatβs Next
Continue to NFC Smart Home Automation to build a Raspberry Pi-based smart home controller that triggers scenes when users tap NFC tags placed around the house.