Forum: Mikrocontroller und Digitale Elektronik ESP32-C3 als Accesspoint - wie fehlersicher machen?


von Tom H. (toemchen)


Lesenswert?

Hallo zusammen,

meist schreibe ich zuviel, deshalb hier zunächst in Kurzform:

ESP32-C3 als Accesspoint konfiguriert.
Alles mit Arduino IDE gebastelt.
Die Sketches sind noch sehr einfach und eindimensional, alles mit Hilfe 
der Anleitungen auf randomnerdtutorial.com gelernt.
Android-Handy mit AP verbunden, simple Website mit ein paar Texten und 
Buttons.

Steigt immer wieder aus.
Noch weiß ich nicht, ob der ganze ESP ins Stocken gerät oder ob es nur 
die Verbindung ist.

Was gibt es für Konzepte, den AP neu zu starten?
Was gibt es für Konzepte, die Verbindung mit dem Handy schneller 
herzustellen?

Mehr Salamischeiben in den nächsten Posts...
Viele Grüße
Tom.

von Tom H. (toemchen)


Lesenswert?

Ich hatte mich bereits in einem anderen Thread für die grundsätzlichen 
Techniken interessiert: 
Beitrag "Peak-Ignitor - Mini 120W Powerbank"
Diesen will ich aber nicht weiter kapern.

Dort schrieb Vanye, das Verfahren wäre ein "pain in the ass", und ich 
beginne zu ahnen...

Allerdings hat es zunächst ziemlich schön funktioniert.
Ja, es ist toll und erschreckend zugleich, wie einfach man sich 
heutzutage so etwas zusammenschrauben kann, wo man gerade noch keine 
Ahnunge davon hatte.
Es ist ein bißchen so, daß erst beim Dazuschalten eines bestimmeten 
Verbrauchers (Danfoss 12V-Kühlschrankkompressor mit eigener 
BLDC-Elektronik) die Sache aussteigt.

Kann also auch sein, daß es einfach handfeste Störungen sind, die den 
kompletten ESP32 zum Absturz bringen.

Werde jetzt mal mit der Onboard-LED ein "heartbeat" signal dazufügen, 
damit ich sehe, ob das Programm weiterläuft.

Allerding kann ich mich auch im dem Fall, daß die Sache ins Stocken 
gerät, immer wieder ins vom ESP32 als AP aufgespannte WLAN einbuchen, 
nur das Aufrufen der Website geht nicht mehr.

von Tom H. (toemchen)


Lesenswert?

Und ebenfalls in dem bereits genannten Thread 
Beitrag "Peak-Ignitor - Mini 120W Powerbank" war von "Captive 
Portal" die Rede, also daß beim Verbinden mit dem AP sofort eine 
bestimmte Website aufgeht. Das würde mich schwer interessieren. Ist das 
programmtechnisch aufwendig?

von Tom H. (toemchen)


Angehängte Dateien:

Lesenswert?

Ich poste jetzt mal den Sketch, ist leider schon etwas vollgeladen. Wenn 
nötig, kürze ich ihn etwas, so daß nur 1 Kanal bedient wird. Vieles 
darin wird ja viermal wiederholt.

Ich kann nicht sagen, daß ich ihn vollends verstehe. Komisch kommt mir 
vor, daß nach meinem Verständnis in der loop immer die Verbindung zum 
Client hergestellt wird, dann wird an einer Stelle der loop gewartet, 
bis der http-Request vom Client vollständig ist, dann wird verarbeitet 
und die Verbindung wieder geschlossen.
Wie gesagt bin ich blutiger Anfänger, aber mir kommt das komisch vor...

Lustigerweise kann man den Code hier nicht reinschreiben, auch wenn man 
ihn mit code und /code kapselt. Also nur als Datei.

von Alexander (alecxs)


Lesenswert?

Tom H. schrieb:
> Ich kann nicht sagen, daß ich ihn vollends verstehe.

Woher stammt der Code wenn nicht von Dir?

Vanye R. schrieb:
> Damit kommen verschiedene Apps auf dem Handy nicht so recht klar die
> gerne im Internet sind und Android wechselt dann gerne zwischendurch mal
> wieder zurueck.

Ist mir noch nicht so aufgefallen. Ich hatte anfangs das Problem. Mit 
der Einrichtung des Captive Portals war es (zumindest auf Android) okay.

Tom H. schrieb:
> Das würde mich schwer interessieren. Ist das programmtechnisch
> aufwendig?

randomnerdtutorials.com ist immer eine gute Anlaufstelle. Ich empfehle 
Dir folgende Vorgehensweise.

Du richtest Dir erstmal ein Beispielprojekt ein für den Webserver. Ich 
empfehle ESPAsyncWebserver.

Statt HTML aus dem Sketch (PROGMEM) zu senden, kannst Du auch gleich auf 
das LittleFS Dateisystem zurückgreifen und deine index.html direkt als 
Datei ablegen.

Wenn das soweit läuft kannst Du das Captive Portal da mit einbauen. Ich 
hab das 1:1 so übernommen.

https://en.wikipedia.org/wiki/Captive_portal#Detection

