#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
// Pin Assignments
#define DHT_PIN 15 // DHT22 data pin
#define PIR_PIN 14 // PIR sensor output pin
#define MQ2_PIN 35 // MQ-2 analog output (ESP32 ADC pin)
#define LDR_PIN 34 // LDR analog output (ESP32 ADC pin)
#define TRIG_PIN 12 // HC-SR04 trigger pin
#define ECHO_PIN 13 // HC-SR04 echo pin
#define RELAY1_PIN 5 // Relay1 control (light)
#define RELAY2_PIN 16 // Relay2 control (fan)
#define RELAY3_PIN 17 // Relay3 control (buzzer/alarm)
#define RELAY4_PIN 18 // Relay4 control (other appliance)
#define LED1_R_PIN 19 // RGB LED1 Red
#define LED1_G_PIN 23 // RGB LED1 Green
#define LED1_B_PIN 25 // RGB LED1 Blue
#define LED2_R_PIN 26 // RGB LED2 Red
#define LED2_G_PIN 27 // RGB LED2 Green
#define LED2_B_PIN 32 // RGB LED2 Blue
#define LED3_R_PIN 33 // RGB LED3 Red
#define LED3_G_PIN 4 // RGB LED3 Green
#define LED3_B_PIN 2 // RGB LED3 Blue
// Sensor and system thresholds
const float TEMP_THRESHOLD = 30.0; // [°C] Temperature above which fan turns on
const int LDR_THRESHOLD = 3000; // LDR analog value above which we consider it "dark"
const int GAS_THRESHOLD = 40; // [%] Gas level above which alarm triggers
const float DIST_THRESHOLD = 50.0; // [cm] Distance below which an object is considered
"detected"
// Initialize DHT22 (using Adafruit DHT library)
#define DHTTYPE DHT22
DHT dht(DHT_PIN, DHTTYPE);
// Initialize LCD (I2C address 0x27, 16 columns, 2 rows)
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
// Serial port for debugging
Serial.begin(115200);
Serial.println("ESP32 Home Automation System Starting...");
// Initialize DHT sensor
dht.begin();
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("ESP32 Home IoT");
lcd.setCursor(0, 1);
lcd.print("System Starting");
delay(2000); // display startup message for 2 seconds
lcd.clear();
// Configure sensor pins
pinMode(PIR_PIN, INPUT); // PIR (could use INPUT_PULLUP if needed)
pinMode(TRIG_PIN, OUTPUT); // Ultrasonic Trigger
pinMode(ECHO_PIN, INPUT); // Ultrasonic Echo
// Configure relay output pins
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);
pinMode(RELAY4_PIN, OUTPUT);
// Ensure all relays off initially
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);
digitalWrite(RELAY4_PIN, LOW);
// Configure RGB LED pins as outputs
pinMode(LED1_R_PIN, OUTPUT); pinMode(LED1_G_PIN, OUTPUT); pinMode(LED1_B_PIN,
OUTPUT);
pinMode(LED2_R_PIN, OUTPUT); pinMode(LED2_G_PIN, OUTPUT); pinMode(LED2_B_PIN,
OUTPUT);
pinMode(LED3_R_PIN, OUTPUT); pinMode(LED3_G_PIN, OUTPUT); pinMode(LED3_B_PIN,
OUTPUT);
// Turn all RGB LEDs off initially
digitalWrite(LED1_R_PIN, LOW); digitalWrite(LED1_G_PIN, LOW); digitalWrite(LED1_B_PIN,
LOW);
digitalWrite(LED2_R_PIN, LOW); digitalWrite(LED2_G_PIN, LOW); digitalWrite(LED2_B_PIN,
LOW);
digitalWrite(LED3_R_PIN, LOW); digitalWrite(LED3_G_PIN, LOW); digitalWrite(LED3_B_PIN,
LOW);
}
void loop() {
// 1. Read sensors
// Read DHT22 temperature and humidity
float temperature = dht.readTemperature(); // in °C
float humidity = dht.readHumidity(); // in %
if (isnan(temperature) || isnan(humidity)) {
// If reading failed, print error and skip the rest of loop iteration
Serial.println("Error reading from DHT22 sensor!");
// We won't update LCD or outputs this cycle if DHT fails, to avoid false triggers
} else {
// Read PIR motion sensor
int motionVal = digitalRead(PIR_PIN); // HIGH if motion, LOW if no motion
// Read MQ-2 gas sensor (analog value)
int gasAnalog = analogRead(MQ2_PIN); // 0-4095
int gasPercent = map(gasAnalog, 0, 4095, 0, 100); // rough conversion to 0-100%
// Read LDR sensor (analog value)
int lightAnalog = analogRead(LDR_PIN); // 0-4095 (higher = darker if pull-down used)
// Read Ultrasonic distance (in cm)
float distance = 0.0;
// Trigger the ultrasonic pulse
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Measure the echo pulse width
long duration_us = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout (~5m)
if (duration_us > 0) {
distance = (duration_us * 0.0343) / 2.0; // speed of sound: 0.0343 cm/us
} else {
distance = 999.0; // if no echo, set distance to a large value (no object or out of range)
}
// 2. Update LCD display
char line1[17]; char line2[17];
// Prepare formatted strings for each line (ensure they fit 16 chars)
snprintf(line1, sizeof(line1), "Temp:%.1fC Hum:%.0f%%", temperature, humidity);
// Gas displayed as %, LDR as raw (or could convert to % brightness)
snprintf(line2, sizeof(line2), "Gas:%d%% LDR:%4d", gasPercent, lightAnalog);
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
// 3. Print to Serial Monitor
Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" C");
Serial.print("Humidity: "); Serial.print(humidity); Serial.println(" %");
Serial.print("Light (LDR): "); Serial.println(lightAnalog);
Serial.print("Gas level: "); Serial.print(gasPercent); Serial.println(" %");
Serial.print("Motion: ");
if (motionVal == HIGH) Serial.println("DETECTED");
else Serial.println("None");
Serial.print("Distance: "); Serial.print(distance); Serial.println(" cm");
Serial.println("------------------------");
// 4. Control Outputs based on sensor values
// Relay1 and Room Light LED (motion + darkness -> light on)
if (motionVal == HIGH && lightAnalog > LDR_THRESHOLD) {
digitalWrite(RELAY1_PIN, HIGH); // turn on light
} else {
digitalWrite(RELAY1_PIN, LOW); // turn off light
} // (We could also add a small timer to hold the light on for a while after motion)
// Relay2 and Temp
LED (high temp -> fan on)
if (temperature >= TEMP_THRESHOLD) {
digitalWrite(RELAY2_PIN, HIGH); // turn on fan/AC
// LED1 Red for hot
digitalWrite(LED1_R_PIN, HIGH);
digitalWrite(LED1_G_PIN, LOW);
digitalWrite(LED1_B_PIN, LOW);
} else {
digitalWrite(RELAY2_PIN, LOW); // turn off fan/AC// LED1 Blue for comfortable
digitalWrite(LED1_R_PIN, LOW);
digitalWrite(LED1_G_PIN, LOW);
digitalWrite(LED1_B_PIN, HIGH);
}// Relay3 and Gas LED (gas above threshold -> alarm on)
if (gasPercent >= GAS_THRESHOLD) {
digitalWrite(RELAY3_PIN, HIGH); // trigger alarm
// LED3 Red for gas danger
digitalWrite(LED3_R_PIN, HIGH);
digitalWrite(LED3_G_PIN, LOW);
digitalWrite(LED3_B_PIN, LOW);
} else {
digitalWrite(RELAY3_PIN, LOW); // alarm off
// LED3 Green for safe
digitalWrite(LED3_R_PIN, LOW);
digitalWrite(LED3_G_PIN, HIGH);
digitalWrite(LED3_B_PIN, LOW);
}// Relay4 (distance-based trigger, e.g., open door if object is very close)
if (distance > 0 && distance < DIST_THRESHOLD) {
digitalWrite(RELAY4_PIN, HIGH); // object detected within range
} else {
digitalWrite(RELAY4_PIN, LOW);
}// RGB LED2 indicates motion status (simple ON/OFF via green channel)
if (motionVal == HIGH) {// Motion detected: LED2 Green ON
digitalWrite(LED2_G_PIN, HIGH);
} else { // No motion: LED2 off
digitalWrite(LED2_G_PIN, LOW);
} // (LED2_R and LED2_B are not used in this project scenario, keep them off)
digitalWrite(LED2_R_PIN, LOW);
digitalWrite(LED2_B_PIN, LOW);
}
// 5. Loop delay
delay(2000); // wait 2 seconds before next sensor read cycle
}