Smart Door Lock System with NFC Implant – A DIY Project
Imagine unlocking your front door just by waving your hand — no keys, no phone, just you. In this project, I built a smart door lock system using a subdermal NExT RFID/NFC implant, an Arduino-based controller, and a Desi Smart Utopic R electronic lock. Designed for makers, smart home tinkerers, and biohackers alike, this build showcases the potential of combining bio-integrated tech with everyday access control.
What is the NExT Implant?
The NExT implant (from Dangerous Things) is a tiny glass-encapsulated chip implanted under the skin, typically between the thumb and forefinger. It contains:
- NTAG216 NFC chip (13.56 MHz – compatible with smartphones and most NFC readers)
- T5577 RFID chip (125 kHz – for low-frequency RFID systems)
It requires no battery — it powers up from the reader’s field — and sends back its unique ID. In this project, I used the NFC side of the chip. Once implanted, it acts like a permanent, personal NFC tag embedded in your body.
Hardware Components Used
- Arduino Uno – main controller
- PN532 NFC Module (I2C mode) – reads my implant’s NFC ID
- 28BYJ-48 stepper motor + ULN2003 driver board – turns the lock
- Desi Smart Utopic R – a smart euro-profile door lock
- TMB12A12 12V Active Buzzer – gives audio feedback (approved/denied)
- Custom 3D-printed mount – secures the motor to the door and aligns with the lock
How It Works
- NFC Reader: The PN532 module constantly listens for NFC tags. When I place my implanted hand near it (within ~2 cm), it detects and reads the chip’s unique ID (UID).
- Authentication: The Arduino checks if the UID matches one of the approved IDs hardcoded into the sketch.
- Access Granted:
- The stepper motor rotates clockwise to turn the Desi Smart Utopic R lock mechanism.
- A 12V buzzer beeps for 1 second to confirm.
- After a delay, the motor reverses to re-lock the door.
- Access Denied:
- The system gives no access.
- The buzzer beeps 3 times briefly as a rejection tone.
- Timeout Protection:
- If the reader becomes unresponsive or no card is detected for 10 seconds, the Arduino resets the PN532 to prevent lockups.
Mechanical Integration
The stepper motor alone isn’t strong enough to directly open most locks — but it works great with the Desi Smart Utopic R, a motor-ready euro-cylinder lock. I designed a custom 3D-printed adapter to securely mount the motor on the inside of my door and interface with the lock’s rotation shaft.
I used PETG filament for durability and included slots for mounting the NFC module and buzzers. This makes the whole system modular, easy to assemble, and non-intrusive to the door’s aesthetics.
Buzzer Feedback System
- Approved implant → 1 second continuous beep
- Unapproved tag/card → 3 short beeps (200 ms ON, 200 ms OFF)
The buzzer is powered via a 12V external source through a transistor circuit controlled by Arduino pin D8.
Software Highlights
- Hardcoded list of approved UIDs
- Timeout logic to auto-reinitialize NFC reader
- Stepper movement control with accurate positioning
- Audible feedback for status
Ideas for Future Improvements
- Wi-Fi/ESP32 integration for remote unlock and logging
- Encrypted challenge-response authentication instead of static UID
- Battery backup for power outages
- OLED screen for system status or tag display
- Mobile app interface for managing authorized IDs
Final Thoughts
This project merges biohacking, electronics, and smart home automation into one fun and practical system. Using an NFC implant to unlock my door has been both incredibly satisfying and surprisingly convenient.
If you’re looking to combine Arduino with real-world utility — or explore the potential of implantable tech — this kind of project is a great place to start. With some basic hardware and a bit of code, you too can turn your hand into a secure key.
#include <Wire.h>
#include <Adafruit_PN532.h>
#include <Stepper.h>
// Stepper motor settings (IN1, IN3, IN2, IN4 connected to D4, D6, D5, D7)
const int stepsPerRevolution = 2048;
Stepper myStepper(stepsPerRevolution, 4, 6, 5, 7);
// PN532 I2C pins
#define PN532_IRQ 2 // Connect to PN532 IRQ pin
#define PN532_RESET 3 // Connect to PN532 RSTO pin
// 12V Active Buzzer connected via a transistor to pin D8
#define BUZZER_PIN 8
// Initialize PN532 NFC reader
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
// Timeout configuration
unsigned long lastReadTime = 0;
const unsigned long timeoutMs = 10000; // 10 seconds
// List of approved card UIDs (can be filled in separately)
String approvedIDs[] = {
// Add authorized UIDs here as uppercase strings, e.g., "04:AB:CD:12:34:56:78"
};
void setup() {
Serial.begin(9600);
myStepper.setSpeed(10);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
Serial.println("Initializing PN532 NFC module...");
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (!versiondata) {
Serial.println("PN532 not found. Check wiring!");
while (1);
}
nfc.SAMConfig();
Serial.println("Ready to scan NFC tags...");
lastReadTime = millis();
}
void loop() {
// Reset NFC reader if no activity after timeout
if (millis() - lastReadTime > timeoutMs) {
Serial.println(">>> Timeout! Restarting PN532...");
nfc.begin();
nfc.SAMConfig();
lastReadTime = millis();
}
// Buffer to store read UID
uint8_t uid[7];
uint8_t uidLength;
if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength)) {
// Format UID as string
String cardID = "";
for (byte i = 0; i < uidLength; i++) {
if (uid[i] < 0x10) cardID += "0";
cardID += String(uid[i], HEX);
if (i < uidLength - 1) cardID += ":";
}
cardID.toUpperCase();
Serial.print("Card ID: ");
Serial.println(cardID);
// Check if card is in the approved list
bool isApproved = false;
for (String id : approvedIDs) {
if (cardID == id) {
isApproved = true;
break;
}
}
if (isApproved) {
Serial.println(">>> Access granted. Activating motor...");
// Buzzer: one long beep
digitalWrite(BUZZER_PIN, HIGH);
delay(1000);
digitalWrite(BUZZER_PIN, LOW);
// Step motor: unlock
myStepper.step(400);
delay(1000);
// Step motor: relock
myStepper.step(-400);
Serial.println(">>> Operation complete.");
} else {
Serial.println(">>> Access denied.");
// Buzzer: three short beeps
for (int i = 0; i < 3; i++) {
digitalWrite(BUZZER_PIN, HIGH);
delay(200);
digitalWrite(BUZZER_PIN, LOW);
delay(200);
}
}
lastReadTime = millis(); // Reset timeout timer
delay(1000); // Prevent multiple reads
}
}