Zum Schluss bastelst Du Dein eigentliches Projekt in den Sketch mit 
rein. Wenn Du es sauber machen willst dann trenne es gleich auf mehrere 
Dateien auf (idealerweise sogar C/C++ konform mit echten .h Header und 
.cpp Source Dateien und den korrekten Includes, aber einfache .ino 
reicht auch für den Anfang)

Die Werte stellst Du dann auf dem Webserver als JSON bereit, dann kannst 
Du das clientseitig mit der HTML in JS auslesen. Dafür empfehle ich 
ArduinoJson von bblanchon.

Das ganze häppchenweise umsetzen, so dass Du auch den Code verstehst den 
Du schreibst.

Bzgl. deines Heartbeats - Du könntest einen Watchdog einrichten der den 
ESP32-C3 neustartet.

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


Lesenswert?

Ja, mach statische HTML Dateien. Wo ist fast egal. Ich würde sie auch in 
ein Filesystem legen. Alles ist besser als dieses String gebastel.

Und dann über JS fetch die aktuellen Daten (Zustände der Lüfter, 
Temperaturen usw) abholen.
Dann muss nur einmal die Seite ausgeliefert werden und ab dem Zeitpunkt 
nur noch kleine Datenmengen, nämlich die Prozessdaten.

von Nemopuk (nemopuk)


Lesenswert?

Der ESP8266 hat im Vergleich nur ca. 5kB Stack. Die sind mit 
String-Operationen schnell gesprengt. Vielleicht ist das beim ESP32 
ähnlich. Ich habe da was von 8kB gelesen.

Ansonsten würde ich mal die Stromversorgung mit einem Oszilloskop 
prüfen. Oft sind Kabel zu dünn, Kontakte zu hochohmig und 
Spannungsregler zu knapp bemessen. Dann hilft ein Elko mit 220 uF 
zwischen 3,3V und GND.

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Nemopuk schrieb:
> Der ESP8266 hat im Vergleich nur ca. 5kB Stack. Die sind mit
> String-Operationen schnell gesprengt. Vielleicht ist das beim ESP32
> ähnlich. Ich habe da was von 8kB gelesen.

Wie kommst Du auf diese interessanten Zahlen?

von Nemopuk (nemopuk)


Lesenswert?

Nemopuk schrieb:
> Der ESP8266 hat im Vergleich nur ca. 5kB Stack.

Ups, da fehlt was: Er hat im Vergleich zum größeren Heap nur ca. 5kB 
Stack.

Harald K. schrieb:
> Wie kommst Du auf diese interessanten Zahlen?

Die 5kB habe ich bei einem akuten Problem durch Ausprobieren 
herausgefunden. Die 8kB nennt Copilot für den ESP32.

: Bearbeitet durch User
Beitrag #8019433 wurde vom Autor gelöscht.
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Das Arduino setup und loop läuft beim ESP32 in einer FreeRTOS Task.
Dieser werden 5k Stack zu geordnet.

Nemopuk schrieb:
> Die sind mit
> String-Operationen schnell gesprengt.

String Instanzen belegen nur wenig Stack.
Die (inneren) Strings landen auf dem Heap.

: Bearbeitet durch User
von Nemopuk (nemopuk)


Lesenswert?

Arduino F. schrieb:
> String Instanzen belegen nur wenig Stack.
> Die (inneren) Strings landen auf dem Heap.

Ja stimmt. Ich meinte auch nicht speziell die String Klasse, sondern das 
Bearbeiten von Zeichenketten allgemein.

Beim Heap kommt noch die Fragmentierung dazu, was durch die parallele 
Verarbeitung von HTTP Requests nicht gerade entschärft wird. PC 
Programmierer kennen das kaum noch, aber auf Geräten mit < 1MB RAM ist 
es wichtig.

Der bereits empfohlene Ansatz mit statischen HTML/Javascript Dateien in 
Kombination separaten JSON Requests passt schon.

: Bearbeitet durch User
von Nick (b620ys)


Lesenswert?

In dem generierten HTML steht "&uuml", das muss "&uuml;" heissen. Gilt 
natürlich für ähnliche Codierungen auch.

Der Rest ist wenig strukturiert, alles in die loop geworfen und 
umgerührt.

von Rüdiger B. (rbruns)


Lesenswert?

Ich habe bei der Anzeige von OSM Kacheln vom Browser vom ESP32 auch 
Probleme gehabt, ich musste im SD-CARD Treiber die Anzahl Files erhöhen, 
frisst aber viel RAM.

: Bearbeitet durch User
von Tom H. (toemchen)


Angehängte Dateien:

Lesenswert?

Puh, danke, Ihr überfordert mich natürlich für den Moment...

Aber bis vor einer Woche hatte ich nicht gedacht, daß ich jemals einen 
ESp rpogrammieren werde und darauf ein Webserver läuft - ich werd mich 
also schon durchbeißen.

