#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Stepper.h>
// Pins
#define DHTPIN 2
#define DHTTYPE DHT22
#define POT_PIN A0
// Stepper Motor Pins (4-wire connection)
const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
// Constants
#define TEMP_LOW 25
#define TEMP_HIGH 30
#define MANUAL_THRESHOLD 15 // Change in pot value to trigger manual mode
// Objects
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
// States
float temperature = 0;
int motorRPM = 0;
bool isManualMode = false;
int lastPotValue = 0;
// Timing (Soft Real-Time)
unsigned long lastSensorRead = 0;
const unsigned long sensorInterval = 2000; // Read DHT every 2s
void setup() {
Serial.begin(9600);
dht.begin();
lcd.init();
lcd.backlight();
pinMode(POT_PIN, INPUT);
lcd.setCursor(0, 0);
lcd.print("Fan Control Sys");
lcd.setCursor(0, 1);
lcd.print("Initializing...");
delay(2000);
lcd.clear();
}
void loop() {
unsigned long currentMillis = millis();
// 1. Read Potentiometer (Manual Override Detection)
int currentPotValue = analogRead(POT_PIN);
if (abs(currentPotValue - lastPotValue) > MANUAL_THRESHOLD) {
isManualMode = true;
}
lastPotValue = currentPotValue;
// 2. Periodic Sensor Reading (Automatic Mode Logic)
if (currentMillis - lastSensorRead >= sensorInterval) {
lastSensorRead = currentMillis;
float tempRead = dht.readTemperature();
if (!isnan(tempRead)) {
temperature = tempRead;
} else {
Serial.println("Sensor Error");
}
// Auto Logic (only updates speed if not in manual override)
if (!isManualMode) {
if (temperature < TEMP_LOW) {
motorRPM = 0;
} else if (temperature >= TEMP_LOW && temperature < TEMP_HIGH) {
motorRPM = 30; // Medium RPM
} else {
motorRPM = 100; // High RPM
}
}
}
// 3. Manual Speed Control
if (isManualMode) {
motorRPM = map(currentPotValue, 0, 1023, 0, 100);
}
// 4. Actuator Control (Stepper)
if (motorRPM > 0) {
myStepper.setSpeed(motorRPM);
myStepper.step(stepsPerRevolution / 10); // Step a small fraction each loop iteration
}
// 5. Update Display
updateDisplay();
}
void updateDisplay() {
static unsigned long lastDisplayUpdate = 0;
if (millis() - lastDisplayUpdate < 500) return; // Update LCD every 500ms
lastDisplayUpdate = millis();
lcd.setCursor(0, 0);
lcd.print("T:");
lcd.print(temperature, 1);
lcd.print("C ");
lcd.setCursor(9, 0);
lcd.print(isManualMode ? "MOD:MAN" : "MOD:AUT");
lcd.setCursor(0, 1);
lcd.print("Spd: ");
lcd.print(motorRPM);
lcd.print(" RPM");
}