Forum: Compiler & IDEs ESP32-Wroom32 und Arduino / C-Code verursacht reset


von Alexander W. (Firma: AW-Elektronik) (alexanderwalter)


Angehängte Dateien:

Lesenswert?

Guten Morgen!

Ich versuche gerade mittels ESP32 auf einen Server zuzugreifen und diesem über JSON Status zu senden und dabei auch Befehle zu empfangen.

Ich verwende hierfür Arduino IDE v2 und den ESP32-Core 3.3.10 (aktuell). Getestet habe ich aber auch den Core 2.0.17 sowie 2.0.9

Die Verbindung baue ich über SSL auf. Ich habe einen merkwürdigen Fehler, den ich nur durch Falschinitialisierung meines Codes erklären kann, diesen Fehler aber nicht finde:

Der ESP resetet sich dabei selbst, wenn er die Funktion:

1
http.addHeader("Content-Type", "application/json");

aufruft. Kommentiere ich das aus (z.B.: durch ein return; davor), läuft der ESP32 stabil. Wichtig: der Reset tritt erst Minuten oder Stunden später auf. Die Abfrage erfolgt aber alle 10 Sekunden. Der Heap wird auch nicht fortlaufend kleiner sondern stabilisiert sich.

Der Resetcode für CPU0/1 sowie den ESP selbst sind dann 12/12 und 4

Der Server liefert die JSON nur als SSL aus und die json.php loggt mir auch die JSON-Frames vom ESP32. Bedeutet für mich, die Verbindung funktioniert.

Dabei spielt es keine Rolle ob ich

1
WiFiClientSecure server_client;
2
server_client.setInsecure();

setze oder nicht! Hier müsste eigentlich dann keine Daten ausgetauscht werden?

Frage: Könnte jemand über den Code drüber schauen und eventuell einen groben Schnitzer sehen der das Verhalten des ESP32 erklärt?

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Das ist kein C, das ist C++.

Abgesehen davon ist es beeindruckend schlechter Stil, sowas in einer *.h-Datei unterzubringen.

von Alexander W. (Firma: AW-Elektronik) (alexanderwalter)


Lesenswert?

Harald K. schrieb:

Das ist kein C, das ist C++.

Abgesehen davon ist es beeindruckend schlechter Stil, sowas in einer *.h-Datei unterzubringen.

Kannst du mir einen Lösungsweg zeigen?

von N. M. (mani)


Lesenswert?

Alexander W. schrieb:

Harald K. schrieb:

Das ist kein C, das ist C++.

Abgesehen davon ist es beeindruckend schlechter Stil, sowas in einer *.h-Datei unterzubringen.

Kannst du mir einen Lösungsweg zeigen?

Aufsplitten nach .h/.cpp. Statische Objekte anlegen. Zumindest für die großen Dinge wie den Client, die JSONs usw. Dann mit init der Objekte arbeiten.

Die Variablen haben im Header auch nichts zu suchen. Beim Intervall könnte man drüber streiten wenn es const wäre. Beim AskServerpreviousMillis nicht.

Die ganzen If sind auch unnötig. Wenn das erste If schon zuschlägt, warum sollte man alle anderen noch prüfen. Beispiel:

1
if (ChargingType == Solar_Charging)    { requestDoc["Modus"] = "Solar"; }
2
        if (ChargingType == Night_Charging)    { requestDoc["Modus"] = "Full";  }
3
        if (ChargingType == Charging_Disabled) { requestDoc["Modus"] = "Off";   }
von N. M. (mani)


Lesenswert?

Alexander W. schrieb:

Der Resetcode für CPU0/1 sowie den ESP selbst sind dann 12/12 und 4

4 ist ne Panic, oder? Dann wäre Speicher schon ein heißer Kandidat.

Include guards fehlen auch...

: Bearbeitet durch User
von Uwe (uhi)


Lesenswert?

