feat: Temperaturen mit Nachkommastelle anzeigen (S3 5.6.4 / P4 1.12.0) #91
No files matched your search
@@ -1,3 +1,20 @@
|
|||||||
|
Version 5.6.4:
|
||||||
|
- Dampf-/Thermoblock-Temperatur wird jetzt mit einer Nachkommastelle angezeigt - im Webinterface, in
|
||||||
|
den Verlaufskurven und auf dem Touch-Display. Bisher wurde der Messwert direkt nach dem Einlesen auf
|
||||||
|
ganze Grad gerundet; die Nachkommastelle war damit schon weg, bevor irgendeine Anzeige sie sehen
|
||||||
|
konnte. Die einzige Ausnahme war die Offset-Kompensation, die im kalten Bereich den Rohwert
|
||||||
|
durchreicht - daher stand beim Wasserkessel dort zufällig eine Nachkommastelle, im Betrieb aber nie.
|
||||||
|
- Das gilt genauso für den Wasserkessel und den Zusatzsensor (Gehäuse/Tassenablage), damit alle
|
||||||
|
Temperaturen einheitlich aufgelöst sind.
|
||||||
|
- Die Regelung bleibt unverändert: PID, Sicherheitsabschaltungen und Auto-Tune arbeiten weiter mit dem
|
||||||
|
auf ganze Grad gerundeten Messwert. Die feinere Zahl entsteht auf einem getrennten Anzeigeweg, damit
|
||||||
|
sich das Heizverhalten durch diese Änderung nicht verschiebt.
|
||||||
|
- Die letzte Stelle ist leicht geglättet. Ungefiltert würde sie ständig springen - das Thermoelement
|
||||||
|
am Dampfkessel liefert ein 0,25-Grad-Raster, der NTC am Wasserkessel das Rauschen des ADC. Ein
|
||||||
|
größerer Temperatursprung wird weiterhin sofort übernommen, die Anzeige läuft also nicht nach.
|
||||||
|
- Das kleine OLED zeigt weiterhin ganze Grad (dort ist kein Platz), rundet den Wert jetzt aber, statt
|
||||||
|
die Nachkommastelle abzuschneiden.
|
||||||
|
|
||||||
Version 5.6.3:
|
Version 5.6.3:
|
||||||
- Bug-Fix: Beim Aufwecken über das Touch-Display blieb die Auswahl „Espresso oder Cold Extraction"
|
- Bug-Fix: Beim Aufwecken über das Touch-Display blieb die Auswahl „Espresso oder Cold Extraction"
|
||||||
manchmal aus, während sie über den Schalter kam. Ursache waren zwei unterschiedliche Bedingungen für
|
manchmal aus, während sie über den Schalter kam. Ursache waren zwei unterschiedliche Bedingungen für
|
||||||
|
|||||||
+60
-17
@@ -369,7 +369,7 @@ Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire);
|
|||||||
* Firmware-Informationen
|
* Firmware-Informationen
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
String version = "5.6.3";
|
String version = "5.6.4";
|
||||||
String versionHersteller = "Thomas Müller";
|
String versionHersteller = "Thomas Müller";
|
||||||
String versionHerstellerMail =
|
String versionHerstellerMail =
|
||||||
"<a href='mailto:thomas@mueller.black' class='info-link'>thomas@mueller.black</a>";
|
"<a href='mailto:thomas@mueller.black' class='info-link'>thomas@mueller.black</a>";
|
||||||
@@ -603,6 +603,10 @@ double SetpointWasser, InputWasser, OutputWasser;
|
|||||||
double OffsetDampf = 0.0, OffsetWasser = 0.0;
|
double OffsetDampf = 0.0, OffsetWasser = 0.0;
|
||||||
double OffsetCase = 0.0;
|
double OffsetCase = 0.0;
|
||||||
double RawInputDampf = NAN, RawInputWasser = NAN;
|
double RawInputDampf = NAN, RawInputWasser = NAN;
|
||||||
|
// Geglaettete Rohwerte - ausschliesslich fuer die Anzeige. Die Regelung arbeitet weiter mit
|
||||||
|
// den auf ganze Grad gerundeten Input*-Werten, damit sich am Regelverhalten nichts aendert;
|
||||||
|
// hier entsteht nur die feinere Zahl fuers Auge.
|
||||||
|
double SmoothRawDampf = NAN, SmoothRawWasser = NAN, SmoothRawCase = NAN;
|
||||||
double displayReferenceRawDampf = NAN, displayReferenceRawWasser = NAN;
|
double displayReferenceRawDampf = NAN, displayReferenceRawWasser = NAN;
|
||||||
bool offsetCompensationEnabled = false;
|
bool offsetCompensationEnabled = false;
|
||||||
const double OFFSET_COMPENSATION_MAX_REFERENCE_RAW_C = 40.0;
|
const double OFFSET_COMPENSATION_MAX_REFERENCE_RAW_C = 40.0;
|
||||||
@@ -621,6 +625,33 @@ void updateOffsetCompensationReferences() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tiefpass fuer die Anzeigewerte. Ohne ihn zappelt die Nachkommastelle dauernd: Das
|
||||||
|
// Thermoelement am Dampfkessel liefert ein 0,25-Grad-Raster, der NTC am Wasserkessel das
|
||||||
|
// Rauschen des ADC. Ein grosser Sprung (Kaltstart, Sensorwechsel, Bezug) wird sofort
|
||||||
|
// uebernommen, damit die Anzeige nicht hinterherlaeuft.
|
||||||
|
const double DISPLAY_TEMP_SMOOTHING = 0.25; // Gewicht des neuen Messwerts je Messtakt
|
||||||
|
const double DISPLAY_TEMP_JUMP_RESET_C = 5.0; // ab dieser Abweichung ungeglaettet uebernehmen
|
||||||
|
|
||||||
|
void updateSmoothedRawTemperature(double &smoothed, double measured) {
|
||||||
|
if (!isfinite(measured)) {
|
||||||
|
smoothed = measured;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isfinite(smoothed) || fabs(measured - smoothed) >= DISPLAY_TEMP_JUMP_RESET_C) {
|
||||||
|
smoothed = measured;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
smoothed += DISPLAY_TEMP_SMOOTHING * (measured - smoothed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anzeigewerte auf eine Nachkommastelle festzurren, damit Weboberflaeche, Display und
|
||||||
|
// Verlaufskurven denselben Wert sehen und die letzte Stelle nicht zwischen den Kanaelen
|
||||||
|
// auseinanderlaeuft.
|
||||||
|
double quantizeDisplayTemperature(double value) {
|
||||||
|
if (!isfinite(value)) return value;
|
||||||
|
return round(value * 10.0) / 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
double getDisplayTemperature(double correctedTemp, double rawTemp, double offset, double referenceRaw) {
|
double getDisplayTemperature(double correctedTemp, double rawTemp, double offset, double referenceRaw) {
|
||||||
if (!offsetCompensationEnabled || offset >= 0.0 || !isfinite(correctedTemp) || !isfinite(rawTemp) || !isfinite(referenceRaw)) {
|
if (!offsetCompensationEnabled || offset >= 0.0 || !isfinite(correctedTemp) || !isfinite(rawTemp) || !isfinite(referenceRaw)) {
|
||||||
return correctedTemp;
|
return correctedTemp;
|
||||||
@@ -634,11 +665,17 @@ double getDisplayTemperature(double correctedTemp, double rawTemp, double offset
|
|||||||
}
|
}
|
||||||
|
|
||||||
double getDisplayedWaterTemperature() {
|
double getDisplayedWaterTemperature() {
|
||||||
return getDisplayTemperature(InputWasser, RawInputWasser, OffsetWasser, displayReferenceRawWasser);
|
return quantizeDisplayTemperature(getDisplayTemperature(
|
||||||
|
SmoothRawWasser + OffsetWasser, SmoothRawWasser, OffsetWasser, displayReferenceRawWasser));
|
||||||
}
|
}
|
||||||
|
|
||||||
double getDisplayedSteamTemperature() {
|
double getDisplayedSteamTemperature() {
|
||||||
return getDisplayTemperature(InputDampf, RawInputDampf, OffsetDampf, displayReferenceRawDampf);
|
return quantizeDisplayTemperature(getDisplayTemperature(
|
||||||
|
SmoothRawDampf + OffsetDampf, SmoothRawDampf, OffsetDampf, displayReferenceRawDampf));
|
||||||
|
}
|
||||||
|
|
||||||
|
double getDisplayedCaseTemperature() {
|
||||||
|
return quantizeDisplayTemperature(SmoothRawCase + OffsetCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PID-Konstanten (Regelungsparameter)
|
// PID-Konstanten (Regelungsparameter)
|
||||||
@@ -3243,6 +3280,7 @@ void resetToDefaults() {
|
|||||||
digitalWrite(SSR_LIGHT_PIN, LOW);
|
digitalWrite(SSR_LIGHT_PIN, LOW);
|
||||||
standbyModeActive = false;
|
standbyModeActive = false;
|
||||||
InputCase = NAN;
|
InputCase = NAN;
|
||||||
|
SmoothRawCase = NAN;
|
||||||
caseSensorError = false;
|
caseSensorError = false;
|
||||||
|
|
||||||
// PID Limits neu setzen (falls Fenstergröße geändert wurde)
|
// PID Limits neu setzen (falls Fenstergröße geändert wurde)
|
||||||
@@ -5546,12 +5584,17 @@ void loop() {
|
|||||||
RawInputWasser = readNTCTemperature();
|
RawInputWasser = readNTCTemperature();
|
||||||
InputDampf = round(RawInputDampf + OffsetDampf);
|
InputDampf = round(RawInputDampf + OffsetDampf);
|
||||||
InputWasser = round(RawInputWasser + OffsetWasser);
|
InputWasser = round(RawInputWasser + OffsetWasser);
|
||||||
|
updateSmoothedRawTemperature(SmoothRawDampf, RawInputDampf);
|
||||||
|
updateSmoothedRawTemperature(SmoothRawWasser, RawInputWasser);
|
||||||
updateOffsetCompensationReferences();
|
updateOffsetCompensationReferences();
|
||||||
if (caseSensorEnabled) {
|
if (caseSensorEnabled) {
|
||||||
InputCase = round(readCaseTemperature() + OffsetCase);
|
double rawCase = readCaseTemperature();
|
||||||
|
InputCase = round(rawCase + OffsetCase);
|
||||||
|
updateSmoothedRawTemperature(SmoothRawCase, rawCase);
|
||||||
caseSensorError = (isnan(InputCase) || InputCase < 0.0);
|
caseSensorError = (isnan(InputCase) || InputCase < 0.0);
|
||||||
} else {
|
} else {
|
||||||
InputCase = NAN;
|
InputCase = NAN;
|
||||||
|
SmoothRawCase = NAN;
|
||||||
caseSensorError = false;
|
caseSensorError = false;
|
||||||
}
|
}
|
||||||
yield();
|
yield();
|
||||||
@@ -6456,7 +6499,7 @@ if (scaleModeActive) {
|
|||||||
display.println(F("Heizt auf 93 C"));
|
display.println(F("Heizt auf 93 C"));
|
||||||
display.println(F("vor..."));
|
display.println(F("vor..."));
|
||||||
display.print(F("Wasser: "));
|
display.print(F("Wasser: "));
|
||||||
display.print((int)displayedWaterTemp);
|
display.print((int)lround(displayedWaterTemp));
|
||||||
display.print(F("/"));
|
display.print(F("/"));
|
||||||
display.print((int)cleaningAssistantWaterSetpoint);
|
display.print((int)cleaningAssistantWaterSetpoint);
|
||||||
display.print(F(" "));
|
display.print(F(" "));
|
||||||
@@ -6480,7 +6523,7 @@ if (scaleModeActive) {
|
|||||||
display.print((remainingMs + 999UL) / 1000UL);
|
display.print((remainingMs + 999UL) / 1000UL);
|
||||||
display.println(F(" s"));
|
display.println(F(" s"));
|
||||||
display.print(F("Wasser: "));
|
display.print(F("Wasser: "));
|
||||||
display.print((int)displayedWaterTemp);
|
display.print((int)lround(displayedWaterTemp));
|
||||||
display.print(F("/"));
|
display.print(F("/"));
|
||||||
display.print((int)cleaningAssistantWaterSetpoint);
|
display.print((int)cleaningAssistantWaterSetpoint);
|
||||||
display.print(F(" "));
|
display.print(F(" "));
|
||||||
@@ -6522,7 +6565,7 @@ if (scaleModeActive) {
|
|||||||
else { display.print(F("Init")); }
|
else { display.print(F("Init")); }
|
||||||
display.println();
|
display.println();
|
||||||
display.print("Temperatur:");
|
display.print("Temperatur:");
|
||||||
display.print((int)(autoTuneWasserActive ? displayedWaterTemp : displayedSteamTemp));
|
display.print((int)lround(autoTuneWasserActive ? displayedWaterTemp : displayedSteamTemp));
|
||||||
display.print(F(" "));
|
display.print(F(" "));
|
||||||
display.print((char)247);
|
display.print((char)247);
|
||||||
display.print(F("C"));
|
display.print(F("C"));
|
||||||
@@ -6553,7 +6596,7 @@ if (scaleModeActive) {
|
|||||||
display.println(F("wenn Temp. erreicht!"));
|
display.println(F("wenn Temp. erreicht!"));
|
||||||
display.println(F(" "));
|
display.println(F(" "));
|
||||||
display.println(F("Temperatur: "));
|
display.println(F("Temperatur: "));
|
||||||
display.print((int)displayedWaterTemp);
|
display.print((int)lround(displayedWaterTemp));
|
||||||
display.print(F(" / "));
|
display.print(F(" / "));
|
||||||
display.print((int)SetpointWasser);
|
display.print((int)SetpointWasser);
|
||||||
display.print(F(" "));
|
display.print(F(" "));
|
||||||
@@ -6832,13 +6875,13 @@ if (scaleModeActive) {
|
|||||||
else if (wasserSensorError) { display.print(F("Sensorfehler!")); }
|
else if (wasserSensorError) { display.print(F("Sensorfehler!")); }
|
||||||
else if (coldExtractionModeActive) {
|
else if (coldExtractionModeActive) {
|
||||||
// Cold Extraction: kein Sollwert-Vergleich sinnvoll, der Wasserkreis heizt nicht
|
// Cold Extraction: kein Sollwert-Vergleich sinnvoll, der Wasserkreis heizt nicht
|
||||||
display.print((int)displayedWaterTemp);
|
display.print((int)lround(displayedWaterTemp));
|
||||||
display.print(F(" "));
|
display.print(F(" "));
|
||||||
display.print((char)247);
|
display.print((char)247);
|
||||||
display.print(F("C (COLD)"));
|
display.print(F("C (COLD)"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
display.print((int)displayedWaterTemp);
|
display.print((int)lround(displayedWaterTemp));
|
||||||
display.print(F(" / "));
|
display.print(F(" / "));
|
||||||
display.print((int)SetpointWasser);
|
display.print((int)SetpointWasser);
|
||||||
display.print(F(" "));
|
display.print(F(" "));
|
||||||
@@ -6857,7 +6900,7 @@ if (scaleModeActive) {
|
|||||||
bool steamDelayActiveSystem = (dampfVerzoegerung > 0 && (millis() - startupTime < (unsigned long)dampfVerzoegerung * 60000UL));
|
bool steamDelayActiveSystem = (dampfVerzoegerung > 0 && (millis() - startupTime < (unsigned long)dampfVerzoegerung * 60000UL));
|
||||||
bool shouldShowDelayMessage = steamDelayActiveSystem && !steamDelayOverridden;
|
bool shouldShowDelayMessage = steamDelayActiveSystem && !steamDelayOverridden;
|
||||||
if (!shouldShowDelayMessage) {
|
if (!shouldShowDelayMessage) {
|
||||||
display.print((int)displayedSteamTemp);
|
display.print((int)lround(displayedSteamTemp));
|
||||||
display.print(F(" / "));
|
display.print(F(" / "));
|
||||||
display.print((int)SetpointDampf);
|
display.print((int)SetpointDampf);
|
||||||
display.print(F(" "));
|
display.print(F(" "));
|
||||||
@@ -8311,9 +8354,9 @@ void recordResetCheckpoint(uint16_t checkpoint) {
|
|||||||
if (steamHeatDisabledByUser) flags |= RESET_DIAG_FLAG_STEAM_HEAT_DISABLED;
|
if (steamHeatDisabledByUser) flags |= RESET_DIAG_FLAG_STEAM_HEAT_DISABLED;
|
||||||
rtcResetDiag.flags = flags;
|
rtcResetDiag.flags = flags;
|
||||||
|
|
||||||
rtcResetDiag.waterTempDeciC = encodeResetDiagSignedTenths((float)InputWasser);
|
rtcResetDiag.waterTempDeciC = encodeResetDiagSignedTenths((float)getDisplayedWaterTemperature());
|
||||||
rtcResetDiag.steamTempDeciC = encodeResetDiagSignedTenths((float)InputDampf);
|
rtcResetDiag.steamTempDeciC = encodeResetDiagSignedTenths((float)getDisplayedSteamTemperature());
|
||||||
rtcResetDiag.caseTempDeciC = encodeResetDiagSignedTenths((float)InputCase);
|
rtcResetDiag.caseTempDeciC = encodeResetDiagSignedTenths((float)getDisplayedCaseTemperature());
|
||||||
rtcResetDiag.weightDeciG = encodeResetDiagSignedTenths(currentWeightReading);
|
rtcResetDiag.weightDeciG = encodeResetDiagSignedTenths(currentWeightReading);
|
||||||
rtcResetDiag.scaleType = scaleType;
|
rtcResetDiag.scaleType = scaleType;
|
||||||
rtcResetDiag.wifiStatus = (int8_t)WiFi.status();
|
rtcResetDiag.wifiStatus = (int8_t)WiFi.status();
|
||||||
@@ -11533,7 +11576,7 @@ void handleChartData(AsyncWebServerRequest *request) {
|
|||||||
if (!caseSensorEnabled || caseSensorError || isnan(InputCase)) {
|
if (!caseSensorEnabled || caseSensorError || isnan(InputCase)) {
|
||||||
response->print(F("null"));
|
response->print(F("null"));
|
||||||
} else {
|
} else {
|
||||||
snprintf(buffer, sizeof(buffer), "%.1f", InputCase);
|
snprintf(buffer, sizeof(buffer), "%.1f", getDisplayedCaseTemperature());
|
||||||
response->print(buffer);
|
response->print(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16544,7 +16587,7 @@ void buildDashboardJson(char *buffer, size_t bufferSize) {
|
|||||||
if (!caseTempDashboardActive || caseSensorError || isnan(InputCase)) {
|
if (!caseTempDashboardActive || caseSensorError || isnan(InputCase)) {
|
||||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":null,");
|
offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":null,");
|
||||||
} else {
|
} else {
|
||||||
dtostrf(InputCase, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":%s,", floatBuf);
|
dtostrf(getDisplayedCaseTemperature(), 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":%s,", floatBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shot-Daten
|
// Shot-Daten
|
||||||
@@ -16973,7 +17016,7 @@ static void buildTouchUartStateJson(char *buffer, size_t bufferSize) {
|
|||||||
if (!caseSensorEnabled || caseSensorError || isnan(InputCase)) {
|
if (!caseSensorEnabled || caseSensorError || isnan(InputCase)) {
|
||||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":null,");
|
offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":null,");
|
||||||
} else {
|
} else {
|
||||||
dtostrf(InputCase, 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":%s,", floatBuf);
|
dtostrf(getDisplayedCaseTemperature(), 4, 1, floatBuf); offset += snprintf(buffer + offset, bufferSize - offset, "\"caseTemp\":%s,", floatBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += snprintf(buffer + offset, bufferSize - offset, "\"maintenanceInterval\":%d,", maintenanceInterval);
|
offset += snprintf(buffer + offset, bufferSize - offset, "\"maintenanceInterval\":%d,", maintenanceInterval);
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
Version 1.12.0:
|
||||||
|
- Die Dampf-/Thermoblock-Temperatur wird jetzt mit einer Nachkommastelle angezeigt, wie die
|
||||||
|
Wassertemperatur. Das gilt für die große Zahl auf der Startseite, den Sollwert darunter und
|
||||||
|
die Beschriftung der Verlaufskurve. Der Wert kam schon immer fein genug über die Verbindung
|
||||||
|
zur Maschine an - nur die Anzeige hat die Stelle weggeworfen. Voraussetzung ist die
|
||||||
|
Maschinen-Firmware 5.6.4, davor liefert die Maschine immer ganze Grad.
|
||||||
|
- Die große Temperaturzahl verkleinert sich automatisch, wenn sie sonst nicht mehr in die
|
||||||
|
Karte passt. "124,5°C" ist rund ein Drittel breiter als "124°C", und in der randlosen
|
||||||
|
Flächen-Darstellung reicht die halbe Bildschirmbreite dafür nicht. Bisher brach LVGL die
|
||||||
|
Zeile dann um und die zweite Zeile fiel aus der Karte - das betraf schon vorher die
|
||||||
|
Wassertemperatur, sobald sie 100 °C erreichte.
|
||||||
|
- Im Reinigungsassistenten steht die Wassertemperatur ebenfalls mit einer Nachkommastelle.
|
||||||
|
|
||||||
Version 1.11.3:
|
Version 1.11.3:
|
||||||
- Der Punkt sitzt wieder genau auf dem letzten Messwert, statt eine halbe Punktbreite davor.
|
- Der Punkt sitzt wieder genau auf dem letzten Messwert, statt eine halbe Punktbreite davor.
|
||||||
Die Linie schaut damit rechts nicht mehr unter ihm hervor. Damit trotzdem nichts
|
Die Linie schaut damit rechts nicht mehr unter ihm hervor. Damit trotzdem nichts
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
// -------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------
|
||||||
// Firmware
|
// Firmware
|
||||||
// -------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------
|
||||||
#define DISPLAY_FW_VERSION "1.11.3" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
|
#define DISPLAY_FW_VERSION "1.12.0" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------
|
||||||
// Protokoll
|
// Protokoll
|
||||||
|
|||||||
+90
-10
@@ -1098,6 +1098,9 @@ static lv_obj_t* tempField(lv_obj_t* parent, const char* title, lv_color_t accen
|
|||||||
// auseinandergezogen; ein paar Pixel weniger binden die Ziffern zu einer Zahl zusammen.
|
// auseinandergezogen; ein paar Pixel weniger binden die Ziffern zu einer Zahl zusammen.
|
||||||
if (valueFont == &lv_font_maven_pro_bold_140) lv_obj_set_style_text_letter_space(*big, -3, 0);
|
if (valueFont == &lv_font_maven_pro_bold_140) lv_obj_set_style_text_letter_space(*big, -3, 0);
|
||||||
else if (valueFont == &lv_font_maven_pro_bold_96) lv_obj_set_style_text_letter_space(*big, -2, 0);
|
else if (valueFont == &lv_font_maven_pro_bold_96) lv_obj_set_style_text_letter_space(*big, -2, 0);
|
||||||
|
// Ausgangsschrift merken: big_temp_apply() darf nur von hier aus verkleinern und muss
|
||||||
|
// zurueckfinden, sobald der Text wieder kuerzer wird.
|
||||||
|
lv_obj_set_user_data(*big, (void*)valueFont);
|
||||||
|
|
||||||
*setp = lv_label_create(c);
|
*setp = lv_label_create(c);
|
||||||
lv_label_set_text(*setp, "Soll --.-");
|
lv_label_set_text(*setp, "Soll --.-");
|
||||||
@@ -1120,6 +1123,79 @@ static lv_obj_t* tempField(lv_obj_t* parent, const char* title, lv_color_t accen
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t big_temp_letter_space(const lv_font_t* f) {
|
||||||
|
if (f == &lv_font_maven_pro_bold_140) return -3;
|
||||||
|
if (f == &lv_font_maven_pro_bold_96) return -2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schriftleiter fuer die grosse Temperaturzahl, von gross nach klein.
|
||||||
|
static const lv_font_t* const kBigTempLadder[] = {
|
||||||
|
&lv_font_maven_pro_bold_140, &lv_font_maven_pro_bold_96,
|
||||||
|
&lv_font_maven_pro_48, &lv_font_maven_pro_40,
|
||||||
|
&lv_font_maven_pro_28
|
||||||
|
};
|
||||||
|
static const int kBigTempLadderLen = (int)(sizeof(kBigTempLadder) / sizeof(kBigTempLadder[0]));
|
||||||
|
|
||||||
|
static const lv_font_t* big_temp_base(lv_obj_t* label) {
|
||||||
|
const lv_font_t* base = (const lv_font_t*)lv_obj_get_user_data(label);
|
||||||
|
return base ? base : lv_obj_get_style_text_font(label, LV_PART_MAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kleinste Stufe, in die der Text noch ohne Umbruch passt. Breite UND Hoehe der
|
||||||
|
// Beschriftung sind fest (siehe tempField) - laeuft der Text ueber, bricht LVGL die Zeile
|
||||||
|
// um und die zweite Zeile faellt aus der Karte heraus, statt nur eng zu wirken. Mit der
|
||||||
|
// Nachkommastelle ist "124,5°C" rund ein Drittel breiter als "124°C"; in der randlosen
|
||||||
|
// Flaechen-Darstellung reicht die halbe Bildschirmbreite dafuer nicht mehr.
|
||||||
|
// -1 heisst "nicht entscheidbar" - dann bleibt es bei der Ausgangsschrift.
|
||||||
|
static int big_temp_fit_index(lv_obj_t* label, const char* txt) {
|
||||||
|
const lv_font_t* base = big_temp_base(label);
|
||||||
|
int idx = 0;
|
||||||
|
while (idx < kBigTempLadderLen && kBigTempLadder[idx] != base) idx++;
|
||||||
|
if (idx >= kBigTempLadderLen) return -1; // Schrift nicht in der Leiter
|
||||||
|
int32_t avail = lv_obj_get_content_width(label);
|
||||||
|
if (avail <= 0) return idx; // vor dem ersten Layout noch unbekannt
|
||||||
|
for (; idx < kBigTempLadderLen - 1; idx++) {
|
||||||
|
lv_point_t sz;
|
||||||
|
lv_text_get_size(&sz, txt, kBigTempLadder[idx], big_temp_letter_space(kBigTempLadder[idx]),
|
||||||
|
0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
|
||||||
|
if (sz.x <= avail) break;
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void big_temp_apply(lv_obj_t* label, int idx, const char* txt) {
|
||||||
|
const lv_font_t* base = big_temp_base(label);
|
||||||
|
const lv_font_t* pick = (idx >= 0 && idx < kBigTempLadderLen) ? kBigTempLadder[idx] : base;
|
||||||
|
if (lv_obj_get_style_text_font(label, LV_PART_MAIN) != pick) {
|
||||||
|
lv_obj_set_style_text_font(label, pick, 0);
|
||||||
|
lv_obj_set_style_text_letter_space(label, big_temp_letter_space(pick), 0);
|
||||||
|
// Die Hoehe bleibt die der Ausgangsschrift (sonst raeumt LVGL das Layout der ganzen
|
||||||
|
// Seite neu). Die kleinere Zahl wird darin per Innenabstand mittig gehalten, damit
|
||||||
|
// sie nicht an der Oberkante klebt.
|
||||||
|
int32_t padTop = (lv_font_get_line_height(base) - lv_font_get_line_height(pick)) / 2;
|
||||||
|
lv_obj_set_style_pad_top(label, padTop > 0 ? padTop : 0, 0);
|
||||||
|
}
|
||||||
|
label_set_if_changed(label, txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setzt beide grossen Temperaturzahlen gemeinsam. Gleich grosse Felder muessen gleich gross
|
||||||
|
// bleiben: Muss eine Zahl kleiner gesetzt werden, geht die andere mit. Sonst schrumpfte
|
||||||
|
// allein der Dampfkessel, weil "125,5°C" breiter ist als "93,5°C" - zwei verschieden
|
||||||
|
// grosse Zahlen nebeneinander sehen aus wie ein Fehler. Wo die Felder absichtlich ungleich
|
||||||
|
// sind (gewichtete Darstellung), bleibt jede Zahl bei ihrer eigenen Stufe.
|
||||||
|
static void big_temp_set_pair(lv_obj_t* a, const char* ta, lv_obj_t* b, const char* tb) {
|
||||||
|
if (!a || !b || !ta || !tb) return;
|
||||||
|
int ia = big_temp_fit_index(a, ta);
|
||||||
|
int ib = big_temp_fit_index(b, tb);
|
||||||
|
if (ia >= 0 && ib >= 0 && big_temp_base(a) == big_temp_base(b)) {
|
||||||
|
int common = (ia > ib) ? ia : ib;
|
||||||
|
ia = ib = common;
|
||||||
|
}
|
||||||
|
big_temp_apply(a, ia, ta);
|
||||||
|
big_temp_apply(b, ib, tb);
|
||||||
|
}
|
||||||
|
|
||||||
// Flache Verlaufskurve unter einer Temperatur. Zeigt, ob die Regelung haelt - das ist die
|
// Flache Verlaufskurve unter einer Temperatur. Zeigt, ob die Regelung haelt - das ist die
|
||||||
// eigentliche Frage an eine PID-Regelung, und eine Zahl kann sie grundsaetzlich nicht
|
// eigentliche Frage an eine PID-Regelung, und eine Zahl kann sie grundsaetzlich nicht
|
||||||
// beantworten. Gespeist wird sie aus derselben Sekundenabtastung wie die Verlaufsseite.
|
// beantworten. Gespeist wird sie aus derselben Sekundenabtastung wie die Verlaufsseite.
|
||||||
@@ -2202,7 +2278,7 @@ static void chart_sample_cb(lv_timer_t*) {
|
|||||||
(int)(dw + 0.5f), (int)(dd + 0.5f));
|
(int)(dw + 0.5f), (int)(dd + 0.5f));
|
||||||
|
|
||||||
if (g_legW) lv_label_set_text(g_legW, ("Wasser " + tempStr(g_state.tempW, 1)).c_str());
|
if (g_legW) lv_label_set_text(g_legW, ("Wasser " + tempStr(g_state.tempW, 1)).c_str());
|
||||||
if (g_legD) lv_label_set_text(g_legD, ("Dampf " + tempStr(g_state.tempD, 0)).c_str());
|
if (g_legD) lv_label_set_text(g_legD, ("Dampf " + tempStr(g_state.tempD, 1)).c_str());
|
||||||
if (g_legC) {
|
if (g_legC) {
|
||||||
if (caseOn) {
|
if (caseOn) {
|
||||||
const char* name = (g_state.caseSensorType == 1) ? "Tassenablage " : "Gehäuse ";
|
const char* name = (g_state.caseSensorType == 1) ? "Tassenablage " : "Gehäuse ";
|
||||||
@@ -2766,13 +2842,13 @@ static void cln_refresh() {
|
|||||||
String s;
|
String s;
|
||||||
if (st.cleaningWaiting) {
|
if (st.cleaningWaiting) {
|
||||||
s = "Heizt auf 93 °C vor...\n\n";
|
s = "Heizt auf 93 °C vor...\n\n";
|
||||||
s += "Wasser: " + tempStr(st.tempW, 0) + " / 93°C\n\n";
|
s += "Wasser: " + tempStr(st.tempW, 1) + " / 93°C\n\n";
|
||||||
s += "Die Zyklen starten automatisch,\nsobald die Temperatur erreicht ist.";
|
s += "Die Zyklen starten automatisch,\nsobald die Temperatur erreicht ist.";
|
||||||
} else {
|
} else {
|
||||||
s = "Zyklus " + String(st.cleaningCycle) + " / " + String(st.cleaningCycles) + "\n\n";
|
s = "Zyklus " + String(st.cleaningCycle) + " / " + String(st.cleaningCycles) + "\n\n";
|
||||||
s += "Phase: " + String(st.cleaningBrewPhase ? "Bezug" : "Pause") + "\n";
|
s += "Phase: " + String(st.cleaningBrewPhase ? "Bezug" : "Pause") + "\n";
|
||||||
s += "Rest: " + String(st.cleaningPhaseRemainSec) + " s\n\n";
|
s += "Rest: " + String(st.cleaningPhaseRemainSec) + " s\n\n";
|
||||||
s += "Wasser: " + tempStr(st.tempW, 0) + " / 93°C\n";
|
s += "Wasser: " + tempStr(st.tempW, 1) + " / 93°C\n";
|
||||||
s += "Dampfheizung aus";
|
s += "Dampfheizung aus";
|
||||||
}
|
}
|
||||||
if (g_clnProgLbl) label_set_if_changed(g_clnProgLbl, s.c_str());
|
if (g_clnProgLbl) label_set_if_changed(g_clnProgLbl, s.c_str());
|
||||||
@@ -4749,14 +4825,20 @@ void ui_update(const MachineState& st) {
|
|||||||
|
|
||||||
// Dashboard - Temperaturkarten (im Fehlerfall Warnsymbol + Klartext statt Zahl, wie OLED)
|
// Dashboard - Temperaturkarten (im Fehlerfall Warnsymbol + Klartext statt Zahl, wie OLED)
|
||||||
if (lblTempW) {
|
if (lblTempW) {
|
||||||
if (st.wasserSafetyShutdown || st.wasserSensorError) {
|
// Beide grossen Zahlen zusammen setzen, damit sie bei knapper Kartenbreite
|
||||||
label_set_if_changed(lblTempW, LV_SYMBOL_WARNING);
|
// gemeinsam eine Stufe kleiner werden (siehe big_temp_set_pair).
|
||||||
|
const bool warnW = st.wasserSafetyShutdown || st.wasserSensorError;
|
||||||
|
const bool warnD = st.dampfSafetyShutdown || st.dampfSensorError;
|
||||||
|
String bigW = warnW ? String(LV_SYMBOL_WARNING) : tempStr(st.tempW, 1);
|
||||||
|
String bigD = warnD ? String(LV_SYMBOL_WARNING) : tempStr(st.tempD, 1);
|
||||||
|
big_temp_set_pair(lblTempW, bigW.c_str(), lblTempD, bigD.c_str());
|
||||||
|
|
||||||
|
if (warnW) {
|
||||||
label_color_if_changed(lblTempW, COL_DANGER);
|
label_color_if_changed(lblTempW, COL_DANGER);
|
||||||
label_set_if_changed(lblSetW, st.wasserSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
label_set_if_changed(lblSetW, st.wasserSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
||||||
label_color_if_changed(lblSetW, COL_DANGER);
|
label_color_if_changed(lblSetW, COL_DANGER);
|
||||||
temp_progress_set(barDutyW, arcTempW, bulbTempW, 0, COL_DANGER);
|
temp_progress_set(barDutyW, arcTempW, bulbTempW, 0, COL_DANGER);
|
||||||
} else {
|
} else {
|
||||||
label_set_if_changed(lblTempW, tempStr(st.tempW, 1).c_str());
|
|
||||||
if (st.cxActive) {
|
if (st.cxActive) {
|
||||||
// Cold Extraction: der Sollwert ist bedeutungslos, es wird nicht geheizt.
|
// Cold Extraction: der Sollwert ist bedeutungslos, es wird nicht geheizt.
|
||||||
// Statt eines Zielbands, das nie erreicht wird, den Grund anzeigen.
|
// Statt eines Zielbands, das nie erreicht wird, den Grund anzeigen.
|
||||||
@@ -4775,17 +4857,15 @@ void ui_update(const MachineState& st) {
|
|||||||
temp_progress_set(barDutyW, arcTempW, bulbTempW, pctW, colW);
|
temp_progress_set(barDutyW, arcTempW, bulbTempW, pctW, colW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (st.dampfSafetyShutdown || st.dampfSensorError) {
|
if (warnD) {
|
||||||
label_set_if_changed(lblTempD, LV_SYMBOL_WARNING);
|
|
||||||
label_color_if_changed(lblTempD, COL_DANGER);
|
label_color_if_changed(lblTempD, COL_DANGER);
|
||||||
label_set_if_changed(lblSetD, st.dampfSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
label_set_if_changed(lblSetD, st.dampfSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
||||||
label_color_if_changed(lblSetD, COL_DANGER);
|
label_color_if_changed(lblSetD, COL_DANGER);
|
||||||
temp_progress_set(barDutyD, arcTempD, bulbTempD, 0, COL_DANGER);
|
temp_progress_set(barDutyD, arcTempD, bulbTempD, 0, COL_DANGER);
|
||||||
} else {
|
} else {
|
||||||
label_set_if_changed(lblTempD, tempStr(st.tempD, 0).c_str());
|
|
||||||
lv_color_t colD = temp_state_color(st.tempD, st.setD);
|
lv_color_t colD = temp_state_color(st.tempD, st.setD);
|
||||||
label_color_if_changed(lblTempD, temp_value_color(colD));
|
label_color_if_changed(lblTempD, temp_value_color(colD));
|
||||||
label_set_if_changed(lblSetD, ("Soll " + tempStr(st.setD, 0)).c_str());
|
label_set_if_changed(lblSetD, ("Soll " + tempStr(st.setD, 1)).c_str());
|
||||||
label_color_if_changed(lblSetD, COL_TEXT_DIM);
|
label_color_if_changed(lblSetD, COL_TEXT_DIM);
|
||||||
int pctD = (st.setD > 0.0f) ? (int)(st.tempD / st.setD * 100.0f + 0.5f) : 0;
|
int pctD = (st.setD > 0.0f) ? (int)(st.tempD / st.setD * 100.0f + 0.5f) : 0;
|
||||||
temp_progress_set(barDutyD, arcTempD, bulbTempD, pctD, colD);
|
temp_progress_set(barDutyD, arcTempD, bulbTempD, pctD, colD);
|
||||||
|
|||||||
Reference in new issue
Block a user