#include <Wire.h>
#include <MPU6050.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
// ============== OBJECTS ==============
MPU6050 mpu;
DHT dht(4, DHT22); // GPIO 4 for DHT22 data
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27
// ============== PIN DEFINITIONS ==============
// SENSORS
#define PIR_PIN 19
#define LDR_ANALOG_PIN 34
#define TRIG_PIN 5
#define ECHO_PIN 18
// #define RAIN_SENSOR_PIN 35 // Future use - rainwater sensor
// OUTPUTS
#define RELAY1_PIN 25 // Street light
#define RELAY2_PIN 26 // Future use (rainwater pump etc)
#define BUZZER_PIN 27
// ============== VARIABLES ==============
// MPU6050 data
int16_t ax, ay, az;
float tilt_x, tilt_y;
// DHT22 data
float temperature, humidity;
// LDR data
int light_level;
// PIR data
int motion_detected;
// Ultrasonic data
long duration;
float distance_cm;
// Future sensor variables
// int rain_value; // Future use
// Alert thresholds
const float TILT_THRESHOLD = 5.0; // 5 degrees
const int LIGHT_THRESHOLD = 500; // Dark if < 500
// ============== SETUP ==============
void setup() {
Serial.begin(115200);
Serial.println("=== INFRA GUARD 3.0 STARTING ===");
// Initialize I2C
Wire.begin();
Serial.println("I2C: OK");
// ===== MPU6050 =====
Serial.print("MPU6050: ");
mpu.initialize(); // Initialize the sensor
// Test connection
if(mpu.testConnection()) {
Serial.println("OK");
} else {
Serial.println("FAILED - Check I2C connections");
}
// ===== DHT22 =====
dht.begin();
Serial.println("DHT22: OK");
// ===== LCD =====
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("InfraGuard 3.0");
lcd.setCursor(0, 1);
lcd.print("IIT Kanpur");
Serial.println("LCD: OK");
delay(2000);
// ===== PIN MODES =====
pinMode(PIR_PIN, INPUT);
pinMode(LDR_ANALOG_PIN, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
// ===== INITIAL STATES =====
digitalWrite(RELAY1_PIN, LOW); // Light OFF
digitalWrite(RELAY2_PIN, LOW); // Future use OFF
digitalWrite(BUZZER_PIN, LOW); // Buzzer OFF
Serial.println("Setup complete!");
Serial.println("========================");
delay(1000);
}
// ============== LOOP ==============
void loop() {
// === 1. READ ALL SENSORS ===
readMPU6050();
readDHT22();
readLDR();
readPIR();
readUltrasonic();
// readRainSensor(); // Future use - uncomment when rain sensor added
// === 2. CALCULATE RISK ===
int risk_level = calculateRisk();
// === 3. CONTROL OUTPUTS ===
controlLight();
controlBuzzer(risk_level);
// === 4. DISPLAY ON LCD ===
updateLCD(risk_level);
// === 5. SEND TO SERIAL ===
printToSerial(risk_level);
// === 6. SEND TO SERVER (Future) ===
// sendToServer(); // Will add when dashboard is ready
delay(1000); // Update every second
}
// ============== SENSOR FUNCTIONS ==============
void readMPU6050() {
// Read acceleration data
mpu.getAcceleration(&ax, &ay, &az);
// Calculate tilt angles (in degrees)
tilt_x = atan2(ax, az) * 180 / PI;
tilt_y = atan2(ay, az) * 180 / PI;
}
void readDHT22() {
temperature = dht.readTemperature();
humidity = dht.readHumidity();
// Check if readings are valid
if (isnan(temperature) || isnan(humidity)) {
Serial.println("DHT22 read failed!");
temperature = 0;
humidity = 0;
}
}
void readLDR() {
light_level = analogRead(LDR_ANALOG_PIN);
// 0 (dark) to 4095 (bright) for ESP32
}
void readPIR() {
motion_detected = digitalRead(PIR_PIN);
// HIGH = motion detected, LOW = no motion
}
void readUltrasonic() {
// Send pulse
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Read echo
duration = pulseIn(ECHO_PIN, HIGH);
// Calculate distance (cm)
distance_cm = duration * 0.034 / 2;
// Handle out of range
if (distance_cm > 400) {
distance_cm = 0; // No object detected
}
}
// FUTURE FUNCTION - Add when rain sensor is available
/*
void readRainSensor() {
rain_value = analogRead(RAIN_SENSOR_PIN);
// 0 (dry) to 4095 (wet)
}
*/
// ============== RISK CALCULATION ==============
int calculateRisk() {
// Returns: 0 = SAFE (GREEN), 1 = WARNING (YELLOW), 2 = CRITICAL (RED)
if (tilt_x > TILT_THRESHOLD || tilt_x < -TILT_THRESHOLD) {
return 2; // CRITICAL - High tilt
}
// Check if any sensor indicates problem
if (temperature > 50 || temperature < -10) { // Extreme temp
return 1; // WARNING
}
if (distance_cm < 10 && distance_cm > 0) { // Object too close (flooding?)
return 1; // WARNING
}
// FUTURE: Add rain sensor condition
// if (rain_value > 3000) { return 1; } // Heavy rain warning
return 0; // SAFE
}
// ============== OUTPUT CONTROL ==============
void controlLight() {
// Auto mode: Light ON when dark
if (light_level < LIGHT_THRESHOLD) {
digitalWrite(RELAY1_PIN, HIGH); // Light ON
} else {
digitalWrite(RELAY1_PIN, LOW); // Light OFF
}
}
void controlBuzzer(int risk_level) {
if (risk_level == 2) { // CRITICAL
// Beep pattern: ON for 200ms, OFF for 200ms
digitalWrite(BUZZER_PIN, HIGH);
delay(200);
digitalWrite(BUZZER_PIN, LOW);
delay(200);
} else {
digitalWrite(BUZZER_PIN, LOW); // Buzzer OFF
}
}
// ============== LCD DISPLAY ==============
void updateLCD(int risk_level) {
lcd.clear();
// Row 0: Tilt + Temp
lcd.setCursor(0, 0);
lcd.print("T:");
lcd.print(tilt_x, 1);
lcd.print((char)223); // Degree symbol
lcd.print(" ");
lcd.print("Tmp:");
lcd.print((int)temperature);
lcd.print("C");
// Row 1: Light status + Risk
lcd.setCursor(0, 1);
// Light status
if (digitalRead(RELAY1_PIN) == HIGH) {
lcd.print("L:ON ");
} else {
lcd.print("L:OFF");
}
lcd.print(" ");
// Risk level with symbol
switch(risk_level) {
case 0: // SAFE
lcd.print("G"); // Green
break;
case 1: // WARNING
lcd.print("Y"); // Yellow
break;
case 2: // CRITICAL
lcd.print("R"); // Red
break;
}
}
// ============== SERIAL OUTPUT ==============
void printToSerial(int risk_level) {
Serial.println("=== INFRA GUARD 3.0 DATA ===");
// Risk level
Serial.print("Risk Level: ");
switch(risk_level) {
case 0: Serial.println("SAFE 🟢"); break;
case 1: Serial.println("WARNING 🟡"); break;
case 2: Serial.println("CRITICAL 🔴"); break;
}
// MPU6050
Serial.print("Tilt X: "); Serial.print(tilt_x, 2); Serial.println(" deg");
// DHT22
Serial.print("Temperature: "); Serial.print(temperature, 1); Serial.println(" C");
Serial.print("Humidity: "); Serial.print(humidity, 1); Serial.println(" %");
// LDR
Serial.print("Light Level: "); Serial.println(light_level);
// PIR
Serial.print("Motion: "); Serial.println(motion_detected ? "YES" : "NO");
// Ultrasonic
Serial.print("Distance: "); Serial.print(distance_cm, 1); Serial.println(" cm");
// Light status
Serial.print("Street Light: "); Serial.println(digitalRead(RELAY1_PIN) ? "ON" : "OFF");
// Future sensor placeholder
// Serial.print("Rain Value: "); Serial.println(rain_value); // Future use
Serial.println("=============================\n");
}
// ============== FUTURE FUNCTIONS ==============
/*
void sendToServer() {
// This will send data to Flask dashboard via WiFi
// Will add when server is ready
}
void manualLightControl(bool state) {
// For manual override from dashboard
digitalWrite(RELAY1_PIN, state ? HIGH : LOW);
}
// ⚠️ RAINWATER SENSOR - Future mein
// GPIO 35 (ADC) → Rain Sensor A0 (jab lagega)
// 3.3V → Rain Sensor VCC
// GND → Rain Sensor GND
*/