Project tutorial
Humidity Controller

Humidity Controller © GPL3+

A simple device that makes controlling humidity and saving energy a snap. Operates as easily as a thermostat.

  • 250 views
  • 0 comments
  • 0 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

About this project

My girlfriend loves to sleep with the fan on. I hate the fan. I need humidity, she needs... whatever the opposite of humidity is. If I don't have enough humidity, I wake up with eyes caked in boogers and a sharp, dry pain where my nasal passage meets my throat. It's not a fun way to start my day, and it's been especially bad since I had a nasty cold a few weeks ago.

A humidifier is the obvious answer to this problem, but the problem with most humidifiers is that they don't have any feedback mechanism, so the whole room often gets too humid and the water tank runs out overnight. Not to mention my partner complained about being too hot to sleep at night, I knew I could use my wits to solve all these problems. I needed something that would control a humidifier so the humidity would be balanced, and save me the hassle of constantly refilling the tank and switching it off and on all the time.

I put together the project with an Arduino Nano, an LCD, a DHT sensor, a couple of buttons, a relay module, a mains voltage socket, and a 5V adapter.

Some pictures from the building process:

The first two nights were a beta test, and two problems became apparent. When the humidity reached the setpoint, the relays would begin constantly clicking on and off, every one second or so. the sound of the relays clicking would wake me up and was rather annoying. I fixed this issue by having the humidity sensor read only every 30 seconds, thereby slowing down the speed of the feedback. The second problem was that I had to unplug it every time I wanted to turn the whole thing off. I solved this by adding a function to the code wherein holding down both calibration buttons would toggle the whole system on and off. It was easier than adding another button or switch.

Code

Humidity controller codeC/C++
code for operating the humidity controller
//HUMIDITY CONTROLLER 1.1
//written for NANO

//controls and displays relative humidity
//sesnor used is DHT11
//uses active-low relay module to control live lines for 2 standard electrical outlets
//uses i2c lcd to display humidity and humidity setting
//turns display off during inactivity
//setting is adjustable from 10%-90% using 2 buttons
//backlight of LCD is controlled by pin 4, connected to top LED jumper pin on i2c backpack
//serial communications to monitor to ensure all code is working.

//added: "system off" function - allows both outlets to be turned off

// █ G █ L █ O █ B █ A █ L █ S █
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <dht.h>

// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);  

dht DHT;

#define DHT11_PIN A2

//buttons and variables to adjust calibration
int calupbtn = A0;
int calup;
int caldownbtn = A1;
int caldown;

//i2c PINS A4, A5

//pin for turning on humidifier relay
int humidifier = 3;
//pin for turning on the fan relay
int fan = 2;
//pin for turning on LCD backlights
int lcdlight = 4;

//calibration variable
int setpoint = 50;  //feedback setpoint.  
bool calstate = false;  //enables calibration adjustments only when LCD is ON.

//backlight timing variables
int displtime = 12000;  //amount of time the display is to be on before turning off
unsigned long displtimeon;  //last recorded time display timer was reset
int calunlock = 0;   //loop counter for unlocking calibration  

//sensor timing variables
unsigned long lastcheck;  //last time DHT was read
long interval = 30000;      //time between DHT readings

//system variables
bool syson = true;    //reference for system on/off. 
byte systog = 2;       //even number toggles on, odds toggle off
int syslock = 0;     //loop counter for unlocking system toggle

