Hallo,
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 werden denn die einmal gezeichneten Kreise wieder abgelöscht?
Dass Konstrukt mit den 2 ifs würde ich auch durch ein else if ersetzen.
Denn beides kann ja nicht sein.
Also evtl so?
Flip B. schrieb:> 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.
Dann zeig deinen kompletten Code.
Das ist der Grund wieso hier immer alle Salami schreien.
Egon M. schrieb:> 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...
N. M. schrieb:> 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).
Und Abb3 dürfte es auch nicht geben
N. M. schrieb:> Dann zeig deinen kompletten Code.> Das ist der Grund wieso hier immer alle Salami schreien.
Ich habe mir extra Mühe gegeben, nur den fraglichen Kram zu übermitteln,
damit man es sich nicht mühsam aus dem größeren Programm heraussuchen
muß.
Aber geheim ist der allerweltcode durchaus nicht:
1
// EPD-kpl-01-230507
2
// kompilierbar, Serial.print funktioniert, Lilygo auch
3
// erster Versuch mit lilygo213
4
// GxEPD_Hello World Example by Jean-Marc Zingg
5
// unnötiges Kram muß noch entfernt werden!
6
// Created by Jean-Marc Zingg based on demo code from Good Display,
7
// available on http://www.e-paper-display.com/download_list//downloadcategoryid=34&isMode=false.html
8
9
// include library, include base class, make path known
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.
VG
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, ...
Korrekt:
Egon M. schrieb:> Aber geheim ist der allerweltcode durchaus nicht:> ...
So schwer kann das doch nicht sein. Was meinst du, was mit dem Hinweis:
1
"Wichtige Regeln - erst lesen, dann posten!
2
...
3
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"
gemeint sein könnte?
Egon M. schrieb:> 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.
Bei der Ausgabe werden
- erst temp_links und temp_rechts in Strings umgewandelt
- dann auf dem Display ausgegeben
- dann werden neue Messwerte in temp_links und temp_rechts eingelesen
- aufgrund der neuen Messwerte werden die Kreise gezeichnet
Da in der loop ein delay von 15 Sekunden ist, weichen diese Werte stark
voneinander ab.
Soll das so sein?
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.
Foobar schrieb:> 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, ...
D a s war der richtige Einfall!
Ich habe es geändert und nun funktioniert es!
Vielen Dank.
VG
knut735
Bernhard M. schrieb:> 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.
Axel R. schrieb:> 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.
VG
knut735
Εrnst B. schrieb:> Warum packst du jeden DS18B20 an seinen eigenen OneWire Bus?
Das habe ich gemacht, weil ich es nicht besser wußte und auch noch keine
Beschreibung der neueren Busversion (gesucht und) gefunden habe.
Ich bin es noch gewohnt von PT100, DS18B20 usw., da hatte man jeweils
einen PIN und mußte dann reihum abfragen.
Ist ja heutzutage wunderbar einfach geworden mit den libraries für alles
und jedes. Allerdings gibt es nicht immer ein Manual.
Rainer W. schrieb:> Die Variablen mit dem anzuzeigenden Text passend dazu zu benennen, wäre> auch klarer, also z.B. textL/textR an Stelle von text1/text2.
Stimmt, war schnell hingeschrieben. Wird bei der nächsten Überarbeitung
besser.
Hallo mani
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.
VG
knut735
Egon M. schrieb:> 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.
Bernhard M. schrieb:> Bei der Ausgabe werden> - erst temp_links und temp_rechts in Strings umgewandelt> - dann auf dem Display ausgegeben> - dann werden neue Messwerte in temp_links und temp_rechts eingelesen> - aufgrund der neuen Messwerte werden die Kreise gezeichnet
Egon M. schrieb:> 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
oder ein
sensorsX.setWaitForConversion(true); im setup
helfen.
Edit: Ah, Ich war bei der Seriellen Ausgabe, nicht bei dem Grafik-Code.
& das setWaitForConversion(true) ist eh default.
Jens G. schrieb:> 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
Egon M. schrieb:> Jens G. schrieb:>> 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 ...
Egon M. schrieb:> temp_links = sensors1.getTempCByIndex(0);> temp_rechts = sensors2.getTempCByIndex(0);
Du musst diese beiden Zeilen nach oben an den Beginn der Funktion
Ausgabe() verschieben, noch vor
> dtostrf(temp_links , 5, 1, text1);> dtostrf(temp_rechts, 5, 1, text2);
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.
Egon M. schrieb:> D a s war der richtige Einfall!
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.