#define BLYNK_TEMPLATE_ID "TMPL6SZpMNJxe"
#define BLYNK_TEMPLATE_NAME "Real Time Environmental Sensing and Control"
#define BLYNK_AUTH_TOKEN "CjyYn6P9lOIkOa75qlaRPwKb6cPr_vvu"
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h> // Library for DHT22 sensor
// Your WiFi credentials
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Pin Definitions
#define DHTPIN 23 // GPIO pin for DHT22 data
#define DHTTYPE DHT22 // Define the DHT sensor type
#define TRIGPIN 12 // GPIO pin for HC-SR04 Trig
#define ECHOPIN 14 // GPIO pin for HC-SR04 Echo
#define LDRPIN 34 // ADC pin for LDR (ensure it's connected to an analog input pin)
#define RELAYPIN 16 // GPIO pin for Relay control
#define BUTTONPIN 18 // GPIO pin for manual control button
// Initialize the DHT22 sensor
DHT dht(DHTPIN, DHTTYPE);
// Variables for sensors
float temperature;
float humidity;
long duration;
float distance;
int lightLevel;
bool manualControl = false; // Manual HVAC control flag
float thresholdDistance = 200.0;
int lightThreshold = 500;
// Timeout-related variables
unsigned long lastMovementTime = 0; // Track the last time movement was detected
unsigned long timeoutDuration = 300000; // Timeout period for lights (5 minutes)
// Variables for scheduling feature
int currentHour = 9; // Starting at 9 AM (simulated time)
int lightSamples[10]; // Buffer to store light readings
int sampleIndex = 0;
int totalLight = 0;
// Temperature thresholds for HVAC control
float upperTempThreshold = 28.0; // HVAC turns ON above this temperature
float lowerTempThreshold = 25.0; // HVAC turns OFF below this temperature
// Blynk timer instance
BlynkTimer timer;
// Virtual pin assignments from Blynk interface
#define VIRTUAL_PIN_TEMP V0
#define VIRTUAL_PIN_HUMIDITY V1
#define VIRTUAL_PIN_OCCUPANCY V2
#define VIRTUAL_PIN_LIGHT V3
#define VIRTUAL_PIN_RELAY V4
// This function sends Arduino's up time every second to Virtual Pin (5).
void myTimerEvent() {
Blynk.virtualWrite(V5, millis() / 1000);
}
void setup() {
// Debug console
Serial.begin(115200);
// Initialize Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// Initialize sensors
dht.begin();
// Set pin modes
pinMode(TRIGPIN, OUTPUT);
pinMode(ECHOPIN, INPUT);
pinMode(RELAYPIN, OUTPUT);
pinMode(BUTTONPIN, INPUT_PULLUP); // Manual button for HVAC control
// Relay starts in OFF position
digitalWrite(RELAYPIN, LOW);
// Setup a function to be called every second
timer.setInterval(1000L, myTimerEvent);
Serial.println(F("System Initialized!"));
printUserGuide(); // Print the user guide on startup
}
void loop() {
// Simulate the passage of time
currentHour++;
if (currentHour > 23) {
currentHour = 0; // Reset at midnight
}
// Run Blynk
Blynk.run();
timer.run(); // Initiates BlynkTimer
// Read sensors separately to avoid overloading
readTemperatureHumidity();
readUltrasonicDistance();
readLightLevel();
checkManualControl();
controlRelay();
controlScheduler(); // Handle scheduling for HVAC system
printSystemStatus(); // Enhanced UI feedback
delay(3000); // 3 seconds delay to avoid constant polling and memory overload
}
void printUserGuide() {
Serial.println(F("\nUser Guide:"));
Serial.println(F("1. DHT22 measures temperature and humidity."));
Serial.println(F("2. HC-SR04 detects occupancy (distance)."));
Serial.println(F("3. LDR measures light levels."));
Serial.println(F("4. Relay controls HVAC based on temperature or manual mode."));
Serial.println(F("5. Press the button to toggle between manual and automatic HVAC control."));
Serial.println(F("6. System operates automatically between 9 AM and 5 PM."));
Serial.println(F("7. HVAC operates based on a temperature range (25°C to 28°C).\n"));
}
void readTemperatureHumidity() {
// Reading temperature and humidity from DHT22
temperature = dht.readTemperature();
humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println(F("Failed to read from DHT sensor!"));
} else {
Serial.print(F("Temperature: "));
Serial.print(temperature);
Serial.print(F(" °C, Humidity: "));
Serial.print(humidity);
Serial.println(F(" %"));
// Send temperature and humidity to Blynk
Blynk.virtualWrite(VIRTUAL_PIN_TEMP, temperature);
Blynk.virtualWrite(VIRTUAL_PIN_HUMIDITY, humidity);
}
}
void readUltrasonicDistance() {
// Reading distance from HC-SR04
digitalWrite(TRIGPIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGPIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGPIN, LOW);
duration = pulseIn(ECHOPIN, HIGH);
distance = (duration * 0.034 / 2); // Convert to cm
Serial.print(F("Distance: "));
Serial.print(distance);
Serial.println(F(" cm"));
// Send occupancy status to Blynk
Blynk.virtualWrite(VIRTUAL_PIN_OCCUPANCY, distance);
// Occupancy-based control: Detect movement and reset timeout
if (distance < thresholdDistance) {
lastMovementTime = millis(); // Reset the timer on movement detection
Serial.println(F("Movement detected. Resetting timeout."));
}
// Turn off HVAC and lights if no movement for the timeout period
if (millis() - lastMovementTime > timeoutDuration) {
Serial.println(F("No occupancy detected for 5 minutes. Turning off HVAC and lights."));
digitalWrite(RELAYPIN, LOW); // Turn off the relay (lights and HVAC)
}
}
void readLightLevel() {
// Reading light level from LDR
totalLight -= lightSamples[sampleIndex]; // Subtract the oldest sample
lightSamples[sampleIndex] = analogRead(LDRPIN); // Read the new sample
totalLight += lightSamples[sampleIndex]; // Add the new sample
sampleIndex = (sampleIndex + 1) % 10; // Circular buffer
int avgLightLevel = totalLight / 10; // Calculate the average light level
Serial.print(F("Light Level (Avg): "));
Serial.println(avgLightLevel);
// Send light levels to Blynk
Blynk.virtualWrite(VIRTUAL_PIN_LIGHT, avgLightLevel);
// Dimming logic based on light level
if (avgLightLevel > lightThreshold) {
Serial.println(F("Dimming lights due to high ambient light."));
digitalWrite(RELAYPIN, LOW); // Turn off the relay (dimming lights)
} else {
Serial.println(F("Turning on lights due to low ambient light."));
digitalWrite(RELAYPIN, HIGH); // Turn on the relay
}
}
void checkManualControl() {
if (digitalRead(BUTTONPIN) == LOW) { // If button is pressed
manualControl = !manualControl; // Toggle manual control
Serial.print(F("Manual control "));
Serial.println(manualControl ? "ON" : "OFF");
delay(500); // Debounce delay
}
}
void controlRelay() {
if (manualControl) {
Serial.println(F("Manual control active: Relay OFF."));
digitalWrite(RELAYPIN, LOW); // Manual control overrides automatic
Blynk.virtualWrite(VIRTUAL_PIN_RELAY, 0);
} else {
if (temperature > upperTempThreshold) {
digitalWrite(RELAYPIN, HIGH); // Turn relay ON
Serial.println(F("Relay ON: Temperature is above 28°C"));
Blynk.virtualWrite(VIRTUAL_PIN_RELAY, 1);
} else if (temperature < lowerTempThreshold) {
digitalWrite(RELAYPIN, LOW); // Turn relay OFF
Serial.println(F("Relay OFF: Temperature is below 25°C"));
Blynk.virtualWrite(VIRTUAL_PIN_RELAY, 0);
}
}
}
void controlScheduler() {
// Simulate scheduling: HVAC is on between 9 AM and 5 PM
if (currentHour >= 9 && currentHour <= 17) {
Serial.println(F("Within working hours (9 AM - 5 PM): Relay ON"));
digitalWrite(RELAYPIN, HIGH); // Turn on the HVAC system
} else {
Serial.println(F("Outside working hours: Relay OFF"));
digitalWrite(RELAYPIN, LOW); // Turn off the HVAC system
}
}
// Print system status
void printSystemStatus() {
Serial.println(F("============================="));
Serial.println(F(" SYSTEM STATUS UPDATE "));
Serial.println(F("============================="));
Serial.print(F("Current Hour (Simulated): "));
Serial.println(currentHour);
Serial.print(F("Temperature: "));
Serial.print(temperature);
Serial.println(F(" °C"));
Serial.print(F("Light Level: "));
Serial.println(totalLight / 10);
Serial.print(F("Distance from Ultrasonic: "));
Serial.print(distance);
Serial.println(F(" cm"));
Serial.print(F("Relay Status: "));
Serial.println(digitalRead(RELAYPIN) == HIGH ? "ON" : "OFF");
Serial.println(F("=============================\n"));
}