// █ S █ E █ T █ U █ P █ + █ + █ + █ + █ + █ + █ + █ + █ + █ + █ + █ + █ + █ + █
void setup(){

  Serial.begin(9600);  //serial communication used to ensure code is working correctly.
  
  lcd.init();  //initialize LCD
  lcd.backlight(); //enable LCD backlight, but doesn't turn it on

  lastcheck = 0;
  digitalWrite(lcdlight, HIGH);
  Serial.println("STARTING");
  lcd.print("   STARTING");

  //pin assignments
  pinMode(calupbtn, INPUT);
  pinMode(caldownbtn, INPUT);
  pinMode(humidifier, OUTPUT);
  pinMode(fan, OUTPUT);
  pinMode(lcdlight, OUTPUT);
  delay(1000);

  
  //test fan
  lcd.setCursor(0,1);
  lcd.print("<FAN>     HMDFR  ");  
  digitalWrite(fan, LOW);
  digitalWrite(humidifier, HIGH);
  delay(6000);
  //test humidifier
  lcd.setCursor(0,1);
  lcd.print(" FAN     <HMDFR> ");
  digitalWrite(fan, HIGH);
  digitalWrite(humidifier, LOW);
  delay(6000);
  //stop startup test
  digitalWrite(humidifier, HIGH);
  digitalWrite(fan, HIGH);
  lcd.clear();

  displtimeon = millis();

  int chk = DHT.read11(DHT11_PIN);
  lastcheck = millis();

  lcd.setCursor(0,0);
  lcd.print("Humidity: ");
  lcd.setCursor(13,0);
  lcd.print(DHT.humidity);
  lcd.setCursor(15,0);
  lcd.print("%  ");
  lcd.setCursor(0,1);
  lcd.print("setting: ");
  lcd.setCursor(13,1);
  lcd.print(setpoint);
  lcd.setCursor(15,1);
  lcd.print("%  ");
  delay(100);
}

