Exhaust Fan Control
A Control System that integrates temperature, humidity, and gas sensors with an LCD display, relay-controlled fan, and visual alerts to automatically and manually ensure optimal and safe environmental conditions.
Components and supplies
1
Digital Temperature and Relative Humidity Sensor DHT11 DHT22 AM2302B AM2301 AM2320 Humidity Sensor Module For Arduino AM2302
1
MQ2(gas sensor)
1
Arduino Uno R3
2
Resistor 10k
1
16x2 LCD display with I²C interface
2
Push Button
1
Red LED 625nm 1.8v 2..5mA
1
SSR-40 DA
1
Resistor 220 ohm
Apps and platforms
1
Arduino IDE
Project description
Code
Exhaust Fan Control
cpp
...
1#include "arduino_secrets.h" 2 3#include <DHT11.h> // Library for DHT11 sensor 4#include <Wire.h> 5#include <LiquidCrystal_I2C.h> // Library for I2C LCD 6 7// Initialize DHT11 sensor on pin 2 8DHT11 dht11(2); 9 10// Initialize LCD with I2C address 0x27, 20 columns, and 4 rows 11LiquidCrystal_I2C lcd(0x27, 20, 4); 12 13#define Threshold 250 14#define MQ2pin A0 15 16int fanRelay = 4; // Fan relay pin 17int mq2D0Pin = 3; // MQ2 digital output pin 18int redLight = 5; // Red light pin 19int buttonPin = 8; // Button pin for manual mode 20int buttonPin1 = 7; // Button pin for manual fan control 21 22int counterHigh = 0; 23int counterLow = 0; 24float sensorValue; // MQ2 sensor analog value 25int sensorDigitalVal; // MQ2 sensor digital value 26 27unsigned long previousMillis = 0; 28unsigned long interval = 2000; // 2-second interval for DHT11 sensor readings 29unsigned long displayUpdateInterval = 1000; // 1-second interval for display updates 30unsigned long lastDHT11Millis = 0; 31unsigned long lastDisplayUpdateMillis = 0; 32unsigned long redLightPreviousMillis = 0; 33bool redLightState = LOW; // State of the red light 34bool dangerMode = false; // Flag for danger mode 35 36bool fanManualMode = false; // State to track manual control of the fan 37bool fanManualState = false; // State of manual fan control 38bool lastButtonState = LOW; // Previous state of the button 39bool lastButtonState1 = LOW; // Previous state of the button 40int buttonState = LOW; // Current button state 41int buttonState1 = LOW; // Current button state 42unsigned long debounceDelay = 50; // Debounce delay for button 43unsigned long lastDebounceTime = 0; // Last time the button was toggled 44unsigned long lastDebounceTime1 = 0; 45 46enum DisplayState { 47 DISPLAY_TEMP_HUMID, 48 DISPLAY_HEAT_INDEX, 49 WAIT_BEFORE_CLEAR, 50 WAIT_BEFORE_TEMP_HUMID 51}; 52 53DisplayState displayState = DISPLAY_TEMP_HUMID; 54unsigned long displayStateStartMillis = 0; 55 56void setup() { 57 lcd.init(); // Initialize the LCD 58 lcd.backlight(); // Turn on the LCD backlight 59 clear_lcd(0); // Clear the first line of the LCD 60 clear_lcd(1); // Clear the second line of the LCD 61 pinMode(fanRelay, OUTPUT); // Set fan relay pin as output 62 pinMode(mq2D0Pin, INPUT); // Set MQ2 digital pin as input 63 pinMode(redLight, OUTPUT); // Set red light pin as output 64 pinMode(buttonPin, INPUT); // Set button pin as input 65 pinMode(buttonPin1, INPUT); // Set button pin as input 66 digitalWrite(fanRelay, LOW); // Turn off the fan relay initially 67 Serial.begin(9600); // Start serial communication 68} 69 70void loop() { 71 unsigned long currentMillis = millis(); 72 73 // Read the button state 74 int reading = digitalRead(buttonPin); 75 76 // Button debouncing logic 77 if (reading != lastButtonState) { 78 lastDebounceTime = currentMillis; 79 } 80 81 if ((currentMillis - lastDebounceTime) > debounceDelay) { 82 if (reading != buttonState) { 83 buttonState = reading; 84 85 // If button is pressed (HIGH state) 86 if (buttonState == HIGH) { 87 fanManualMode = !fanManualMode; // Toggle manual mode 88 digitalWrite(fanRelay, fanManualMode ? HIGH : LOW); // Set fan state based on manual mode 89 if (fanManualState){ 90 fanManualState = false; 91 } 92 } 93 } 94 } 95 96 if (fanManualMode){ 97 int reading1 = digitalRead(buttonPin1); 98 99 if (reading1 != lastButtonState1) { 100 lastDebounceTime1 = currentMillis; 101 } 102 103 if ((currentMillis - lastDebounceTime1) > debounceDelay) { 104 if (reading1 != buttonState1) { 105 buttonState1 = reading1; 106 107 // If button is pressed (HIGH state) 108 if (buttonState1 == HIGH) { 109 fanManualState = !fanManualState; // Toggle fan state 110 digitalWrite(fanRelay, fanManualState ? HIGH : LOW); // Set fan state based on manual control 111 } 112 } 113 } 114 115 lastButtonState1 = reading1; 116 } 117 // Save the current button state for next iteration 118 lastButtonState = reading; 119 120 // Check MQ2 sensor 121 sensorValue = analogRead(MQ2pin); 122 sensorDigitalVal = digitalRead(mq2D0Pin); 123 124 if (sensorDigitalVal == 0) { 125 Serial.println(sensorValue); 126 if (sensorValue > Threshold) { 127 dangerMode = true; 128 } 129 } 130 131 // Handle danger mode 132 if (dangerMode) { 133 if (currentMillis - previousMillis >= interval) { 134 previousMillis = currentMillis; 135 136 sensorValue = analogRead(MQ2pin); 137 clear_lcd(0); 138 clear_lcd(1); 139 lcd.setCursor(0, 0); 140 lcd.print("DANGER!!!"); 141 lcd.setCursor(0, 1); 142 lcd.print("Smoke/Gas!!!"); 143 144 digitalWrite(fanRelay, HIGH); // Turn on the fan 145 if (sensorValue < Threshold) { 146 dangerMode = false; 147 digitalWrite(redLight, LOW); // Turn off the red light 148 digitalWrite(fanRelay, LOW); // Turn off the fan 149 counterHigh = 0; 150 counterLow = 0; 151 clear_lcd(0); 152 clear_lcd(1); 153 } 154 } 155 156 // Blink red light 157 if (currentMillis - redLightPreviousMillis >= interval) { 158 redLightPreviousMillis = currentMillis; 159 redLightState = !redLightState; 160 digitalWrite(redLight, redLightState); 161 } 162 } else { 163 // Read DHT11 sensor once per loop and only if the interval has passed 164 if (currentMillis - lastDHT11Millis >= interval) { 165 lastDHT11Millis = currentMillis; 166 167 int temperature = 0; 168 int humidity = 0; 169 int result = dht11.readTemperatureHumidity(temperature, humidity); 170 171 if (result == 0) { 172 // Update display every displayUpdateInterval 173 if (currentMillis - lastDisplayUpdateMillis >= displayUpdateInterval) { 174 lastDisplayUpdateMillis = currentMillis; 175 176 // State machine for display updates 177 switch (displayState) { 178 case DISPLAY_TEMP_HUMID: 179 clear_lcd(0); 180 lcd.setCursor(0, 0); 181 lcd.print("Temp:"); 182 lcd.setCursor(6, 0); 183 lcd.print(temperature); 184 lcd.setCursor(9, 0); 185 lcd.print((char)223); 186 lcd.setCursor(10, 0); 187 lcd.print("C"); 188 189 clear_lcd(1); 190 lcd.setCursor(0, 1); 191 lcd.print("Humid:"); 192 lcd.setCursor(7, 1); 193 lcd.print(humidity); 194 lcd.setCursor(10, 1); 195 lcd.print("%"); 196 197 displayState = WAIT_BEFORE_CLEAR; 198 displayStateStartMillis = currentMillis; 199 break; 200 201 case WAIT_BEFORE_CLEAR: 202 if (currentMillis - displayStateStartMillis >= displayUpdateInterval) { 203 int heat_index = int(round(calculate_HI(temperature, humidity))); 204 clear_lcd(0); 205 lcd.setCursor(0, 0); 206 lcd.print("Heat Index:"); 207 lcd.setCursor(12, 0); 208 lcd.print(heat_index); 209 lcd.setCursor(14, 0); 210 lcd.print((char)223); 211 lcd.setCursor(15, 0); 212 lcd.print("C"); 213 214 if (!fanManualMode) { 215 clear_lcd(1); 216 lcd.setCursor(0, 1); 217 lcd.print("Mode:"); 218 lcd.setCursor(6, 1); 219 lcd.print("Auto"); 220 221 // Control fan based on heat index 222 if (temperature >= 27) { 223 counterLow = 0; 224 counterHigh += 1; 225 if (counterHigh == 5 && !fanManualMode) { // Only change the fan state if not in manual mode 226 counterHigh = 0; 227 digitalWrite(fanRelay, HIGH); 228 } 229 } else { 230 counterHigh = 0; 231 counterLow += 1; 232 if (counterLow == 5 && !fanManualMode) { // Only change the fan state if not in manual mode 233 counterLow = 0; 234 digitalWrite(fanRelay, LOW); 235 } 236 } 237 } else { 238 counterLow = 0; 239 counterHigh = 0; 240 clear_lcd(1); 241 lcd.setCursor(0, 1); 242 lcd.print("Mode:"); 243 lcd.setCursor(6, 1); 244 lcd.print("Manual"); 245 } 246 247 displayState = WAIT_BEFORE_TEMP_HUMID; 248 displayStateStartMillis = currentMillis; 249 } 250 break; 251 252 case WAIT_BEFORE_TEMP_HUMID: 253 if (currentMillis - displayStateStartMillis >= displayUpdateInterval) { 254 displayState = DISPLAY_TEMP_HUMID; 255 displayStateStartMillis = currentMillis; 256 } 257 break; 258 259 default: 260 displayState = DISPLAY_TEMP_HUMID; 261 displayStateStartMillis = currentMillis; 262 break; 263 } 264 } 265 } else { 266 clear_lcd(0); 267 clear_lcd(1); 268 lcd.print(DHT11::getErrorString(result)); 269 } 270 } 271 } 272} 273 274void clear_lcd(int line) { 275 for (int n = 0; n < 20; n++) { 276 lcd.setCursor(n, line); 277 lcd.print(" "); 278 } 279} 280 281float calculate_HI(int temp, int RH) { 282 // Convert temperature from Celsius to Fahrenheit 283 float T = (temp * 9 / 5) + 32; 284 285 // Calculate the initial heat index 286 float HI = -42.379 + 2.04901523 * T + 10.14333127 * RH - 0.22475541 * T * RH 287 - 0.00683783 * T * T - 0.05481717 * RH * RH 288 + 0.00122874 * T * T * RH + 0.00085282 * T * RH * RH 289 - 0.00000199 * T * T * RH * RH; 290 291 // Adjust for low humidity 292 if (RH < 13 && T >= 80 && T <= 110) { 293 float adjust = ((13 - RH) / 4) * sqrt(17 - abs(T - 95.) / 17); 294 HI -= adjust; 295 } 296 // Adjust for high humidity 297 else if (RH > 85 && T > 80 && T < 87) { 298 float adjust = ((RH - 85) / 10) * ((87 - T) / 5); 299 HI += adjust; 300 } 301 // Calculation for temperatures below 80°F 302 else if (T < 80) { 303 HI = 0.5 * (T + 61.0 + ((T - 68.0) * 1.2) + (RH * 0.094)); 304 } 305 306 // Convert the heat index back to Celsius 307 return (HI - 32) * 5 / 9; 308}
Comments
Only logged in users can leave comments