Smart Fan

The Smart Fan is one of my IOT projects which used a temperature and humidity sensor to control the speed of a fan connected to it. It also incorporates a LCD screen to display the readings from the temperature and humidity sensor. The project was built using an Arduino Uno, a DHT11 sensor. Below is diagram of the project for the circuitry:

Smart Fan Circuit Diagram

How the smart fan works

The smart fan works by reading the temperature and humidity from the DHT11 sensor and then adjusting the speed of the fan based on the readings. Below is a video showing the smart fan in action:

Code

There are a few versions of the smart fan that I implemented:

  • Version 1: This one is basic and just turns on the fan when the temperature is above 22 degrees farhenheit
  • Version 3: This one used the PWM to control the speed of the fan based on the temperature
  • Version 2: This one is modified to turn on the fan when the temperature is above 70 degrees farhenheit
  • Version 4: This one is modified to play around with the DIRA and DIRB pins to control the direction of the fan

Version 1

This one is basic and just turns on the fan when the temperature is above 22 degrees farhenheit

#include <dht_nonblocking.h>
#include <LiquidCrystal.h>

#define DHT_SENSOR_TYPE DHT_TYPE_11
static const int DHT_SENSOR_PIN = 2;
DHT_nonblocking dht_sensor(DHT_SENSOR_PIN, DHT_SENSOR_TYPE);

boolean fan_on = false;

#define ENABLE 5
#define DIRA 3
#define DIRB 6

// Initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
  Serial.begin(9600);
  
  pinMode(ENABLE, OUTPUT);
  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);

  digitalWrite(DIRA, HIGH); //one way
  digitalWrite(DIRB, LOW);
  digitalWrite(ENABLE, LOW); // enable off

  // Set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
}

/*
 * Poll for a measurement, keeping the state machine alive.  Returns
 * true if a measurement is available.
 */
static bool measure_environment(float *temperature, float *humidity) {
  static unsigned long measurement_timestamp = millis();

  /* Measure once every four seconds. */
  if (millis() - measurement_timestamp > 3000ul) {
    if (dht_sensor.measure(temperature, humidity) == true) {
      measurement_timestamp = millis();
      return (true);
    }
  }

  return (false);
}

void loop() {
  float temperature;
  float humidity;

  if (measure_environment(&temperature, &humidity) == true) {
    if (temperature > 22.0) {
      digitalWrite(ENABLE, HIGH);
      if (!fan_on) {
        Serial.println("High temperature - turn on fan");
        fan_on = true;
      }
    } else {
      digitalWrite(ENABLE, LOW);
      if (fan_on) {
        Serial.println("Low temperature - turn off fan");
        fan_on = false;
      }
    }
    Serial.print("T = ");
    Serial.print(temperature, 1);
    Serial.print(" deg. C, H = ");
    Serial.print(humidity, 1);
    Serial.println("%");

    // Clear the LCD screen
    lcd.clear();
    // Print temperature and humidity on the LCD
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(temperature);
    lcd.print(" C");
    lcd.setCursor(0, 1);
    lcd.print("Humidity: ");
    lcd.print(humidity);
    lcd.print("%");
  }
}

Version 2

This one is modified to turn on the fan when the temperature is above 70 degrees farhenheit

#include <dht_nonblocking.h>
#include <LiquidCrystal.h>

#define DHT_SENSOR_TYPE DHT_TYPE_11
static const int DHT_SENSOR_PIN = 2;
DHT_nonblocking dht_sensor(DHT_SENSOR_PIN, DHT_SENSOR_TYPE);

boolean fan_on = false;

#define ENABLE 5
#define DIRA 3
#define DIRB 6

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
  Serial.begin(9600);
  
  pinMode(ENABLE, OUTPUT);
  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);

  digitalWrite(DIRA, HIGH);
  digitalWrite(DIRB, LOW);
  digitalWrite(ENABLE, LOW);

  lcd.begin(16, 2);
}

static bool measure_environment(float *temperature, float *humidity) {
  static unsigned long measurement_timestamp = millis();

  if (millis() - measurement_timestamp > 3000ul) {
    if (dht_sensor.measure(temperature, humidity) == true) {
      *temperature = *temperature * 9.0 / 5.0 + 32; // Use the Cel to Far formula to calculate the temperature in Far
      measurement_timestamp = millis();
      return (true);
    }
  }

  return (false);
}

void loop() {
  float temperature;
  float humidity;

  if (measure_environment(&temperature, &humidity) == true) {
    if (temperature > 70.0) { // Change number to as temps are in F
      digitalWrite(ENABLE, HIGH);
      if (!fan_on) {
        Serial.println("High temperature - turn on fan");
        fan_on = true;
      }
    } else {
      digitalWrite(ENABLE, LOW);
      if (fan_on) {
        Serial.println("Low temperature - turn off fan");
        fan_on = false;
      }
    }
    Serial.print("T = ");
    Serial.print(temperature, 1);
    Serial.print(" deg. F, H = "); //F instead of C
    Serial.print(humidity, 1);
    Serial.println("%");

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(temperature);
    lcd.print(" F");
    lcd.setCursor(0, 1);
    lcd.print("Humidity: ");
    lcd.print(humidity);
    lcd.print("%");
  }
}

Version 3

This one used the PWM to control the speed of the fan based on the temperature