Soweit ich das aus randomnerdtutorials.com übernommene Script verstanden 
habe, geht die Kommunikation über das Senden von http requests, bei der 
"Varianten" der Website aufgerufen werden.
(Verzeiht mir die ahnungslose, und andere Anfänger vielleicht 
verwirrende Nomenklatur - ich stehe erst am Anfang)
Und da ahne ich liegt die Krux: Das Handy hüpft gerne auf 
zwischengespeicherte Links (z.B. 192.168.4.1/Luefter/on statt 
192.168.4.1/Luefter/off) und den bekommt es dann nicht?

WLAN-Reichweite brauch ich Gottseidank auch nicht, Handy und ESP sind 
nur einen halben Meter voneinander entfernt. (Das schreib ich, weil in 
einem anderen aktuellen Thread davon die Rede ist.) Kann sich aber 
ändern, wenn der ESP in ein großes Gehäuse aus Alu-Dibond gesteckt wird. 
Aber vermutlich bringe ich ihn dann in einem "Erker" aus Kunststoff 
außerhalb an.

Vielleicht aber statt der komischen Programmstruktur doch einfache 
Verbindungsprobleme. Manchmal braucht es eine Minute und mehr, dann 
kommt der request auf einmal doch durch und der Lüfter springt an...

Gestern war ich mit dem Gebilde zunächst in der Werkstatt, dort gab es 
viele Verbindungsprobleme. Danach an meinem Büro-Platz, dort gab es gar 
kein Problem mehr. Heute zuhause im Bastelkeller, da funktioniert es 
wieder überhaupt nicht.

Ich stell das jetzt ein paar Tage zurück und gehe zurück auf die 
USB-Verbindung, ich muß die Performance eines Kühlsystems mit ein paar 
Temperatursensoren testen.

Zur Auflockerung ein Bild vom Verwendungszweck des ESP: Steuerung des 
Kompressors eines Kühlanhängers im Maßstab 1:8

von Tom H. (toemchen)


Lesenswert?

Nick schrieb:
> In dem generierten HTML steht "&uuml", das muss "&uuml;" heissen. Gilt
> natürlich für ähnliche Codierungen auch.
> Der Rest ist wenig strukturiert, alles in die loop geworfen und
> umgerührt.

Das mit dem &uuml wird gleich repariert, scheint aber kein Problem 
gewesen zu sein.

Ja, unstrukturiert, mein Problem beim Programmieren. Das hab ich nie 
"von der Pike auf" gelernt. Und meistens beschränkt es sich darauf, 
(relativ einfache und wenig strukturierte) Programmbeispiele zu nehmen 
und auf meine Bedürfnisse aufzubohren.
Richtig ordentliche Projekte auf github kann ich dafür wieder nicht 
lesen und verstehen. Für mich ist das ein Wust aus 100er ten Dateien, 
und in jeder stehen nur drei Definitionen und zwei Funktionen.

Gerne nehme ich Tipps an, wo ich lernen kann, wie ein modernes und 
sauberes Software aufgezogen wird. Also quasi ein Anfängerkurs in 
Software-Entwicklung. Wo gibt es sowas?

von Nemopuk (nemopuk)


Lesenswert?

Tom H. schrieb:
> Das Handy hüpft gerne auf zwischengespeicherte Links (z.B.
> 192.168.4.1/Luefter/on statt 192.168.4.1/Luefter/off) und den bekommt es
> dann nicht?

Wie dein Handy von "on" zu "off" kommt weiß ich nicht. Aber ich kenne 
eine einfache Methode, sämtliche Caches zu umgehen: Hänge die 
fortlaufenden Millisekunden an die URL an. Zum Beispiel 
http://192.168.4.1/Luefter/on?ts=15af6c30

(Hexadezimal ist für den Mikrocontroller weniger aufwändig als Dezimal)

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Nemopuk schrieb:
> Die 5kB habe ich bei einem akuten Problem durch Ausprobieren
> herausgefunden. Die 8kB nennt Copilot für den ESP32.

Auf praktisch jeder* Mikroprozessorarchitektur der vergangenen 50 Jahre 
teilen sich Heap und Stack den Speicherbereich, den man ihnen dafür zur 
Verfügung stellt. Eine harte Begrenzung des einen oder anderen ist 
ausgesprochen ungewöhnlich.

Vielleicht meinst Du ja das, was das IDF Dir bei einer bestimmten 
Konfiguration und dem statischen Speicherverbrauch Deines Programms 
übriglässt.



*) es gibt sehr kleine µCs, die einen Hardwarestack haben, aber der ist 
dann wirklich nur eine Handvoll Bytes groß. Solche µCs programmiert man 
dann i.d.R. nicht in einer Hochsprache.

von Nemopuk (nemopuk)


Lesenswert?

Harald K. schrieb:
> Vielleicht meinst Du ja das, was das IDF Dir bei einer bestimmten
> Konfiguration und dem statischen Speicherverbrauch Deines Programms
> übriglässt.

Natürlich meine ich das.

von Alexander (alecxs)


Lesenswert?

Tom H. schrieb:
> Für mich ist das ein Wust aus 100er ten Dateien, und in jeder stehen nur
> drei Definitionen und zwei Funktionen.

Das ist doch gut. Das sind die Häppchen die Du brauchst.

von Chris K. (kathe)


Lesenswert?

