|
|
|
// load library for display
|
|
|
|
#include <LiquidCrystal.h>
|
|
|
|
// load library for DHT22 sensor
|
|
|
|
#include <DHT22.h>
|
|
|
|
|
|
|
|
#define TRESHOLD 1
|
|
|
|
#define HYSTERESIS 1
|
|
|
|
#define MIN_OUT_TEMP 5 // °C
|
|
|
|
#define ALLOWED_HUMIDITY 50 // %
|
|
|
|
|
|
|
|
#define RELAY_PIN 5
|
|
|
|
|
|
|
|
#define DHT22_OUTSIDE_PIN 6
|
|
|
|
#define DHT22_INSIDE_PIN 7
|
|
|
|
|
|
|
|
#define LCD_D7_PIN 8
|
|
|
|
#define LCD_D6_PIN 9
|
|
|
|
#define LCD_D5_PIN 10
|
|
|
|
#define LCD_D4_PIN 11
|
|
|
|
#define LCD_EN_PIN 12
|
|
|
|
#define LCD_RS_PIN 13
|
|
|
|
|
|
|
|
|
|
|
|
// create objects for sensor communication
|
|
|
|
DHT22 dht22inside(DHT22_INSIDE_PIN);
|
|
|
|
DHT22 dht22outside(DHT22_OUTSIDE_PIN);
|
|
|
|
|
|
|
|
// create object for LCD communication
|
|
|
|
LiquidCrystal lcd(LCD_RS_PIN, LCD_EN_PIN, LCD_D4_PIN, LCD_D5_PIN, LCD_D6_PIN, LCD_D7_PIN);
|
|
|
|
|
|
|
|
// these variables are used to capture error states of the sensors:
|
|
|
|
int inside_state = 0;
|
|
|
|
int outside_state = 0;
|
|
|
|
|
|
|
|
// these variables hold measures from the sensors
|
|
|
|
float inside_temp = 0, outside_temp = 0, inside_humi = 0, outside_humi = 0;
|
|
|
|
|
|
|
|
// these arrays are used to create some special characters for the LCD
|
|
|
|
byte degree[8] = {
|
|
|
|
0b00010,
|
|
|
|
0b00101,
|
|
|
|
0b00010,
|
|
|
|
0b00000,
|
|
|
|
0b00000,
|
|
|
|
0b00000,
|
|
|
|
0b00000,
|
|
|
|
0b00000
|
|
|
|
};
|
|
|
|
|
|
|
|
byte tau[8] = {
|
|
|
|
0b00000,
|
|
|
|
0b00000,
|
|
|
|
0b11110,
|
|
|
|
0b01000,
|
|
|
|
0b01000,
|
|
|
|
0b01001,
|
|
|
|
0b00110,
|
|
|
|
0b00000
|
|
|
|
};
|
|
|
|
|
|
|
|
byte on[8] = {
|
|
|
|
0b11111,
|
|
|
|
0b10001,
|
|
|
|
0b11111,
|
|
|
|
0b11111,
|
|
|
|
0b11111,
|
|
|
|
0b11111,
|
|
|
|
0b10001,
|
|
|
|
0b11111
|
|
|
|
};
|
|
|
|
|
|
|
|
byte off[8] = {
|
|
|
|
0b11111,
|
|
|
|
0b10001,
|
|
|
|
0b10001,
|
|
|
|
0b10001,
|
|
|
|
0b10001,
|
|
|
|
0b10001,
|
|
|
|
0b10001,
|
|
|
|
0b11111
|
|
|
|
};
|
|
|
|
|
|
|
|
void table(){
|
|
|
|
// prepare "table" on LCD
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
lcd.print(" IN OUT");
|
|
|
|
|
|
|
|
lcd.setCursor(0,1);
|
|
|
|
lcd.print("Temp . . ");
|
|
|
|
lcd.write((int)0);
|
|
|
|
lcd.print("C");
|
|
|
|
|
|
|
|
lcd.setCursor(0,2);
|
|
|
|
lcd.print("Humi . . %");
|
|
|
|
|
|
|
|
lcd.setCursor(0,3);
|
|
|
|
lcd.print(" ");
|
|
|
|
lcd.write((int)1);
|
|
|
|
lcd.print(" . . ");
|
|
|
|
lcd.write((int)0);
|
|
|
|
lcd.print("C");
|
|
|
|
}
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
// set up the LCD
|
|
|
|
lcd.begin(16, 4);
|
|
|
|
lcd.createChar(0, degree);
|
|
|
|
lcd.createChar(1, tau);
|
|
|
|
lcd.createChar(2, on);
|
|
|
|
lcd.createChar(3, off);
|
|
|
|
|
|
|
|
table();
|
|
|
|
|
|
|
|
// set up the relay
|
|
|
|
pinMode(RELAY_PIN,OUTPUT);
|
|
|
|
|
|
|
|
// TODO: is this needed any longer?
|
|
|
|
pinMode(4,OUTPUT);
|
|
|
|
digitalWrite(4,LOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
void printVal(float v){
|
|
|
|
if (v<10) lcd.print(" ");
|
|
|
|
lcd.print(v,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void relayOff(){
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
lcd.print("OFF");
|
|
|
|
digitalWrite(RELAY_PIN,LOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
void relayOn(){
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
lcd.print("ON ");
|
|
|
|
digitalWrite(RELAY_PIN,HIGH);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fehler(int col, int code){
|
|
|
|
lcd.setCursor(col,1);
|
|
|
|
lcd.print("Err ");
|
|
|
|
lcd.setCursor(col,2);
|
|
|
|
lcd.print(" ");
|
|
|
|
lcd.print(code);
|
|
|
|
lcd.print(" ");
|
|
|
|
lcd.setCursor(col,3);
|
|
|
|
lcd.print("--- ");
|
|
|
|
relayOff();
|
|
|
|
}
|
|
|
|
|
|
|
|
float taupunkt(float t, float r) {
|
|
|
|
float a, b;
|
|
|
|
|
|
|
|
if (t >= 0) {
|
|
|
|
a = 7.5;
|
|
|
|
b = 237.3;
|
|
|
|
} else {
|
|
|
|
a = 7.6;
|
|
|
|
b = 240.7;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sättigungsdampfdruck in hPa
|
|
|
|
float sdd = 6.1078 * pow(10, (a*t)/(b+t));
|
|
|
|
|
|
|
|
// Dampfdruck in hPa
|
|
|
|
float dd = sdd * (r/100);
|
|
|
|
|
|
|
|
// v-Parameter
|
|
|
|
float v = log10(dd/6.1078);
|
|
|
|
|
|
|
|
// Taupunkttemperatur (°C)
|
|
|
|
return (b*v) / (a-v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void loop() {
|
|
|
|
delay(2500); // dht 22 sensor may only be read every two seconds
|
|
|
|
inside_temp = dht22inside.getTemperature();
|
|
|
|
inside_humi = dht22inside.getHumidity();
|
|
|
|
inside_state = dht22inside.getLastError();
|
|
|
|
outside_temp = dht22outside.getTemperature();
|
|
|
|
outside_humi = dht22outside.getHumidity();
|
|
|
|
outside_state = dht22outside.getLastError();
|
|
|
|
int secs = millis()/1000;
|
|
|
|
if (secs % 3600 < 3) table();
|
|
|
|
|
|
|
|
boolean inside_error = false, outside_error = false;
|
|
|
|
|
|
|
|
if (inside_state != dht22inside.OK || isnan(inside_temp)||isnan(inside_humi)) {
|
|
|
|
fehler(5,inside_state);
|
|
|
|
inside_error = true;
|
|
|
|
} else {
|
|
|
|
if (inside_temp<-40 || inside_temp>80){
|
|
|
|
lcd.setCursor(5,1);
|
|
|
|
lcd.print("OOR!"); // out of range!
|
|
|
|
inside_error = true;
|
|
|
|
} else {
|
|
|
|
lcd.setCursor(5,1);
|
|
|
|
printVal(inside_temp);
|
|
|
|
}
|
|
|
|
if (inside_humi<0 || inside_humi>100){
|
|
|
|
lcd.setCursor(5,2);
|
|
|
|
lcd.print("OOR!"); // out of range
|
|
|
|
inside_error = true;
|
|
|
|
} else {
|
|
|
|
lcd.setCursor(5,2);
|
|
|
|
printVal(inside_humi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outside_state != dht22outside.OK) {
|
|
|
|
fehler(10,outside_state);
|
|
|
|
outside_error = true;
|
|
|
|
} else {
|
|
|
|
if (outside_temp<-40 || outside_temp>80){
|
|
|
|
lcd.setCursor(10,1);
|
|
|
|
lcd.print("OOR!"); // out of range!
|
|
|
|
outside_error = true;
|
|
|
|
} else {
|
|
|
|
lcd.setCursor(10,1);
|
|
|
|
printVal(outside_temp);
|
|
|
|
}
|
|
|
|
if (outside_humi<0 || outside_humi>100){
|
|
|
|
lcd.setCursor(10,2);
|
|
|
|
lcd.print("ORR!"); // out of range!
|
|
|
|
outside_error = true;
|
|
|
|
} else {
|
|
|
|
lcd.setCursor(10,2);
|
|
|
|
printVal(outside_humi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lcd.setCursor(5,3);
|
|
|
|
float tau_outside, tau_inside;
|
|
|
|
if (inside_error){
|
|
|
|
lcd.print("----");
|
|
|
|
} else {
|
|
|
|
tau_inside = taupunkt(inside_temp,inside_humi);
|
|
|
|
printVal(tau_inside);
|
|
|
|
}
|
|
|
|
|
|
|
|
lcd.setCursor(10,3);
|
|
|
|
if (outside_error){
|
|
|
|
lcd.print("----");
|
|
|
|
} else {
|
|
|
|
tau_outside = taupunkt(outside_temp,outside_humi);
|
|
|
|
printVal(tau_outside);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inside_error || outside_error || outside_temp < MIN_OUT_TEMP){
|
|
|
|
relayOff();
|
|
|
|
} else {
|
|
|
|
if (inside_humi > ALLOWED_HUMIDITY && tau_inside > tau_outside + TRESHOLD + HYSTERESIS) {
|
|
|
|
relayOn();
|
|
|
|
}
|
|
|
|
if (tau_inside < tau_outside + TRESHOLD) {
|
|
|
|
relayOff();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|