Ich grüße Euch,
ich programmiere gerade meinen ersten µc. Ich habe ein Hochbeet, welches
automatisch gewässert, gelüftet und beleuchtet werden soll. Die
Messdaten dafür kommen von einem Xiaomi MiFlora Sensor. Die Auswertung
läuft über einen smarthomeng-Server, der mit dem ESP32 im Beet über MQTT
kommuniziert. Ausgangsbasis war dieser Code:
https://github.com/e6on/ESP32_MiFlora_MQTT
Jetzt funktioniert fast alles, für die verbliebenen Probleme erhoffe ich
mir hier Hilfe :)
Den gesamten Code habe ich als Textfile beigefügt.
Problem 1:
Der Eingang für den Schwimmer des Wassertanks soll sofort übertragen
werden. Der Interrupt macht aber nichts, heißt er wird einfach
ignoriert. Es könnte auch ein physischen Problem mit dem Schalter sein,
das überprüfe ich am WE
Problem 2:
Was kann ich in meinem loop optimieren hinsichtlich:
- mehr Energie-Effizienz, also weniger idle Rechenleistung während ich
auf MQTT Nachrichten oder Interrupts vom Input warte
- Selbstüberwachung: Der µc soll im Fehlerfall das Problem erstmal
versuchen durch einen Neustart zu lösen. Frage: Sind regelmäßige
geplante Reboots sinnig und wie würdet ihr sie umsetzen?
Problem 3:
Prinzipiell kommen die MQTT Nachrichten an. Nur bei "pumpe" passiert
nichts. Wahrscheinlich nur ein Tippfehler, aber ich finde ihn partout
nicht :(
Serial Monitor:
1
23:16:17.147 -> --Pin set HIGH; returning to main programm
2
23:16:17.147 -> Running loop
3
23:16:17.147 -> Running loop
4
23:16:22.355 -> -- connection alive, connect.loop sent
Im Interrupt Kontext darf man nicht beliebige API Funktionen aufrufen,
schon gar nicht Serial.print oder MQTT senden. Außerdem fehlt das
Attribut das die Funktion im RAM gehalten wird.
Suche erstmal nach Interruptprogrammierung des ESP.
Sicher das der pumpe topic gesendet wird? Zum testen würde ich eher
sowas wie MQTTExplorer verwenden.
Danke für deine Antwort.
Das Pumpen-Problem war tatsächlich ähnlich einfach wie angenommen: Da
das Signal des Wasser-Sensors fehlt, gibt der smarthomeng-Server das
Pumpenitem nicht frei. Deshalb wird nichts gesendet. Also gelöst.
Die Interruptprogrammierung werde ich mir dann mal zu Gemüte führen, mal
sehen, ob ich selbst auf die Lösung komme :)
Im ersten Go bin ich auf folgenden Artikel gestossen:
https://wolles-elektronikkiste.de/esp32-mit-arduino-code-programmieren#interrupts
Hier wird ein Interrupt über einen GPIO beschrieben, also eigentlich so
wie es bei mir auch geplant ist.
Die Krux: Ich halte den Interrupt so für völlig unnütz! Die ISR setzt ja
eine bool Variable, die dann im loop ausgelesen wird. Dann kann ich ja
auch einfach den Input im loop auslesen und mir den Interrupt sparen,
oder?
1
intinterruptPin=4;// define GPIO4 as interrupt pin
2
volatileboolevent=false;
3
4
voidIRAM_ATTReventISR(){
5
event=true;
6
detachInterrupt(interruptPin);
7
}
8
9
voidsetup(){
10
Serial.begin(115200);
11
while(!Serial){}
12
pinMode(interruptPin,INPUT_PULLDOWN);
13
attachInterrupt(interruptPin,eventISR,RISING);
14
}
15
16
voidloop(){
17
if(event){
18
Serial.println("Interrupt!");
19
delay(1000);//debouncing
20
event=false;
21
attachInterrupt(interruptPin,eventISR,RISING);
22
}
23
}
Wie würdet ihr den Eingang für den Schwimmerschalter überwachen?
Vielleicht einfach ein eigener Task, der den Sensor überwacht?
Ja du kannst deinen Schwimmerschalter auch regelmäßig in der loop
einlesen was für den Zweck vollkommen ausreicht.
Beim ESP kannst du auch keinen Strom sparen indem du in der loop weniger
nichts machst, nicht benutzte Rechenzeit wird immer irgendwo vertrödelt
- egal ob mit dem Code in der loop oder einem delay im Hintergrund.
Der Interrupt macht für Eingänge nur Sinn wenn das Signal so kurz
anliegt das die Gefahr besteht das es bei entsprechender Durchlaufzeit
der loop bis zur nächsten Abfrage schon wieder weg ist.
Sascha
Timo G. schrieb:> Sind regelmäßige geplante Reboots sinnig und wie würdet ihr sie> umsetzen?
Mikrocontroller laufen normalerweise viele Jahre lang fehlerfrei durch.
Wenn nicht, würde ich das gerne wissen um es beheben zu können.
Regelmäßige Neustarts doktorn am Symptom herum, ohne das Problem zu
lösen.
Der ESP8266 (vermutlich auch der ESP32) hat schon einen Watchdog, der
den Chip automatisch neu startet, wenn er hängt. Nach meiner Erfahrung
nützt das wenig, weil er kurz danach wieder Fehlfunktionen hat, und oft
sogar schon beim Booten (bevor die erste Zeile eigener Code ausgeführt
wird) stecken bleibt.
Ernsthaft Strom sparen kannst du nur, indem du WLAN deaktivierst oder
den light sleep Modus nutzt.
Steve van de Grens schrieb:> Mikrocontroller laufen normalerweise viele Jahre lang fehlerfrei durch.
So sollte es sein.
> Wenn nicht, würde ich das gerne wissen um es beheben zu können.> Regelmäßige Neustarts doktorn am Symptom herum, ohne das Problem zu> lösen.
Genau so ist das.
Sascha W. schrieb:> Der Interrupt macht für Eingänge nur Sinn wenn das Signal so kurz> anliegt das die Gefahr besteht das es bei entsprechender Durchlaufzeit> der loop bis zur nächsten Abfrage schon wieder weg ist.
Nicht nur dann. Sinnvoll ist ein Interrupt auch dann, wenn besonders
schnell darauf reagiert werden muss. Wenn man immer erst wartet, bis
loop() an der Abfrage vorbei kommt, kann es für manche Anwendungen zu
spät sein.
Im Fall des OP trifft beides nicht zu, da sollte man ohne Interrupt
arbeiten.
Timo G. schrieb:> Hier wird ein Interrupt über einen GPIO beschrieben, also eigentlich so> wie es bei mir auch geplant ist.
Das ist ja nur eine Demo, die zeigen soll, wie man mit Interrupts
umgehen kann. Sie sagt nicht, unter welchem Umständen das sinnvoll ist.
Übrigens steckt da ein "Makel" drin, den man immer wieder sieht. Wozu
denn in der ISR den Interrupt aushängen und später wieder einhängen? Das
führt in vielen Szenarien zu gelegentlichen Fehlern.
Was passiert z. B., wenn das nächste Ereignis erscheint, während die ISR
gerade ausgehängt ist? Dann wird es unter Umständen nicht erkannt.
Besser lässt man die ISR ständig eingehängt und lässt sie (oder loop)
entscheiden, ob sie das Ereignis ignorieren will oder nicht.
Klar, man kann immer Gegenbeispiele für obige Argumente finden. Aber die
sinnvolle Grundregel ist IMHO so.
Timo G. schrieb:> Wie würdet ihr den Eingang für den Schwimmerschalter überwachen?> Vielleicht einfach ein eigener Task, der den Sensor überwacht?
Mir scheint, du bist auf den falschen Zeitskalen unterwegs.
Auch wenn ein richtige Flutwelle über dein Beet schwappt und es
innerhalb von Bruchteilen von Sekunden flutet, nützt es dir überhaupt
nichts, den Sensor im Mikrosekundenbereich auszuwerten. Was willst du
dadurch veranlassen?
Timo G. schrieb:> Der Eingang für den Schwimmer des Wassertanks soll sofort übertragen> werden.
Was heißt in diesem Zusammenhang "sofort"?
Wie zeitkritisch ist diese Meldung?
µs[ ], ms[ ] oder s[ ] (zutreffendes bitte ankreuzen)
Vielen Dank für eure Antworten und euren Input!
Der ESP läuft, momentan noch auf einem Breadboard, am Blumenbeet.
Bislang läuft alles wie erhofft, jetzt stehen erstmal die Restarbeit am
Beet selbst an.
Steve van de Grens schrieb:> Der ESP8266 (vermutlich auch der ESP32) hat schon einen Watchdog, der> den Chip automatisch neu startet, wenn er hängt.
Den Watchdog habe ich auch schon entdeckt =) Du hast natürlich recht, er
löst keine Code Probleme, aber er ist ja nunmal da.
Steve van de Grens schrieb:> Ernsthaft Strom sparen kannst du nur, indem du WLAN deaktivierst oder> den light sleep Modus nutzt.
Also WLAN ausschalten geht schonmal nicht, das Beet muss ja Befehle via
MQTT empfangen können. sleep ist eine gute Idee, um das Beet nachts
länger zu pausieren. Da reicht es ja, wenn es alle 1-2h aufwacht, der
Server ggf. die Lüftung verfährt und ihn danach wieder schlafen schickt.
Das wäre dann aber ziemlich weit unten auf der ToDo Liste.
Rainer W. schrieb:> Mir scheint, du bist auf den falschen Zeitskalen unterwegs.> Auch wenn ein richtige Flutwelle über dein Beet schwappt und es> innerhalb von Bruchteilen von Sekunden flutet, nützt es dir überhaupt> nichts, den Sensor im Mikrosekundenbereich auszuwerten. Was willst du> dadurch veranlassen?
Ja, da hast du definitiv recht. Wenn der Sensor "leer" anzeigt, zieht
die Pumpe ja nicht direkt Luft. Insofern:
Rainer W. schrieb:> Was heißt in diesem Zusammenhang "sofort"?> Wie zeitkritisch ist diese Meldung?> µs[ ], ms[ ] oder s[x] (zutreffendes bitte ankreuzen)
Ich habe jetzt folgendes im loop stehen:
1
// check if input changed
2
if(!wasserstand==digitalRead(waterSensorPin)){
3
Serial.println("input changed - sending value");
4
delay(500);
5
wasserstand=digitalRead(waterSensorPin);
6
MQTTsendWLL();
7
}
Das funktioniert wie gewünscht. Das delay von 500ms soll den Sensor
etwas entprellen, dass nicht ständig eine Änderung geschickt wird wenn
der Schwimmer umschaltet und die Pumpe so zum stottern bringt.
Ich schreibe einfach mal hier weiter und mache keinen neuen Post dafür
auf:
Kaum läuft die erste Version, habe ich schon erste Veränderungen im
Sinn. Denn der µc muss sowieso nochmal getauscht werden. Der WLAN
Empfang der onboard Antenne lässt zu wünschen übrig und derzeit steht
deshalb Repeater vor der Terassentür. Also will ich auf einen Seeed Xiao
wechseln, da ich hier eine "richtige" WLAN Antenne anschließen kann.
Außerdem läuft alles derzeit noch auf einem Breadboard, auch kein
Dauerzustand. Die Schaltung von Beleuchtung (12V LED Streifen,
definitive Länge und damit Stromverbrauch steht noch nicht fest),
Bewässerungspumpe (12V 5A Membranpumpe) und Linearmotor für die
Beetöffnung läuft derzeit über eine fertige 4 Kanal Relais + 1 Finder
Doppelrelais für die Polaritätsumkehr des Linearantriebes. Für die
Zukunft möchte ich den Anschluss für eine kleine Schlauch-/Dosierumpe
für Düngemittel vorsehen. Funktioniert alles, finde es aber irgendwie
nicht elegant genug. Außerdem nutze ich meine Projekte ja immer um etwas
zu lernen.
Von Euch erhoffe ich mir nun Input zu folgenden Fragen:
- Welche Art der Ansteuerung könnt ihr mir für welchen Ausgang
empfehlen?
- Wo finde ich einen guten Artikel zum Thema "Welche Last wie schalten"?
Meine aktuelle Idee:
- 2 Kanal Motortreiber für Linearantrieb (wg. Richtungswechel) und
Dosierpumpe (PWM zur feinen Dosierung)
- FET oder Relais für LED-Licht: FET könnte man zwar dimmen, aber
braucht man das in diesem Anwendungsfall?
- Relais + ?Kondensator? für Bewässerungspumpe: Hier habe ich in der
Hauptsache Sorge um den µc, da er via 7805 an der selben 12V
Spannungsversorgung hängt. Kondensator dann im 12V Teil oder im 5V Teil?
Vielen Dank für Euren Input