Tom H. schrieb:
> Gestern war ich mit dem Gebilde zunächst in der Werkstatt, dort gab es
> viele Verbindungsprobleme. Danach an meinem Büro-Platz, dort gab es gar
> kein Problem mehr. Heute zuhause im Bastelkeller, da funktioniert es
> wieder überhaupt nicht.

Wie kannst du von deinem Handy garantieren das du immer den AP des ESP 
erreichst und nicht zufällig im WLAN der Umgebung eingebucht bist ?
Wenn du im WLAN der Umgebung bist klappt die Verbindung zum ESP nicht da 
sicherlich ein anderer Adressrange  DNS  DHCP dir die Route über den 
Router verändern.

Hast du ein Tab von dem du alle WLAN Zugriffspunkte löschen kannst und 
nur das dieses ESP einrichtest. Mit dem kannst du dann versuchen in 
allen Umgebungen.

von Tom H. (toemchen)


Lesenswert?

Natürlich schaue ich ständig zwischendurch nach, ob das Handy noch auf 
dem AP des ESP32 eingebucht ist.
Wenn ich den ESP32 neu starte, dann fällt das Handy natürlich auf das 
normale WLAN zuhause oder im Büro zurück. Dann muß ich über die 
entsprechenden Einstellungen des Handys wieder das WLAN "Augustiner" des 
ESP anwählen.

In den Fehlerfällen, die mir hier zu schaffen machen, ist das Handy aber 
weiterhin im "Augustiner" WLAN.
Für einen Versuch, den Fehler zu bereinigen, muß ich das Handy extra auf 
das normale WLAN buchen und dann wieder zurück auf das "Augustiner". Das 
Verbinden klappt - demnach ist der ESP nicht vollständig ausgestiegen. 
Das Aufrufen der Website klappt danach trotzdem nicht.

: Bearbeitet durch User
von Alexander (alecxs)


Lesenswert?

Hast Du mal mobile Daten deaktiviert?

von Alexander (alecxs)


Angehängte Dateien:

Lesenswert?

Alexander schrieb:
> Wenn das soweit läuft kannst Du das Captive Portal da mit einbauen. Ich
> hab das 1:1 so übernommen.
> https://en.wikipedia.org/wiki/Captive_portal#Detection

Ich hab Dir mal eine Demo zusammenkopiert. Es kompiliert nur mit den 
nötigen Libs die Du im Arduino Library Manager selbst installieren 
musst.

- github.com/bblanchon/ArduinoJson
- github.com/ESP32Async/ESPAsyncWebServer
- github.com/ESP32Async/AsyncTCP (die ohne den ESP Prefix)

Zum speichern des `data` Ordners benötigst Du das ESP32 LittleFS Add-on, 
hier eine Anleitung zum installieren.

https://randomnerdtutorials.com/arduino-ide-2-install-esp32-littlefs

Alexander schrieb:
> Die Werte stellst Du dann auf dem Webserver als JSON bereit, dann kannst
> Du das clientseitig mit der HTML in JS auslesen.

Den JSON String kannst Du Dir über 192.168.4.1/data.json ansehen, sieht 
dann ungefähr so aus.
1
{
2
  "example1":
3
  {
4
    "key1":0,
5
    "key2":0,
6
    "key3":0,
7
    "key4":0
8
  }
9
}
Das können natürlich auch Booleans sein die Du mit irgendwelchen Buttons 
verknüpfst (statt 192.168.4.1/Luefter/off) das JSON Schema und die Namen 
sind frei wählbar.

Am besten den ganzen JS Demo Block rauslöschen und selbst was erstellen. 
Vielleicht sogar was generisches was die Namen der globalen Variablen 
aus den JSON Labels dynamisch rekonstruiert, dann braucht man nicht 
alles hardcoden.

: Bearbeitet durch User
von Tom H. (toemchen)


Lesenswert?

Mobile Daten: Ich hab so das Gefühl, daß es damit nichts zu tun hat. 
Aber es ist schnell ausprobiert - ich mach das bald.

Die ganzen anderen Infos, ja fast ein Tutorial:
Wow, danke!

Das nehme ich ernst und versuche, es auszuprobieren und zu verstehen. 
Vielleicht noch nicht heute abend. Aber ganz bestimmt bald.

Nochmal vielen Dank für diese Hilfe und die Mühe, die Du Dir mit mir 
gibst.

von Alexander (alecxs)


Lesenswert?

Noobs helfen Noobs, die Profis halten sich raus.

Es gibt auch Fertiglösungen mit MQTT. Home Assistant, Tasmota, Zigbee 
und wie die alle heißen, aber bisher noch keine Lust gehabt was zu 
testen.

von Tom H. (toemchen)


Angehängte Dateien:

Lesenswert?

Hatte bis jetzt nicht den Eindruck, daß Du ein Noob bist.

Das Abschalten der mobilen Daten hat keine Veränderung gebracht.

Eine reine Reichweitengeschichte ist es wohl nicht. Um zu sehen, ob eine 
zwischendurch abreißende Verbindung die Sache ins Stocken bringt, habe 
ich mich recht weit vom AP entfernt: Eine Stahlbetondecke und ein 
weiteres Stockwerk dazwischen. Spaßeshalber ausprobiert - es ging da 
immer noch! (solange es halt ging.)

