#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <ESP32Servo.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo doorServo;
// ---------------- PINS ----------------
int servoPin = 25;
int buzzerPin = 15;
// ---------------- 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] = {2,4,16,17};
byte colPins[COLS] = {5,18,19,23};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ---------------- SECURITY ----------------
String userPIN = "123456";
String adminPIN = "999999";
String inputPIN = "";
int wrongAttempts = 0;
const int maxAttempts = 3;
bool lockedOut = false;
unsigned long lockStart = 0;
const unsigned long lockTime = 5000;
bool adminMode = false;
unsigned long unlockStart = 0;
bool doorUnlocked = false;
void setup() {
Serial.begin(115200);
Wire.begin(21,22);
lcd.init();
lcd.backlight();
lcd.print("Enter 6-digit");
lcd.setCursor(0,1);
lcd.print("PIN:");
doorServo.attach(servoPin);
doorServo.write(0);
pinMode(buzzerPin, OUTPUT);
Serial.println("System Started");
}
void loop() {
handleLockout();
handleAutoLock();
handleKeypad();
delay(5);
}
// ---------------- KEYPAD ----------------
void handleKeypad() {
char key = keypad.getKey();
if (!key || lockedOut) return;
processInput(key);
}
// ---------------- PROCESS INPUT ----------------
void processInput(char key) {
if (key == '*') {
inputPIN = "";
resetLCD();
return;
}
if (key == '#') {
processPIN(inputPIN);
inputPIN = "";
return;
}
if (isdigit(key) && inputPIN.length() < 6) {
inputPIN += key;
lcd.setCursor(inputPIN.length()-1,1);
lcd.print("*");
}
}
// ---------------- PROCESS PIN ----------------
void processPIN(String entered) {
lcd.clear();
if (adminMode) {
if (entered.length() == 6) {
userPIN = entered;
adminMode = false;
lcd.print("PIN Updated");
Serial.println("LOG: PIN Changed by Admin");
delay(1500);
resetLCD();
}
return;
}
if (entered == userPIN) {
lcd.print("Access Granted");
Serial.println("LOG: Door Unlocked");
wrongAttempts = 0;
unlockDoor();
}
else if (entered == adminPIN) {
adminMode = true;
lcd.print("Admin Mode");
lcd.setCursor(0,1);
lcd.print("New PIN:");
Serial.println("LOG: Admin Access");
}
else {
wrongAttempts++;
lcd.print("Wrong PIN");
lcd.setCursor(0,1);
lcd.print("Attempts:");
lcd.print(wrongAttempts);
lcd.print("/");
lcd.print(maxAttempts);
Serial.println("LOG: Failed Attempt");
beep(3);
if (wrongAttempts >= maxAttempts) {
activateLockout();
}
delay(1500);
resetLCD();
}
}
// ---------------- UNLOCK ----------------
void unlockDoor() {
doorServo.write(90);
doorUnlocked = true;
unlockStart = millis();
beep(1);
}
// ---------------- AUTO LOCK ----------------
void handleAutoLock() {
if (doorUnlocked && millis() - unlockStart >= 5000) {
doorServo.write(0);
doorUnlocked = false;
resetLCD();
}
}
// ---------------- LOCKOUT ----------------
void activateLockout() {
lockedOut = true;
lockStart = millis();
lcd.clear();
lcd.print("LOCKED 5 SEC");
Serial.println("LOG: System Lockout");
beep(1);
}
void handleLockout() {
if (lockedOut && millis() - lockStart >= lockTime) {
lockedOut = false;
wrongAttempts = 0;
resetLCD();
}
}
// ---------------- UTILITIES ----------------
void beep(int times) {
for(int i=0;i<times;i++){
digitalWrite(buzzerPin, HIGH);
delay(150);
digitalWrite(buzzerPin, LOW);
delay(150);
}
}
void resetLCD() {
lcd.clear();
lcd.print("Enter 6-digit");
lcd.setCursor(0,1);
lcd.print("PIN:");
}