könnte mir vielleicht jemmand helfen, das nachfolgende kleine Programmschnipsel eines ESP32 / Arduinocode zu sanieren?
Die Aufgabe ist, daß von zwei DS18B20-Temperaturen die Unter-bzw. Übertemperaturen durch kleine schwarze Kreise signalisiert werden sollen.
Dazu habe ich vier if-Anweisungen geschrieben, die leider gar nicht so funktionieren, wie das gedacht war: wenn beide Temperaturen das Minimum (<18.0) unterschreiten, sind beide Kreise von temp_links aktiviert. Wenn die rechte Temperatur das Maximum (>23.0) überschreitet, sind beide Kreise vom temp_rechts aktiviert. Manchmal funktioniert es richtig, aber das ist die Ausnahme.
Man könnte denken, daß vom vorangegangenen Durchlauf noch etwas hängen gebleiben sei, aber es wird ja alles gelöscht und neu geschrieben. Daran sollte es also nicht liegen.
Ich lasse zur Kontrolle die temp-Werte seriell ausdrucken, sie sind alle richtig.
Irgend etwas an den If-Befehlen mache ich falsch, aber was?
Hier das Stück des Programm:
1
// temporär zur Kontrolle, ob die richtigen temp_Werte die Alarmierungssequenz erreichen
2
temp_links=sensors1.getTempCByIndex(0);
3
Serial.print("temp_links ");
4
Serial.println(temp_links);
5
temp_rechts=sensors2.getTempCByIndex(0);
6
Serial.print("temp_rechts ");
7
Serial.println(temp_rechts);
8
9
// Alarmierung (funktioniert nicht richtig)
10
if(temp_links<18.0){
11
display.fillCircle(30,40,10,GxEPD_BLACK);}
12
if(temp_links>23.0){
13
display.fillCircle(30,98,10,GxEPD_BLACK);}
14
15
if(temp_rechts<18.0){
16
display.fillCircle(220,40,10,GxEPD_BLACK);}
17
if(temp_rechts>23.0){
18
display.fillCircle(220,98,10,GxEPD_BLACK);}
19
20
display.update();// hiermit wird die neue Display-konfiguration auf das Display geschrieben
wo wird der displayinhalt geleert, oder die kreise gezielt
gelöscht?
nein, nicht gezielt gelöscht, der Displayinhalt wird mit display.update(); komplett neu geschrieben.
Außerdem: wenn sich die Temperaturen ändern, verschwinden die überflüssigen Kreise.
nein, nicht gezielt gelöscht, der Displayinhalt wird mit
display.update(); komplett neu geschrieben.
Das ist der Grund wieso wir auf löschen oder überschreiben hingewiesen haben.
In vielen Libraries wird mit Update nur erneut der Puffer auf das Display geschrieben.
Du musst aber den Kreis den du nicht möchtest zuerst aus dem Puffer entfernen bevor er geschrieben wird.
Der Puffer kann je nach Hardware im uC (Librarie) oder im Display selbst sein...
Wo werden denn die einmal gezeichneten Kreise wieder abgelöscht?
ich werde Deinen Vorschlag probieren , aber ich glaube, das mit GxEPD_WHITE hilft nicht weiter. Weshalb? Weil die schwarzen Kreise automatisch verschwinden, wenn sich ein anderer Temperaturzustand einstellt.
Z.B. temp_links unter 18.0 mit den beiden Kreisen, wo einer nicht hingehört (Abb1),
dann verschwindet bei Erhöhung temp_links über 23.0 einer der beiden rückstandslos und an anderer Stelle erscheint ein anderer (diesmal eine richtige Version) (Abb2).
display.getTextBounds(text1,0,0,&tbx,&tby,&tbw,&tbh);// it works for origin 0, 0, fortunately (negative tby!)
103
display.fillScreen(GxEPD_WHITE);// set the background to white (fill the buffer with value for white)
104
105
display.drawRect(4,6,242,120,GxEPD_BLACK);// Rechteck am Rand
106
display.setCursor(45,50);
107
display.print(text1);
108
display.setCursor(45,110);
109
display.print(text2);
110
111
// temporär zur Kontrolle, ob die richtigen temp_Werte die Alarmierungssequenz erreichen
112
temp_links=sensors1.getTempCByIndex(0);
113
Serial.print("temp_links ");
114
Serial.println(temp_links);
115
temp_rechts=sensors2.getTempCByIndex(0);
116
Serial.print("temp_rechts ");
117
Serial.println(temp_rechts);
118
119
// Alarmierung (funktioniert nicht richtig)
120
if(temp_links<18.0){
121
display.fillCircle(30,40,10,GxEPD_BLACK);}
122
if(temp_links>23.0){
123
display.fillCircle(30,98,10,GxEPD_BLACK);}
124
125
if(temp_rechts<18.0){
126
display.fillCircle(220,40,10,GxEPD_BLACK);}
127
if(temp_rechts>23.0){
128
display.fillCircle(220,98,10,GxEPD_BLACK);}
129
130
display.update();// hiermit wird die neue Display-konfiguration auf das Display geschrieben
131
}
Bitte sieh Dir die Bilder aus meinem vorletzten Post an. Wie mir scheint, ist es nicht eine Frage. ob alte Kreise gelöscht oder überschrieben werden. Es erscheinen vielmehr Kreise, wo sie gar nicht hingehören und irgendwie sind sie in der Lage, wieder zu verschwinden. Ich vermute, mit den if-Befehlen habe ich etwas falsch gemacht.
Ich denke, dass x und y bei den fillCircles falsch sind. Die beiden Kreise der temp_links-Vergleiche sind nicht die beiden oberen Kreise, sondern die beiden linken, ...
Wie mir scheint, ist es nicht eine Frage. ob alte Kreise gelöscht oder
überschrieben werden.
Die Kreise löscht du mit dem Funktionsaufruf in deiner Zeile 103
1
display.fillScreen(GxEPD_WHITE);// set the background to white (fill the buffer with value for white)
und das ist ganz entscheidend, um das Verhalten deines Programms zu verstehen, wie du ja auch an den Rückfragen gemerkt haben dürftest.
Wie Foobar schon richtig angemerkt hat, werden die gezeichneten Kreise so angezeigt, wie in deinem Programm kodiert:
1
+--------------------+
2
¦ L<18 TempL R<18 ¦
3
¦ ¦
4
¦ L>23 TempR R>23 ¦
5
+--------------------+
Ein Tipp zu den Photos:
Wenn deine Kamera auf den kurzen Abstand nicht fokussieren kann, gehe weiter weg vom Objekt und schneide hinterher aus. Bei einem schärferen Bild würde man auch den dünnen Rand vom Funktionsaufruf in deiner Zeile 105 erkennen können und müsste nicht raten.
p.s.
Um solche Fehler zu vermeide, hilft klarerer Quelltext.
Definiere die Koordinaten für die Kreise besser als Konstanten (z.B. KREISX_LOW, KREISX_HIGH, POSY_L, POSY_R) und streue sie nicht als "magic numbers" in den Quelltext ein. Die Cursorkoordinaten für die Textausgabe können sich dann auch auf diese Konstanten beziehen, z.B. für den linken Sensor in der Art "display.setCursor(TEXTX, POSY_L+TEXTY_OFFSET);".
Dann wird es auch einfach, später irgendetwas auf dem Display zu verschieben, ohne sich die Beziehung zwischen den Zahlen wieder klar machen zu müssen und irgendetwas zu vergessen.
In deinem jetzigen Code ist z.B. die Zeilenausrichtung von Punkten und Text für die obere Zeile anders als für die untere (2 Pixel Unterschied).
Die Variablen mit dem anzuzeigenden Text passend dazu zu benennen, wäre auch klarer, also z.B. textL/textR an Stelle von text1/text2.
man muss doch sicher auch nicht alle 15 Sekunden einen neuen Font initialisieren und das Display neu drehen?
Das würde ich einmal im Setup machen. Dann würde man auch sehen, dass die Kreise eben nicht auf magische Weise verschwinden.
geil ist natürlich andererseits, dass man einfach so, ohne nachzudenken dtostrf() verwenden kann, keine Kommas schieben muss oder andere Verrenkungen machen muss und auch die Texte der seriellen Ausgaben einfach so in den RAM packen kann. ich schreib da immer ein (F("TEXT")) hin. Hier ist ja genug RAM vorhanden.
Ich denke, dass x und y bei den fillCircles falsch sind. Die beiden
Kreise der temp_links-Vergleiche sind nicht die beiden oberen Kreise,
sondern die beiden linken, ...
Da in der loop ein delay von 15 Sekunden ist, weichen diese Werte stark
voneinander ab.
Soll das so sein?
Es stört zwar nicht (so schnell ändert sich die Temperatur im Aquarienwasser nicht), aber ich werde es ändern. Das doppelte Einlesen hatte ich zur Kontrolle, ob die Werte bei der if-Sequenz richtig ankommen.
man muss doch sicher auch nicht alle 15 Sekunden einen neuen Font
initialisieren und das Display neu drehen?
Nein, ich werde auf 1-5 min gehen, weil die Temperaturen quasi konstant sind (Aqurienwasser). Allerdings muß ich mir das mit dem deep sleep noch genauer ansehen, bisher hat der ESP32 nicht darauf reagiert.
Die 15 sec habe in der Testphase eingestellt, damit ich nicht so lange warten muß.
Und bei dem Übertragen ins setup stimme ich Dir zu, das werde ich ändern.
da Du nun den ganzen Code gesehen hast, hätte ich eine Frage zu einem Problem am Rande. Vielleicht fällt Dir etwas ein:
Die Anzeige geht nach. Wenn sich die Temperatur entspr. ändert, erscheint schon der Kreis und noch die alte Temperatur. Erst beim nächsten Durchlauf zeigt siich die neue Temperatur und der Kreis.
Und wenn ich neu starte, wird zunächst 0 angezeict, obwohl im Code doch zuerst die DS18B20 abgefragt und danach display.print(text1); folgt. Sollte doch nicht 0 sein.
Das Nachgehen stört im laufenden Betrieb eigentlich nicht, aber es ist unschön.
Die Anzeige geht nach. Wenn sich die Temperatur entspr. ändert,
erscheint schon der Kreis und noch die alte Temperatur. Erst beim
nächsten Durchlauf zeigt siich die neue Temperatur und der Kreis.
Das war doch der Einwand, dass in deinem Code temp_links und temp_rechts erst nach der Textausgabe auf dem Display mit Messdaten gefüttert werden, dh. immer alte (oder eben noch keine) gültigen Daten angezeigt werden.
Und wenn ich neu starte, wird zunächst 0 angezeict, obwohl im Code doch
zuerst die DS18B20 abgefragt und danach display.print(text1); folgt.
Sollte doch nicht 0 sein.
Die DS18B20 sind sehr langsam. Deshalb kann man die Temperatur-Messung zweiteilen. Zuerst Messung anstoßen, dann hat der µC lange Zeit, was anderes zu tun oder zu schlafen, und dann, nach ~750ms, kann man den Messwert abholen.
Dein Code wartet zwischen dem
sensors1.requestTemperatures();
und
sensors1.getTempCByIndex(0);
evtl. nicht lange genug.
Müsste man in der Bibliothek(s-Dokumentation) nachsehen, auf den ersten Blick könnte ein extra delay, eine Schleife
Ja, warum wohl - weil Du zuerst die Temp. ausgibst, dann erst die Temp.
ermittelst, dann den Kreis zeichnest.
Ja, da beschreibst Du das Dilemma genau: der Kreis sollte zuletzt gezeichnet werden und er erscheint in Wirklichkeit zuerst und die Temperatur wird später ausgegeben, obwohl sie doch zuerst ermittelt wurde.
Nun gut, wenn die DS18B20_Abfrage zu lange dauert - woher weiß dann der Kreis so schnell, daß er erscheinen soll?
Ja, warum wohl - weil Du zuerst die Temp. ausgibst, dann erst die Temp.
ermittelst, dann den Kreis zeichnest.
Ja, da beschreibst Du das Dilemma genau: der Kreis sollte zuletzt
gezeichnet werden und er erscheint in Wirklichkeit zuerst und die
Temperatur wird später ausgegeben, obwohl sie doch zuerst ermittelt
wurde.
Nun gut, wenn die DS18B20_Abfrage zu lange dauert - woher weiß dann der
Kreis so schnell, daß er erscheinen soll?
VG
Du scheinst irgendwie nichts begriffen zu haben ...
Ansonsten erzeugst du die Textausgabe nicht von der aktuellen Temperatur (links/rechts) sondern von der vorherigen Messung die vor 15 Sekunden stattfand.
Noch etwas:
float temp_links, temp_rechts;
Da du diese beiden Variablen nur innerhalb der Funktion Ausgabe() verwendest, gehören diese Zeilen in die Funktion verschoben. Wenn du das machst, wird dein obiger Fehler vielleicht auch offensichtlicher.
Na dann ist ja alles Bestens. Dir ist hoffentlich auch aufgefallen, daß Dein Problem nur mit Deinem ursprünglichen Code-Schnipsel praktisch nicht lösbar ist?
Denn dazu muß man ja wissen was Du sonst noch wo auf Dein Display malst.