#include <DHT.h>
#include <Wire.h> // π I2C protocol
#include <Adafruit_GFX.h> // π Graphics library
#include <Adafruit_SSD1306.h> // π OLED library
// ========== PIN DEFINITIONS ==========
#define LED_PIN 2 // Red LED
#define PIR_PIN 13 // Motion Sensor
#define DHT_PIN 15 // DHT22 Data
#define LDR_PIN 4 // Light Sensor
#define MQ2_PIN 5 // π MQ-2 Gas/Smoke Sensor
#define DHTTYPE DHT22
// π RGB LED Pins
#define RGB_RED 8 // Red channel
#define RGB_GREEN 9 // Green channel
#define RGB_BLUE 10 // Blue channel
// ========== OLED DISPLAY SETUP ==========
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Reset pin (nuk pΓ«rdoret nΓ« I2C)
#define OLED_ADDRESS 0x3C // I2C address
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// π Buzzer
#define BUZZER_PIN 11 // Buzzer
#define BUTTON_PIN 12 // Push button
// ========== RGB LED CONTROL FUNCTION ==========
void setRGBColor(int red, int green, int blue) {
analogWrite(RGB_RED, red); // 0-255
analogWrite(RGB_GREEN, green); // 0-255
analogWrite(RGB_BLUE, blue); // 0-255
}
// Quick color helpers
void rgbRed() { setRGBColor(255, 0, 0); } // DANGER
void rgbYellow() { setRGBColor(255, 255, 0); } // WARNING
void rgbGreen() { setRGBColor(0, 255, 0); } // OCCUPIED
void rgbBlue() { setRGBColor(0, 0, 255); } // EMPTY
void rgbOff() { setRGBColor(0, 0, 0); } // OFF
// ========== INITIALIZE SENSORS ==========
DHT dht(DHT_PIN, DHTTYPE);
void setup() {
// Start Serial Monitor
Serial.begin(115200);
// Configure pins
pinMode(LED_PIN, OUTPUT);
pinMode(PIR_PIN, INPUT);
pinMode(LDR_PIN, INPUT);
pinMode(MQ2_PIN, INPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
// π RGB LED pins
pinMode(RGB_RED, OUTPUT);
pinMode(RGB_GREEN, OUTPUT);
pinMode(RGB_BLUE, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
// Start DHT22
dht.begin();
// Test RGB on startup (optional)
rgbRed(); delay(500);
rgbGreen(); delay(500);
rgbBlue(); delay(500);
rgbOff();
// Welcome message
Serial.println("\nββββββββββββββββββββββββββββββββββββββ");
Serial.println("β SMART ROOM OCCUPANCY SYSTEM β");
Serial.println("β ESP32-S3 IoT Project β");
Serial.println("ββββββββββββββββββββββββββββββββββββββ\n");
delay(2000); // DHT22 needs 2 sec to stabilize
}
void loop() {
Serial.println("ββββββββββββββββββββββββββββββββββ");
Serial.println("π SENSOR READINGS");
Serial.println("ββββββββββββββββββββββββββββββββββ\n");
// ========== READ DHT22 ==========
Serial.println("π‘οΈ [DHT22 - Temperature & Humidity]");
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println(" β ERROR: Cannot read DHT22!");
Serial.println(" β Check GPIO 15, VCC, GND\n");
} else {
Serial.print(" Temperature: ");
Serial.print(temperature);
Serial.println("Β°C β
");
Serial.print(" Humidity: ");
Serial.print(humidity);
Serial.println("% β
\n");
}
// ========== READ PIR ==========
Serial.println("π€ [PIR - Motion Detection]");
int motion = digitalRead(PIR_PIN);
if (motion == HIGH) {
Serial.println(" πΆ MOTION DETECTED! β
");
digitalWrite(LED_PIN, HIGH); // Turn LED ON
Serial.println(" π‘ LED Status: ON\n");
} else {
Serial.println(" βͺ No motion detected");
digitalWrite(LED_PIN, LOW); // Turn LED OFF
Serial.println(" π‘ LED Status: OFF\n");
}
// ========== READ LDR ==========
Serial.println("π‘ [LDR - Light Sensor]");
int lightRaw = analogRead(LDR_PIN);
float lightPercent = (lightRaw / 4095.0) * 100;
Serial.print(" Raw Value: ");
Serial.print(lightRaw);
Serial.println(" (0-4095) β
");
Serial.print(" Light Level: ");
Serial.print(lightPercent, 1);
Serial.println("%");
// Light interpretation
if (lightPercent < 20) {
Serial.println(" β π Dark room\n");
} else if (lightPercent < 60) {
Serial.println(" β π Normal lighting\n");
} else {
Serial.println(" β βοΈ Bright room\n");
}
// ========== READ MQ-2 (Gas/Smoke Sensor) ==========
Serial.println("π₯ [MQ-2 - Gas/Smoke Detection]");
int gasValue = analogRead(MQ2_PIN); // 0-4095
float gasPercent = (gasValue / 4095.0) * 100;
Serial.print(" Raw Value: ");
Serial.print(gasValue);
Serial.println(" (0-4095) β
");
Serial.print(" Gas Level: ");
Serial.print(gasPercent, 1);
Serial.println("%");
// Gas interpretation
if (gasValue < 500) {
Serial.println(" β β
Air Quality: GOOD\n");
} else if (gasValue < 1500) {
Serial.println(" β β οΈ Air Quality: MODERATE (Ventilation needed)\n");
} else if (gasValue < 2500) {
Serial.println(" β β Air Quality: POOR (High gas detected!)\n");
} else {
Serial.println(" β π¨ DANGER: Smoke/Gas leak detected!\n");
}
// ========== SYSTEM STATUS ==========
Serial.println("π§ [SYSTEM INFO]");
Serial.print(" Uptime: ");
Serial.print(millis() / 1000);
Serial.println(" seconds");
Serial.print(" Free Memory: ");
Serial.print(ESP.getFreeHeap());
Serial.println(" bytes\n");
Serial.println("ββββββββββββββββββββββββββββββββββ");
Serial.println("β³ Next reading in 3 seconds...\n\n");
delay(3000); // Wait 3 seconds
// ========== RGB LED STATUS ==========
Serial.println("π¨ [RGB LED - System Status]");
// Priority 1: DANGER (High gas)
if (gasValue > 2500) {
rgbRed();
Serial.println(" π΄ RED - DANGER! Gas leak!\n");
}
// Priority 2: WARNING (Moderate gas)
else if (gasValue > 1500) {
rgbYellow();
Serial.println(" π‘ YELLOW - Warning, ventilate!\n");
}
// Priority 3: OCCUPIED (Motion + Safe)
else if (motion == HIGH) {
rgbGreen();
Serial.println(" π’ GREEN - Room occupied\n");
}
// Priority 4: EMPTY (No motion)
else {
rgbBlue();
Serial.println(" π΅ BLUE - Room empty\n");
}
// ========== BUZZER ALERT ==========
if (gasValue > 2500) {
// DANGER level - sound alarm!
tone(BUZZER_PIN, 2000, 500); // 2kHz beep for 500ms
Serial.println("π BUZZER: ALARM ACTIVE!\n");
}
else if (gasValue > 1500) {
// WARNING level - short beep
tone(BUZZER_PIN, 1000, 200); // 1kHz beep for 200ms
}
// π Initialize OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
Serial.println(F("β OLED allocation failed!"));
for (;;); // Loop forever
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("SMART ROOM");
display.println("Initializing...");
display.display();
delay(2000);
// ========== UPDATE OLED DISPLAY ==========
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
// Header
display.println("SMART ROOM v1.0");
display.println("---------------");
// Temperature
display.print("Temp: ");
display.print(temperature, 1);
display.println("C");
// Humidity
display.print("Hum: ");
display.print(humidity, 1);
display.println("%");
// Motion
display.print("Motion: ");
display.println(motion ? "YES" : "NO ");
// Light
display.print("Light: ");
display.print((lightRaw / 4095.0) * 100, 0);
display.println("%");
// Gas
display.print("Gas: ");
if (gasValue > 2500) {
display.println("DANGER!");
} else if (gasValue > 1500) {
display.println("WARNING");
} else {
display.println("GOOD ");
}
display.display(); // Push to screen
// ========== BUTTON CHECK ==========
int buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW) { // Button pressed (pull-up inverts)
Serial.println("π BUTTON PRESSED - Manual override!");
digitalWrite(LED_PIN, HIGH); // Force LED ON
rgbWhite(); // RGB white = manual mode
}
}