// SMART ROOM SYSTEM - Wokwi Compatible Code
// EC8020 Design Task 2
#include <Servo.h>
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ===== LCD SETUP =====
LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address 0x27 (common for LCD2004)
// ===== PIN DEFINITIONS =====
// Door Lock System
#define SERVO_PIN 9
#define LED_LOCKED 10
#define LED_UNLOCKED 11
#define BUZZER_LOCK 12
// Lighting System
#define PIR_SENSOR 8
#define LIGHT_RELAY 7
// Smoke Detection System
#define SMOKE_SENSOR A0
#define ALARM_BUZZER 6
#define ALARM_LED 5
// ===== 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] = {A1, A2, A3, A4}; // Keypad rows
byte colPins[COLS] = {2, 3, 4, 13}; // Keypad columns
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ===== GLOBAL VARIABLES =====
// Door Lock
Servo doorServo;
String password = "1234"; // Default password
String enteredPassword = "";
bool doorLocked = true;
unsigned long unlockTime = 0;
const unsigned long AUTO_LOCK_TIME = 10000; // 10 seconds
// Lighting System
unsigned long lastMotionTime = 0;
bool lightOn = false;
const unsigned long LIGHT_TIMEOUT = 30000; // 30 seconds
// Smoke Detection
const int SMOKE_THRESHOLD = 910; // Adjust based on sensor calibration
bool alarmActive = false;
// ===== SETUP =====
void setup() {
Serial.begin(9600);
// LCD Setup
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 1); lcd.print("Enter Password: ");
lcd.setCursor(0, 2); lcd.print("Door: LOCKED");
lcd.setCursor(0, 3); lcd.print("Light: OFF");
// Door Lock Setup
doorServo.attach(SERVO_PIN);
pinMode(LED_LOCKED, OUTPUT);
pinMode(LED_UNLOCKED, OUTPUT);
pinMode(BUZZER_LOCK, OUTPUT);
lockDoor(); // Start in locked state
// Lighting System Setup
pinMode(PIR_SENSOR, INPUT);
pinMode(LIGHT_RELAY, OUTPUT);
digitalWrite(LIGHT_RELAY, LOW); // Light off
// Smoke Detection Setup
pinMode(ALARM_BUZZER, OUTPUT);
pinMode(ALARM_LED, OUTPUT);
digitalWrite(ALARM_BUZZER, LOW);
digitalWrite(ALARM_LED, LOW);
}
// ===== MAIN LOOP =====
void loop() {
handleDoorLock();
handleLighting();
handleSmokeDetection();
delay(50); // Small delay for stability
}
// ===== DOOR LOCK FUNCTIONS =====
void handleDoorLock() {
// Check for keypad input
char key = keypad.getKey();
if (key) {
if (key == '#') { // Submit password
checkPassword();
} else if (key == '*') { // Clear password
enteredPassword = "";
lcd.setCursor(0, 1); lcd.print("Enter Password: ");
} else if (enteredPassword.length() < 4) {
enteredPassword += key;
displayEnteredPassword();
// Auto-submit when 4 digits entered
if (enteredPassword.length() == 4) {
checkPassword();
}
}
}
// Auto-lock after timeout
if (!doorLocked && millis() - unlockTime > AUTO_LOCK_TIME) {
lockDoor();
// Reset LCD layout
lcd.clear();
lcd.setCursor(0, 1); lcd.print("Enter Password: ");
lcd.setCursor(0, 2); lcd.print("Door: LOCKED ");
lcd.setCursor(0, 3); lcd.print(lightOn ? "Light: ON " : "Light: OFF");
Serial.println(">> Auto-locking door (timeout)");
}
}
void displayEnteredPassword() {
lcd.setCursor(0, 1);
lcd.print("Password: ");
for (int i = 0; i < enteredPassword.length(); i++) {
lcd.print("*");
}
lcd.print(" "); // Clear leftover chars
}
void checkPassword() {
Serial.println("----------------------------");
Serial.print("Verifying password: ");
for (int i = 0; i < enteredPassword.length(); i++) {
Serial.print("*");
}
Serial.println();
if (enteredPassword == password) {
unlockDoor();
lcd.setCursor(0, 2);
lcd.print("Door: UNLOCKED ");
Serial.println("✓ ACCESS GRANTED - Door Unlocked");
} else {
Serial.println("✗ ACCESS DENIED - Wrong Password");
wrongPasswordAlert();
lcd.setCursor(0, 2);
lcd.print("ACCESS DENIED ");
delay(2000);
// Reset LCD for next try
lcd.setCursor(0, 1); lcd.print("Enter Password: ");
lcd.setCursor(0, 2); lcd.print("Status: LOCKED ");
}
Serial.println("----------------------------");
enteredPassword = ""; // Clear for next attempt
}
void unlockDoor() {
doorLocked = false;
doorServo.write(90); // Unlock position (90 degrees)
digitalWrite(LED_UNLOCKED, HIGH);
digitalWrite(LED_LOCKED, LOW);
unlockTime = millis();
// Success beep
tone(BUZZER_LOCK, 1000, 200);
delay(250);
tone(BUZZER_LOCK, 1200, 200);
}
void lockDoor() {
doorLocked = true;
doorServo.write(0); // Lock position (0 degrees)
digitalWrite(LED_LOCKED, HIGH);
digitalWrite(LED_UNLOCKED, LOW);
// Lock beep
tone(BUZZER_LOCK, 800, 150);
}
void wrongPasswordAlert() {
// Blink red LED and sound buzzer 3 times
for (int i = 0; i < 3; i++) {
digitalWrite(LED_LOCKED, LOW);
tone(BUZZER_LOCK, 2000, 200);
delay(250);
digitalWrite(LED_LOCKED, HIGH);
delay(250);
}
}
// ===== LIGHTING SYSTEM FUNCTIONS =====
void handleLighting() {
int motionDetected = digitalRead(PIR_SENSOR);
if (motionDetected == HIGH) {
// Motion detected
if (!lightOn) {
turnLightOn();
}
lastMotionTime = millis(); // Reset timer
} else {
// No motion
if (lightOn && (millis() - lastMotionTime > LIGHT_TIMEOUT)) {
turnLightOff();
}
}
}
void turnLightOn() {
digitalWrite(LIGHT_RELAY, HIGH);
lightOn = true;
lcd.setCursor(0, 3);
lcd.print("Light: ON ");
Serial.println(">> Light ON - Motion detected");
}
void turnLightOff() {
digitalWrite(LIGHT_RELAY, LOW);
lightOn = false;
lcd.setCursor(0, 3);
lcd.print("Light: OFF ");
Serial.println(">> Light OFF - No motion (timeout)");
}
// ===== SMOKE DETECTION FUNCTIONS =====
void handleSmokeDetection() {
int smokeLevel = analogRead(SMOKE_SENSOR);
// Always display smoke level on LCD line 0
lcd.setCursor(0, 0);
lcd.print("Smoke Level: ");
lcd.print(smokeLevel);
lcd.print(" "); // Clear extra chars
if (smokeLevel > SMOKE_THRESHOLD) {
// Smoke detected above threshold
if (!alarmActive) {
activateAlarm();
}
// Keep alarm sounding while smoke is present
static unsigned long lastBeep = 0;
if (millis() - lastBeep > 500) {
tone(ALARM_BUZZER, 3000, 400);
lastBeep = millis();
}
// Overwrite with ALERT if danger
lcd.setCursor(0, 0);
lcd.print("!!! SMOKE ALERT !!!");
} else {
// No dangerous smoke level
if (alarmActive) {
deactivateAlarm();
}
}
}
void activateAlarm() {
alarmActive = true;
digitalWrite(ALARM_LED, HIGH);
Serial.println("⚠⚠⚠ ALARM ACTIVATED ⚠⚠⚠");
Serial.println("SMOKE/GAS DETECTED!");
Serial.println("⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠");
}
void deactivateAlarm() {
alarmActive = false;
digitalWrite(ALARM_LED, LOW);
noTone(ALARM_BUZZER);
Serial.println(">> Alarm deactivated - Air quality normal");
}
// ===== UTILITY FUNCTIONS (for testing) =====
void printStatus() {
Serial.println("\n===== SYSTEM STATUS =====");
Serial.print("Door: ");
Serial.println(doorLocked ? "LOCKED" : "UNLOCKED");
Serial.print("Light: ");
Serial.println(lightOn ? "ON" : "OFF");
Serial.print("Alarm: ");
Serial.println(alarmActive ? "ACTIVE" : "INACTIVE");
Serial.println("========================\n");
}