Ich hatte ein sehr ähnliches Phänomen neulich. ESP32 mit Arduino, schickt alle 10s ein http an einen Server. Das geht ein paar Minuten gut, und dann resettet er. Bei mir ist offenbar die Ursache, dass die Internetverbindung zwischen Router und Anbieter ab und zu kurz aussetzt. Das WLAN bleibt stabil verbunden. Die "Standard-Implementierung" der Arduino/ESP-Bibliotheken läuft dann offenbar in einen Taskwatchdog.

Wie kann man das lösen? Ich hab die Problembeschreibung in ein Textfile gepackt, und dann Claude Opus machen lassen. Der hat dann etwas spekuliert, den Code und das serielle Log analysiert, Änderungen gemacht, und damit funktioniert es bei mir.

Details hier: https://github.com/uhi22/accucheck2/blob/main/doc/issues/issue1_resets_after_10_to_15_minutes.md

: Bearbeitet durch User
von Alexander W. (Firma: AW-Elektronik) (alexanderwalter)


Lesenswert?

Uwe schrieb:

Ich hatte ein sehr ähnliches Phänomen neulich

genau deine Beschreibung kommt mir sehr bekannt vor! Wir haben in der Tat sporadisch eine "lange Leitung". Aber der ESP-Core sollte doch so etwas abfangen können!

N. M. schrieb:

Aufsplitten nach .h/.cpp. Statische Objekte anlegen. Zumindest für die großen Dinge wie den Client, die JSONs usw. Dann mit init der Objekte arbeiten.

ok, das werde ich dann umsetzen! Der Code ist hier sehr alt (Core 2.0.9) und ich baue nun die weiteren Funktionen ein.

N. M. schrieb:

Die ganzen If sind auch unnötig. Wenn das erste If schon zuschlägt, warum sollte man alle anderen noch prüfen. Beispiel:

1
        if (ChargingType == Solar_Charging)    { requestDoc["Modus"] = "Solar"; }
2
        if (ChargingType == Night_Charging)    { requestDoc["Modus"] = "Full";  }
3
        if (ChargingType == Charging_Disabled) { requestDoc["Modus"] = "Off";   }
4
        if (Timer_Charging == true)            { requestDoc["Timer_Charging"] = "Enabled";  }
