#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#define DHTPIN 10
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#define menuButton 2
#define enter 4
#define ledStatus 8
#define alarmBuzzer 7
#define potTemp A0
#define relayCoil 3
LiquidCrystal_I2C lcd(0x27,20,4);
volatile long lastMillisTimer = 0;
volatile long lastMillisLcdOff = 0;
volatile long timerMillis = 0;
volatile bool isLcdOn = true;
volatile bool menuButtonState = HIGH;
volatile int menu = 1;
bool isPowerOn = true;
bool isTimerOn = false;
float temperature, humidity;
int spValue = 15;
int difValue = 2;
byte symbol_C[] = {
B00110,
B01001,
B01001,
B00110,
B00000,
B00000,
B00000,
B00000
};
byte symbol_drop[] = {
B00100,
B01010,
B10001,
B10001,
B10001,
B10001,
B01110,
B00000
};
void resetComponents(){
lcd.clear();
lcd.home();
noTone(alarmBuzzer);
tone(alarmBuzzer, 1500, 15);
}
void checkMenuButton(){
if(debounceButton(menuButtonState) == LOW && menuButtonState == HIGH){
menuButtonState = LOW;
if(!isLcdOn){
isLcdOn = true;
lastMillisLcdOff = millis() - 1000;
}else{
menu++;
if(menu > 4)
menu = 1;
}
}else if(debounceButton(menuButtonState) == HIGH && menuButtonState == LOW){
menuButtonState = HIGH;
}
}
volatile boolean debounceButton(boolean state){
boolean stateNow = digitalRead(menuButton);
if(state != stateNow){
delayMicroseconds(2000);
//delay(10);
stateNow = digitalRead(menuButton);
}
return stateNow;
}
void showTemp(){
long tm = 0;
resetComponents();
lcd.setCursor(8,0); lcd.print("ROOM");
lcd.setCursor(5,1); lcd.print("TEMPERATURE");
lastMillisLcdOff = millis();
while(menu == 1){
//checkMenuButton();
if(millis() - lastMillisLcdOff > 10000 && isLcdOn == true) {
lcd.noBacklight();
isLcdOn = false;
}
if(isLcdOn){
lcd.backlight();
}
long cm = millis();
if((cm - tm) > 5000 ){
tm = cm;
temperature = dht.readTemperature();
humidity = dht.readHumidity();
checkTemperature();
if (isnan(temperature)) {
Serial.println(F("Failed to read from DHT sensor!"));
lcd.clear();
lcd.setCursor(4,1); lcd.print("DHT22 sensor");
lcd.setCursor(7,2); lcd.print("failed");
tone(alarmBuzzer, 500, 15);
}else{
lcd.setCursor(7,2); lcd.print(" ");
lcd.setCursor(7,2); lcd.print(temperature,1);
lcd.write(0); lcd.print("C");
lcd.setCursor(8,3); lcd.print(" ");
lcd.setCursor(8,3); lcd.print(humidity,0);
lcd.print("%"); lcd.write(1);
}
}
}
}
void setPoint(){
resetComponents();
int potValue;
lcd.setCursor(6,1); lcd.print("SET POINT");
lcd.setCursor(9,2); lcd.print(spValue);
while(menu == 2){
//checkMenuButton();
potValue = analogRead(potTemp);
potValue = map(potValue,0,1023,15,35);
lcd.setCursor(9,2); lcd.print(potValue);
if(digitalRead(enter) == LOW){
lcd.setCursor(5,3); lcd.print("SELECTED OK");
tone(alarmBuzzer, 2500, 15);
spValue = potValue;
Serial.print("SetPoint setted at "); Serial.println(spValue);
isPowerOn = true;
delay(1000);
menu = 1;
}
}
}
void setDif(){
resetComponents();
int dv;
lcd.setCursor(4,1); lcd.print("DIFFERENTIAL");
while(menu == 3){
//checkMenuButton();
dv = analogRead(potTemp);
dv = map(dv,0,1023,1,8);
lcd.setCursor(9,2); lcd.print(dv);
if(digitalRead(enter) == LOW){
lcd.setCursor(5,3); lcd.print("SELECTED OK");
tone(alarmBuzzer, 2500, 15);
difValue = dv;
Serial.print("Differential SetPoint setted at "); Serial.println(difValue);
delay(1000);
menu = 1;
}
}
}
void setTimer(){
resetComponents();
int dv;
lcd.setCursor(4,0); lcd.print("TIMER SET UP");
lcd.setCursor(6,2); lcd.print("MINUTES");
while(menu == 4){
dv = analogRead(potTemp);
dv = map(dv,0,1023,1,120);
if(dv < 100){
lcd.setCursor(8,1); lcd.print(dv + String(" "));
}else{
lcd.setCursor(8,1); lcd.print(dv);
}
if(digitalRead(enter) == LOW){
lcd.setCursor(5,3); lcd.print("SELECTED OK");
tone(alarmBuzzer, 2500, 15);
timerMillis = (dv * 60000) + millis();
isPowerOn = true; isTimerOn = true;
delay(1000);
menu = 1;
}
}
}
void checkTemperature(){
if(temperature >= spValue){
digitalWrite(relayCoil, LOW);
digitalWrite(ledStatus, LOW);
}
if(temperature <= (spValue - difValue) && isPowerOn){
digitalWrite(relayCoil, HIGH);
digitalWrite(ledStatus, HIGH);
}else if(temperature <= (spValue - difValue) && !isPowerOn){
digitalWrite(relayCoil, LOW);
digitalWrite(ledStatus, LOW);
}
if(isTimerOn){
Serial.println("TIMER IS ACTIVE");
if(millis() > timerMillis) {
Serial.println("TIMER IS OFF");
isPowerOn = false;
isTimerOn = false;
}
}
}
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(alarmBuzzer, OUTPUT);
pinMode(menuButton, INPUT_PULLUP);
pinMode(enter,INPUT_PULLUP);
pinMode(potTemp, INPUT);
pinMode(relayCoil, OUTPUT);
pinMode(ledStatus, OUTPUT);
lcd.print("System Booted");
lcd.setCursor(0,1);
lcd.print("Thermostat Control");
lcd.setCursor(0,2);
lcd.print("Programmer");
lcd.setCursor(0,3);
lcd.print("Nick Andrikopoulos");
lcd.createChar(0, symbol_C);
lcd.createChar(1, symbol_drop);
dht.begin();
spValue = map(analogRead(potTemp),0,1023,15,35);
Serial.print("SET POINT SETTED AT START TO "); Serial.println(spValue);
delay(3000);
attachInterrupt(digitalPinToInterrupt(menuButton), checkMenuButton, FALLING);
}
void loop(){
switch (menu) {
case 1:
showTemp();
break;
case 2:
setPoint();
break;
case 3:
setDif();
break;
case 4:
setTimer();
break;
}
}