#include <Wire.h>
#include <SPI.h>
#include <Servo.h>
#include <Keypad.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
#include <string.h>
// ==================================================
// LCD
// ==================================================
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ==================================================
// RFID RC522
// ==================================================
const byte RFID_SS_PIN = 53;
const byte RFID_RST_PIN = 5;
MFRC522 rfid(RFID_SS_PIN, RFID_RST_PIN);
// Any readable card is accepted in this demo.
// WARNING: This is not secure access authentication.
// ==================================================
// COMPONENT PINS
// ==================================================
const byte PIR_PIN = 30;
const byte SERVO_PIN = 9;
const byte RED_LED = 32;
const byte GREEN_LED = 33;
const byte BUZZER_PIN = 31;
// ==================================================
// 4x4 KEYPAD
// ==================================================
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {22, 23, 24, 25};
byte colPins[COLS] = {26, 27, 28, 29};
Keypad keypad = Keypad(
makeKeymap(keys),
rowPins,
colPins,
ROWS,
COLS
);
// ==================================================
// SERVO SETTINGS
// ==================================================
Servo lockServo;
const int LOCKED_ANGLE = 0;
const int UNLOCKED_ANGLE = 90;
const unsigned long UNLOCK_TIME = 5000;
// ==================================================
// SECURITY SETTINGS
// ==================================================
const unsigned long ENTRY_TIME = 10000;
const unsigned long BLINK_INTERVAL = 300;
const unsigned long DISPLAY_INTERVAL = 250;
// ==================================================
// PASSWORD
// ==================================================
const char PASSWORD[] = "1234";
const byte PASSWORD_LENGTH = 4;
char enteredPassword[PASSWORD_LENGTH + 1];
byte enteredLength = 0;
// ==================================================
// SYSTEM STATE
// ==================================================
bool isUnlocked = false;
bool entryCountdown = false;
bool alarmActive = false;
bool pirArmed = true;
bool redLedState = false;
byte wrongAttempts = 0;
unsigned long countdownStarted = 0;
unsigned long unlockedAt = 0;
unsigned long lastBlink = 0;
unsigned long lastDisplayUpdate = 0;
// ==================================================
// LCD DISPLAY FUNCTIONS
// ==================================================
void showLockedScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SYSTEM LOCKED");
lcd.setCursor(0, 1);
lcd.print("Scan RFID/enter");
}
void clearPassword() {
enteredLength = 0;
enteredPassword[0] = '\0';
}
void updateDisplay() {
lcd.clear();
if (alarmActive) {
lcd.setCursor(0, 0);
lcd.print("!!! ALARM !!!");
lcd.setCursor(0, 1);
lcd.print("Scan/enter code");
}
else if (entryCountdown) {
unsigned long elapsed = millis() - countdownStarted;
unsigned long remaining = 0;
if (elapsed < ENTRY_TIME) {
remaining = (ENTRY_TIME - elapsed + 999) / 1000;
}
lcd.setCursor(0, 0);
lcd.print("MOTION! ");
lcd.print(remaining);
lcd.print(" seconds");
lcd.setCursor(0, 1);
lcd.print("PASSWORD:");
for (byte i = 0; i < enteredLength; i++) {
lcd.print('*');
}
}
else if (isUnlocked) {
lcd.setCursor(0, 0);
lcd.print("ACCESS GRANTED");
lcd.setCursor(0, 1);
lcd.print("Door unlocked");
}
else {
showLockedScreen();
}
}
// ==================================================
// ALARM FUNCTIONS
// ==================================================
void startAlarm() {
if (alarmActive) {
return;
}
alarmActive = true;
entryCountdown = false;
redLedState = false;
lastBlink = millis();
Serial.println("ALARM ACTIVATED!");
updateDisplay();
}
void stopAlarm() {
alarmActive = false;
noTone(BUZZER_PIN);
digitalWrite(BUZZER_PIN, LOW);
redLedState = false;
digitalWrite(RED_LED, HIGH);
Serial.println("Alarm stopped");
}
// ==================================================
// LOCK AND UNLOCK
// ==================================================
void lockDoor() {
lockServo.write(LOCKED_ANGLE);
isUnlocked = false;
entryCountdown = false;
alarmActive = false;
noTone(BUZZER_PIN);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
redLedState = false;
clearPassword();
// Require the PIR to go LOW before another
// motion event can start a countdown.
pirArmed = (digitalRead(PIR_PIN) == LOW);
showLockedScreen();
Serial.println("DOOR LOCKED");
}
void unlockDoor(const char* method) {
// Stop any active alarm.
stopAlarm();
entryCountdown = false;
isUnlocked = true;
unlockedAt = millis();
wrongAttempts = 0;
clearPassword();
lockServo.write(UNLOCKED_ANGLE);
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("ACCESS GRANTED");
lcd.setCursor(0, 1);
lcd.print(method);
Serial.print("Access granted: ");
Serial.println(method);
}
// ==================================================
// WRONG PASSWORD
// ==================================================
void rejectPassword() {
wrongAttempts++;
clearPassword();
Serial.print("Wrong password. Attempts: ");
Serial.println(wrongAttempts);
if (wrongAttempts >= 3) {
startAlarm();
}
else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WRONG PASSWORD");
lcd.setCursor(0, 1);
lcd.print("Attempts: ");
lcd.print(wrongAttempts);
}
}
// ==================================================
// RFID READER
// ==================================================
void checkRFID() {
if (!rfid.PICC_IsNewCardPresent()) {
return;
}
if (!rfid.PICC_ReadCardSerial()) {
return;
}
Serial.print("Card UID: ");
for (byte i = 0; i < rfid.uid.size; i++) {
if (rfid.uid.uidByte[i] < 0x10) {
Serial.print('0');
}
Serial.print(rfid.uid.uidByte[i], HEX);
Serial.print(' ');
}
Serial.println();
// Accept every card the reader can read.
// Only unlock if the door is currently locked.
if (!isUnlocked) {
unlockDoor("RFID ACCEPTED");
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
// ==================================================
// KEYPAD
// ==================================================
void checkKeypad() {
char key = keypad.getKey();
if (!key || isUnlocked) {
return;
}
// Clear entered password.
if (key == '*') {
clearPassword();
updateDisplay();
return;
}
// Submit password.
if (key == '#') {
enteredPassword[enteredLength] = '\0';
if (enteredLength == PASSWORD_LENGTH &&
strcmp(enteredPassword, PASSWORD) == 0) {
unlockDoor("PASSWORD OK");
} else {
rejectPassword();
if (!alarmActive) {
updateDisplay();
}
}
return;
}
// Accept numeric keys only.
if (key >= '0' && key <= '9') {
if (enteredLength < PASSWORD_LENGTH) {
enteredPassword[enteredLength] = key;
enteredLength++;
enteredPassword[enteredLength] = '\0';
updateDisplay();
}
}
}
// ==================================================
// SETUP
// ==================================================
void setup() {
Serial.begin(9600);
pinMode(PIR_PIN, INPUT);
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
lcd.init();
lcd.backlight();
// Initialize RFID over hardware SPI.
SPI.begin();
rfid.PCD_Init();
// Initialize servo.
lockServo.attach(SERVO_PIN);
lockServo.write(LOCKED_ANGLE);
clearPassword();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Starting system");
lcd.setCursor(0, 1);
lcd.print("Wait for PIR...");
// PIR stabilization period.
delay(30000);
lockDoor();
Serial.println("Security system ready");
Serial.println("Keypad password: 1234");
Serial.println("Press # to submit");
Serial.println("Press * to clear");
Serial.println("Compatible RFID cards accepted");
}
// ==================================================
// MAIN LOOP
// ==================================================
void loop() {
unsigned long now = millis();
// Re-arm motion detection after PIR output goes LOW.
if (digitalRead(PIR_PIN) == LOW) {
pirArmed = true;
}
// Automatically lock the door after five seconds.
if (isUnlocked && now - unlockedAt >= UNLOCK_TIME) {
lockDoor();
}
// No locked-state security processing while unlocked.
if (isUnlocked) {
return;
}
// Start a 10-second entry countdown after motion.
if (pirArmed &&
digitalRead(PIR_PIN) == HIGH &&
!entryCountdown &&
!alarmActive) {
pirArmed = false;
entryCountdown = true;
countdownStarted = now;
Serial.println("Motion detected!");
Serial.println("You have 10 seconds to authenticate.");
updateDisplay();
}
// Start alarm when the countdown expires.
if (entryCountdown &&
now - countdownStarted >= ENTRY_TIME) {
startAlarm();
}
// Blink red LED and sound buzzer during alarm.
if (alarmActive) {
if (now - lastBlink >= BLINK_INTERVAL) {
lastBlink = now;
redLedState = !redLedState;
digitalWrite(RED_LED, redLedState);
}
tone(BUZZER_PIN, 2000);
}
else {
noTone(BUZZER_PIN);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(RED_LED, HIGH);
}
// Refresh the countdown display periodically.
if (entryCountdown &&
now - lastDisplayUpdate >= DISPLAY_INTERVAL) {
lastDisplayUpdate = now;
updateDisplay();
}
// These remain active during countdown and alarm.
checkRFID();
checkKeypad();
}
Loading
mfrc522
mfrc522