#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <RTClib.h>
const int GREEN_LED = 9;
const int RED_LED = 8;
const int BUTTON_PIN = 3;
const int PIR_SENSON = 2;
// --- System State ---
bool isSystemOn = false;
bool lastButtonState = HIGH;
bool currentButtonState;
bool isSystemArmed = false;
bool isMotionDetected = false;
unsigned long motionDetectedTime = 0;
String correctCode = "1234";
String enteredCode = "";
// --- Timing for Non-blocking LED Flicker ---
unsigned long previousMillis = 0;
const long interval = 500;
bool ledState = LOW;
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231 rtc;
DateTime lastMotionTime;
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] = {4, 5, 6, 7};
byte colPins[COLS] = {10, 11, 12, 13};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void setup()
{
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(PIR_SENSON, INPUT);
lcd.init();
lcd.backlight();
lcd.clear();
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, LOW);
if (!rtc.begin())
{
lcd.setCursor(0, 0);
lcd.print("RTC Failed!");
while(1);
}
if (rtc.lostPower())
{
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
updateSystemDisplay();
}
void updateSystemDisplay()
{
isSystemArmed ? displaySystemArmed() : displaySystemDisarmed();
}
void displaySystemArmed()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System Armed!");
lcd.setCursor(0, 1);
lcd.print("Enter Code: ");
}
void displaySystemDisarmed()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System Not Armed!");
lcd.setCursor(0, 1);
lcd.print("Enter Code: ");
}
void displayMotionDetected(bool isArmed)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(isArmed ? "INTRUSION ALERT!" : "Motion Detected!");
lcd.setCursor(0, 1);
if (isArmed)
{
char buffer[9];
sprintf(buffer, "%02d:%02d:%02d", lastMotionTime.hour(), lastMotionTime.minute(), lastMotionTime.second());
lcd.print(buffer);
}
else
{
lcd.print("Please Arm System");
}
}
void handleCorrectCode()
{
isSystemArmed = !isSystemArmed;
updateSystemDisplay();
}
void handleWrongCode()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Wrong Code!");
delay(1000);
updateSystemDisplay();
}
void loop()
{
currentButtonState = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && currentButtonState == LOW)
{
isSystemOn = !isSystemOn;
updateSystemDisplay();
delay(200);
}
lastButtonState = currentButtonState;
if (isSystemOn)
{
handleKeypadInput();
handleMotionDetection();
handleLedBehavior();
}
else
{
turnOffLeds();
lcd.clear();
}
}
void handleKeypadInput()
{
char key = keypad.getKey();
if (key)
{
if (isMotionDetected)
{
isMotionDetected = false;
updateSystemDisplay();
}
enteredCode += key;
lcd.setCursor(12, 1);
lcd.print(enteredCode);
if (enteredCode.length() == 4)
{
enteredCode == correctCode ? handleCorrectCode() : handleWrongCode();
enteredCode = "";
}
}
}
void handleMotionDetection()
{
if (digitalRead(PIR_SENSON) == HIGH)
{
if (!isMotionDetected)
{
isMotionDetected = true;
motionDetectedTime = millis();
lastMotionTime = rtc.now();
displayMotionDetected(isSystemArmed);
}
}
else if (isMotionDetected && (millis() - motionDetectedTime > 4000))
{
isMotionDetected = false;
updateSystemDisplay();
}
}
void handleLedBehavior()
{
unsigned long currentMillis = millis();
if (!isSystemArmed && !isMotionDetected && (currentMillis - previousMillis >= interval))
{
previousMillis = currentMillis;
ledState = !ledState;
digitalWrite(GREEN_LED, ledState);
}
else
{
digitalWrite(GREEN_LED, LOW);
}
if (isSystemArmed && isMotionDetected && (currentMillis - previousMillis >= 100))
{
previousMillis = currentMillis;
ledState = !ledState;
digitalWrite(RED_LED, ledState);
digitalWrite(GREEN_LED, LOW);
}
}
void turnOffLeds()
{
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, LOW);
}