Die Ausfälle sind also meiner Meinung nach unabhängig von der Entfernung 
(= Signalstärke) da, sporadisch bis häufig.

Auch wenn vielleicht der radikale Umbau des Programms in Richtung 
statischer HTML, in einem Filesystem, mit lediglich dem Austausch der 
wenigen Prozessdaten, zielführender wäre  -  ich habe jetzt das 
existierende Programm nochmal aufgeräumt und Funktionen ausgelagert, so 
daß das, was in der loop passiert, auf eine Bildschirmseite passt.

Ich verstehe es schon ein bißchen besser, und möchte es ganz verstehen.

Bei den Ausfällen bleibt die serielle Ausgabe nach "New Client" stehen, 
es wird kein empfangenes Byte angezeigt. Als nächstes werde ich in 
dieser Gegend des Programmtextes Debug-Meldungn einbauen, um zu sehen, 
ob da noch was läuft und an welcher Stelle er kreist.

von Alexander (alecxs)


Lesenswert?

Mach mal ein kleines delay(10) rein in die while Schleife, die rennt 
sonst weg. Und ein größeres delay(100) in der main loop kann auch nicht 
schaden.
1
    while (client.connected()) {
2
      if (client.available()) {
3
        ...
4
        } else if (c != '\r') {
5
          currentLine += c;
6
        }
7
      } else {      // <-
8
        delay(10);  // <- hier
9
      }             // <-
10
    }
11
    // Clear the header variable
12
    header = "";
13
    // Close the connection
14
    client.stop();
15
    // Close the connection
16
    client.stop();
17
    Serial.println("Client disconnected.");
18
    Serial.println("");
19
    delay(100);  // <- hier
20
  }
21
  delay(100); // <- und hier
22
}

von Richie (mikro123)


Lesenswert?

Harald K. schrieb:
> Nemopuk schrieb:
>> Die 5kB habe ich bei einem akuten Problem durch Ausprobieren
>> herausgefunden. Die 8kB nennt Copilot für den ESP32.
>
> Auf praktisch jeder* Mikroprozessorarchitektur der vergangenen 50 Jahre
> teilen sich Heap und Stack den Speicherbereich, den man ihnen dafür zur
> Verfügung stellt. Eine harte Begrenzung des einen oder anderen ist
> ausgesprochen ungewöhnlich.
>
> Vielleicht meinst Du ja das, was das IDF Dir bei einer bestimmten
> Konfiguration und dem statischen Speicherverbrauch Deines Programms
> übriglässt.
>
>
>
> *) es gibt sehr kleine µCs, die einen Hardwarestack haben, aber der ist
> dann wirklich nur eine Handvoll Bytes groß. Solche µCs programmiert man
> dann i.d.R. nicht in einer Hochsprache.


Die Stackgröße läßt sich ja frei einstellen:

1
// This sets Arduino Stack Size - comment this line to use default 8K stack size
2
SET_LOOP_TASK_STACK_SIZE(16 * 1024);  // 16KB
3
4
void setup() {
5
  Serial.begin(115200);
6
7
  Serial.printf("Arduino Stack was set to %zu bytes", getArduinoLoopTaskStackSize());
8
9
  // Print unused stack for the task that is running setup()
10
  Serial.printf("\nSetup() - Free Stack Space: %u", uxTaskGetStackHighWaterMark(NULL));
11
}

Siehe Arduino-IDE:
Files->Examples->ESP32-ArduinoStackSize

von Obelix X. (obelix)


Lesenswert?

Alexander schrieb:
> Mach mal ein kleines delay(10) rein in die while Schleife, die rennt
> sonst weg. Und ein größeres delay(100) in der main loop kann auch nicht
> schaden.

Gar nicht erst angewöhnen überall delays zu verwenden. Das ist oft Müll, 
da in dieser Zeit nichts anderes ausgeführt wird.

z.B. statt (Pseudocode)
1
loop() {
2
  LED = on;
3
  delay(1000);
4
  LED = off;
5
  delay(1000);
6
7
  do something;
8
}

lieber
1
timer = millis();
2
3
loop() {
4
  if (timer < millis()) {
5
    timer = millis() + 1000;
6
    LED = toggle;
7
  }
8
9
  do something;
10
}

Hätte auch den Vorteil, das die 1000ms besser eingehalten werden wenn 
"do something" etwas mehr Zeit benötigt.

von Alexander (alecxs)


Lesenswert?

Obelix X. schrieb:
> Gar nicht erst angewöhnen überall delays zu verwenden. Das ist oft Müll,
> da in dieser Zeit nichts anderes ausgeführt wird.

Ähm.. hast Du dir den ganzen Code mal angesehen?

von Nemopuk (nemopuk)


Lesenswert?

Tom H. schrieb:
> Die Ausfälle sind ... sporadisch bis häufig.


Hast du das geprüft?:

