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.
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.
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?
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.
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
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.
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
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?
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.
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
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
In dem generierten HTML steht "ü", das muss "ü" heissen. Gilt natürlich für ähnliche Codierungen auch. Der Rest ist wenig strukturiert, alles in die loop geworfen und umgerührt.
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
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
Nick schrieb: > In dem generierten HTML steht "ü", das muss "ü" 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 ü 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?
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
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.
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.
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.
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.
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
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
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.
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.
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.
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 | }
|
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
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.
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?
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.
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)
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.
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
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.
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
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.
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
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.
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.
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
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
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.
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.
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.
