#include <Keypad.h>
#include <Servo.h>
/* ====== USER SETTINGS ====== */
#define PIN_LENGTH 4 // digits in the PIN
#define UNLOCK_WINDOW_MS 1000 // how long to stay unlocked (ms)
#define MAX_TRIES 3 // lockout after N wrong tries
#define LOCKOUT_MS 1000 // lockout duration (ms)
#define LOCKED_ANGLE 0 // servo angle when locked
#define UNLOCKED_ANGLE 90 // servo angle when unlocked
const char MASTER_PIN[PIN_LENGTH + 1] = "1234"; // <- change this!
/* ====== PINS ====== */
const byte servoPin = 10; // use any digital pin on most Arduinos
// 4x4 keypad wiring: rows then cols
const byte ROWS = 4, COLS = 4;
byte rowPins[ROWS] = {5, 4, 3, 2};
byte colPins[COLS] = {6, 7, 8, 9};
/* ====== KEYPAD LAYOUT ====== */
// Adjust to match your keypad’s legends
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
Servo door;
char entered[PIN_LENGTH + 1];
byte idx = 0;
unsigned long lockoutUntil = 0;
byte failed = 0;
void lockDoor() {
door.write(LOCKED_ANGLE);
}
void unlockDoorFor(unsigned long ms) {
door.write(UNLOCKED_ANGLE);
unsigned long start = millis();
while (millis() - start < ms) {
// keep reading keypad so we don't miss presses; allow manual re-lock on '#'
char k = keypad.getKey();
if (k == '#') break;
}
lockDoor();
}
void resetBuffer() {
memset(entered, 0, sizeof(entered));
idx = 0;
}
void setup() {
Serial.begin(9600);
door.attach(servoPin);
lockDoor();
// Keypad best-practice: set a gentle debounce
keypad.setDebounceTime(15);
Serial.println(F("Door Lock Ready"));
Serial.println(F("Enter 4-digit PIN:"));
}
bool pinMatches() {
return strncmp(entered, MASTER_PIN, PIN_LENGTH) == 0;
}
void handleKey(char key) {
if (key == NO_KEY) return;
// Clear buffer
if (key == '*') {
resetBuffer();
Serial.println(F("[CLR]"));
return;
}
// Submit early with '#'
if (key == '#') {
// ignore if no digits
if (idx == 0) return;
// pad/truncate if needed
entered[PIN_LENGTH] = '\0';
if (pinMatches()) {
Serial.println(F("✅ Correct PIN. Unlocked!"));
failed = 0;
resetBuffer();
unlockDoorFor(UNLOCK_WINDOW_MS);
Serial.println(F("🔒 Locked."));
Serial.println(F("Enter 4-digit PIN:"));
} else {
Serial.println(F("⛔ Wrong PIN."));
failed++;
resetBuffer();
if (failed >= MAX_TRIES) {
lockoutUntil = millis() + LOCKOUT_MS;
Serial.println(F("🚫 Too many attempts. Locked out."));
}
}
return;
}
// Accept digits only; ignore A-D for a simple numeric PIN
if (key >= '0' && key <= '9') {
if (idx < PIN_LENGTH) {
entered[idx++] = key;
Serial.print('*'); // don’t echo digits
if (idx == PIN_LENGTH) {
// Auto-submit when full length reached
if (pinMatches()) {
Serial.println();
Serial.println(F("✅ Correct PIN. Unlocked!"));
failed = 0;
resetBuffer();
unlockDoorFor(UNLOCK_WINDOW_MS);
Serial.println(F("🔒 Locked."));
Serial.println(F("Enter 4-digit PIN:"));
} else {
Serial.println();
Serial.println(F("⛔ Wrong PIN."));
failed++;
resetBuffer();
if (failed >= MAX_TRIES) {
lockoutUntil = millis() + LOCKOUT_MS;
Serial.println(F("🚫 Too many attempts. Locked out."));
}
}
}
}
} else {
// optional: beep/ignore non-numeric keys
}
}
void loop() {
if (lockoutUntil) {
if (millis() < lockoutUntil) {
// In lockout; still read keys to keep keypad responsive,
// but ignore entries.
(void)keypad.getKey();
return;
} else {
lockoutUntil = 0;
failed = 0;
Serial.println(F("🔓 Lockout ended. Try again."));
Serial.println(F("Enter 4-digit PIN:"));
}
}
char key = keypad.getKey(); // non-blocking
handleKey(key);
}
No comments:
Post a Comment