#include <Keypad.h>
#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// --- LCD ---
LiquidCrystal_I2C lcd(0x27, 16, 2);
// --- 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,3,4,5};
byte colPins[COLS] = {6,7,8,9};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// --- Servo & Outputs ---
Servo myServo;
const int servoPin = 10;
const int relayPin = 11;
const int buzzerPin = 12;
const int ledGreen = 13;
const int ledRed = A0;
const int pushPin = A1; // Emergency push-button
// --- System ---
String inputCode = "";
const String PASSWORD = "1234";
unsigned long unlockDuration = 5000;
// --- Smooth servo movement ---
void servoSmoothMove(int startPos, int endPos, int stepDelay){
if (endPos > startPos){
for (int pos = startPos; pos <= endPos; pos++){
myServo.write(pos);
delay(stepDelay);
}
} else {
for (int pos = startPos; pos >= endPos; pos--){
myServo.write(pos);
delay(stepDelay);
}
}
}
void setup(){
pinMode(relayPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(ledGreen, OUTPUT);
pinMode(ledRed, OUTPUT);
pinMode(pushPin, INPUT_PULLUP);
// Push button module: HIGH = idle, LOW = pressed
digitalWrite(relayPin, HIGH); // Solenoid OFF default
myServo.attach(servoPin);
myServo.write(180); // posisi awal kunci tertutup
Serial.begin(9600);
// LCD init
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Enter Password:");
}
// --- LOOP UTAMA ---
void loop(){
// ================================
// 1. EMERGENCY BUTTON (A1)
// ================================
if (digitalRead(pushPin) == LOW) { // LOW = ditekan
delay(40); // debounce
if (digitalRead(pushPin) == LOW) {
buzzShort();
accessGranted();
return;
}
}
// ================================
// 2. KEYPAD INPUT
// ================================
char key = keypad.getKey();
if(key){
if(key == '#'){
checkCode();
}
else if(key == '*'){
inputCode = "";
buzzShort();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Enter Password:");
lcd.setCursor(0,1);
lcd.print("Cleared");
}
else {
inputCode += key;
buzzShort();
lcd.setCursor(0,1);
lcd.print(inputCode);
}
Serial.println(inputCode);
}
}
// --- CHECK PASSWORD ---
void checkCode(){
if(inputCode == PASSWORD){
accessGranted();
} else {
accessDenied();
}
inputCode = "";
}
// --- AKSES BENAR ---
void accessGranted(){
digitalWrite(ledGreen, HIGH);
digitalWrite(ledRed, LOW);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Access Granted");
lcd.setCursor(0,1);
lcd.print("Door Opening...");
buzzShort();
// Solenoid ON → pintu buka
digitalWrite(relayPin, LOW);
// Buka pintu: 180° → 0°
servoSmoothMove(180, 0, 12);
delay(unlockDuration);
// Tutup pintu: 0° → 180°
servoSmoothMove(0, 180, 12);
digitalWrite(relayPin, HIGH);
digitalWrite(ledGreen, LOW);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Door Locked");
delay(1500);
lcd.clear();
lcd.print("Enter Password:");
}
// --- AKSES SALAH ---
void accessDenied(){
digitalWrite(ledRed, HIGH);
digitalWrite(ledGreen, LOW);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Access Denied!");
lcd.setCursor(0,1);
lcd.print("Wrong Code");
for(int i=0;i<3;i++){
digitalWrite(buzzerPin, HIGH);
delay(300);
digitalWrite(buzzerPin, LOW);
delay(150);
}
digitalWrite(ledRed, LOW);
lcd.clear();
lcd.print("Enter Password:");
}
// --- Buzzer pendek ---
void buzzShort(){
digitalWrite(buzzerPin, HIGH);
delay(50);
digitalWrite(buzzerPin, LOW);
}