5
        else                                   { requestDoc["Timer_Charging"] = "Disabled

Das habe ich nicht verstanden? Eines der Modi vom Server soll halt übernommen werden, damit ich auch aus "der Ferne" die Box schalten kann. Nicht nur lokal!

oder meinst du diese Art:

1
requestDoc["Modus"] =
2
    (ChargingType == Solar_Charging)    ? "Solar" :
3
    (ChargingType == Night_Charging)    ? "Full"  :
4
    (ChargingType == Charging_Disabled) ? "Off"   :
5
                                          "";
6
7
requestDoc["Timer_Charging"] = Timer_Charging ? "Enabled" : "Disabled";

?

: Bearbeitet durch User
von N. M. (mani)


Lesenswert?

Alexander W. schrieb:

Das habe ich nicht verstanden?

Na wenn Modus "Solar" ist, dann kann es nicht mehr "Full" sein, oder? Also könnte man ein else if draus machen. Dann prüft er die weiteren Bedingungen nicht mehr wenn eine true ist.

von Jens K. (jensky)


Lesenswert?

N. M. schrieb:

Alexander W. schrieb:

Das habe ich nicht verstanden?

Na wenn Modus "Solar" ist, dann kann es nicht mehr "Full" sein, oder? Also könnte man ein else if draus machen. Dann prüft er die weiteren Bedingungen nicht mehr wenn eine true ist.

Aber Full oder Off! Lies sein Code noch einmal!

von N. M. (mani)


Lesenswert?

Jens K. schrieb:

Aber Full oder Off! Lies sein Code noch einmal!

OK, hab nicht aufgepasst und hab die Zuweisung der Variable zitiert anstatt die Prüfung. Im Handy ist der Umbruch des Codes etwas schlecht wenn man es nicht quer hält.

Ich schrieb ja er soll ein else if nehmen. Damit meinte ich dass ChargingType (nicht Modus) immer nur einen Wert haben kann. Deshalb macht meines Erachtens eine mehrfache Prüfung auf unterschiedliche Werte keinen Sinn.

Also so:

1
if (ChargingType == Solar_Charging)    { ...}
2
else if (ChargingType == Night_Charging)    { ...}
3
else if (ChargingType == Charging_Disabled) {...}

Bei der Wandlung der Response ist es das gleiche.

von Jens K. (jensky)


Lesenswert?

N. M. schrieb:

Also so:if (ChargingType == Solar_Charging) { ...} else if (ChargingType == Night_Charging) { ...} else if (ChargingType == Charging_Disabled) {...}

Bei der Wandlung der Response ist es das gleiche.

Letztendlich hilft das ihm halt überhaupt nicht, außer das wir und wichtig machen können!

von N. M. (mani)


Lesenswert?

Jens K. schrieb:

Letztendlich hilft das ihm halt überhaupt nicht, außer das wir und wichtig machen können!

Meinen Rat zum eigentlichen Problem hatte ich hier gegeben:

N. M. schrieb:

Aufsplitten nach .h/.cpp. Statische Objekte anlegen. Zumindest für die großen Dinge wie den Client, die JSONs usw. Dann mit init der Objekte arbeiten.

Das mit dem else if ist nicht notwendig, das stimmt. Trotzdem würde ich das optimieren. Spart er sich schon etwas Laufzeit.

von Harald K. (kirnbichler)


Lesenswert?

N. M. schrieb:

Also so:if (ChargingType == Solar_Charging) { ...} else if (ChargingType == Night_Charging) { ...} else if (ChargingType == Charging_Disabled) {...}

Statt langer "if-else-if-else"-Ketten kann man auch ein übersichtlicheres "switch/case" verwenden, vorausgesetzt, die Variable, die hier abgeprüft wird, ist kein String, sondern irgendwas ganzzahliges.

von N. M. (mani)


Lesenswert?

Bei ChargingType sieht man den Typ nicht. Könnte ein enum sein.

Unten bei der Response ist es klar:

1
responseDoc["Modus"].as<String>()

N. M. schrieb:

Bei der Wandlung der Response ist es das gleiche.

von Harald K. (kirnbichler)


Lesenswert?

N. M. schrieb:

Unten bei der Response ist es klar:

Sowas ist natürlich maximal ungünstig. Und dann noch lange if-else-Ketten, in denen ständig Strings miteinander verglichen werden.

von N. M. (mani)


Lesenswert?

Harald K. schrieb:

in denen ständig Strings miteinander verglichen werden

In Frontends/Webdiensten arbeitet man halt oft mit Strings/JSON. Dann kommst du um den Stringvergleich halt nicht drum rum...

von Harald K. (kirnbichler)


Lesenswert?

Schlecht gewählte Protokolle sind schlecht gewählte Protokolle. Aber macht ja nichts, man kann ja Rechenleistung und Speicher heute beliebig verballern, notfalls nimmt man halt 'nen fetteren und schnelleren µC.

von N. M. (mani)


Lesenswert?

Was wäre deiner Meinung nach ein verbreitetes Daten Austauschformat was bei Webdiensten geläufig ist, am besten nativ unterstützt wird und besser für schmalbrüstige Embedded Devices geeignet ist?

CBOR? BSON?

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Man kann auch mit Json andere Datentypen als Strings transportieren.

von Alexander (alecxs)


Lesenswert?

Nach http.end() würde ein delay(10) helfen den Speicher aufzuräumen.

Wenn die JSON Größe bekannt ist, reserviere den Speicher vorher.

Alexander W. schrieb:

Dabei spielt es keine Rolle ob ich WiFiClientSecure server_client; server_client.setInsecure(); setze oder nicht! Hier müsste eigentlich dann keine Daten ausgetauscht werden?

Wenn es keine Rolle spielt, dann lass es drin?

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.