// LCD unsigned char customCharSun[] = {B00100, B10001, B01110, B11111, B11111, B01110, B10001, B00100}; //unsigned char customCharMoon[] = {B11000, B01110, B00110, B00111, B00111, B00110, B01110, B11000}; unsigned char customCharMoon[] = {B00011, B01110, B01100, B11100, B11100, B01100, B01110, B00011}; unsigned char customCharArrowRight[] = {B01000, B01100, B01110, B01111, B01110, B01100, B01000, B00000}; unsigned char customCharDegC[] = {B01000, B10100, B01000, B00011, B00100, B00100, B00011, B00000}; unsigned char customCharConn[] = {B00000, B00000, B11100, B00010, B11001, B00101, B10101, B00000}; unsigned char customCharDisconn[] = {B10001, B01010, B00100, B01010, B10001, B00000, B10000, B00000}; unsigned char customCharReduction2[] = {B00000, B11111, B01110, B00100, B00000, B11111, B01110, B00100}; //(2 arrows down) unsigned char customCharFlame[] = {B00100, B00100, B01010, B01010, B10101, B10101, B10101, B01110}; unsigned char customCharLock[] = {B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000}; unsigned char customCharPause[] = {B11011, B11011, B11011, B11011, B11011, B11011, B11011, B11011}; // boolean displayActive = false; unsigned long displayLastOnMillis = 0; void enableDisplay() { lcd.backlight(); displayActive = true; displayLastOnMillis = millis(); } void disableDisplay() { lcd.noBacklight(); displayActive = false; } void extendDisplayTimeout() { displayLastOnMillis = millis(); } void handleDisplayTimeout() { if (displayActive && (millis() - displayLastOnMillis) > (confBas.displayTimeout * 1000)) { disableDisplay(); } } void initDisplay() { lcd.init(); lcd.createChar(0, customCharMoon); lcd.createChar(1, customCharSun); lcd.createChar(2, customCharArrowRight); // replaced by > char lcd.createChar(3, customCharDegC); lcd.createChar(4, customCharConn); lcd.createChar(5, customCharDisconn); lcd.createChar(6, customCharReduction2); lcd.createChar(7, customCharFlame); //lcd.createChar(7, customCharLock); // only 8 custom chars are possible :-/ lcd.setCursor(0, 0); lcd.print("WiFiThermostat "); lcd.setCursor(0, 1); lcd.print("(c) by FloKra.at"); // 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(); } void displayShowWifiConnected() { lcd.setCursor(0, 0); lcd.print("WiFi connected "); lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(WiFi.localIP()); lcd.backlight(); displayActive = true; displayLastOnMillis = millis(); delay(2000); } void displayShowWifiConnectionError() { lcd.setCursor(0, 0); lcd.print("WiFi connecting "); lcd.setCursor(0, 1); lcd.print("FAILED "); lcd.backlight(); displayActive = true; displayLastOnMillis = millis(); delay(2000); lcd.setCursor(0, 0); lcd.print("AP mode active "); lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(persWM.getApSsid()); lcd.backlight(); displayActive = true; displayLastOnMillis = millis(); delay(2000); lcd.setCursor(0, 0); lcd.print("Password: "); lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(confDevWiFi.WiFiAPModePassword); lcd.backlight(); displayActive = true; displayLastOnMillis = millis(); delay(2000); } void displayShowMQTTConnected() { lcd.setCursor(0, 0); lcd.print("MQTT conn. to: "); lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(confMqtt.mqtt_server); lcd.backlight(); displayActive = true; displayLastOnMillis = millis(); displayShowFullscreenMsg = true; countDisplayInterval = 0; displayInterval = displayOverlayMsgTimeout; } void displayShowMQTTConnectionError() { lcd.setCursor(0, 0); lcd.print("MQTT connection "); lcd.setCursor(0, 1); lcd.print("FAILED "); lcd.backlight(); displayActive = true; displayLastOnMillis = millis(); displayShowFullscreenMsg = true; countDisplayInterval = 0; displayInterval = displayOverlayMsgTimeout; } void displayShowLine2OverlayMessage(char *msg) { lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.write((uint8_t)2); // arrow right symbol lcd.print(" "); lcd.print(msg); for (int i = strlen(msg); i < 14; i++) { lcd.print(" "); } displayShowLine2OverlayMsg = true; countDisplayInterval = 0; displayInterval = displayOverlayMsgTimeout; } void displayAddConnectionIcon() { lcd.setCursor(14, 1); lcd.print(" "); if (mqttConnected) lcd.write((uint8_t)4); // connected symbol else lcd.write((uint8_t)5); // disconnected symbol } void updateDisplay() { if (displayShowFullscreenMsg) { displayShowFullscreenMsg = false; displayInterval = confBas.displayInterval; updateDisplayImmediately = true; } else { boolean showTemp = false; char ch_temp[6]; long now = millis(); if (confBas.togglingTempHumAIDisplay) { char ch_hum[4]; char tempLabel[2]; if (((now - outTempHumLastUpdate) < maxMeasurementAgeOut) && outTempHumLastUpdate != 0 && whichTempToDisplay == 1 && ((now - lastDisplayToggle) > (displayInterval * 1000))) { // outside temp has been updated < 5 min ago, last displayed temp was INSIDE and display interval is overdue whichTempToDisplay = 2; // 1= I, 2= O lastDisplayToggle = now; } else if (whichTempToDisplay != 1 && ((now - lastDisplayToggle) > (displayInterval * 1000))) { whichTempToDisplay = 1; // 1= I, 2= O lastDisplayToggle = now; } lastDisplayUpdate = now; if (whichTempToDisplay == 2) { // 2 = outside temp/hum received via MQTT if (outTempHumLastUpdate != 0 && (now - outTempHumLastUpdate) < maxMeasurementAgeOut) { showTemp = true; dtostrf(outTemp, 5, 1, ch_temp); sprintf(ch_hum, "%2i", outHum); strcpy(tempLabel, confAdv.oTempLabel); } } else { if (lastTempUpdate != 0 && (now - lastTempUpdate) < maxMeasurementAge) { showTemp = true; dtostrf(currTemp, 5, 1, ch_temp); sprintf(ch_hum, "%2i", currHum); strcpy(tempLabel, confAdv.iTempLabel); } } // 12345667890123456 // =20.0° 35% >22.5° // A -10.2° 95% N // A 22.2° 95% N // A 5.2° 95% N // LCD line 1 // print temperature incl = and ° symbol + humidity to lcd, line 1, first 11 chars lcd.setCursor(0, 0); if (showTemp) { // lcd.write(0x3D); // = Zeichen lcd.print(tempLabel); lcd.print(ch_temp); // lcd.write(0xDF); // degree symbol lcd.write((uint8_t)3); // °C symbol lcd.print(" "); if (currHum == 0) lcd.print("--"); else if (currHum < 10) { lcd.print(" "); lcd.print(ch_hum); } else { lcd.print(ch_hum); } lcd.print("%"); lcd.print(" "); } else { lcd.print(" "); } } else { // non toggling temperature I + A display without humidity in line 1 lcd.setCursor(0, 0); lcd.print(confAdv.iTempLabel); if (lastTempUpdate != 0 && (now - lastTempUpdate) < maxMeasurementAge) { dtostrf(currTemp, 5, 1, ch_temp); lcd.print(ch_temp); } else { lcd.print(" --.-"); } lcd.write((uint8_t)3); // °C symbol lcd.print(" "); if (outTempHumLastUpdate != 0 && (now - outTempHumLastUpdate) < maxMeasurementAgeOut) { lcd.print(" "); lcd.print(confAdv.oTempLabel); dtostrf(outTemp, 5, 1, ch_temp); lcd.print(ch_temp); lcd.write((uint8_t)3); // °C symbol } else { lcd.print(" "); } } updateCurrSetTemp(); char ch_currSetTemp[6]; dtostrf(currSetTemp, 5, 1, ch_currSetTemp); // LCD line 2 // display target temperature to line 2, 8 chars length incl space at the end lcd.setCursor(0, 1); if (doRestart) { lcd.print("Restarting... "); } else if (pendingRestart) { lcd.print("Restart? "); } else if (heatingMode == 0) { // when the heating mode is OFF, do not display target temp - instead show "Heating off" info in line 2 // 1234567890123456 lcd.print(" "); lcd.setCursor(0, 1); lcd.print(confAdv.offMessage); // for(int i=strlen(offMessage); i < 14; i++) { // lcd.print(" "); //} displayAddConnectionIcon(); } //else if (heatingPause > 0) //{ // when heating pause mode is active, do not display target temp - instead show "PAUSE" info in line 2 // // 1234567890123456 // lcd.print(" "); // lcd.setCursor(0, 1); // //lcd.print(confAdv.pauseMessage); // lcd.print("PAUSE 0:"); // // unsigned int _pauseMin = heatingPause / 60; // if(_pauseMin < 10) lcd.print("0"); // lcd.print(_pauseMin); // // displayAddConnectionIcon(); //} else if (displayShowLine2OverlayMsg) { displayShowLine2OverlayMsg = false; displayInterval = confBas.displayInterval; if (pendingPresetToggle) { preset = pendingPreset; updateCurrentPresetName(); pendingPresetToggle = false; } updateDisplayImmediately = true; } else { lcd.write((uint8_t)2); // arrow right symbol //lcd.print(">"); // lcd.print(" "); lcd.print(ch_currSetTemp); // lcd.write(0xDF); // degree symbol lcd.write((uint8_t)3); // °C symbol lcd.print(" "); lcd.setCursor(8, 1); lcd.print(" "); // display status info to line 2 from char 9 -> 8 chars length lcd.setCursor(9, 1); if (preset == 0) { // day/normal mode lcd.write((uint8_t)1); // sun symbol if mode is day/normal } else if (preset == 1) { // night/reduction mode lcd.write((uint8_t)0); // moon symbol if mode is night/reduction } else if (preset == 2) { // night/reduction mode lcd.write((uint8_t)6); // reduction 2 (2 arrows down) symbol if mode is reduction 2 } if (heatingPause > 0) { lcd.createChar(7, customCharPause); lcd.setCursor(12, 1); lcd.write((uint8_t)7); // pause symbol if heating is paused } else if (heatingLockTime > 0) { lcd.createChar(7, customCharLock); lcd.setCursor(12, 1); lcd.write((uint8_t)7); // lock symbol if heating should run BUT lockout time is active } else if (turnHeatingOn) { lcd.createChar(7, customCharFlame); lcd.setCursor(12, 1); lcd.write((uint8_t)7); // flame symbol if heating is active } else { lcd.setCursor(12, 1); lcd.print(" "); } displayAddConnectionIcon(); } } }