Nemopuk schrieb:
> Ansonsten würde ich mal die Stromversorgung mit einem Oszilloskop
> prüfen. Oft sind Kabel zu dünn, Kontakte zu hochohmig und
> Spannungsregler zu knapp bemessen. Dann hilft ein Elko mit 220 uF
> zwischen 3,3V und GND.

von Tom H. (toemchen)


Lesenswert?

Nemopuk schrieb:
> Tom H. schrieb:
>> Die Ausfälle sind ... sporadisch bis häufig.
> Hast du das geprüft?:
> Nemopuk schrieb:
>> Ansonsten würde ich mal die Stromversorgung mit einem Oszilloskop
>> prüfen. Oft sind Kabel zu dünn, Kontakte zu hochohmig und
>> Spannungsregler zu knapp bemessen. Dann hilft ein Elko mit 220 uF
>> zwischen 3,3V und GND.

Bis jetzt noch nicht. Heute abend werde ich den ESP mittels dünner Kabel 
vom momentanen Sockel auf meiner Lochraster-Platine wegverlängern (ca. 
12-15cm), damit ich das USB-Kabel bequem einstecken kann.
Dann wird diese Gefahr höher.
Dann werde ich auf jeden Fall ohne/mit zusätzlichen Stützelko prüfen.

(Stützelko ist ein komisches Wort... vielleicht besser Stütz-Elko)

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Tom H. schrieb:
> vielleicht besser Stütz-Elko

Nein!

von Alexander (alecxs)


Lesenswert?

Willst du eine saubere Katze haben,

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Obelix X. schrieb:
> Gar nicht erst angewöhnen überall delays zu verwenden. Das ist oft Müll,
> da in dieser Zeit nichts anderes ausgeführt wird.

Da auf ESP32, zumindest in der Arduino Welt, FreeRTOS läuft, führt ein 
solches delay() zu Scheduler Aufrufen. Also zu Taskwechseln.
Die Zeit ist also nicht unbedingt verplempert, da eben was anderes 
ausgeführt wird.

von Obelix X. (obelix)


Lesenswert?

Arduino F. schrieb:
> Die Zeit ist also nicht unbedingt verplempert, da eben was anderes
> ausgeführt wird.

Vom FreeRTOS schon aber von deinem eigenen Programm nicht.

Beispiel aus eigener Erfahrung : Ich hatte eine Lib für animierte GIFs 
verwendet. Die meisten Leute verwenden wohl nur ein GIF. Ich hingen 
wollte zwei oder mehr animierte GIFs gleichzeitig anzeigen. Aber sch... 
was das, die laufen nur im Schneckentempo. Ist halt super, wenn die Zeit 
zwischen zwei Frames mit delay gelöst wurde. Außerdem sollte mein 
Programm ja noch etwas anderes machen außer die GIFs anzeigen.

Alexander schrieb:
> Ähm.. hast Du dir den ganzen Code mal angesehen?

Was meinst du genauer?

: Bearbeitet durch User
von Alexander (alecxs)


Lesenswert?

Die main loop hängt zwischen `while (client.connected())` und `if 
(client.available())` mit 100% CPU Last fest (oder 50% beim Dual-core). 
Der ganze Programmaufbau ist blocking.

von Obelix X. (obelix)


Lesenswert?

