Hallo,
ich kommuniziere seriell mit einem Modul.
Dazu muss ich auch die Antwort richtig auswerten.
In manchen Beispielen im Netz wird einfach davon ausgegangen das das
Modul sich wie erwartet verhallt, das ist aber Mist wenn mal ein Fahler
auftritt.
In dem Beispiel wird es z.B. so gemacht wenn auf eine Antwort gewartet
wird:
1
while (!sSerial.find("OK"));
das ist aber Mist da es vorkommen kann das Error zurück kommt.
Wie kann ich es in ähnlich einfacher Art umbauen das unterschieden wird
ob nun OK oder ERROR kommt?
Lukas schrieb:> Wie kann ich es in ähnlich einfacher Art umbauen das unterschieden wird> ob nun OK oder ERROR kommt?
Auf CR/LF warten, erst dann Antwort prüfen.
Lukas schrieb:> CR LF kommt ja immer zum Schluss, das wertet aber nicht ERROR oder OK> aus.
Natürlich kommt das zum Schluss - vorher kannst du ja auch nichts
auswerten - verstehe nicht wie du das sonst auswerten willst ?
Zeichen für Zeichen ?
Normallerweise schreibt man alles in einen Buffer bis CR/LF kommt,
erst dann wird der Buffer ausgewertet.
Lukas schrieb:> CR LF kommt ja immer zum Schluss, das wertet aber nicht ERROR oder> OK> aus.
Nein, das Auswerten sollte ja auch du machen, aber erst, nachdem du
CR/LF empfangen hast. Du pufferst also so lange, bis CR/LF kommt (oder
eine maixmale Anzahl Zeichen empfangen wurden), und dann wertest du aus.
Einen Timeout würde ich auch noch vorsehen. Du weißt ja nicht, was alles
schiefgeht...
Bei Modulen, die mit Text-Kommandos (z.B. AT-Befehle) gesteuert werden,
mache ich das immer so:
Ich sende den Befehl, danach sammle ich die Antwort in einem Ringpuffer,
der mindestens so groß ist, wie die gewünschte Antwort. So einen Puffer
hat man ja ohnehin in der Regel wenn man mit Interrupts arbeitet.
Dann warte ich eine gewisse Anzahl Millisekunden bis die gewünschte
Antwort irgendwo im Puffer liegt. Danach warte ich zusätzlich so lange,
bis 100ms lang Stille Herrscht (nichts weiter dazu kommt).
Wenn die erwartete Antwort nicht rechtzeitig kommt, melde ich das als
Fehler.
Das Zusätzliche Warten auf Stille sorgt dafür das der oder die
Zeilenumbrüche nach dem Ok auch noch abgeholt werden und dass sich die
Kommunikation sich nach einer unerwarteten Störung wieder zuverlässig
einpendelt. Kostet natürlich auch Performance - man muss sich halt
überlegen, was wichtiger ist.
Ich habe damit viel bessere Erfahrung gemacht, als auf irgendwelche
Zeilenumbrüche zu warten, deren Format vielleicht sogar unklar ist oder
sich von Firmware Version zu Version ändert. Außerdem bekomme ich so
keinen bösen Absturz, wenn das Modul mal mit einer viel längeren Antwort
daher kommt, als ich erwartet hatte.
Stefan U. schrieb:> Dann warte ich eine gewisse Anzahl Millisekunden bis die gewünschte> Antwort irgendwo im Puffer liegt. Danach warte ich zusätzlich so lange,> bis 100ms lang Stille Herrscht (nichts weiter dazu kommt).
Ja, das macht sich besonders gut bei GPS Meldungen aus, vor allem
da alle hintereinander kommen und erst danach eine Pause...
> Ich habe damit viel bessere Erfahrung gemacht, als auf irgendwelche> Zeilenumbrüche zu warten, deren Format vielleicht sogar unklar ist oder> sich von Firmware Version zu Version ändert.
Zeilenumbruch ist und bleibt immer Zeilenumbruch, da kann sich nichts
ändern.
Marc V. schrieb:> Natürlich kommt das zum Schluss - vorher kannst du ja auch nichts> auswerten - verstehe nicht wie du das sonst auswerten willst ?
Man könnte, unabhängig von <cr><lf>, natürlich auch gucken, ob vom Gerät
die Buchstabenfolge OK oder ERROR kommt, z.B. mit einer kleinen FSM
Wolfgang schrieb:> Man könnte, unabhängig von <cr><lf>, natürlich auch gucken, ob vom Gerät> die Buchstabenfolge OK oder ERROR kommt, z.B. mit einer kleinen FSM
Dazu müsste man (in der ISR) viel mehr Abfragen machen, sowohl auf
bestimmte Zeichen als auch auf deren Reihenfolge.
Und egal ob OK oder ERROR kommt, trotzdem muss CR/LF abgewartet werden,
damit sowohl diese als auch die nächste Meldung bearbeitet werden kann.
Manche Module haben es gar nicht gerne, wenn man das nächste Kommando
sendet, bevor die vorherige Antwort komplett beendet ist (mitsamt aller
Zeilenumbrüche).
@Wolfgang (Gast)
>Man könnte, unabhängig von <cr><lf>, natürlich auch gucken, ob vom Gerät>die Buchstabenfolge OK oder ERROR kommt, z.B. mit einer kleinen FSM
Das KÖNNTE man nicht nur, das MUSS man sogar, wenn man eine solide
Software jenseits der Fricklerszene schreiben will.
Falk B. schrieb:>>Man könnte, unabhängig von <cr><lf>, natürlich auch gucken, ob vom Gerät>>die Buchstabenfolge OK oder ERROR kommt, z.B. mit einer kleinen FSM> Das KÖNNTE man nicht nur, das MUSS man sogar, wenn man eine solide> Software jenseits der Fricklerszene schreiben will.
Aha.
Das erweist sich als besonders praktisch wenn 20 oder mehr verschiedene
Antworten zu erwarten sind.
Jedes ankommende Zeichen auf sinnvoll oder nicht zu prüfen, ist
absoluter Schwachsinn, einerseits wegen der benötigten Zeit und
andererseits wegen der benötigten Tabellen zum Vergleich.
Prüfen auf:
1) Timeout
2) Pufferüberschreitung
3) Ende der Nachricht
Ist das, was man jenseits der Fricklerszene machen MUSS.
Da du mit Programmieren und besonders mit der Logik auf Kriegsfuss
zu stehen scheinst, will ich versuchen, dir das zu erklären:
Falls man in der ISR jedes Zeichen prüft, ergibt das bei nur 4
möglichen Antworten (als Beispiel) schon einen recht schönen Baum.
Als Beispiel: OK, READY, ERROR, ERFOLG.
Bei 2 empfangenen Zeichen (E und R) weiss man immer noch nicht, um
was für eine Meldung es sich handelt, es steht nur fest, dass kein
Fehler in den bisher empfangener Zeichenfolge vorliegt.
Also werden jedesmal die bisher empfangenen Zeichen von neuem mit
möglichen Antworten verglichen, etwa so:
1
Ist erstes char ein "O" ? -ja-> Ist zweites char ein "K" -> ja es ist, und was jetzt ?
2
| nein
3
\/
4
Ist erstes char ein "R" ? -ja-> Ist zweites char ein "E" ? -> ja, jetzt noch 3 Mal dasselbe wiederholen
5
| und trotzdem auf CR/LF warten...
6
| nein
7
\/
8
Ist erstes char ein "E" ? -ja-> Ist man wirklich so Blöd, um das alles weiter in der ISR zu machen ?
9
| nein
10
\/
11
FEHLER -> LOL. Flag setzen, auf CR/LF oder Timeout warten, Antwort löschen...
P.S.
Wie schon gesagt:
Ob mit oder ohne Fehler - ein CR/LF oder Timeout muss sowiesoabgewartet werden - man kann keine Antwort senden bevor die Meldung
komplett empfangen worden ist oder ein Timeout zugeschlagen hat...
P.P.S.
Im Gegensatz dazu, wird bei der Bearbeitung in der main() nur
einmal gerade nach unten durchgeprüft, nicht jedesmal von neuem.
> etwa so
Genau das macht die strcmp() Funktion ohen großartige Klimmzüge.
Voraussetzung ist lediglich, dass der Puffer ein Byte größer ist, als
die größte Antwort, die man auswerten will, damit man eine 0 als
String-Terminator hinten dran hängen kann.
@ Marc Vesely (Firma: Vescomp) (logarithmus)
>>>Man könnte, unabhängig von <cr><lf>, natürlich auch gucken, ob vom Gerät>>>die Buchstabenfolge OK oder ERROR kommt, z.B. mit einer kleinen FSM>> Das KÖNNTE man nicht nur, das MUSS man sogar, wenn man eine solide>> Software jenseits der Fricklerszene schreiben will.> Aha.> Das erweist sich als besonders praktisch wenn 20 oder mehr verschiedene> Antworten zu erwarten sind.
Das mit dem sinnerfassenden Lesen muss du noch ein wenig üben. Mein
Kommentar bezog sich darauf, daß man die ANTWORTEN im allgemeinen mit
einer FSM prüfen muss. Vor einzelnen Zeichen steht da nichts.
> Da du mit Programmieren und besonders mit der Logik auf Kriegsfuss> zu stehen scheinst, will ich versuchen, dir das zu erklären:
Spar dir deine wertvolle Zeit, du trägst nur Eulen nach Athen ;-)
Falk B. schrieb:> Das mit dem sinnerfassenden Lesen muss du noch ein wenig üben. Mein> Kommentar bezog sich darauf, daß man die ANTWORTEN im allgemeinen mit> einer FSM prüfen muss. Vor einzelnen Zeichen steht da nichts.
LOL.