Männer ich brauche Eure geschulten Augen.
Es geht wieder um mein heißbegehrten ESP8266 mit dem Atmega8. Ich hab
ein Programm geschrieben, welche mir alle 10s ein Statusbericht in Form
einer Zahl an eine php sendet
(.../test/haa/write.php?wert=1234567890123456). In der Funktion
1
TCP_Laenge()
aus der esp8226.c gibt es eine For-Schleife. Wenn ich diese aktiviere,
funktioniert das Senden. Nehme ich diese raus, sendet er genau einmal
und das wars, bis irgendwann der Server die Verbinung wieder schliesst,
siehe Foto.
Die For-Schleife macht eigentlich nichts anderes als etwas zeit zu
verplempern, deswegen hab ich testweise in der Funktion aus main.c
1
Protokoll_senden()
in Case 1 eine Wartschleife eingebaut. Leider ohne Erfolg.
In weiteren Tests hab ich gesehen, das nach dem senden von
"AT+CIPSEND=79\r\n" nichts weiter passiert. In dem Fall sollte er nach
einem "OK" die eigentliche GET-Anfrage senden, was er aber nicht tut.
Ich verstehe aber nicht genau warum.
Kann mir jemand helfen ?
Gruss
Wenn der Prompt ">" kommt, hat er das AT-Kommando CIPSEND akzeptiert.
Wenn dann nichts weiter passiert, wurden sehr wahrscheinlich weniger
Bytes an den ESP abgegeben, als die im CIPSEND angegebene Länge.
Da in der For-Schleife ja "#" gesendet wird, würde ein solches Problem
dadurch geheilt.
Wenn Länge richtig berechnet wurde, hat der ESP vielleicht ein Zeichen
"verschluckt". Möglicherweise das erste, wenn der Prompt ">" nicht
abgewartet wurde.
Was sieht denn der Server bzw. wie sehen die Datenpakete dort aus?
Einfach mal mit tcpdump oder Wireshark nachschauen.
Stefan U. schrieb:> Füge log Meldungen hinzu um herauszufinden wo genau er hängen bleibt.
Ich dachte das hätte ich schon herausgefunden. Beim zweiten senden von
"AT+CIPSEND=79\r\n" passiert nichts mehr. Ich hab mein RS232-Wandler an
den TX vom µC angeschlossen und gesehen, dass es ab da nicht mehr weiter
geht, siehe Foto. Damit meine ich, das Programm läuft weiter, nur der
sendet nichts mehr über UART.
Stefan U. schrieb:> Hast du einen Stack überlauf ausgeschlossen?
Ich hoffe ich hab alles beachtet, sicher sein kann man sich nie.
ARiese schrieb:> Wenn der Prompt ">" kommt, hat er das AT-Kommando CIPSEND akzeptiert.> Wenn dann nichts weiter passiert, wurden sehr wahrscheinlich weniger> Bytes an den ESP abgegeben, als die im CIPSEND angegebene Länge.
Das klingt logisch, nur hab ich ja schon herrausgefunden, dass er nach
dem zweiten senden von "AT+CIPSEND=79\r\n" nichts mehr sendet. Das
Problem würde dann an der Software liegen und nicht, dass der Server
etwas "anderes" oder "mehr" Daten erwartet als angekündigt. Sehe ich das
falsch ?
ARiese schrieb:> Wenn Länge richtig berechnet wurde, hat der ESP vielleicht ein Zeichen> "verschluckt". Möglicherweise das erste, wenn der Prompt ">" nicht> abgewartet wurde.
Da ist bei mir noch Verbesserungspotential. Ich such in den String nur
nach "OK". D.h. ich kann momentan nur nach etwas suchen, was ein
Stringabschluss hat, was bei dem "> " nicht der Fall ist. Ich bin dran
das zu verbessern, ist aber nicht so einfach.
ARiese schrieb:> Einfach mal mit tcpdump oder Wireshark nachschauen.
Ich hab mir jetzt mal nen WLAN-Dongle bestellt. Mit der Kabelverbindung
kann ich die Pakete leider nicht sehen.
Ja habe ich. Mit der AT Firmware Version 0.50 hatte ich noch
gelegentliche Hänger (ca. 1x pro Woche), deswegen auch die Reset Leitung
beschaltet. Bei der Version 1.1.0.0 hatte ich in einem wochenlangen Test
keine Aussetzer mehr beobachtet.
Mein problem war aber nicht, daß der AVR mit dem Senden stoppte, sondern
daß das ESP Modul nicht mehr antwortete.
http://stefanfrings.de/wlan_io/index.html
Ich empfehle Dir, deinen Quelltext weiter zu untersuchen. Du hast
geschrieben, dass der µC plötzlich aufhört, zu senden. Also blockiert
irgend etwas deinen Programmablauf. Das ESP Modul kann es nicht sein,
denn du verwendest keine Hardware-Handshake Leitungen (kann es auch gar
nicht). Der serielle Port vom AVR kann eigentlich auch nicht hängen, es
sei denn, er wird deaktiviert.
Eine sehr oft erfolgreiche Strategie ist:
Reduziere dein Programm immer weiter, bis der Fehler verschwindet. Zeige
uns dann die kleinste mögliche Version, wo der Fehler noch auftritt und
die noch kleinere Version, wo der Fehler nicht mehr auftritt.
Hänge bitte keine RAR Files an. Kaum jemand hat das dazu nötige Entpack
Programm. Dies zu installieren wäre zwar kein Problem, aber wenn ich
alles installieren würde, was andere hier gerne nutzen, dann würde mein
Computer aus allen Nähten platzen und nicht mehr zuverlässig
funktionieren.
Stefan U. schrieb:> Reduziere dein Programm immer weiter, bis der Fehler verschwindet. Zeige> uns dann die kleinste mögliche Version, wo der Fehler noch auftritt und> die noch kleinere Version, wo der Fehler nicht mehr auftritt.
Das werde ich wohl machen müssen. Das Programm ist mittlerweile relativ
groß und hatte gehofft, dass es zur Fehlerfindung ausreicht, wenn ich
schonmal weiß wo es hackt.
Oliver S. schrieb:> Wieso lässt du nicht einfach alles direkt auf dem ESP laufen?
Ich benutze das Modul für meine Alarmanlage. Da sind noch zahlreiche
Ein- und Ausgänge in Verwendung, die paar Stück vom Modul reichen dafür
nicht aus.
Hi,
wahrscheinlich ein Problem des Timings.
Der Zeichenempfang läuft asynchron (über die ISR). Es werden nicht alle
empfangenen Zeichen kontrolliert. Mindestens das „>“ müsste noch
abgefragt werden, denn dann darf vermutlich sowieso erst gesendet
werden.
Es könnte sein, dass der erste Durchlauf klappt, weil das „OK“ vom
CONNECT noch im Puffer steht und das „OK\n>“vom CIPSEND noch nicht
empfangen wurde.
Dann wird gesendet und es kommt die Antwort (http-Response).
Dann kommt der nächste CIPSEND. Zwischen „OK“ und „>“ gibt es ein
Newline. Wenn das schnell genug kommt, steht nur noch „>“ im Puffer.
Gewartet wird aber auf „OK“.
Also folgende Massnahme: Mindestens das „>“ noch abfragen. Das ist
nämlich eine Stelle, an der der ESP wartet und erst mal nichts weiter
sendet. Beim „OK“ wartete er nach dem CIPSEND nicht, sondern sendet
„\n>“. Dieses OK dürfte also so nicht sicher erkannt werden.
Testweise würde ich am Ende des http-Responses mal ein „OK\n“ einfügen.
Gruß
P. F. schrieb:> Ich benutze das Modul für meine Alarmanlage. Da sind noch zahlreiche> Ein- und Ausgänge
Ah, ok. Dann brauchst du was stabileres als diese Steinzeit serielle AT
Software. Irgendwo gab's was, findet sich aber nicht. Vielleicht hat
ein Mitleser eine Idee.
P. F. schrieb:> Die For-Schleife macht eigentlich nichts anderes als etwas zeit zu> verplempern
Der ESP mag es gerne asynchron. Keine delays bitte.
Schau Dir mal LUA an für den ESP8266.
P. F. schrieb:> Ich hab mir jetzt mal nen WLAN-Dongle bestellt. Mit der Kabelverbindung> kann ich die Pakete leider nicht sehen.
So, ich hab jetzt mein WLAN-USB-Dongle bekommen und gleich mal getestet.
Ich hab den Treiber, Wireshark und Acrylic_WiFi installiert. Dannach
noch den NDIS Treiber wie es auf den Seite
https://www.acrylicwifi.com/de/blog/wie-fangt-man-wlan-traffic-mit-wireshark-in-windows-ein/
steht. Den Dongle mit dem selben WLAN verbunden wie mein ESP8266 und den
Wireshark als Admin gestartet. Dort sehe ich mein Adapter und wähle ihn
aus, doch mit den abgefangenen Daten kann ich nciht viel Anfangen. Ich
sehe zwar etwas was der ESP8266 sein könnte, aber ein HTTP-Request kann
ich dort nicht sehen.
Ich bin mir ziemlich sicher, dass der Fehler zwischen Rücklehne und
Tastatur ist. Kann jemand Hilfestellung geben wie ich das "Abhören" der
gesendeten Daten zur Fehleranalyse richtig nutzen kann ?
Gruss
Hmm, ja, Verschlüsselung.
Da steht man dann vor der Entscheidung, knipst man sie zum Testen aus,
oder trägt man den Key im Wireshark ein.
Mal bei „Edit“ „Preferences“ „Protocols“ "IEE 802.11“ nachschauen. Dort
kann man Keys eintragen.
Oder vorher noch einmal über’s Programm nachdenken?
Es funktionierte ja im ersten Fall. Da ist vorher der CIPSTART
(TCP-Connect) gelaufen. Der hat im Receive Buffer (_uart_string) „OK\n“
hinterlassen. Dann kommt der erste CIPSEND und und unmittelbar nach dem
Aufruf von ESP_Query() findet die Funktion ESP_Response() im Buffer den
erwarteten String (die Antwort vom CIPSTART) und anschließend wird der
Request an den ESP gesendet und der sendet ihn zum Server. Das sieht man
in haenger.jpg. Auch die Server Antwort, die aus 2 Datenpaketen besteht
(2 mal +IBD).
Dann kommt der 2. CIPSEND. Im Buffer steht vorher jetzt „+IPD,5:0“ oder
nur „\n“. Das mag ich jetzt nicht entscheiden.
Aber unmittelbar nach dem Absenden des CIPSEND steht jetzt kein „OK\n“
im Buffer.
Der ESP antwortet auf den CIPSEND mit “OK\n>“. Die Empfangsmimik
arbeitet zeilenorientiert. Deshalb wird das OK nach dem
ESP_Query(_cipsend, „OK“); nur dann erkannt, wenn zwischen dem
Interrupt für das „\n“ und dem Interrupt für das „>“ auch
Protokoll_senden() aufgerufen wird und darin ESP_Response() und in
ESP_Response() der Vergleich durchgeführt wurde.
Das hat nach meiner Beurteilung nicht funktioniert und man kann sich
grundsätzlich auch nicht darauf verlassen.
Bei CIPSEND muss die "gesuchte Antwort" also „>“ sein und nicht „OK“.
ARiese schrieb:> Bei CIPSEND muss die "gesuchte Antwort" also „>“ sein und nicht „OK“.
So...ich hab die Software jetzt etwas vereinfacht und sie so angepasst,
dass es auch nach den einzelnen Zeichen ">" sucht.
Bis dahin funktioniert es auch erstmal. Nur diesmal bekomme ich vom
Server nach 1-3 erfolgreich gesendeten Datenpaktet nicht die Antowrt die
ich mir erhoffe...
-----------
Recv 87 byte
SEND OK
+IPD,241....usw
-----------
...sollte es eigentlich immer sein.
Es kommt nur ein...
-----------
Recv 87 byte
-----------
...und das wars. Reagiere ich auf "Recv" anstatt auf das letzte "OK" von
"SEND OK" und sende 10s später einen neuen Datensatz, kommt "busy s...".
Warte ich einfach noch ein bisschen, bis der Server mir "richtig" darauf
antwortet, wird die Verbindung nach einen Timeout automatisch wieder
geschlossen. Das ist echt langsam frustiertend. Hat jemand einen Rat ?
Was genau sendet denn dein Programm?
Die Frage ist nicht "was sollte es nach deiner Meinung senden", sondern
was sendet es tatsächlich? DAS solltest du protokollieren und prüfen.
Mein Verdacht wäre, das du weniger Bytes sendest, als bei CIPSEND
angegeben.
Und dann sollte man noch wissen, dass die AT Firmware oft spinnt, wenn
sie etwas vom Netz empfängt während man gerade sendet. Die AT Firmware
funktioniert nur im Half-Duplex Modus zuverlässig. Deswegen kannst du
lieber den HTTP Header "Connection: close" verwenden.
Stefan U. schrieb:> Mein Verdacht wäre, das du weniger Bytes sendest, als bei CIPSEND> angegeben.
Hi Stefan, so ein Verdacht hatte ich auch und hab mich mal direkt an Tx
den Controllers gehangen. Er sendet zu Testzwecken vorerst immer das
selbe mit der gleichen Zeichenlänge. Dort sieht man auch das er nicht
weitersendet, weil er die passende Antwort nicht findet.
Stefan U. schrieb:> Deswegen kannst du> lieber den HTTP Header "Connection: close" verwenden.
Das hatte ich mal versucht. Ich hab nicht ganz verstanden, wo und wann
genau ich das senden soll. Direkt nach der der Get-Anfrage ?
So ungefähr:
Wenn du bei einer HTTP-GET Anfrage den HTTP header "Connection: close"
sendest sagst du dem Server damit, dass der Server nach der Übertragung
der Antwort die Verbindung schließen soll.
Wenn du das nicht tust, bliebt die Verbindung offen und der Server
wartet auf die nächste Abfrage. Bei mehreren Abfragen nacheinander
können sie sich mit den Antworten überlappen. Du kannst zum Beispiel
sofort nacheinander 5 HTTP-GET Requests senden und die Antworten kommen
irgendwann danach oder parallel dazu rein.
Wenn du den "Connection: close" Header verwendest, kann das nicht
passieren. Du sendest deine Anfrage und erhältst genau eine Antwort.
Danach ist die Verbindung zu. Für die nächste Anfrage musst du eine neue
Verbindung aufbauen. Damit kommt die AT-Firmware gut klar.
So ist es richtig:
1
GET /test/haa/write.php?wert=1234567890123456&log=nx0 HTTP/1.1\r\n
2
Host: 192.168.1.100\r\n
3
Connection: close\r\n\r\n
Der doppelte Zeilenumbruch kennzeichnet das Ende der HTTP Header. Und da
es ein GET Request ist, kennzeichnet der doppelte Zeilenumbruch zugleich
das Ende der Anfrage.
Stefan U. schrieb:> So ist es richtig:GET /test/haa/write.php?wert=1234567890123456&log=nx0> HTTP/1.1\r\n> Host: 192.168.1.100\r\n> Connection: close\r\n\r\n
Hallo,
ich hab die Schaltung jetzt nochmal gestartet und musste feststellen,
das Sie erstmal wieder funktioniert hat. Da ich aber kein Risiko
eingehen will, habe ich das "Connection: close" wie oben beschrieben
eingebaut und nun funktioniert es tatsächlich seit knapp 1h ohne Fehler.
Ich werde es weiter beobachten, ob es so bleibt. Die Firmware lass ich
erstmal so, solange es stabil läuft. Mal eine andere Frage. Bei der
Antwort des Server steht immer eine 3 drin. Ich hab festgestellt , dass
das die Zeichenlänge sein müsste die er als Antwort erhält. Wenn ich
eine "Test" ausgebe, steht nämlich eine 7 drin. Woher kommt den die "3",
wenn es eigentlich kein Rückgabewert gibt ?
Gruss
Letztendlich geht es dabei darum, dass der Client erkennen kann, wann er
die Antwort vollständig empfangen hat. Denn HTTP/1.1 erlaubt ja mehrere
Requests/Responses auf einer langfristig bestehenden Verbindung. Der
Client kann 5 Requests senden und der Server schickt danach irgendwann 5
Antworten zurück. Irgendwie muss der Client diese 5 Stücke auseiander
halten können.
Der Server kündigt damit also die Anzahl der Bytes an, die kommen
werden. Es können auch mehrere Chunks zu einer Response gehören. Der
Letzte Chunk pro Response wird entweder mit 0 oder den Schließen der
Verbindung gekennzeichnet.
Bei HTTP/1.0 wird das Ende immer durch Schließen der Verbindung
gekennzeichnet. Dort gibt es diese "chunks" nicht.
Ich begreife das nicht. Dieselbe Software die gestern noch 1h ohne
Probleme lief, bekommt jetzt nach dem dritten Senden ein Error. Einziger
Hoffnungsschimmer bleibt mit der Firmware - Update, was nebenbei gesagt
auch nicht so richtig klappen will. Ich verzweifel langsam an den Modul.
Stefan U. schrieb:> Ist denn die Stromversorgung in Ordnung? Auf Steckbrettern laufen die> Module nicht zuverlässig.
Die Spannungsversorgung ist ok. Ja, es läuft noch auf nem Breadboard.
Ich werde auf meine Plantine löten um der Fehlerquelle aus dem Weg zu
gehen. Wie ist denn deine vorgehensweise ? Lötest du jedes Modul nur um
es zu testen ?
Die o.g. Version funktioniert bei meiner Software nicht. Teilweise ist
es so, dass das Modul andere Antworten als erwartet zurück gibt.
Beispielsweise reagiert er mit dem Restet mit "OK" und nicht wie
erwartet mit "ready", bei einer anderen Antwort kommt "OK" ohne
kompletten Zeilenumbruch wenn ich das richtig gesehen hab. Ich müsste
meine komplette Software umschreiben, um zu testen, ob es mit einer
älteren Version stabil läuft. Man könnte doch meinen, dass die neuere
Version die Bugs der alten liquidieren.
Ich hab mir sogar die neuste Firmware "ESP8266_NONOS_SDK-2.2.0"
runtergeladen und nach Anweisungen in "..\bin\at\README.MD" einmal "###
Flash size 16Mbit: 512KB+512KB" und einmal "### Flash size 16Mbit-C1:
1024KB+1024KB" geladen. Bei beiden Varianten kommt nur Murks raus und er
sendet mit ununterbrochen Kauderwelsch, siehe Bild.
Irgendwie ist gerade echt der Wurm drin.
Für die neue Firmware musste ich die Software geringfügig anpassen. Wenn
ich den "AT+CIPSTART="TCP","192.168.1.100",80" kommt manchmal nur ein
"WIFI CONNECTED" und das "WIFI GOT IP" was darauf folgen müsste kommt
nicht. Warum auch immer. Nach ein paar mal resets später bekommt er dann
doch die IP. Doch beim senden der Pakete verhält es sich genauso wie die
vorherige Version. Nach 2-3 Datenpaketen gibt es einfach keine Antowrt
mehr, wie oben bereits beschrieben.
Bleibt echt nur das festlöten auf die Platine ????
Ich hab mal die Software nochmal angehangen, vielleicht gibt es noch da
Probleme. Ich klammer mich mittlerweile an jeden Strohalm, weil ich die
ganze Zeit im dunkeln tappe und weiß nicht was los ist.
> Bleibt echt nur das festlöten auf die Platine ????
Zumindest die Stromversorgung sollte direkt ans Modul angelötet werden.
Und ein 100 bis 220µF Kondensator zur Stabilisierung (außer beim
NodemMCU Modul, das hat schon einen).
Die Kontakte von Steckbretter haben zu hohe Übergangswiderstände, um
derart hungrige Module zu versorgen. Das Thema haben wir hier neuerdings
wöchentlich mit unterschiedlichen Funkmodulen.
P. F. schrieb:> Ich hab mal die Software nochmal angehangen, vielleicht gibt es noch da> Probleme. Ich klammer mich mittlerweile an jeden Strohalm, weil ich die> ganze Zeit im dunkeln tappe und weiß nicht was los ist.
Hi,
ich komme also noch einmal auf die Software zurück, obwohl ich den jetzt
gesuchten Fehler dort nicht vermute.
Eine „Sollbruchstelle“ in der Software liegt innerhalb der Usart-ISR.
Dort werden die empfangenen Zeichen in den String _uart_string
übernommen und immer wenn ein \n empfangen wurde, wird ein \0 an dessen
Stelle eingestellt und der „Pointer“ auf das nächste Zeichen erhält den
Wert 0.
Ein Überlauf von _uart_string ist nicht zu erwarten, denn von den 50
möglichen Stellen werden nur 49 benutzt und die letzte ist wegen des
memset() immer \0. Das ist auch gut so.
Zeichen aus vorhergegangenen Antworten werden vor Absenden der Anfragen
durch den memset() Aufruf gelöscht. Sie können danach also keine
Verwirrung stiften. Problematisch könnten die Echos der eingegebenen
AT-Kommandos werden. Sie gelangen auch in _uart_string und werden erst
nach Empfang eines weiteren \n durch einen leeren String sozusagen
überschrieben.
Das Programm erkennt die Ausgaben OK nach CIPSTART, > nach CIPSEND und
CLOSED des ESP8266, nach denen er auf eine weitere Eingabe wartet,
sicher.
Problematisch würde es bei Antworten wie „OK\n\n“. Wenn das 2. \n
schnell genug empfangen wird, steht anschließend „\0K\0“, also der
String „K“, in _uart_string und das wird dann mit Sicherheit nicht als
„OK“ erkannt werden.
Fazit: Antworten des ESP8266, die mit 2 mal \n kommen, können so nicht
sicher erkannt werden und ein Antwortstring, der in dem vorausgegangenen
AT-Kommando enthalten war, würde schon als Antwort erkannt.