float tmpHum, tmpTemp; int DHTreadRetries = 2; //int DHTreadDelay = 20; void readDHTsensorTemp() { //delay(DHTreadDelay); tmpTemp = dht.readTemperature(); // Read temperature as Celsius (the default) } void readDHTsensorHum() { //delay(DHTreadDelay); tmpHum = dht.readHumidity(); } void measureTempHum() { for (int i = 0; i < DHTreadRetries; i++) { readDHTsensorTemp(); if (!isnan(tmpTemp)) { sendLog(F("DHT: reading Temp OK"), LOGLEVEL_VERBOSE); i = DHTreadRetries; } else { sendLog(F("DHT: reading Temp failed - retrying.."), LOGLEVEL_INFO); } } // for (int i = 0; i < DHTreadRetries; i++) { readDHTsensorHum(); if (!isnan(tmpHum)) { sendLog(F("DHT: reading Hum OK"), LOGLEVEL_VERBOSE); i = DHTreadRetries; } else { sendLog(F("DHT: reading Hum failed - retrying.."), LOGLEVEL_INFO); } } // Check if any reads failed if (isnan(tmpHum) || isnan(tmpTemp)) { //Serial.println("Failed to read from DHT sensor!"); sendLog(F("Error: Failed to read from DHT sensor!"), LOGLEVEL_ERROR); } else { tmpTemp = tmpTemp + confAdv.tempCorrVal; tmpHum = round(tmpHum) + confAdv.humCorrVal; int tmpHumInt = tmpHum; if (tmpTemp < 50.0 && tmpTemp > -20.0) { // measurement is in range currTemp_raw = tmpTemp; currHum_raw = tmpHumInt; if ( lastTempUpdate > 0 && tmpTemp <= ( currTemp + 2.0 ) && tmpTemp >= ( currTemp - 2.0 ) ) { // temp has already been measured - only accept new measurement if it does not differ much from the last value //Temp = (Temp * (FilterFaktor -1) + AktuellerMesswert) / FilterFaktor; //temperature = tmpTemp; currTemp = (currTemp * 9 + tmpTemp) / 10; // filter currHum = (currHum * 9 + tmpHumInt) / 10; // filter lastTempUpdate = millis(); } else if ( lastTempUpdate == 0 || (millis() - lastTempUpdate) > maxMeasurementAge ) { // this is the first measurement or the last one is older than 5m - then accept this measurement currTemp = tmpTemp + confAdv.tempCorrVal; currHum = tmpHumInt + confAdv.humCorrVal; lastTempUpdate = millis(); } // skip in all other cases //#ifdef DEBUG_VERBOSE // Serial.print("lastTempUpdate: "); // long lastTempUpdateDelta = millis() - lastTempUpdate; // Serial.print(lastTempUpdateDelta / 1000); // Serial.println("s ago"); //#endif } } } void updateCurrSetTemp() { // set target temp for heating mode if (heatingMode > 0) { // heating on if (preset == 0) { // normal/day preset currSetTemp = setTemp; currActualSetTemp = setTemp - confAdv.setTempDecreaseVal; } else if (preset == 1) { // night/reduction preset currSetTemp = setTempLow; currActualSetTemp = setTempLow - confAdv.setTempDecreaseVal; } else if (preset == 2) { // night/reduction 2 preset currSetTemp = setTempLow2; currActualSetTemp = setTempLow2 - confAdv.setTempDecreaseVal; } } else { // if heatingMode == 0 currSetTemp = DEFAULT_SETTEMP_HEATOFF; currActualSetTemp = currSetTemp; } } void thermostat() { updateCurrSetTemp(); //char tmp_topic_out[50]; if (heatingMode > 0 && turnHeatingOn) { heatingOnTime = (millis() - heatingLastOnMillis) / 1000; //char buf[101]; //sprintf(buf, "heating on for %lus", heatingOnTime); //sendLog(buf, LOGLEVEL_INFO); } else if (heatingMode > 0 && !turnHeatingOn) { if(heatingLastOnMillis > 0) { // prevent locking the heating after a reboot heatingOffTime = (millis() - heatingLastOffMillis) / 1000; } //char buf[101]; //sprintf(buf, "heating off for %lus", heatingOffTime); //sendLog(buf, LOGLEVEL_INFO); } //char tmp_topic_out[50]; //sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heating"); if ( lastTempUpdate != 0 && (millis() - lastTempUpdate) <= maxMeasurementAge ) { // thermostat - only active if measured temperature is < 2 min old #ifdef DEBUG_VERBOSE Serial.print("thermostat, lastTempUpdate="); Serial.print(lastTempUpdate); Serial.print(", lastTempUpdate_delta="); long lastTempUpdateDelta = millis() - lastTempUpdate; Serial.println(lastTempUpdateDelta); #endif // thermostat with hysteresis if ( turnHeatingOn && currTemp >= currActualSetTemp ) { turnHeatingOn = false; heatingLastOffMillis = millis(); heatingLockTime = confAdv.heatingMinOffTime; digitalWrite(PIN_RELAIS, !RELAISONSTATE); updateDisplay(); char buf[101]; sprintf_P(buf, "TSTAT: %s OFF, on for %lus", PGMStr_switchHeating, heatingOnTime); sendLog(buf, LOGLEVEL_INFO); //Serial.println("heating off"); //mqttclient.publish(tmp_topic_out, "off"); publishCurrentThermostatValues(); } else if ( !turnHeatingOn && heatingMode > 0 && heatingLockTime == 0 && heatingPause == 0 && ( currTemp < (currActualSetTemp - confAdv.hysteresis) ) ) { if ( heatingOffTime > confAdv.heatingMinOffTime || heatingLastOnMillis == 0) { turnHeatingOn = true; //heatingLockTimeActive = false; //heatingLockTime = 0; heatingLastOnMillis = millis(); digitalWrite(PIN_RELAIS, RELAISONSTATE); updateDisplay(); char buf[101]; sprintf(buf, "TSTAT: switch heating ON, off for %lus", heatingOffTime); sendLog(buf, LOGLEVEL_INFO); //Serial.println("heating on"); //mqttclient.publish(tmp_topic_out, "on"); publishCurrentThermostatValues(); } //else { // // heating should run BUT lock time is active // heatingLockTimeActive = true; // heatingLockTime = confAdv.heatingMinOffTime - heatingOffTime; // updateDisplay(); //} } else if (heatingPause > 0) { turnHeatingOn = false; heatingLastOffMillis = millis(); digitalWrite(PIN_RELAIS, !RELAISONSTATE); updateDisplay(); } } else { // turn off as no temp reading is available if (turnHeatingOn) { digitalWrite(PIN_RELAIS, !RELAISONSTATE); turnHeatingOn = false; heatingLastOffMillis = millis(); } if ( lastTempUpdate != 0 ) sendLog(F("TSTAT: heating OFF, temp reading not yet available"), LOGLEVEL_INFO); else if ( (millis() - lastTempUpdate) > maxMeasurementAge ) sendLog(F("TSTAT: heating OFF, last temp reading too old"), LOGLEVEL_WARN); //mqttclient.publish(tmp_topic_out, "off"); publishCurrentThermostatValues(); } } void toggleOnOff() { if (heatingMode > 0) { heatingMode = 0; heatingPause = 0; heatingLockTime = 0; lastValueChange = millis(); heatingModeAlreadySaved = false; } else { heatingMode = 1; heatingPause = 0; heatingLockTime = 0; lastValueChange = millis(); heatingModeAlreadySaved = false; } updateCurrentHeatingModeName(); updateDisplay(); } void togglePreset() { //sendLog(F("switch preset to ")); if (pendingPreset < 0 || pendingPreset > 2) pendingPreset = preset; // if (pendingPresetToggle && preset == 0 && pendingPreset == 0) pendingPreset = 1; // else if (pendingPresetToggle && preset == 1 && pendingPreset == 1) pendingPreset = 0; // else if (pendingPreset == 1 && pendingPresetToggle) pendingPreset = 2; // else if (pendingPreset == 2 && !pendingPresetToggle) pendingPreset = 0; // else if (pendingPreset == 2 && pendingPresetToggle) pendingPreset = 1; // pendingPreset 0 => Normal // pendingPreset 1 => Reduction 1 // pendingPreset 2 => Reduction 2 if(preset == 0) { // Normal > Reduction 1 > Reduction 2 if (pendingPreset == 0) pendingPreset = 1; else if (pendingPreset == 1) pendingPreset = 2; else if (pendingPreset == 2) pendingPreset = 0; } else if(preset == 1) { // Reduction 1 > Normal > Reduction 2 if (pendingPreset == 1) pendingPreset = 0; else if (pendingPreset == 0) pendingPreset = 2; else if (pendingPreset == 2) pendingPreset = 1; } else if(preset == 2) { // Reduction 2 > Normal > Reduction 1 if (pendingPreset == 2) pendingPreset = 0; else if (pendingPreset == 0) pendingPreset = 1; else if (pendingPreset == 1) pendingPreset = 2; } // if (preset == 0 && pendingPreset == 0) pendingPreset = 1; // else if (preset == 0 && pendingPreset == 1) pendingPreset = 2; // else if (preset == 1 && pendingPreset == 0) pendingPreset = 2; // else if (preset == 1 && pendingPreset == 1) pendingPreset = 0; // else if (preset == 1 && pendingPreset == 2) pendingPreset = 1; // else if (preset == 1 && pendingPreset == 0) pendingPreset = 1; // else if (preset == 2 && pendingPreset == 0) pendingPreset = 1; // else if (preset == 2 && pendingPreset == 1) pendingPreset = 0; // else if (preset == 2 && pendingPreset == 2) pendingPreset = 0; lastValueChange = millis(); presetAlreadySaved = false; updatePendingPresetName(); //updateDisplay(); //pendingPresetToggle = true; displayShowLine2OverlayMessage(pendingPresetName); //Serial.print(pendingPreset); //Serial.print(" - \""); //Serial.print(currentPresetName); //Serial.println("\""); } void updateCurrentHeatingModeName() { if (heatingMode == 0) strlcpy(currentModeName, confAdv.modeName0, 14); else if (heatingMode == 1) strlcpy(currentModeName, confAdv.modeName1, 14); } void updateCurrentPresetName() { if (preset == 0) strlcpy(currentPresetName, confAdv.psetName0, 14); else if (preset == 1) strlcpy(currentPresetName, confAdv.psetName1, 14); else if (preset == 2) strlcpy(currentPresetName, confAdv.psetName2, 14); } void updatePendingPresetName() { if (pendingPreset == 0) strlcpy(pendingPresetName, confAdv.psetName0, 14); else if (pendingPreset == 1) strlcpy(pendingPresetName, confAdv.psetName1, 14); else if (pendingPreset == 2) strlcpy(pendingPresetName, confAdv.psetName2, 14); } void setTempStepUp() { if (heatingMode == 1) { sendLog(F("TSTAT: setTemp +0.5")); if ( setTemp <= (confBas.setTempMax - 0.5)) { setTemp += 0.5; lastValueChange = millis(); setTempAlreadySaved = false; } updateDisplay(); } } void setTempStepDown() { if (heatingMode == 1) { sendLog(F("TSTAT: setTemp -0.5")); if ( setTemp >= (confBas.setTempMin + 0.5)) { setTemp -= 0.5; lastValueChange = millis(); setTempAlreadySaved = false; } updateDisplay(); } } void setTempTo(float setTo) { boolean changes = false; float tmpSetTemp; if(setTo != setTemp) { if (setTo >= confBas.setTempMin && setTo <= confBas.setTempMax) { tmpSetTemp = setTo; changes = true; } else if (setTo > confBas.setTempMax) { tmpSetTemp = confBas.setTempMax; changes = true; } else if (setTo < confBas.setTempMin) { tmpSetTemp = confBas.setTempMin; changes = true; } if (changes) { setTemp = tmpSetTemp; lastValueChange = millis(); setTempAlreadySaved = false; updateDisplay(); publishCurrentThermostatValues(); char buf1[30]; //sprintf(buf1, "setTemp changed to %2.1f", setTemp); sprintf_P(buf1, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTemp, PGMStr_changedTo, setTemp); //sendLog(F("setTemp changed")); sendLog(buf1); } } } void setTempLowStepUp() { sendLog(F("TSTAT: setTempLow +0.5")); if ( setTempLow <= (setTempLowMax - 0.5)) { setTempLow += 0.5; lastValueChange = millis(); setTempLowAlreadySaved = false; } updateDisplay(); } void setTempLowStepDown() { sendLog(F("TSTAT: setTempLow -0.5")); if ( setTempLow >= (setTempLowMin + 0.5)) { setTempLow -= 0.5; lastValueChange = millis(); setTempLowAlreadySaved = false; } updateDisplay(); } void setTempLowTo(float setTo) { boolean changes = false; float tmp_setTempLow; if(setTo != setTempLow) { if (setTo >= setTempLowMin && setTo <= setTempLowMax) { tmp_setTempLow = setTo; changes = true; } else if (setTo > setTempLowMax) { tmp_setTempLow = setTempLowMax; changes = true; } else if (setTo < setTempLowMin) { tmp_setTempLow = setTempLowMin; changes = true; } if (changes) { setTempLow = tmp_setTempLow; lastValueChange = millis(); setTempLowAlreadySaved = false; updateDisplay(); publishCurrentThermostatValues(); //Serial.println("setTempLow CHANGED"); char buf1[30]; //sprintf(buf1, "setTempLow changed to %2.1f", setTempLow); sprintf_P(buf1, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTempLow, PGMStr_changedTo, setTempLow); sendLog(buf1); } } } void setTempLow2StepUp() { sendLog(F("TSTAT: setTempLow2 +0.5")); if ( setTempLow2 <= (setTempLowMax - 0.5)) { setTempLow2 += 0.5; lastValueChange = millis(); setTempLow2AlreadySaved = false; } updateDisplay(); } void setTempLow2StepDown() { sendLog(F("TSTAT: setTempLow2 -0.5")); if ( setTempLow2 >= (setTempLowMin + 0.5)) { setTempLow2 -= 0.5; lastValueChange = millis(); setTempLow2AlreadySaved = false; } updateDisplay(); } void setTempLow2To(float setTo) { boolean changes = false; float tmp_setTempLow2; if(setTo != setTempLow2) { if (setTo >= setTempLowMin && setTo <= setTempLowMax) { tmp_setTempLow2 = setTo; changes = true; } else if (setTo > setTempLowMax) { tmp_setTempLow2 = setTempLowMax; changes = true; } else if (setTo < setTempLowMin) { tmp_setTempLow2 = setTempLowMin; changes = true; } if (changes) { setTempLow2 = tmp_setTempLow2; lastValueChange = millis(); setTempLow2AlreadySaved = false; updateDisplay(); publishCurrentThermostatValues(); //Serial.println("setTempLow2 CHANGED"); char buf1[30]; //sprintf(buf1, "setTempLow2 changed to %2.1f", setTempLow2); sprintf_P(buf1, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTempLow2, PGMStr_changedTo, setTempLow2); sendLog(buf1); } } } void setHeatingmodeTo(unsigned char setTo) { if(setTo != heatingMode) { heatingMode = setTo; heatingPause = 0; heatingLockTime = 0; updateCurrSetTemp(); lastValueChange = millis(); heatingModeAlreadySaved = false; updateCurrentHeatingModeName(); updateDisplay(); publishCurrentThermostatValues(); //Serial.println("heatingMode CHANGED"); char buf1[30]; //sprintf(buf1, "heatingMode changed to %u", heatingMode); sprintf_P(buf1, "%s: %s %s %u", PGMStr_thermostat, PGMStr_heatingMode, PGMStr_changedTo, heatingMode); sendLog(buf1); } } void setHeatingPause(uint8_t _setTo) { bool _change = false; char _buf1[30]; if(_setTo == 0) { heatingPause = 0; _change = true; sprintf_P(_buf1, "%s: %s %s", PGMStr_thermostat, PGMStr_heatingPause, PGMStr_disabled); } else if (_setTo == 1 && heatingPause == 0) { heatingPause = confAdv.pauseTout; _change = true; sprintf_P(_buf1, "%s: %s %s", PGMStr_thermostat, PGMStr_heatingPause, PGMStr_enabled); } if(_change) { lastValueChange = millis(); thermostat(); updateDisplay(); publishCurrentThermostatValues(); sendLog(_buf1); } } void setPresetTo(unsigned char setTo) { if(setTo != preset) { if(setTo >= 0 && setTo <=2) { preset = setTo; pendingPreset = setTo; updateCurrSetTemp(); lastValueChange = millis(); presetAlreadySaved = false; updateCurrentPresetName(); updateDisplay(); publishCurrentThermostatValues(); //Serial.println("preset CHANGED"); char buf1[30]; sprintf_P(buf1, "%s: %s %s %u", PGMStr_thermostat, PGMStr_preset, PGMStr_changedTo, preset); sendLog(buf1); } } } void checkValuesChanged() { // called every second by everySecond() / scheduler.ino if ( !setTempAlreadySaved || !heatingModeAlreadySaved || !presetAlreadySaved || !setTempLowAlreadySaved || !setTempLow2AlreadySaved ) { if ( (millis() - lastValueChange) > saveValuesTimeout ) { // value was changed 5s ago. now save if auto-save enabled if (!setTempAlreadySaved) { lastUpdate_setTemp = millis(); if (confBas.autoSaveSetTemp && setTemp != setTempSaved) { saveSetTemp(); sendLog(F("TSTAT: setTemp autosave done")); } setTempAlreadySaved = true; } if (!setTempLowAlreadySaved) { lastUpdate_setTempLow = millis(); if (confBas.autoSaveSetTemp && setTempLow != setTempLowSaved) { saveSetTempLow(); sendLog(F("TSTAT: setTempLow autosave done")); } setTempLowAlreadySaved = true; } if (!setTempLow2AlreadySaved) { lastUpdate_setTempLow2 = millis(); if (confBas.autoSaveSetTemp && setTempLow2 != setTempLow2Saved) { saveSetTempLow2(); sendLog(F("TSTAT: setTempLow2 autosave done")); } setTempLow2AlreadySaved = true; } if (!heatingModeAlreadySaved) { lastUpdate_heatingMode = millis(); if (confBas.autoSaveHeatingMode && heatingMode != heatingModeSaved) { saveHeatingMode(); sendLog(F("TSTAT: heatingMode autosave done")); } heatingModeAlreadySaved = true; } if (!presetAlreadySaved) { lastUpdate_preset = millis(); preset = pendingPreset; if (confBas.autoSaveHeatingMode && preset != presetSaved) { savePreset(); sendLog(F("TSTAT: preset autosave done")); } presetAlreadySaved = true; } publishCurrentThermostatValues(); } } }