Alexander schrieb:
> Die main loop hängt zwischen `while (client.connected())` und `if

Was ist die Schlussfolgerung daraus? Du musst die while-Schleife 
zwischendurch mal verlassen, den Rest von loop() ohne delay abarbeiten, 
und bei dem nächsten Durchlauf von loop() in der while-Schleife für eine 
gewisse Zeit weiter machen. Und einen Time-out einfügen, nachdem die 
Verbindung geschlossen wird.

Die delays einfügen bringt dich kein Stück weiter.

: Bearbeitet durch User
von Tom H. (toemchen)


Lesenswert?

Daß dieses Programm suboptimal ist, ist mir klar.
Ich glaube, die Programme, die bei diversen Tutorials gezeigt werden, 
sind eher als Demo oder Schulbeispiel zu verstehen.
Aber für mich im Moment genau richtig.

Übrigens sorry, gestern abend ging leider keine Minute Basteln...
Man muß sich halt doch mal um Familie, Haushalt, Gesundheit kümmern.

Heute abend wieder.

von Alexander (alecxs)


Lesenswert?

Obelix X. schrieb:
> Die delays

... sind das Mindeste um das Programm nicht heißlaufen zu lassen.

Der TE hat Probleme mit Abstürzen.

: Bearbeitet durch User
von Tom H. (toemchen)


Lesenswert?

Sodala, da bin ich wieder.

Hab die delays jetzt einfach mal eingefügt, kost ja nix.

Jedes funktionierende Frage-Antwort-Spiel zwischen ESP als Server und 
Handy als Client dauert jetzt deutlich länger.
Und wie es aussieht, gibt es jetzt nur noch funktionierende :-)

Nach wie vor bleibt dieses Programm kryptisch. Ich weiß natürlich nicht 
genau, liegt es an meinem begrenzten Verständnis oder daran, daß es 
einfach ziemlich von hinten durchs Bein geschossen ist?

Ich habe also noch Fragen genau zu diesem Programm. Müssen nicht 
dringend beantwortet werden - demnächst werde ich mich damit 
beschäftigen, das ganze wie weiter oben vorgeschlagen mit statischem 
HTML und json-Daten umsetzen.

Ich habe aber mit dem ganzen Gebilde, was ich da baue, Deadline am 
Donnerstag abend. Ich werde also vorerst nur dieses Programm noch ein 
bißchen aufbohren, nur meine Temperaturwerte und Akkuspannung noch mit 
rausschreiben. Die updaten sich halt nur, wenn ich die Website refreshe, 
also neu anfrage.

Nun noch die Fragen:

- In der while connected - Schleife füllt es zwei Strings auf: Zum einen 
header mit dem gesamten Inhalt des HTTP-Requests, zum anderen 
currentLine, nur um festzustellen ob da eine Leerzeile ist, mithin das 
Ende des HTTP-Requests. Hätte man das nicht auch mit einem Flag lösen 
können? Erstmaliges Auftauchen eines '\n' Zeichens setzt das Flag, wenn 
danach noch eins kommt, ist Ende, wenn danach wieder ein anderes Zeichen 
kommt wird das Flag wieder zurückgesetzt. Oder ist das umständlicher?

- Warum wird vom Server dem Client "Connection: close" mitgeteilt? Dann 
kommt ja ein weiteres println, also für den Client ist dieser 
HTTP-Header zu Ende. Der Client schließt dann aber nicht? Denn danach 
kommt ja erst der html-Code vom Server. Und dann schließt der Server.

- Warum in aller Welt wird die Connection geschlossen, wenn sie (vom 
Client?) danach sofort wieder geöffnet wird? Und der ESP dann 
stundenlang in dieser Schleife glüht, in der er auf die Zeichen wartet? 
Bin ICH zu dumm, das zu verstehen, oder ist ES dumm?

- Liegt das Problem darin, daß das Programm in dieser kleinen Schleife 
hängt, auch wenn die Verbindung unterbrochen wurde, und da nicht mehr 
rauskommt? Wäre es also gut, diese Schleife mit einem Timeout zu 
versehen, so daß das Programm ab und zu wieder auf die Ebene 
rausspringt, in der nach einem Client gesucht wird? Also ganz raus in 
die main loop.

von Alexander (alecxs)


Lesenswert?

Tom H. schrieb:
> Hab die delays jetzt einfach mal eingefügt, kost ja nix.

Wenn das so deutlich spürbar ist, dann kann man schon mal sagen dass es 
an den delay(100) liegt - das ist schon mal gut zu wissen d.h. der 
loop() blockiert nicht wie vermutet unnötig lang. delay(100) kannste 
wieder rausnehmen.

von Hans W. (hanswieland)


Lesenswert?

Tom H. schrieb:
> Warum wird vom Server dem Client "Connection: close" mitgeteilt?

Das signalisiert, daß nach der Übertragung des Dokumentes die Verbindung 
geschlossen wird. Das Schließen zeigt dann an, dass das Dokument zu Ende 
ist.

Die effizientere Alternative wäre, die Verbindung für den nächsten 
Request offen zu halten. Dazu muss man aber entweder

a) die Größe des Dokumentes im Header angeben, also schon vor der 
Übertragung kennen, oder

b) das Dokument in "chunks" zerlegt übertragen, was nicht trivial ist. 
Ein leerer Chunk markiert das Ende.

Das kannst du in der Spezifikation vom HTTP 1.1 Protokoll nachlesen. 
Microsoft hatte dazu auch mal ein paar schöne Artikel veröffentlicht. 
Vielleicht findest du sie mit Google.

: Bearbeitet durch User
von Alexander (alecxs)


Lesenswert?

Tom H. schrieb:
> daran, daß es einfach ziemlich von hinten durchs Bein geschossen ist

Wird in den Arduino docs aber tatsächlich genau so gemacht.

Mit der Library geht das aber einfacher. Also z.b. 
http://192.168.4.1/webserver ruft die Datei webserver.html ab. Der Code 
dazu sieht so aus. Das ist auch schon alles.
1
void setup() {
2
  server.on("/webserver", HTTP_GET, [](AsyncWebServerRequest *req){
3
    req->send(LittleFS, "/webserver.html", "text/html");
4
  });
5
}
Einmal eingerichtet muss man auch nicht den ganzen Sketch jedesmal neu 
flashen, da reicht es bei Änderungen nur die HTML Dateien hochzuladen 
(geht deutlich schneller)

: Bearbeitet durch User
von Tom H. (toemchen)


Lesenswert?

So, die Temperaturmessung und Spannungsmessung hanebüchen 
dazugeschraubt.
Beide Messungen und Konvertierung zu String (damit die Funktion 
Client.println() sie frißt) passieren erst in dem Moment, wo der 
html-body ausgegeben wird. Verzögert die Sache aber nicht spürbar.

Neue Messwerte sehen, indem man die Website refresht, klappt wie 
erwartet.

Für heute ist aber jetzt Feierabend.

von Tom H. (toemchen)


Lesenswert?

Habe im Büro das "Maschinchen" neben mir stehen und probiere ab und zu, 
ob die Kommunikation noch geht.

Geht.
Wie neuerdings gewohnt langsam (noch keine delays wieder rausgenommen), 
aber stabil.

Bis zu dem Punkt, an dem man das Handy forciert in ein anderes WLAN 
bringt und dann in das ESP-WLAN zurückkehrt.
Aufruf der Seite bringt dann nach geraumer Wartezeit "Website nicht 
erreichbar".

Mich wundert es mittlerweile auch nicht.
Nach meinem Verständnis rotiert das Programm innerhalb einer kleinen 
While-Schleife und wartet auf Zeichen aus einer mittlerweile 
abgebrochenen Verbindung. Es wird ja niemals geprüft, ob die Verbindung 
noch besteht.

Kann mir jemand nochmal bestätigen, daß meine Einschätzung richtig ist?

Ich werde also mindestens einen Timeout einbauen.

Vielleicht gehe ich auch in meiner bisherigen oldschool Programmierart 
als 57jähriger Knacker nochmal hin, und schreibe ein monolithisches 
.ino, in dem eine State Machine das Webgedöns behandelt:

1. Nach Client suchen
2. bei Client nach Zeichen lauschen, nach 5s raus, Verbindung abbrechen, 
zurück zu 1. Bei Zeichen zu 3.
3. Zeichenkette vom Client flott fressen, bei erfolgreichen Lesen zu 4, 
sonst zu 1.
4. Website an den Client rausschreiben, Client schließen, zurück zu 1.

Mit den 5s-Ticks kann ich die Temperaturen und die Akkuspannung intern 
updaten und seriell was zum Debuggen bzw. für den Serial Plotter 
rausschreiben. Und eine Zweipunkt-Temperaturregelung mit dem Kompressor 
realisieren. Vielleicht sogar noch eine State Machine, damit der 
Kompressor nicht sofort nach dem Ausschalten wieder eingeschalten wird. 
Und Abschaltung bei zu geringer Akkuspannung.

von Alexander (alecxs)


Lesenswert?

Kompiliere doch mal das Beispiel ich Dir gegeben habe dazu könnte ich 
Dir auch helfen. Ich weiß es sieht erstmal viel aus, aber eigentlich ist 
es ne Sache von 10 min. Dann musst Du Dich um das Webgedöns gar nicht 
mehr kümmern, nur noch mit Daten füttern. Wie man nach Libraries sucht 
weißt Du?

von Tom H. (toemchen)


Lesenswert?

Ich hab eigentlich nur noch heute abend zum Programmieren. Die Hürde ist 
nicht 10 Minuten (das ist auch nur Deine Sicht), sondern mental.
Ich mach mich da schon noch dran. Ich will ja auch die angezeigte 
Website schöner haben.

Aber für den Moment noch das alte Programm.

Was ich zuvor schrieb, stimmt nicht ganz.
Eigentlich tanzt das Programm in der Schleife "while 
(client.connected())".
Und aus der sollte es rausfallen, wenn die Verbindung abreißt, dann wird 
"Client disconnected" gemeldet, der Client geschlossen und neu gesucht.
Eigentlich.
Denn das klappt offensichtlich nicht.
Ich habe in dieser Schleife ein Serial.print(".") eingefügt, es wird ein 
Punkt bei jedem Durchlauf der Schleife geschrieben.
Und diese Punktereihe rattert fröhlich weiter, auch wenn das Handy auf 
ein ganz anderes WLAN eingebucht wird, wieder zurück auf das ESP-WLAN, 
wenn man versucht dann die Website zu refreshen...
Also das Erkennen des Verlusts der Verbindung klappt irgendwie nicht.

Also als nächstes Timeout.
Hoffentlich klappt dann auch das Trennen der Verbindung und wieder neu 
finden.

von Alexander (alecxs)


Lesenswert?

Tom H. schrieb:
> Ich hab eigentlich nur noch heute abend zum Programmieren.

Das tut mir ja schon ein bisschen Leid dass Du Dich da noch auf 
Protokollebene rumärgern musst.

Tom H. schrieb:
> Die Hürde ist nicht 10 Minuten (das ist auch nur Deine Sicht), sondern
> mental.

Eben! Ich meinte nicht das Umschreiben sondern nur die Demo gucken.

Tom H. schrieb:
> Also als nächstes Timeout.
> Hoffentlich klappt dann auch das Trennen der Verbindung und wieder neu
> finden.

Ich bin mir nicht mal sicher ob hier die Verbindung zum Client gemeint 
ist. Das wird wohl einfach das Ende der Session sein. Kenne mich mit den 
Eigenheiten von HTTP Übertragung null aus, da muss jemand anders helfen.

Tom H. schrieb:
> Ich mach mich da schon noch dran. Ich will ja auch die angezeigte
> Website schöner haben.
> Aber für den Moment noch das alte Programm.

Dann ein andermal. Ich bin auf Arbeit leider auch auf das Handy 
beschränkt. Das Programm kannst Du dann copy-paste übertragen, die 
loop() ist frei. (Webserver läuft als Hintergrundtask)

: 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.