#include <dht_nonblocking.h>   // Include the library for non-blocking DHT sensor
#include <LiquidCrystal.h>     // Include the library for LCD display

#define DHT_SENSOR_TYPE DHT_TYPE_11   // Define the type of DHT sensor
static const int DHT_SENSOR_PIN = 2;  // Define the pin for DHT sensor
DHT_nonblocking dht_sensor(DHT_SENSOR_PIN, DHT_SENSOR_TYPE);  // Create an instance of the DHT sensor

#define FAN_PIN 5   // Define the pin for fan control (PWM pin)
#define DIRA 3      // Define the pin for direction control A
#define DIRB 6      // Define the pin for direction control B

// Initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
  Serial.begin(9600);   // Initialize serial communication
  
  pinMode(FAN_PIN, OUTPUT);  // Set the fan control pin as output
  pinMode(DIRA, OUTPUT);     // Set the pin for direction control A as output
  pinMode(DIRB, OUTPUT);     // Set the pin for direction control B as output

  digitalWrite(DIRA, HIGH);  // Set direction control A to high (one way)
  digitalWrite(DIRB, LOW);   // Set direction control B to low

  // Set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
}

/*
 * Poll for a measurement, keeping the state machine alive.  Returns
 * true if a measurement is available.
 */
static bool measure_environment(float *temperature, float *humidity) {
  static unsigned long measurement_timestamp = millis();  // Initialize measurement timestamp

  /* Measure once every four seconds. */
  if (millis() - measurement_timestamp > 3000ul) {  // Check if it's time to measure
    if (dht_sensor.measure(temperature, humidity) == true) {  // Measure temperature and humidity
      measurement_timestamp = millis();  // Update measurement timestamp
      return (true);  // Return true if measurement is available
    }
  }

  return (false);  // Return false if measurement is not available
}

void setFanSpeed(float temperature) {
  // Divide the temperature range into four segments and adjust fan speed accordingly
  if (temperature > 19.0) {
    analogWrite(FAN_PIN, 255);  // Set fan speed to maximum (255)
  } else if (temperature > 25.0) {
    analogWrite(FAN_PIN, 200);  // Set fan speed to 80% (approximately 200)
  } else if (temperature > 20.0) {
    analogWrite(FAN_PIN, 150);  // Set fan speed to 60% (approximately 150)
  } else {
    analogWrite(FAN_PIN, 100);  // Set fan speed to 40% (approximately 100)
  }
}

void loop() {
  float temperature;
  float humidity;

  if (measure_environment(&temperature, &humidity) == true) {  // If measurement is available
    setFanSpeed(temperature);  // Adjust fan speed based on temperature

    Serial.print("T = ");
    Serial.print(temperature, 1);
    Serial.print(" deg. C, H = ");
    Serial.print(humidity, 1);
    Serial.println("%");

    // Clear the LCD screen
    lcd.clear();
    // Print temperature and humidity on the LCD
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(temperature);
    lcd.print(" C");
    lcd.setCursor(0, 1);
    lcd.print("Humidity: ");
    lcd.print(humidity);
    lcd.print("%");
  }
}

Version 4

This one is modified to play around with the DIRA and DIRB pins to control the direction of the fan

#include <dht_nonblocking.h>
#include <LiquidCrystal.h>

#define DHT_SENSOR_TYPE DHT_TYPE_11
static const int DHT_SENSOR_PIN = 2;
DHT_nonblocking dht_sensor(DHT_SENSOR_PIN, DHT_SENSOR_TYPE);


#define ENABLE 5
#define DIRA 3
#define DIRB 6

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
  Serial.begin(9600);

  pinMode(ENABLE, OUTPUT);
  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);

  digitalWrite(ENABLE, LOW);  // Initially turn off fan

  lcd.begin(16, 2);
}

static bool measure_environment(float *temperature, float *humidity) {
  static unsigned long measurement_timestamp = millis();

  if (millis() - measurement_timestamp > 3000ul) {
    if (dht_sensor.measure(temperature, humidity) == true) {
      *temperature = *temperature * 9.0 / 5.0 + 32;  // Convert Celsius to Fahrenheit
      measurement_timestamp = millis();
      return (true);
    }
  }

  return (false);
}

void loop() {
  float temperature;
  float humidity;

  if (measure_environment(&temperature, &humidity) == true) {
    if (temperature > 80.0) {
      digitalWrite(DIRA, HIGH);  // Set motor direction clockwise
      digitalWrite(DIRB, LOW);  // Set motor direction clockwise
      digitalWrite(ENABLE, HIGH);  // Turn on fan
      Serial.println("High temperature - Cooling mode");
    } else {
      digitalWrite(DIRA, LOW);  // Set motor direction counter-clockwise
      digitalWrite(DIRB, HIGH); // Set motor direction counter-clockwise
      digitalWrite(ENABLE, HIGH);  // Turn on fan
      Serial.println("Low temperature - Reverse mode");
    }
    Serial.print("T = ");
    Serial.print(temperature, 1);
    Serial.print(" deg. F, H = ");
    Serial.print(humidity, 1);
    Serial.println("%");

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(temperature);
    lcd.print(" F");
    lcd.setCursor(0, 1);
    lcd.print("Humidity: ");
    lcd.print(humidity);
    lcd.print("%");
  }
}