#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <ESP32Servo.h>
#include <MFRC522.h>
#include <SPI.h>
#include "RTClib.h"
// --- Configuration Pins ---
#define LIGHT_PIN 4
#define FAN_PIN 15
#define POT_PIN 34
#define SERVO_PIN 17
#define BUZZER_PIN 2
#define RST_PIN 0
#define SS_PIN 5
// --- Timezone Offset ---
#define TIME_OFFSET 19800
// --- Objects ---
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myServo;
MFRC522 rfid(SS_PIN, RST_PIN);
RTC_DS1307 rtc;
// --- Keypad Setup ---
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] = {13, 12, 14, 27};
byte colPins[COLS] = {26, 25, 33, 32};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// --- Variables ---
String inputCode = "";
const String masterCode = "1234";
bool lightState = false;
bool fanState = false;
bool autoTriggered = false;
void setup() {
Serial.begin(115200);
SPI.begin();
rfid.PCD_Init();
lcd.init();
lcd.backlight();
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
}
DateTime compileTime = DateTime(F(__DATE__), F(__TIME__));
rtc.adjust(DateTime(compileTime.unixtime() + TIME_OFFSET));
pinMode(LIGHT_PIN, OUTPUT);
pinMode(FAN_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
myServo.attach(SERVO_PIN);
myServo.write(0);
lcd.setCursor(0,0);
lcd.print("SMART HOME START");
delay(1500);
lcd.clear();
}
void unlockDoor() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("ACCESS GRANTED");
// Single beep for success
digitalWrite(BUZZER_PIN, HIGH);
delay(300);
digitalWrite(BUZZER_PIN, LOW);
myServo.write(90);
delay(3000);
myServo.write(0);
lcd.clear();
}
void wrongPasswordAlert() {
lcd.setCursor(0,0);
lcd.print("INVALID CODE! ");
// Two short beeps for failure
digitalWrite(BUZZER_PIN, HIGH);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
delay(100);
digitalWrite(BUZZER_PIN, HIGH);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
delay(1000);
lcd.clear();
}
void loop() {
DateTime now = rtc.now();
// --- 1. Automation (Trigger at 4:00 PM / 16:00) ---
if (now.hour() >= 16 && !autoTriggered) {
lightState = true;
fanState = true;
digitalWrite(LIGHT_PIN, HIGH);
digitalWrite(FAN_PIN, HIGH);
autoTriggered = true;
}
if (now.hour() == 0) autoTriggered = false;
// --- 2. Manual Controls ---
char key = keypad.getKey();
if (key) {
if (key == 'A') {
lightState = !lightState;
digitalWrite(LIGHT_PIN, lightState);
}
else if (key == 'B') {
fanState = !fanState;
digitalWrite(FAN_PIN, fanState);
}
else if (key == '#') {
if (inputCode == masterCode) {
unlockDoor();
} else {
wrongPasswordAlert(); // Updated to beep on failure
}
inputCode = "";
}
else if (isdigit(key)) {
inputCode += key;
}
}
// --- 3. RFID Check ---
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
unlockDoor();
rfid.PICC_HaltA();
}
// --- 4. LCD Display ---
lcd.setCursor(0, 0);
if (inputCode == "") {
char timeStr[17];
sprintf(timeStr, "%02d:%02d:%02d L:%d F:%d",
now.hour(), now.minute(), now.second(),
lightState, fanState);
lcd.print(timeStr);
} else {
lcd.print("CODE: " + inputCode + " ");
}
// Energy Meter (Row 1)
int raw = analogRead(POT_PIN);
float watts = (raw / 4095.0) * 500.0;
lcd.setCursor(0, 1);
lcd.print("USAGE: ");
lcd.print(watts, 1);
lcd.print("W ");
delay(100);
}