Embedded systems · In the CV
Smart Home Automation System
Built a system that runs a fan by temperature, warns of gas and dispenses water touch-free.
- Arduino Uno
- C++
- DHT11
- MQ-2
- ultrasonic and IR sensors
- L298N
About
An Arduino-based automation system that combines sensors and actuators to monitor the environment, detect hazards and dispense water without touch, using an L298N motor driver, an LCD and several sensors.
When the LDR senses low light, the system activates. The DHT11 watches the temperature and switches the fan on above a set threshold and off below it. The MQ-2 sensor monitors air quality and sounds the buzzer when the gas level reaches the threshold; a reset button silences it. The ultrasonic sensor measures the distance inside the tank to estimate the water level, shown on the LCD with the temperature and the fan and gas status. For water, the IR sensor detects a hand near the outlet and only then runs the pump. All readings are also printed to the Serial Monitor for debugging.
Components
- LDR (light dependent resistor): detects light intensity and decides whether the system should activate in low light
- DHT11: measures temperature and humidity
- MQ-2 gas sensor: detects harmful gases and triggers the buzzer above the threshold
- Ultrasonic sensor (HC-SR04): measures the distance in the water tank to calculate the water level
- IR proximity sensor: detects a hand near the dispenser to start the water pump
- L298N motor driver: drives the cooling fan and the water pump
- Buzzer: sounds the alarm when gas is detected
- LCD display (I2C, 16x2): shows temperature, water level, fan status and gas status
- Push button: resets or silences the buzzer
Arduino pin connections
From Arduino_Pin_Connections.docx in the repository.
Sensors & Inputs
| A0 | LDR voltage divider output |
|---|---|
| D2 | DHT11 data pin |
| A2 | MQ-2 gas sensor digital out |
| D7 | HC-SR04 Trig |
| D8 | HC-SR04 Echo |
| D9 | IR proximity sensor output |
| D10 | Reset pushbutton → GND (INPUT_PULLUP) |
Outputs / Actuators
| D4 | Buzzer (via NPN transistor) |
|---|
Fan (Motor 1)
| D5 (PWM) | L298N ENA |
|---|---|
| D11 | L298N IN1 |
| D12 | L298N IN2 |
| L298N OUT A & OUT B | Fan motor terminals |
Pump (Motor 2)
| D6 (PWM) | L298N ENB |
|---|---|
| D13 | L298N IN3 |
| A1 | L298N IN4 |
| L298N OUT C & OUT D | Pump/valve terminals |
Other
| A4 (SDA) & A5 (SCL) | I2C LCD 16×2 (address 0x27) |
|---|---|
| 5V & GND | All sensor modules and LCD |
| 12V & GND | L298N motor power input (share GND with Arduino) |
Photos and video
Source code
attemp.ino
#include <DHT.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
/* -------- Pin assignments -------- */
const int PIN_LDR_A0 = A0;
const int PIN_DHT = 2;
const int PIN_GAS_A0 = A2; // MQ-2 analog output
const int PIN_BUZZER = 4; // via NPN transistor
// L298N Channel for FAN (Motor 1 -> OUT A/B)
const int PIN_ENA = 5; // PWM
const int PIN_IN1 = 11;
const int PIN_IN2 = 12;
// L298N Channel for PUMP (Motor 2 -> OUT C/D)
const int PIN_ENB = 6; // PWM
const int PIN_IN3 = 13;
const int PIN_IN4 = A1; // use analog pin as digital
// Ultrasonic
const int PIN_TRIG = 7;
const int PIN_ECHO = 8;
// IR proximity for dispensing
const int PIN_IR = 9;
// Manual reset button (to GND)
const int PIN_RESET = 10;
/* -------- Devices -------- */
#define DHTTYPE DHT11
DHT dht(PIN_DHT, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
/* -------- Tunables -------- */
int LDR_THRESHOLD = 300; // System ON if LDR <= this
float TEMP_ON_C = 31; // Fan ON threshold
long TANK_DEPTH_CM = 30;
long ULTRA_TIMEOUT_US = 25000;
int GAS_THRESHOLD = 300; // Gas trigger threshold (0–1023)
uint8_t FAN_PWM = 255;
uint8_t PUMP_PWM = 255;
/* -------- State -------- */
bool systemActive = false;
bool alarmLatched = false;
bool fanOn = false;
unsigned long lastLCD = 0;
// --- Buzzer silence timer ---
unsigned long buzzerSilenceUntil = 0; // millis until buzzer is suppressed
/* -------- Helpers -------- */
long measureDistanceCm() {
digitalWrite(PIN_TRIG, LOW); delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH); delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
long duration = pulseIn(PIN_ECHO, HIGH, ULTRA_TIMEOUT_US);
if (duration == 0) return -1;
long cm = duration / 58;
return cm;
}
void fan_set(bool on, uint8_t duty = 255) {
if (on) {
digitalWrite(PIN_IN1, HIGH);
digitalWrite(PIN_IN2, LOW);
analogWrite(PIN_ENA, duty);
} else {
analogWrite(PIN_ENA, 0);
digitalWrite(PIN_IN1, LOW);
digitalWrite(PIN_IN2, LOW);
}
}
void pump_set(bool on, uint8_t duty = 255) {
if (on) {
digitalWrite(PIN_IN3, HIGH);
digitalWrite(PIN_IN4, LOW);
analogWrite(PIN_ENB, duty);
} else {
analogWrite(PIN_ENB, 0);
digitalWrite(PIN_IN3, LOW);
digitalWrite(PIN_IN4, LOW);
}
}
void setBuzzer(bool on) { digitalWrite(PIN_BUZZER, on ? HIGH : LOW); }
/* -------- Arduino setup -------- */
void setup() {
Serial.begin(9600);
pinMode(PIN_IR, INPUT);
pinMode(PIN_RESET, INPUT_PULLUP);
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_ENA, OUTPUT);
pinMode(PIN_IN1, OUTPUT);
pinMode(PIN_IN2, OUTPUT);
pinMode(PIN_ENB, OUTPUT);
pinMode(PIN_IN3, OUTPUT);
pinMode(PIN_IN4, OUTPUT);
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
fan_set(false, 0);
pump_set(false, 0);
setBuzzer(false);
dht.begin();
lcd.init(); lcd.backlight();
lcd.clear();
lcd.setCursor(0,0); lcd.print("EEE4604 System");
lcd.setCursor(0,1); lcd.print("Init...");
delay(800);
}
/* -------- Main Loop -------- */
void loop() {
// --- LDR Control ---
int ldr = analogRead(PIN_LDR_A0);
systemActive = (ldr <= LDR_THRESHOLD);
if (!systemActive) {
fan_set(false, 0);
pump_set(false, 0);
setBuzzer(false);
alarmLatched = false;
if (millis() - lastLCD > 500) {
lastLCD = millis();
lcd.clear();
lcd.setCursor(0,0); lcd.print("System: OFF");
lcd.setCursor(0,1); lcd.print("High light...");
}
Serial.print("LDR: "); Serial.print(ldr);
Serial.println(" (System OFF)");
delay(100);
return;
}
// --- Temperature & Humidity ---
float tempC = dht.readTemperature();
float hum = dht.readHumidity();
if (!isnan(tempC)) {
if (tempC >= TEMP_ON_C) {
fan_set(true, FAN_PWM);
fanOn = true;
} else {
fan_set(false, 0);
fanOn = false;
}
}
// --- Gas sensor (analog threshold) ---
int gasValue = analogRead(PIN_GAS_A0);
bool gasDetected = (gasValue >= GAS_THRESHOLD); // ✅ buzzer ON if >= threshold
if (gasDetected) {
alarmLatched = true;
} else {
alarmLatched = false; // buzzer OFF when below threshold
}
// Reset button pressed → silence buzzer for 12 minutes
if (digitalRead(PIN_RESET) == LOW) {
alarmLatched = false;
buzzerSilenceUntil = millis() + (12UL * 60UL * 1000UL); // 12 min
}
// Only allow buzzer if not in silence period
bool buzzerActive = false;
if (alarmLatched && millis() > buzzerSilenceUntil) {
buzzerActive = true;
}
setBuzzer(buzzerActive);
// --- Ultrasonic Tank Level ---
long dist = measureDistanceCm();
int levelPct = 0;
if (dist > 0 && dist <= TANK_DEPTH_CM + 5) {
long filled = TANK_DEPTH_CM - dist;
if (filled < 0) filled = 0;
if (filled > TANK_DEPTH_CM) filled = TANK_DEPTH_CM;
levelPct = (int)((filled * 100L) / TANK_DEPTH_CM);
}
// --- IR dispensing (hand detection only) ---
int irRaw = digitalRead(PIN_IR);
bool handPresent = (irRaw == LOW);
bool pumpActive = (systemActive && handPresent);
pump_set(pumpActive, PUMP_PWM);
if (pumpActive) {
Serial.println("[PUMP] Dispensing (IR detected hand)");
}
// --- LCD Update ---
if (millis() - lastLCD > 500) {
lastLCD = millis();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("T:"); lcd.print(!isnan(tempC) ? (int)tempC : -1); lcd.print("C ");
lcd.print("Lvl:"); lcd.print(levelPct); lcd.print("%");
lcd.setCursor(0,1);
lcd.print("Fan:"); lcd.print(fanOn ? "ON " : "OFF");
lcd.print(" Gas:"); lcd.print(gasDetected ? "!" : "-");
}
// --- Serial Monitoring (real-time) ---
Serial.print("LDR: "); Serial.print(ldr);
Serial.print(" | Temp: "); Serial.print(tempC); Serial.print(" C");
Serial.print(" | Hum: "); Serial.print(hum); Serial.print(" %");
Serial.print(" | Water Level: "); Serial.print(levelPct); Serial.print(" %");
Serial.print(" | Distance: "); Serial.print(dist); Serial.print(" cm");
Serial.print(" | GasVal: "); Serial.print(gasValue);
Serial.print(" | Buzzer: "); Serial.print(buzzerActive ? "ON" : "OFF");
Serial.print(" | IRraw: "); Serial.print(irRaw);
Serial.println();
delay(200);
}
