///////////////////////////////////////////////////////////////////////////////////////////////
//REMINDER * relay_is_inverted to HIGH
//
//
///////////////////////////////////////////////////////////////////////////////////////////////
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <ESP32Servo.h>
#define e_SIZE 256
#define DHT1PIN 14
#define DHT2PIN 27
#define DHT1TYPE DHT22
#define DHT2TYPE DHT22
Servo servo;
DHT dht1(DHT1PIN, DHT1TYPE);
DHT dht2(DHT2PIN, DHT2TYPE);
LiquidCrystal_I2C lcd(0x27, 16,2);
//inputs
byte select_button = 15; //pin for the on/off button
byte up_button = 34; //pin for the humidity down button
byte down_button = 35; //pin for the timer dry button
//outputs
byte Heater_and_fanpin = 12; //pin for the heater and fan output
byte buzzer_pin = 23; //pin for the buzzer
const int servo_pin = 18; //servo attatched to this pin
int servo_power_pin = 4; //2N2222 attatched to this pin
//configurable variables
int default_humidity_target = 50; //default humidity target in celcius
int min_humidity_target = 10; //minimum humidity target in celcius
unsigned long dry_timer = 30; //timer mode dry time in minutes
int alarm_temp = 50; //alarm temperature
unsigned long Main_timeout = 4; //hours
unsigned long backlight_timeout = 60; //minutes
int max_temp = 45; //max temperature able to set
int temp_lag = 1; //wait for temp to drop this value before trning on
unsigned long back_to_on_delay = 1; //seconds to wait to switch back on to (compressor)
bool Default_to_prev_humidity = LOW; //HIGH - revert to previous humidity, LOW - revert to off
bool relay_is_inverted = LOW; //set to high if relay output is inverted
int max_motor_temp = 30; //switch off for overheat protection
int min_angle = 0;
int max_angle = 180;
//local variables
bool alarm_triggered = LOW;
bool state_changed = HIGH; // set HIGH to start in OFF state, low to start in dehumidify state
bool select_button_pressed_once = LOW;
unsigned long any_button_timer;
bool mode_triggered_once = LOW;
bool timer_already_tripped = LOW;
bool dampener = LOW;
bool heater_and_fan = LOW;
int pos = 0;
int display_mode = 0;
int box_temp;
int box_humidity;
int target_humidity;
int Outside_temp;
int Outside_humidity;
bool Heater_and_fan_state = LOW;
unsigned long back_to_on_delay_timer; //mark switched off state to prevent turn on too soon
int saved_temp;
int saved_hum;
unsigned long time1;
unsigned long time2;
unsigned long time3;
bool up_button_pressed_once;
bool down_button_pressed_once;
bool refresh;
int mode = 0;
int settings_mode;
int mode_selector;
void loop() {
//read temp and humidity
box_temp = dht1.readTemperature();
box_humidity = dht1.readHumidity();
Outside_temp = dht2.readTemperature();
Outside_humidity = dht2.readHumidity();
//Read select button
if(digitalRead(select_button) == HIGH && select_button_pressed_once == LOW){
select_button_pressed_once = HIGH;
time1 = millis();
delay(100);
}
if(digitalRead(select_button) == LOW && select_button_pressed_once == HIGH){
select_button_pressed_once = LOW;
time2 = millis();
delay(100);
time3 = time2 - time1; // DEFINITION OF time3 - DONT CHANGE THIS - for click and long click
}
//Read up button
if(digitalRead(up_button) == HIGH && up_button_pressed_once == LOW){
up_button_pressed_once = HIGH;
}
else if(digitalRead(up_button) == LOW && up_button_pressed_once == HIGH){
up_button_pressed_once = LOW;
}
//Read down button
if(digitalRead(down_button) == HIGH && down_button_pressed_once == LOW){
down_button_pressed_once = HIGH;
}
else if(digitalRead(down_button) == LOW && down_button_pressed_once == HIGH){
down_button_pressed_once = LOW;
}
//Read any button to reset timer
if(digitalRead(down_button) == HIGH || digitalRead(up_button) == HIGH || digitalRead(down_button) == HIGH){
any_button_timer = millis();
lcd.backlight();
}
//mode selector
//mode 0 - off
//mode 1 - auto dehumidify - standby
// - on state
//mode 2 - timer
//mode 3 - smart
//mode 4 - settings
//click to select
//long click to go back
//settings mode 1 - max temp
//settings mode 2 - switch on delay
//settings mode 3 - Backlight timeout
//settings mode 4 - main timeout period
//settings mode 5 - timeout bahaviour
//settings mode 6 - output relay inversion
//settings mode 7 - alarm temp
//settings mode 8 - smart humidity difference
//settings mode 9 - save to eeprom
//alarm state
if(box_temp >= alarm_temp && alarm_triggered == LOW){
alarm_triggered = HIGH;
tone(buzzer_pin, 2300);
mode = 0;
}
if(box_temp < max_temp && alarm_triggered == HIGH){
alarm_triggered = LOW;
noTone(buzzer_pin);
delay(100);
servo.attach(servo_pin, 500, 2400);
}
//Refresh dislay if box_temp value change
if(saved_temp < box_temp || saved_temp > box_temp){
saved_temp = box_temp;
refresh = HIGH;
}
//Refresh dislay if humidity value change
if(saved_hum < box_humidity || saved_hum > box_humidity){
saved_hum = box_humidity;
refresh = HIGH;
}
//power off after main timer
if(millis() - any_button_timer >= Main_timeout*60000*60){
mode = 0;
}
//Backlight timeout
if(millis() - any_button_timer >= backlight_timeout*60000){
lcd.noBacklight();
}
//open dampener
if(dampener == HIGH && pos != max_angle){
digitalWrite(servo_power_pin, HIGH);
// for loop that increases the angle by 1 from 0 to max_angle with a delay of 10 ms per angle
for (pos = min_angle; pos <= max_angle; pos += 1) {
servo.write(pos);
delay(10);
}
digitalWrite(servo_power_pin, LOW);
}
//close dampener
else if(dampener == LOW && pos != min_angle){
digitalWrite(servo_power_pin, HIGH);
// for loop that decreases the angle by 1 from max_angle to 0 with a delay of 10 ms per angle
for (pos = max_angle; pos >= min_angle; pos -= 1) {
servo.write(pos);
delay(10);
}
digitalWrite(servo_power_pin, LOW);
}
//turn on heater and fan
if(heater_and_fan == LOW && Heater_and_fan_state == HIGH){
Heater_and_fan_state = LOW;
digitalWrite(Heater_and_fanpin, !relay_is_inverted); //TURN ON
}
//turn off heater and fan
if(heater_and_fan == HIGH && Heater_and_fan_state == LOW){
Heater_and_fan_state = HIGH;
digitalWrite(Heater_and_fanpin, relay_is_inverted); //TURN OFF
}
//mode selector - if mode = 0(off), change mode option
if(mode == 0){
if(up_button_pressed_once == HIGH && mode_selector <= 4){
mode_selector ++;
}
if(down_button_pressed_once == HIGH && mode_selector >= 0){
mode_selector --;
}
if(select_button_pressed_once == HIGH){
mode = mode_selector;
mode_selector = 0;
}
}
//mode 0 - off
if(mode == 0 && mode_triggered_once == LOW){
mode_triggered_once = HIGH;
dampener = LOW;
heater_and_fan = LOW;
display_mode = 0;
}
//mode 1 - auto dehumidify (go on and off according to temp and humidity)
//go off if dry
if(mode == 1){
if(box_humidity < target_humidity && mode_triggered_once == LOW){
mode_triggered_once = HIGH;
dampener = LOW;
heater_and_fan = LOW;
display_mode = 2;
}
if(box_temp < max_temp){
//go on if humid
if(box_humidity > target_humidity && mode_triggered_once == LOW){
mode_triggered_once = HIGH;
dampener = HIGH;
heater_and_fan = HIGH;
display_mode = 1;
}
}
}
//mode 2 - timer
if(mode == 2){
if(millis() > any_button_timer + dry_timer*60000){
if(timer_already_tripped == LOW){
timer_already_tripped = HIGH;
mode = 0; // TIMER EXPIRED - OFF
}
}
else if(box_temp < max_temp - temp_lag){
//wait for on delay timer
if(millis() > back_to_on_delay*1000 + back_to_on_delay_timer){
mode_triggered_once = LOW;
dampener = HIGH;
heater_and_fan = HIGH;
display_mode = 3; // TIMER ON
}
}
else if(box_temp > max_temp){
mode_triggered_once = LOW;
dampener = LOW;
heater_and_fan = LOW;
display_mode = 4; // MAKE STANDBY
}
}
// mode 3 - if outside is very dry, start drying
if(mode == 3){
//if 5% more humid inside box
if(Outside_humidity < box_humidity + 5){
if(box_temp < max_temp - temp_lag){
//wait for on delay timer
if((millis() - back_to_on_delay_timer > back_to_on_delay*1000) && mode_triggered_once == LOW){
mode_triggered_once == HIGH;
dampener = HIGH;
heater_and_fan = HIGH;
display_mode = 5; // MAKE SMART MODE
}
}
}
}
//if ever in mode 0(off), reset target humidity
if(mode == 0 && target_humidity != default_humidity_target){
target_humidity == default_humidity_target;
}
//if mode = (1)auto, use the up and down buttons to lower or raise taraget humidity
if(mode == 1){
if(down_button_pressed_once == HIGH){
target_humidity --;
}
if(up_button_pressed_once == HIGH){
target_humidity ++;
}
}
//settings mode 1 - menu - change max temp
if (settings_mode == 1){
if(digitalRead(up_button) == LOW){
max_temp ++;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW){
max_temp --;
refresh = HIGH;
delay(500);
}
}
//settings mode 2 - menu - change temp lag
if (settings_mode == 2){
if(digitalRead(up_button) == LOW){
temp_lag ++;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW){
temp_lag --;
refresh = HIGH;
delay(500);
}
}
//settings mode 3 - menu - change switch on delay
if (settings_mode == 3){
if(digitalRead(up_button) == LOW){
back_to_on_delay ++;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW){
back_to_on_delay --;
refresh = HIGH;
delay(500);
}
}
//settings mode 4 - menu - change backlight timeout
if(mode == 4){
//increments of 1
if(backlight_timeout >= 0 && backlight_timeout < 10){
if(digitalRead(up_button) == LOW){
backlight_timeout ++;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW){
backlight_timeout --;
refresh = HIGH;
delay(500);
}
}
//increments of 10
else if(backlight_timeout >= 10){
if(digitalRead(up_button) == LOW){
backlight_timeout = backlight_timeout + 10;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW){
backlight_timeout = backlight_timeout - 10;
refresh = HIGH;
delay(500);
}
}
}
//settings mode 5 - menu - change main timeout period (the long one)
if(settings_mode == 5){
if(digitalRead(up_button) == LOW){
Main_timeout ++;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW && Main_timeout > 1){
Main_timeout --;
refresh = HIGH;
delay(500);
}
}
//settings mode 6 - menu - change the default timeout behaviour
if(settings_mode == 6){
if(digitalRead(up_button) == LOW){
Default_to_prev_humidity = LOW;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW && Main_timeout > 1){
Default_to_prev_humidity = HIGH;
refresh = HIGH;
delay(500);
}
}
//settings mode 7 - menu - change the output relay inversion
if(settings_mode == 7){
if(digitalRead(up_button) == LOW){
relay_is_inverted = LOW;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW){
relay_is_inverted = HIGH;
refresh = HIGH;
delay(500);
}
}
//settings mode 8 - menu - overheat temp
if(settings_mode == 8){
if(digitalRead(up_button) == LOW){
max_motor_temp ++;
refresh = HIGH;
delay(500);
}
if(digitalRead(down_button) == LOW){
max_motor_temp --;
refresh = HIGH;
delay(500);
}
}
//settings mode 9 - menu - save to eeprom
if(settings_mode == 9){
if(digitalRead(up_button) == LOW){
for (int i = 0; i < 512; i++) {
EEPROM.write(i, 0);
}
EEPROM.commit();
delay(500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("EEPROM WIPED!");
EEPROM.put(10, max_temp);
EEPROM.commit();
delay(100);
EEPROM.put(20, temp_lag);
EEPROM.commit();
delay(100);
EEPROM.put(30, back_to_on_delay);
EEPROM.commit();
delay(100);
EEPROM.put(40, backlight_timeout);
EEPROM.commit();
delay(100);
EEPROM.put(50, Main_timeout);
EEPROM.commit();
delay(100);
EEPROM.put(60, Default_to_prev_humidity);
EEPROM.commit();
delay(100);
EEPROM.put(70, relay_is_inverted);
EEPROM.commit();
delay(100);
EEPROM.put(80, max_motor_temp);
EEPROM.commit();
delay(100);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("SAVED TO EEPROM!");
delay(2000);
mode = 0;
refresh = HIGH;
}
}
//LCD
if(refresh == HIGH){
lcd.clear();
refresh = LOW;
if(display_mode == 0){
lcd.setCursor(0,0);
lcd.print("OFF");
lcd.setCursor(0,1);
lcd.print(box_temp);
lcd.print((char)223);
lcd.print("C");
if(box_temp > max_temp){
lcd.print("!");
}
lcd.setCursor(8,1);
lcd.print(box_humidity);
lcd.print("%");
}
if(display_mode == 1){
lcd.setCursor(0,0);
lcd.print("STANDBY");
lcd.setCursor(0,1);
lcd.print(box_temp);
lcd.print((char)223);
lcd.print("C");
if(box_temp > max_temp){
lcd.print("!");
}
lcd.setCursor(8,1);
lcd.print(box_humidity);
lcd.print("%");
lcd.print((char)126);
lcd.print(target_humidity);
lcd.print("%");
}
if(display_mode == 2){
lcd.setCursor(0,0);
lcd.print("DRYING FILAMENT");
lcd.setCursor(0,1);
lcd.print(box_temp);
lcd.print((char)223);
lcd.print("C");
if(box_temp > max_temp){
lcd.print("!");
}
lcd.setCursor(8,1);
lcd.print(box_humidity);
lcd.print("%");
lcd.print((char)126);
lcd.print(target_humidity);
lcd.print("%");
}
}
}
LOWERS THE HUMIDITY TARGET BY 5%
SETS 30 MIN TIMER @ 0% HUMIDTY
(RESETS TO PREVIOUS HUMIDITY TARGET)
ON/OFF
AIR INLET DAMPENER
MAIN RELAY
2N2222 POWER TO SERVO