#include <WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>
// Define Wi-Fi credentials
const char* ssid = "Wokwi-GUEST"; // Replace with your Wi-Fi SSID
const char* password = ""; // Replace with your Wi-Fi password
// Define MQTT broker details
const char* mqtt_broker = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* lux_topic = "home/sensors/lux";
const char* motion_topic = "home/sensors/motion";
const char* condition_topic = "home/sensors/condition";
const char* night_mode_topic = "home/mode/night";
const char* night_mode_security = "home/mode/night/security";
// Initialize Wi-Fi and MQTT client
WiFiClient espClient;
PubSubClient client(espClient);
// Define pins
#define LDR_PIN 36
#define PIR_PIN 16
#define NEOPIXEL_PIN 19
#define NUM_PIXELS 16
#define BUTTON_PIN 18
#define BUZZER_PIN 17 // GPIO 17 where the buzzer is connected
// Constants for photoresistor calculations
const float GAMMA = 0.7;
const float RL10 = 50;
// LCD initialization
LiquidCrystal_I2C lcd(0x27, 20, 4);
// NeoPixel initialization
Adafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Sensor data structure
struct SensorData {
float lux;
bool motionDetected;
const char* condition;
};
SensorData sensorData;
// Flags for controls
bool nightModeEnabled = false;
void setup() {
Serial.begin(115200);
Serial.println("Initializing System...");
// Initialize Wi-Fi and MQTT
connectToWiFi();
client.setServer(mqtt_broker, mqtt_port);
connectToMQTT();
// Initialize sensors and peripherals
pinMode(BUZZER_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(PIR_PIN, INPUT);
lcd.init();
lcd.backlight();
pixels.begin();
pixels.clear();
pixels.show();
delay(1000);
lcd.clear();
lcd.print("System Ready");
delay(1000);
lcd.clear();
}
// Connect to Wi-Fi
void connectToWiFi() {
Serial.print("Connecting to Wi-Fi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("\nConnected to Wi-Fi!");
}
// Connect to MQTT broker
void connectToMQTT() {
Serial.print("Connecting to MQTT broker");
while (!client.connected()) {
if (client.connect("ESP32Client")) {
Serial.println("\nConnected to MQTT broker!");
} else {
Serial.print(".");
delay(100); // Reduced delay to match Wi-Fi
}
}
}
// Read light intensity
void readPhotoresistor() {
int ldrValue = analogRead(LDR_PIN);
float voltage = ldrValue / 4095.0 * 5.0;
float resistance = 2000 * voltage / (1 - voltage / 5);
sensorData.lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
}
// Detect motion
void detectMotion() {
sensorData.motionDetected = digitalRead(PIR_PIN) == HIGH;
}
// Update room condition
void updateRoomCondition() {
if (nightModeEnabled) {
pixels.clear();
pixels.show();
sensorData.condition = "Night Mode";
return;
}
if (sensorData.lux < 50) {
sensorData.condition = "Dark";
setNeoPixelColor(255, 100, 0);
} else if (sensorData.lux < 500) {
sensorData.condition = "Dim";
setNeoPixelColor(255, 255, 150);
} else {
sensorData.condition = "Bright";
setNeoPixelColor(150, 200, 255);
}
}
// Set NeoPixel color
void setNeoPixelColor(uint8_t red, uint8_t green, uint8_t blue) {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(red, green, blue));
}
pixels.show();
}
// Toggle night mode
void toggleNightMode() {
static bool lastButtonState = HIGH;
bool currentButtonState = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && currentButtonState == LOW) {
nightModeEnabled = !nightModeEnabled;
lcd.clear();
lcd.print(nightModeEnabled ? "Night Mode ON" : "Night Mode OFF");
// Publish night mode status to MQTT
if (!client.connected()) {
connectToMQTT();
}
client.publish(night_mode_topic, nightModeEnabled ? "ON" : "OFF");
// Debug message
Serial.println(nightModeEnabled ? "Night Mode Activated" : "Night Mode Deactivated");
delay(500);
}
lastButtonState = currentButtonState;
}
// Night mode logic
void nightMode() {
if (nightModeEnabled) {
pixels.clear();
pixels.show();
lcd.clear();
if (sensorData.lux < 1) {
if (!sensorData.motionDetected) {
lcd.setCursor(4, 1);
lcd.print("Safe & Sound");
Serial.println("Safe & Sound");
// Publish to the new topic
client.publish(night_mode_security, "Safe & Sound");
} else {
lcd.setCursor(1, 1);
lcd.print("Intruder Detected");
Serial.println("Intruder Detected");
// Publish to the new topic
client.publish(night_mode_security, "Intruder Detected");
soundAlarm();
}
delay(3000);
}
}
}
// Alarm logic
void soundAlarm() {
Serial.println("ALARM! Intruder Detected!");
// Make the buzzer beep 5 times
for (int i = 0; i < 5; i++) {
tone(BUZZER_PIN, 256); // Turn the buzzer on
delay(500); // Wait for 500ms
noTone(BUZZER_PIN);
delay(500); // Wait for 500ms
}
}
// Publish sensor data to MQTT
void publishData() {
if (!client.connected()) {
Serial.println("MQTT Disconnected! Reconnecting...");
connectToMQTT();
}
client.loop();
// Publish lux, motion, and condition
client.publish(lux_topic, String(sensorData.lux).c_str());
client.publish(motion_topic, sensorData.motionDetected ? "true" : "false");
client.publish(condition_topic, sensorData.condition);
Serial.println("Published data to MQTT:");
Serial.print("Lux: "); Serial.println(sensorData.lux);
Serial.print("Motion: "); Serial.println(sensorData.motionDetected ? "Detected" : "None");
Serial.print("Condition: "); Serial.println(sensorData.condition);
}
// Update LCD display
void updateLCD() {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Light: ");
lcd.print(sensorData.lux);
lcd.print(" Lux");
lcd.setCursor(0, 2);
lcd.print("Room: ");
lcd.print(sensorData.condition);
}
// Main loop
unsigned long previousMillis = 0;
const unsigned long interval = 3000;
void loop() {
if (WiFi.status() != WL_CONNECTED) {
connectToWiFi();
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
readPhotoresistor();
detectMotion();
toggleNightMode();
nightMode();
updateRoomCondition();
publishData();
updateLCD();
}
}