|
@@ -0,0 +1,699 @@
|
|
|
+
|
|
|
+
|
|
|
+#include <ESP8266WiFi.h> //ESP8266 Core WiFi Library (you most likely already have this in your sketch)
|
|
|
+#include <PubSubClient.h>
|
|
|
+
|
|
|
+#include <Wire.h>
|
|
|
+#include "LiquidCrystal_I2C.h"
|
|
|
+
|
|
|
+//#include <DNSServer.h> //Local DNS Server used for redirecting all requests to the configuration portal
|
|
|
+//#include <ESP8266WebServer.h> //Local WebServer used to serve the configuration portal
|
|
|
+//#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager WiFi Configuration Magic
|
|
|
+
|
|
|
+#include <AS_BH1750.h> // BH1750 lux sensor
|
|
|
+#include "DHT.h"
|
|
|
+
|
|
|
+#define DHTTYPE DHT22
|
|
|
+#define LCDADDR 0x27
|
|
|
+#define LUXSENSORADDR 0x23
|
|
|
+
|
|
|
+const int DHTPin = 13;
|
|
|
+const int RelaisPin = 16;
|
|
|
+const int PlusButtonPin = 0;
|
|
|
+const int MinusButtonPin = 2;
|
|
|
+const int ModeButtonPin = 14;
|
|
|
+const int PIRPin = 12;
|
|
|
+
|
|
|
+const bool RelaisOnState = LOW;
|
|
|
+const bool ButtonOnState = LOW;
|
|
|
+
|
|
|
+float setTemp;
|
|
|
+float setTempDay = 21.5;
|
|
|
+float setTempNight = 18.0;
|
|
|
+
|
|
|
+float setTempMin = 14.0;
|
|
|
+float setTempMax = 29.0;
|
|
|
+float setTempMinLow = 10.0;
|
|
|
+float setTempMaxLow = 19.0;
|
|
|
+float hysteresis = 0.5;
|
|
|
+
|
|
|
+long heatingLastOnMillis;
|
|
|
+long heatingLastOffMillis;
|
|
|
+long minOffTime = 10; // s
|
|
|
+//uint16_t lux;
|
|
|
+//int lux;
|
|
|
+//float lux;
|
|
|
+
|
|
|
+int measureinterval = 60000; // ms
|
|
|
+
|
|
|
+bool heatingEnabled = true;
|
|
|
+byte heatingMode = 1;
|
|
|
+///// 0 = off
|
|
|
+// 1 = default/day
|
|
|
+// 2 = night/reduction
|
|
|
+
|
|
|
+bool turnHeatingOn = false;
|
|
|
+
|
|
|
+float humidity, temperature;
|
|
|
+
|
|
|
+const char* ssid = "KS61T5SH"; // WiFi SSID
|
|
|
+const char* password = "Gurken651salat"; // WiFi PWD
|
|
|
+
|
|
|
+const char* mqtt_server = "10.1.1.11";
|
|
|
+const int mqtt_port = 1883;
|
|
|
+
|
|
|
+//const char* mqtt_topic_prefix = "Test/Thermostat/";
|
|
|
+const char* mqtt_topic_temp = "Test/Thermostat/Temp";
|
|
|
+const char* mqtt_topic_settemp = "Test/Thermostat/SetTemp";
|
|
|
+//const char* mqtt_topic_setmode = "Test/Thermostat/SetMode";
|
|
|
+const char* mqtt_topic_hum = "Test/Thermostat/Hum";
|
|
|
+const char* mqtt_topic_lux = "Test/Thermostat/Lux";
|
|
|
+const char* mqtt_topic_heating = "Test/Thermostat/Heating";
|
|
|
+const char* mqtt_topic_heating_lastofftime = "Test/Thermostat/HeatingLastOffTime";
|
|
|
+const char* mqtt_topic_heating_lastontime = "Test/Thermostat/HeatingLastOnTime";
|
|
|
+
|
|
|
+// subscribe topic
|
|
|
+const char* mqtt_topic_in = "Test/Thermostat/in";
|
|
|
+
|
|
|
+DHT dht(DHTPin, DHTTYPE);
|
|
|
+
|
|
|
+//AS_BH1750 lightMeter; // Lichtstärkemessung mit BH1750
|
|
|
+
|
|
|
+LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
|
|
|
+
|
|
|
+WiFiClient espClient;
|
|
|
+PubSubClient client(espClient);
|
|
|
+
|
|
|
+long lastMsg = 0;
|
|
|
+char msg[50];
|
|
|
+
|
|
|
+char topic[50];
|
|
|
+
|
|
|
+// LCD
|
|
|
+byte customCharSun[8] = {0b00100, 0b10001, 0b01110, 0b11111, 0b11111, 0b01110, 0b10001, 0b00100};
|
|
|
+byte customCharMoon[8] = {0b11000, 0b01110, 0b00110, 0b00111, 0b00111, 0b00110, 0b01110, 0b11000};
|
|
|
+byte customCharArrowRight[8] = {0b00000, 0b00100, 0b00110, 0b11111, 0b11111, 0b00110, 0b00100, 0b00000};
|
|
|
+bool displayActive = false;
|
|
|
+unsigned long displayLastOnMillis = 0;
|
|
|
+int displayTimeout = 10000;
|
|
|
+
|
|
|
+//bool lightMeter_present;
|
|
|
+
|
|
|
+void setup_wifi() {
|
|
|
+
|
|
|
+ delay(10);
|
|
|
+ // We start by connecting to a WiFi network
|
|
|
+ Serial.println();
|
|
|
+ Serial.print("Connecting to ");
|
|
|
+ Serial.println(ssid);
|
|
|
+
|
|
|
+ WiFi.begin(ssid, password);
|
|
|
+
|
|
|
+ while (WiFi.status() != WL_CONNECTED) {
|
|
|
+ delay(500);
|
|
|
+ Serial.print(".");
|
|
|
+ }
|
|
|
+
|
|
|
+ randomSeed(micros());
|
|
|
+
|
|
|
+ Serial.println("");
|
|
|
+ Serial.println("WiFi connected");
|
|
|
+ Serial.println("IP address: ");
|
|
|
+ Serial.println(WiFi.localIP());
|
|
|
+}
|
|
|
+
|
|
|
+void callback(char* topic, byte* payload, unsigned int length) {
|
|
|
+ Serial.print("Message arrived [");
|
|
|
+ Serial.print(topic);
|
|
|
+ Serial.print("] ");
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
+ Serial.print((char)payload[i]);
|
|
|
+ }
|
|
|
+ Serial.println();
|
|
|
+
|
|
|
+ if ((char)payload[0] == 's' && \
|
|
|
+ (char)payload[1] == 'e' && \
|
|
|
+ (char)payload[2] == 't' && \
|
|
|
+ (char)payload[3] == ' ' ) {
|
|
|
+ if ((char)payload[4] == 't' && \
|
|
|
+ (char)payload[5] == 'e' && \
|
|
|
+ (char)payload[6] == 'm' && \
|
|
|
+ (char)payload[7] == 'p' && \
|
|
|
+ (char)payload[8] == ' ' ) {
|
|
|
+ char inValue[length - 9 + 1];
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
+ inValue[i] = (char)payload[i + 9];
|
|
|
+ }
|
|
|
+ inValue[sizeof(inValue) - 1] = '\0';
|
|
|
+ Serial.print(inValue);
|
|
|
+ Serial.println();
|
|
|
+ float invalueFloat = round(atof(inValue) * 2.0) / 2.0;
|
|
|
+
|
|
|
+ Serial.print(invalueFloat);
|
|
|
+ if (invalueFloat >= setTempMin && invalueFloat <= setTempMax) {
|
|
|
+ setTempDay = invalueFloat;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ else if (invalueFloat > setTempMax) {
|
|
|
+ setTempDay = setTempMax;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ else if (invalueFloat < setTempMin) {
|
|
|
+ setTempDay = setTempMin;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ((char)payload[4] == 't' && \
|
|
|
+ (char)payload[5] == 'l' && \
|
|
|
+ (char)payload[6] == 'o' && \
|
|
|
+ (char)payload[7] == 'w' && \
|
|
|
+ (char)payload[8] == ' ' ) {
|
|
|
+ char inValue[length - 9 + 1];
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
+ inValue[i] = (char)payload[i + 9];
|
|
|
+ }
|
|
|
+ inValue[sizeof(inValue) - 1] = '\0';
|
|
|
+ Serial.print(inValue);
|
|
|
+ Serial.println();
|
|
|
+ float invalueFloat = round(atof(inValue) * 2.0) / 2.0;
|
|
|
+
|
|
|
+ Serial.print(invalueFloat);
|
|
|
+ if (invalueFloat >= setTempMinLow && invalueFloat <= setTempMaxLow) {
|
|
|
+ setTempNight = invalueFloat;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ else if (invalueFloat > setTempMaxLow) {
|
|
|
+ setTempNight = setTempMaxLow;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ else if (invalueFloat < setTempMinLow) {
|
|
|
+ setTempNight = setTempMinLow;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ((char)payload[4] == 'm' && \
|
|
|
+ (char)payload[5] == 'o' && \
|
|
|
+ (char)payload[6] == 'd' && \
|
|
|
+ (char)payload[7] == 'e' && \
|
|
|
+ (char)payload[8] == ' ' ) {
|
|
|
+ if ((char)payload[9] == '1') {
|
|
|
+ // switch to mode default/day
|
|
|
+ heatingMode = 1;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ else if ((char)payload[9] == '2') {
|
|
|
+ // switch to mode night/reduction
|
|
|
+ heatingMode = 2;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ else if ((char)payload[4] == 'e' && \
|
|
|
+ (char)payload[5] == 'n' && \
|
|
|
+ (char)payload[6] == 'a' && \
|
|
|
+ (char)payload[7] == 'b' && \
|
|
|
+ (char)payload[8] == ' ' ) {
|
|
|
+ if ((char)payload[9] == '0') {
|
|
|
+ // switch heating off
|
|
|
+ heatingEnabled = false;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ else if ((char)payload[9] == '1') {
|
|
|
+ // switch heating on
|
|
|
+ heatingEnabled = true;
|
|
|
+ lastMsg = 0; // reset var lastMsg to speed up lcd update
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void reconnect() {
|
|
|
+ // Loop until we're reconnected
|
|
|
+ while (!client.connected()) {
|
|
|
+ Serial.print("Attempting MQTT connection...");
|
|
|
+ // Create a random client ID
|
|
|
+ String clientId = "ESP8266Client-";
|
|
|
+ clientId += String(random(0xffff), HEX);
|
|
|
+ // Attempt to connect
|
|
|
+ if (client.connect(clientId.c_str())) {
|
|
|
+ Serial.println("connected");
|
|
|
+ // Once connected, publish an announcement...
|
|
|
+ //client.publish("TestoutTopic", "hello world");
|
|
|
+ // ... and resubscribe
|
|
|
+ client.subscribe(mqtt_topic_in);
|
|
|
+ } else {
|
|
|
+ Serial.print("failed, rc=");
|
|
|
+ Serial.print(client.state());
|
|
|
+ Serial.println(" try again in 5 seconds");
|
|
|
+ // Wait 5 seconds before retrying
|
|
|
+ delay(5000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void setup() {
|
|
|
+ //WiFiManager wifiManager;
|
|
|
+ //wifiManager.autoConnect("Thermostat", "configesp");
|
|
|
+ //wifiManager.setConfigPortalTimeout(180);
|
|
|
+ Serial.begin(115200);
|
|
|
+ delay(300);
|
|
|
+
|
|
|
+ pinMode(RelaisPin, OUTPUT);
|
|
|
+ digitalWrite(RelaisPin, HIGH);
|
|
|
+ pinMode(PlusButtonPin, INPUT_PULLUP);
|
|
|
+ pinMode(MinusButtonPin, INPUT_PULLUP);
|
|
|
+ pinMode(ModeButtonPin, INPUT_PULLUP);
|
|
|
+
|
|
|
+ // DHT11/22 Temp/Hum-Sensor initialisieren
|
|
|
+ dht.begin();
|
|
|
+
|
|
|
+ // // lightMeter BH1750
|
|
|
+ // //if (! lightMeter.begin(BH1750_CONTINUOUS_HIGH_RES_MODE_2)) {
|
|
|
+ // if (! lightMeter.begin(RESOLUTION_AUTO_HIGH)) {
|
|
|
+ // lightMeter_present = false;
|
|
|
+ // delay(50);
|
|
|
+ // Serial.println(F("ERROR: no BH1750 light meter found"));
|
|
|
+ // }
|
|
|
+ // else {
|
|
|
+ // lightMeter_present = true;
|
|
|
+ // delay(50);
|
|
|
+ // Serial.println(F("BH1750 light meter found"));
|
|
|
+ // }
|
|
|
+
|
|
|
+ setup_wifi();
|
|
|
+ client.setServer(mqtt_server, mqtt_port);
|
|
|
+ client.setCallback(callback);
|
|
|
+
|
|
|
+ lcd.init();
|
|
|
+ lcd.createChar(0, customCharMoon);
|
|
|
+ lcd.createChar(1, customCharSun);
|
|
|
+ lcd.createChar(2, customCharArrowRight);
|
|
|
+
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+
|
|
|
+ lcd.print("WiFi-Thermostat ");
|
|
|
+ lcd.setCursor(0, 1);
|
|
|
+ lcd.print(" by Flo Kra");
|
|
|
+
|
|
|
+ // for ( int i = 0; i < 3; i++) {
|
|
|
+ // lcd.backlight();
|
|
|
+ // delay(200);
|
|
|
+ // lcd.noBacklight();
|
|
|
+ // delay(200);
|
|
|
+ // }
|
|
|
+ lcd.backlight();
|
|
|
+ delay(1000);
|
|
|
+ lcd.clear();
|
|
|
+ displayActive = true;
|
|
|
+ displayLastOnMillis = millis();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool plusButtonCurrentState = HIGH;
|
|
|
+bool plusButtonLastState = HIGH;
|
|
|
+unsigned long plusButtonDownMillis = 0;
|
|
|
+unsigned long plusButtonRepeatMillis = 0;
|
|
|
+unsigned long plusButtonHoldTime = 0;
|
|
|
+bool plusButtonFired = false;
|
|
|
+
|
|
|
+bool minusButtonCurrentState = HIGH;
|
|
|
+bool minusButtonLastState = HIGH;
|
|
|
+unsigned long minusButtonDownMillis = 0;
|
|
|
+unsigned long minusButtonRepeatMillis = 0;
|
|
|
+unsigned long minusButtonHoldTime = 0;
|
|
|
+bool minusButtonFired = false;
|
|
|
+
|
|
|
+bool modeButtonCurrentState = HIGH;
|
|
|
+bool modeButtonLastState = HIGH;
|
|
|
+unsigned long modeButtonDownMillis = 0;
|
|
|
+unsigned long modeButtonHoldTime = 0;
|
|
|
+bool modeButtonFired = false;
|
|
|
+bool modeButtonHoldFired = false;
|
|
|
+
|
|
|
+void enableDisplay() {
|
|
|
+ lcd.backlight();
|
|
|
+ displayActive = true;
|
|
|
+ displayLastOnMillis = millis();
|
|
|
+}
|
|
|
+
|
|
|
+void disableDisplay() {
|
|
|
+ lcd.noBacklight();
|
|
|
+ displayActive = false;
|
|
|
+}
|
|
|
+
|
|
|
+void extendDisplayTimeout() {
|
|
|
+ displayLastOnMillis = millis();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void plusButtonAction() {
|
|
|
+ if(heatingMode == 1 && heatingEnabled) {
|
|
|
+ Serial.println("+");
|
|
|
+ if ( setTempDay <= (setTempMax - 0.5)) setTempDay += 0.5;
|
|
|
+ }
|
|
|
+ extendDisplayTimeout();
|
|
|
+ lastMsg = 0; // to enforce immediate display update
|
|
|
+}
|
|
|
+
|
|
|
+void minusButtonAction() {
|
|
|
+ if(heatingMode == 1 && heatingEnabled) {
|
|
|
+ Serial.println("-");
|
|
|
+ if ( setTempDay >= (setTempMin + 0.5)) setTempDay -= 0.5;
|
|
|
+ }
|
|
|
+ extendDisplayTimeout();
|
|
|
+ lastMsg = 0; // to enforce immediate display update
|
|
|
+}
|
|
|
+
|
|
|
+void modeButtonAction() {
|
|
|
+ extendDisplayTimeout();
|
|
|
+ if (heatingEnabled) {
|
|
|
+ Serial.print("switch mode to ");
|
|
|
+ if (heatingMode == 1) heatingMode = 2;
|
|
|
+ else if (heatingMode == 2) heatingMode = 1;
|
|
|
+ Serial.println(heatingMode);
|
|
|
+ //lastMsg = lastMsg + measureinterval; // force update
|
|
|
+ lastMsg = 0; // to enforce immediate display update
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void modeButtonHoldAction() {
|
|
|
+ Serial.println("switch off/on");
|
|
|
+ extendDisplayTimeout();
|
|
|
+ if (heatingEnabled) heatingEnabled = false;
|
|
|
+ else heatingEnabled = true;
|
|
|
+ //lastMsg = lastMsg + measureinterval; // force update
|
|
|
+ lastMsg = 0; // to enforce immediate display update
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void loop() {
|
|
|
+
|
|
|
+ if (!client.connected()) {
|
|
|
+ reconnect();
|
|
|
+ }
|
|
|
+ client.loop();
|
|
|
+
|
|
|
+
|
|
|
+ // Buttons einlesen
|
|
|
+
|
|
|
+ // plus button
|
|
|
+ plusButtonCurrentState = digitalRead(PlusButtonPin);
|
|
|
+ if (plusButtonCurrentState == LOW && plusButtonLastState == HIGH) { // button was unpressed and is now pressed
|
|
|
+ plusButtonDownMillis = millis();
|
|
|
+ plusButtonLastState = plusButtonCurrentState;
|
|
|
+ }
|
|
|
+ else if (plusButtonCurrentState == LOW && plusButtonLastState == LOW) { // button is held
|
|
|
+ plusButtonHoldTime = millis() - plusButtonDownMillis;
|
|
|
+ if ( plusButtonHoldTime > 50 ) {
|
|
|
+ plusButtonLastState = plusButtonCurrentState;
|
|
|
+ if (!displayActive && !plusButtonFired ) {
|
|
|
+ enableDisplay();
|
|
|
+ plusButtonFired = true;
|
|
|
+ }
|
|
|
+ // else if (displayActive && !plusButtonFired ) {
|
|
|
+ // plusButtonAction();
|
|
|
+ // plusButtonFired = true;
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ if ( plusButtonHoldTime > 1250 ) {
|
|
|
+ // button is held longer - repeating
|
|
|
+ if ( (millis() - plusButtonRepeatMillis) > 300 ) {
|
|
|
+ plusButtonAction();
|
|
|
+ plusButtonRepeatMillis = millis();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (plusButtonCurrentState == HIGH && plusButtonLastState == LOW) { // button is released again
|
|
|
+ plusButtonLastState = plusButtonCurrentState;
|
|
|
+
|
|
|
+ if (displayActive && !plusButtonFired) {
|
|
|
+ plusButtonAction();
|
|
|
+ }
|
|
|
+ plusButtonFired = false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // minus button
|
|
|
+ minusButtonCurrentState = digitalRead(MinusButtonPin);
|
|
|
+ if (minusButtonCurrentState == LOW && minusButtonLastState == HIGH) { // button was unpressed and is now pressed
|
|
|
+ minusButtonDownMillis = millis();
|
|
|
+ minusButtonLastState = minusButtonCurrentState;
|
|
|
+ }
|
|
|
+ else if (minusButtonCurrentState == LOW && minusButtonLastState == LOW) { // button is held
|
|
|
+ minusButtonHoldTime = millis() - minusButtonDownMillis;
|
|
|
+ if ( minusButtonHoldTime > 50 ) {
|
|
|
+ minusButtonLastState = minusButtonCurrentState;
|
|
|
+ if (!displayActive && !minusButtonFired ) {
|
|
|
+ enableDisplay();
|
|
|
+ minusButtonFired = true;
|
|
|
+ }
|
|
|
+ // else if (displayActive && !minusButtonFired ) {
|
|
|
+ // minusButtonAction();
|
|
|
+ // minusButtonFired = true;
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ if ( minusButtonHoldTime > 1250 ) {
|
|
|
+ // button is held longer - repeating
|
|
|
+ if ( (millis() - minusButtonRepeatMillis) > 300 ) {
|
|
|
+ minusButtonAction();
|
|
|
+ minusButtonRepeatMillis = millis();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (minusButtonCurrentState == HIGH && minusButtonLastState == LOW) { // button is released again
|
|
|
+ minusButtonLastState = minusButtonCurrentState;
|
|
|
+
|
|
|
+ if (displayActive && !minusButtonFired) {
|
|
|
+ minusButtonAction();
|
|
|
+ }
|
|
|
+ minusButtonFired = false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // mode button
|
|
|
+ modeButtonCurrentState = digitalRead(ModeButtonPin);
|
|
|
+ if (modeButtonCurrentState == LOW && modeButtonLastState == HIGH) { // button was unpressed and is now pressed
|
|
|
+ modeButtonDownMillis = millis();
|
|
|
+ modeButtonLastState = modeButtonCurrentState;
|
|
|
+ }
|
|
|
+ else if (modeButtonCurrentState == LOW && modeButtonLastState == LOW) { // button is held
|
|
|
+ modeButtonHoldTime = millis() - modeButtonDownMillis;
|
|
|
+ if ( modeButtonHoldTime > 50 ) {
|
|
|
+ modeButtonLastState = modeButtonCurrentState;
|
|
|
+ if (!displayActive && !modeButtonFired ) {
|
|
|
+ enableDisplay();
|
|
|
+ modeButtonFired = true;
|
|
|
+ }
|
|
|
+ // else if (displayActive && !modeButtonFired ) {
|
|
|
+ // modeButtonAction();
|
|
|
+ // modeButtonFired = true;
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ if ( modeButtonHoldTime > 2000 && !modeButtonHoldFired ) {
|
|
|
+ // button is held longer
|
|
|
+ modeButtonHoldFired = true;
|
|
|
+ modeButtonHoldAction();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (modeButtonCurrentState == HIGH && modeButtonLastState == LOW) { // button is released again
|
|
|
+ modeButtonLastState = modeButtonCurrentState;
|
|
|
+ if (displayActive && !modeButtonFired) {
|
|
|
+ modeButtonAction();
|
|
|
+ }
|
|
|
+ modeButtonFired = false;
|
|
|
+ modeButtonHoldFired = false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ unsigned long now = millis();
|
|
|
+
|
|
|
+ if (displayActive && (now - displayLastOnMillis) > displayTimeout) {
|
|
|
+ disableDisplay();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ( (now - lastMsg) > measureinterval) {
|
|
|
+ lastMsg = now;
|
|
|
+
|
|
|
+ humidity = dht.readHumidity();
|
|
|
+ temperature = dht.readTemperature(); // Read temperature as Celsius (the default)
|
|
|
+
|
|
|
+ unsigned long heatingOnTime, heatingOffTime;
|
|
|
+
|
|
|
+ if (heatingEnabled && turnHeatingOn) {
|
|
|
+ heatingOnTime = (now - heatingLastOffMillis) / 1000;
|
|
|
+ Serial.print("heatingOnTime: ");
|
|
|
+ Serial.print(heatingOnTime);
|
|
|
+ Serial.println();
|
|
|
+ }
|
|
|
+ else if (heatingEnabled && !turnHeatingOn) {
|
|
|
+ heatingOffTime = (now - heatingLastOnMillis) / 1000;
|
|
|
+ Serial.print("heatingOffTime: ");
|
|
|
+ Serial.print(heatingOffTime);
|
|
|
+ Serial.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( temperature >= setTemp ) {
|
|
|
+ turnHeatingOn = false;
|
|
|
+ heatingLastOnMillis = now;
|
|
|
+ digitalWrite(RelaisPin, !RelaisOnState);
|
|
|
+ Serial.println("heating off");
|
|
|
+
|
|
|
+ Serial.print("last onTime: ");
|
|
|
+ Serial.print(heatingOnTime);
|
|
|
+ Serial.println();
|
|
|
+
|
|
|
+ client.publish(mqtt_topic_heating, "off");
|
|
|
+
|
|
|
+ //client.publish(mqtt_topic_heating_lastontime, heatingOnTime);
|
|
|
+ }
|
|
|
+ else if ( heatingEnabled && ( temperature < (setTemp - hysteresis) ) && ( heatingOffTime > minOffTime ) ) {
|
|
|
+ turnHeatingOn = true;
|
|
|
+ digitalWrite(RelaisPin, RelaisOnState);
|
|
|
+ Serial.println("heating on");
|
|
|
+
|
|
|
+ Serial.print("last offTime: ");
|
|
|
+ Serial.print(heatingOffTime);
|
|
|
+ Serial.println();
|
|
|
+
|
|
|
+ client.publish(mqtt_topic_heating, "on");
|
|
|
+
|
|
|
+ //client.publish(mqtt_topic_heating_lastofftime, heatingOffTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ // set target temp for heating mode
|
|
|
+ if (heatingMode == 1) { // heating on - default/day mode
|
|
|
+ setTemp = setTempDay;
|
|
|
+ }
|
|
|
+ else if (heatingMode == 2) { // heating of - night/reduction mode
|
|
|
+ setTemp = setTempNight;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // if (lightMeter_present) {
|
|
|
+ // delay(50);
|
|
|
+ // lux = lightMeter.readLightLevel();
|
|
|
+ //
|
|
|
+ // String lux_str = String(lux, 1); //converting humidity (the float variable above) to a string with 0 decimals
|
|
|
+ // char lux_chararr[lux_str.length() + 1];
|
|
|
+ // lux_str.toCharArray(lux_chararr, lux_str.length() + 1); //packaging up the data to publish to mqtt whoa...
|
|
|
+ //
|
|
|
+ // Serial.print("Lux: ");
|
|
|
+ // Serial.println(lux_str);
|
|
|
+ // client.publish(mqtt_topic_lux, lux_chararr);
|
|
|
+ // }
|
|
|
+
|
|
|
+ String hum_str = String(humidity, 0); //converting humidity (the float variable above) to a string with 0 decimals
|
|
|
+ char hum_chararr[hum_str.length() + 1];
|
|
|
+ hum_str.toCharArray(hum_chararr, hum_str.length() + 1); //packaging up the data to publish to mqtt whoa...
|
|
|
+
|
|
|
+ String temp_str = String(temperature, 1); //converting Temperature (the float variable above) to a string with 1 decimal
|
|
|
+ char temp_chararr[temp_str.length() + 1];
|
|
|
+ temp_str.toCharArray(temp_chararr, temp_str.length() + 1); //packaging up the data to publish to mqtt whoa...
|
|
|
+
|
|
|
+ char setTemp_chararr[5]; //result string 4 positions + \0 at the end
|
|
|
+ // convert float to fprintf type string format 2 positions with 1 decimal place
|
|
|
+ dtostrf(setTemp, 2, 1, setTemp_chararr );
|
|
|
+
|
|
|
+ Serial.println("Publish messages temp/hum ");
|
|
|
+
|
|
|
+ client.publish(mqtt_topic_temp, temp_chararr);
|
|
|
+ client.publish(mqtt_topic_hum, hum_chararr);
|
|
|
+ client.publish(mqtt_topic_settemp, setTemp_chararr);
|
|
|
+
|
|
|
+
|
|
|
+ Serial.print("set temp: ");
|
|
|
+ Serial.println(setTemp_chararr);
|
|
|
+ Serial.print("current temp: ");
|
|
|
+ Serial.println(temp_str);
|
|
|
+
|
|
|
+ // print is-temperature incl = and ° symbol + humidity to lcd, line 1, first 11 chars
|
|
|
+ lcd.setCursor(0, 0);
|
|
|
+ lcd.write(0x3D); // = Zeichen
|
|
|
+ lcd.print(" ");
|
|
|
+ //if (temperature < -9) lcd.print(" ");
|
|
|
+ //else if (temperature < 0) lcd.print("");
|
|
|
+ //else if (temperature < 10) lcd.print(" ");
|
|
|
+ //else lcd.print(" ");
|
|
|
+ //lcd.print(tempstr2);
|
|
|
+ lcd.print(temp_str); // inside temperature should hopefully always be 2.1 chars, so no special formatting necessary
|
|
|
+ lcd.write(0xDF); // degree symbol
|
|
|
+ lcd.print(" ");
|
|
|
+
|
|
|
+ //lcd.print(humstr2);
|
|
|
+ lcd.print(hum_str); // always 2 chars
|
|
|
+ lcd.print("%");
|
|
|
+
|
|
|
+
|
|
|
+ // display current mode on LCD
|
|
|
+ lcd.setCursor(13, 0); // to char 15, line 1
|
|
|
+ if (heatingEnabled) {
|
|
|
+ if ( heatingMode == 1 ) { // day/normal mode
|
|
|
+ lcd.print(" ");
|
|
|
+ lcd.write((uint8_t)1); // sun symbol if mode is day/normal
|
|
|
+ lcd.print(" ");
|
|
|
+ }
|
|
|
+ else if ( heatingMode == 2 ) { // night/reduction mode
|
|
|
+ lcd.print(" ");
|
|
|
+ lcd.write((uint8_t)0); // moon symbol if mode is night/reduction
|
|
|
+ lcd.print(" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else lcd.print(" "); // mode is heating off
|
|
|
+
|
|
|
+
|
|
|
+ // display target temperature to line 2, 8 chars length incl space at the end
|
|
|
+ lcd.setCursor(0, 1);
|
|
|
+
|
|
|
+ // when the heating mode is OFF, do not display target temp - instead show "Heating off" info in line 2
|
|
|
+ if ( !heatingEnabled ) {
|
|
|
+ // 1234567890123456
|
|
|
+ lcd.print(" Heizung aus ");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ lcd.write((uint8_t)2); // Pfeil rechts
|
|
|
+ lcd.print(" ");
|
|
|
+ lcd.print(setTemp_chararr);
|
|
|
+ lcd.write(0xDF); // degree symbol
|
|
|
+ lcd.print(" ");
|
|
|
+
|
|
|
+ // display status info to line 2 from char 9 -> 8 chars length
|
|
|
+ lcd.setCursor(8, 1);
|
|
|
+ if (turnHeatingOn) {
|
|
|
+ // 12345678
|
|
|
+ lcd.print("heizen..");
|
|
|
+ }
|
|
|
+ else if ( heatingMode == 1 ) { // day/normal mode
|
|
|
+ // 12345678
|
|
|
+ lcd.print(" ");
|
|
|
+ }
|
|
|
+ else if ( heatingMode == 2 ) { // night/reduction mode
|
|
|
+ // 12345678
|
|
|
+ lcd.print("N-Absenk");
|
|
|
+ }
|
|
|
+ else lcd.print(" ");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // Check if any reads failed and exit early (to try again).
|
|
|
+ //if (isnan(hum) || isnan(temp)) {
|
|
|
+ // Serial.println("Failed to read from DHT sensor!");
|
|
|
+ // return;
|
|
|
+ //}
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|