// █ L █ O █ O █ P █ = █ = █ = █ = █ = █ = █ = █ = █ = █ = █ = █ = █ = █ = █ = █
void loop(){

  //check calibration buttons
  calup = digitalRead(calupbtn);
  caldown = digitalRead(caldownbtn);

  if(calup == HIGH and caldown == HIGH){  //--------SYSTEM TOGGLE
    syslock ++;
    Serial.println(syslock);
    if(syslock == 20){  //if both buttons held down for this many loops
      systog++;
      if(systog % 2 == 1){  //--------SYSTEM OFF
        syson = false;
        digitalWrite(fan, HIGH);
        digitalWrite(humidifier, HIGH);
        digitalWrite(lcdlight, HIGH);
        Serial.println("SYSTEM TURNED OFF");
        lcd.clear();
        lcd.print("   SYSTEM OFF");
        lcd.setCursor(0,1);
        lcd.print("  hold both btns");
        delay(2000);
        lcd.setCursor(0,1);
        lcd.print("  to turn on    ");
        displtimeon = millis();
      }
      if(systog % 2 == 0){  //--------SYSTEM ON
        syson = true;
        Serial.println("SYSTEM TURNED ON");
        digitalWrite(lcdlight, HIGH);
        lcd.clear();
        lcd.print("   SYSTEM ON");
        delay(2000);
        lcd.clear();
        displtimeon = millis();
      }
      syslock = 0;
    }
  }
  else(syslock = 0);
  
  //read humidity at appropriate intervals
  if(millis() > lastcheck + interval and syson == true){  //read the DHT humidity
    int chk = DHT.read11(DHT11_PIN);
    lastcheck = millis();
    Serial.print("DHT read = ");
    Serial.print(DHT.humidity);
    Serial.print("%");
    Serial.println(" ");
    }

  //turn on the led lights when calibration buttons are pressed
  if(calup == HIGH xor caldown == HIGH){
    digitalWrite(lcdlight, HIGH);
    calstate = true;
    displtimeon = millis();  //set display timer
    Serial.println("cal btn ACTIVE");
    if(syson == false){
      digitalWrite(lcdlight, HIGH);
      lcd.clear();
      lcd.print("   SYSTEM OFF");
      lcd.setCursor(0,1);
      lcd.print("  hold both btns");
      delay(3000);
      lcd.setCursor(0,1);
      lcd.print("  to turn on    ");
      displtimeon = millis();
    }
  }

  if(calstate == true and syson == true){  //--------DISPLAY ROUTINE
    Serial.println("printing display");
    //display variables on LCD
    lcd.setCursor(0,0);
    lcd.print("Humidity: ");
    lcd.setCursor(13,0);
    lcd.print(DHT.humidity);
    lcd.setCursor(15,0);
    lcd.print("%  ");
    lcd.setCursor(0,1);
    lcd.print("setting: ");
    lcd.setCursor(13,1);
    lcd.print(setpoint);
    lcd.setCursor(15,1);
    lcd.print("%  ");
    delay(100);

    calunlock ++;  
    //keeps calibration locked until display cycles 5 times after initially turned on
    //prevents adjustments on initial button press.
  }

//--------CALIBRATION ADJUSTMENTS
  if(calup == HIGH and caldown == LOW and calstate == true and syson == true){ 
    if(setpoint < 90 and calunlock > 5){ 
      setpoint = setpoint + 5;  //increase setpoint 
      Serial.println("adj setpoint up");
    }
    Serial.println(setpoint);
    delay(100);
    displtimeon = millis();     //reset backlight timeout
  }

  if(caldown == HIGH and calup == LOW and calstate == true and syson == true){
    if(setpoint > 10 and calunlock > 5){
      setpoint = setpoint - 5;  //decrease setpoint
      Serial.println("adj setpoint dn");
      }
    Serial.println(setpoint);
    delay(100);  
    displtimeon = millis();     //reset backlight timeout
  }

  if(millis() > displtimeon + displtime){  //-----------------BACKLIGHT TIMEOUT
    digitalWrite(lcdlight, LOW); //turn off the screen
    calstate = false;
    Serial.println("displ + backlights off");
    lcd.clear();
    calunlock = 0;  //lock calibration
  }

  if(millis() < lastcheck){
    lastcheck = millis();  //reset timers in a millisecond rollover
  }

                                      //--------SETPOINT ERROR PROCEDURE
  if(setpoint > 91 or setpoint < 9){  //in case setpoint is ever out of bounds
    Serial.println("O/B ERROR");
    digitalWrite(lcdlight, HIGH);
    lcd.clear();
    lcd.print("O/B ERROR");  //display error message on lcd
    lcd.setCursor(0,1);
    lcd.print("RESETTING");
    delay(1000);
    for(int count = 9; count >= 0; count = count - 1){
      lcd.setCursor(15,1);
      lcd.print(count);     //count down from 10
      delay(1000);
    }
    setpoint = 50;        //reset setpoint at 50.
    displtimeon = millis();
  }

  //turn on humidifier relay if below setpoint  --------RELAY CONTROL
  //RELAY MODULE IS ACTIVE LOW
  if(DHT.humidity <= setpoint - 3 and syson == true){  //if humidity is 3% lower than setpoint
    Serial.println("humidifier ON, fan OFF");  
    digitalWrite(humidifier, LOW);  //turn on humidifier
    digitalWrite(fan, HIGH);
  }
  else if(DHT.humidity >= setpoint + 3 and syson == true){  //if humidity is 3% above setpoint
    Serial.println("humidifier OFF, fan ON");
    digitalWrite(humidifier, HIGH);  //turn on fan
    digitalWrite(fan, LOW);
  }
  else{
    Serial.println("all off");  //if humidity is within 3% of setpoint
    digitalWrite(humidifier, HIGH);  //turn both off
    digitalWrite(fan, HIGH);
  }
  //delay(700);  //un-comment for serial debugging

  Serial.print("setpoint = ");
  Serial.println(setpoint);

  //delay(700);  //un-comment for serial debugging
}

/*  WIRING DIAGRAMS
 https://66.media.tumblr.com/98426b566744beacdd42bc0221092b76/tumblr_pvr0u8kvZy1yrmjh9o1_1280.png
 */

Schematics

wiring diagram
Wiring diagram zcv471oqfe

Comments

Similar projects you might like

Soldering Iron Controller for Hakko 907 v.2

Project tutorial by Alexander

  • 27,353 views
  • 178 comments
  • 65 respects

Soldering Iron Controller for Hakko 907

Project tutorial by Alexander

  • 33,695 views
  • 22 comments
  • 71 respects

Arduino GrowBox Controller

Project tutorial by Michele Valentini

  • 11,149 views
  • 5 comments
  • 44 respects

Health Kit: Humidity and Temperature Control

Project tutorial by Diana Khalipina

  • 6,882 views
  • 2 comments
  • 45 respects

Watersource Controller

Project showcase by designedrat

  • 6,200 views
  • 0 comments
  • 17 respects

Scorbot ER-V+ Controller & Simulator Design

Project tutorial by Amit Nandi (BigWiz)

  • 693 views
  • 2 comments
  • 6 respects
Add projectSign up / Login