Wann sollte man von ASCII zu erweiterten seriellen Protokollen wechseln?

28

Alle meine Mikrocontroller-Geräte, die über UART mit dem PC kommunizieren, verwenden ASCII-Zeichenfolgen zum Senden und Empfangen von Daten (wie in Arduino implementiert). Das habe ich gelernt, als ich angefangen habe, mich mit Elektronik zu beschäftigen, und ich fand es immer genug, bloße Saiten zu senden. Mir ist jedoch aufgefallen, dass die meisten Geräte, auf die ich gestoßen bin, ausgefeilte Binärprotokolle verwenden, die Funktionscodes, Adressen und CRC-Fehlerprüfungen enthalten.

Wann ist grundlegende ASCII-Kommunikation akzeptabel und wann sollte ich etwas Fortgeschritteneres wie Modbus in Betracht ziehen? Verwenden kommerzielle Geräte solche ASCII-Zeichen? Industrie?

Ich habe keine Ahnung was ich tue
quelle
3
Kurze Antwort: Wenn Ihre Anwendung es braucht. Ja, kommerzielle Geräte verwenden ASCII. Nehmen Sie als Beispiel GPS NMEA. (Und noch einmal, ich werde meine eigene Frage hier
ansprechen
1
Modbus hat einen ASCII-Modus. Siehe Modicon Modbus-Protokoll - Referenzhandbuch
Dienstag,
@EugeneSh .: Es ist erwähnenswert, dass NMEA über ein Prüfsummenfeld verfügt, und das Löschen eines einzelnen Abtastimpulses aufgrund eines Prüfsummenfehlers (der häufiger auftritt, als Sie vielleicht glauben) ist im Allgemeinen kein kritischer Fehler. Dies ist bei anderen Protokollen möglicherweise nicht der Fall ... und es werden zahlreiche binäre GPS-Protokolle (z. B. Garmin) für Anwendungen verwendet, bei denen dies tatsächlich kritisch sein kann (oder bei denen eine Abtastrate von mehr als 1 Hz vorliegt) erforderlich, wofür NMEA zu ausführlich ist). Obwohl dies wirklich nur Ihren Standpunkt festigt.
Leichtigkeitsrennen mit Monica

Antworten:

28
  1. ASCII und CRC schließen sich nicht gegenseitig aus. ASCII ist eine Codierung und CRC dient zur Fehlerprüfung.

  2. ALLES kann als ASCII gesendet werden. Wir Alten erinnern uns sicherlich an UUEncoding, das alles in einen ASCII-String verwandelt.

  3. A) Für mich ist es normalerweise eine Frage der Geschwindigkeit und Effizienz. Das Senden einer großen 32-Bit-Zahl per ASCII kann sehr lange dauern, es werden jedoch nur 4 Bytes benötigt, um sie als Binärdaten über ein serielles Protokoll zu senden.

    B) Das Senden von ZAHLEN über ASCII bedeutet, dass Sie die Zahl in ASCII konvertieren müssen, was ein klarer zusätzlicher Schritt ist (dies ist ein Teil dessen, was "printf" tut).

  4. Wenn Sie irgendwie Ihren Platz verlieren, Fehler machen, das Format verlieren, den falschen Endian erhalten usw., kann ein binäres Kommunikationsprotokoll sicherlich Fehler machen. Wenn Sie ASCII senden, kann es einfacher sein, Fehler zu beheben, indem Sie einfach in den Datenstrom schauen.

Scott Seidman
quelle
12
+1 für "ASCII ist eine Kodierung". Es ist kein Protokoll; Protokolle können auf ASCII aufgebaut werden.
Pete Becker
8
Das automatische Wiederherstellen von Fehlern ist für ein textbasiertes Protokoll als binäres Protokoll an sich nicht einfacher, aber das Überprüfen und Debuggen ist mit Sicherheit nicht einfacher.
Nick Johnson
1
@ NickJohnson - absolut. Sobald Sie eine Datei in einem Hex-Editor öffnen, um zu sehen, was Sie wiederherstellen können, sind Sie bereits bei FUBAR
Scott Seidman,
1
@nickjohnson das stimmt nicht wirklich. ASCII bietet zahlreiche Out-of-Band-Framing- / Delimiter-Optionen zur Unterstützung der Synchronisation und Wiederherstellung, die zusätzliches Escaping, Bitstuffing, Zeitintervalle oder andere Tricks erfordern, wenn der Kanal für Binärdaten in voller Breite verwendet wird.
Chris Stratton
2
Ich bevorzuge immer ASCII, wenn ich Protokolle schreibe, wegen all der offensichtlichen Vorteile (Lesbarkeit, Protokollierbarkeit usw.). Es gibt zwei Fälle, in denen Binärdateien sinnvoller sind: Erstens, wenn Geschwindigkeit ein Problem ist und Sie Binärdateien benötigen, um so viele Daten wie möglich in den Stream zu packen, und zweitens, wenn Sie absichtlich versuchen, die Daten zu verschleiern oder sogar zu verschlüsseln streamen, um Reverse Engineering zu behindern oder zu verhindern. Dabei habe ich binäre Protokolle rückentwickelt und es hat mich größtenteils nur mehr irritiert als eigentlich verhindert.
J ...
10

Hier einige Gedanken dazu:

  • ASCII ist schön, weil Sie einen seriellen Monitor verwenden können, um manuell nachzuschauen, was gesendet wird.
  • Wenn Ihre Verbindung nicht zuverlässig ist, müssen Sie mit Übertragungsfehlern rechnen und sollten mithilfe einer CRC die Integrität jeder empfangenen Nachricht überprüfen. Dies kann auch für ASCII-Nachrichten erfolgen.
  • Wenn Ihre Verbindung zu langsam ist, können Sie die Größe Ihrer Nachrichten reduzieren, indem Sie in ein Binärformat wechseln
  • Ein spezialisiertes Binärformat kann auf der Empfängerseite einfacher zu dekodieren sein als ASCII
MrSmith42
quelle
7

Auf der einfachsten Ebene kann man sagen, dass ein einfaches Kommunikationsprotokoll drei Ebenen aufweist: physisch, Transport und Anwendung. (Es gibt Modelle mit mehr als OSI mit 7 oder TCP / IP mit 4. Die Anzahl der Schichten ist im Zusammenhang mit dieser Frage nicht besonders wichtig.)

Die Anwendungsebene ist die Ebene, mit der Sie sich direkt in Ihrem Code befassen, und der Fokus der Frage. Für die Transportschicht ist das Byte, das Sie in send_data an sie übergeben haben, nur ein binäres Muster. Sie können es jedoch in Ihrem Anwendungscode als den Buchstaben "A" interpretieren. Die CRC- oder Prüfsummenberechnung ist dieselbe, unabhängig davon, ob Sie das Byte als 'A', '0x41' oder '0b01000001' betrachten.

Die Transportschicht ist die Paketebene, auf der sich Ihre Nachrichtenköpfe befinden, und die Fehlerprüfung, ob es sich um eine CRC-Datei oder eine einfache Prüfsumme handelt. Im Zusammenhang mit Firmware haben Sie möglicherweise eine Funktion wie send_data, bei der Sie ein zu sendendes Byte übergeben. Innerhalb dieser Funktion wird es in ein Paket geschrieben, das sagt: "Hey, das ist eine normale Nachricht, erfordert eine Bestätigung, und die Prüfsumme ist 0x47, die aktuelle Zeit ist X." Dieses Paket wird über die physikalische Schicht an den empfangenden Knoten gesendet.

Auf der physischen Schicht werden die Elektronik und die Schnittstelle definiert: Anschlüsse, Spannungspegel, Timing usw. Diese Schicht kann von einigen Spuren reichen, auf denen TTL-Signale für einen Basis-UART auf einer Leiterplatte ausgeführt werden, bis zu einem vollständig isolierten differentiellen Paar, wie in einigen CAN- Implementierungen.

Auf dem empfangenden Knoten kommt das Paket auf der physischen Schicht an, wird auf der Transportschicht entpackt und dann steht Ihr Binärmuster der Anwendungsschicht zur Verfügung. Die Ebene der empfangenden Knotenanwendung muss wissen, ob dieses Muster als "A", "0x41" oder "0b01000001" interpretiert werden soll und was damit zu tun ist.

Zusammenfassend ist es so gut wie immer akzeptabel, ASCII-Zeichen zu senden, wenn die Anwendung dies erfordert. Das Wichtigste ist, Ihr Kommunikationsschema zu verstehen und einen Fehlerprüfungsmechanismus einzuschließen.

Matt Young
quelle
ASCII-Protokolle können auch Prüfsummen enthalten. Ich bin auf Hex-as-ascii-Variationen gestoßen, bei denen eine ASCII-Darstellung von Zahlen verwendet wurde.
Eugene Sh.
@EugeneSh. Klarstellung dieses Punktes
Matt Young
Nicht zu picken, aber TCP besteht nicht aus vier Schichten. es wird als passend in Schicht vier des OSI-Modells angesehen. Die serielle Kommunikation passt nicht wirklich zum OSI-Modell.
Batsplatsterson
@batsplatsterson Das ist nicht sehr aussagekräftig und ziemlich irrelevant für den Punkt, den ich mache.
Matt Young
5

Ein Punkt, der noch nicht erwähnt wurde, ist, dass unabhängig davon, ob ASCII oder ein Binärprotokoll verwendet wird, das Senden eines Rub-Out-Zeichens vor jedem Paket sicherstellt, dass alle Zeichen nach dem Rub- Wenn kein weiteres Rauschen zu hören ist, wird out korrekt gerahmt. Wenn man andernfalls kontinuierlich Pakete sendet und keine Zeichen enthält, von denen garantiert wird, dass sie eine Resynchronisation erreichen, kann ein Fehler alles beschädigen, was bis zur nächsten Sendepause folgt. Das 0xFF-Zeichen ist nett, da es garantiert, dass jeder Empfänger das folgende Zeichen erneut synchronisieren kann.

(*) 0xFF - wird als Ausradieren bezeichnet, da jemand, der beim Schreiben von Daten auf ein Papierband ein fehlerhaftes Zeichen eingibt, die Taste "Rücklauf" drücken und auf Ausradieren klicken kann, um das fehlerhaft gestanzte Zeichen durch 0xFF zu ersetzen von den meisten Empfängern ignoriert werden).

Superkatze
quelle
2

Ein Vorteil des Sendens von ASCII-Zeichenfolgen besteht darin, dass die Steuercodes dann verwendet werden können, um den Beginn / das Ende einer Nachricht zu signalisieren. zB STX (char 2) und ETX (char 3) können die Übertragung starten und beenden. Alternativ können Sie einen einfachen Zeilenvorschub hinzufügen, um das Ende der Übertragung zu markieren.

Beim Senden von Binärdaten wird dies komplizierter, da kein bestimmtes Bitmuster für einen Steuercode reserviert werden kann (ohne zusätzlichen Aufwand oder Komplexität), da ein gültiges Datenbyte das gleiche Muster haben kann.

Transistor
quelle
3
Viele Binärprotokolle reservieren zwar ein oder mehrere Bitmuster als Steuercodes, enthalten jedoch auch einen Escape-Mechanismus, um diese Codes zu verarbeiten, wenn sie in den Daten erscheinen.
Dave Tweed
Sie können ein beliebiges Muster reservieren, um beliebige Binärdateien zu markieren. Zum Beispiel arbeite ich an einem Projekt mit einem schnellen Datenstrom und einem langsamen Datenstrom, die denselben Ausgang haben. Ich habe das größte negative int32 als Flag für meine langsamen Daten reserviert und sättige meine negativen Daten nur mit dem größten negativen +1.
Scott Seidman
Einverstanden. Ich hoffe, dass ich dies in der bearbeiteten Antwort klargestellt habe.
Transistor
2

ASCII ist in Ordnung, ich benutze es in fast allen Projekten. Dies erleichtert das Debuggen bei der Überwachung des Ports erheblich und würde nur dann zu einem Problem werden, wenn viele Daten gesendet werden müssten.

Ein weiterer Bonus: Ich verwende serielle Funkgeräte, um Nachrichten zwischen Arduinos abzurufen, und ich kann einen seriellen Monitor verwenden, der an meinen Laptop angeschlossen ist, und Nachrichten einspeisen, um bestimmte Dinge geschehen zu lassen. Ideal zum Testen.

Das Senden von Dingen als Binärdatei ist nicht unmöglich zu debuggen. Abhängig von Ihren Tools können Sie die Binärdatei extrahieren und in eine für Menschen lesbare Datei konvertieren. Oder wenn Sie wissen, wonach Sie suchen, können Sie den Datenstrom visuell untersuchen und Werte erkennen, wo sie sein sollten, und auf diese Weise Fehler finden, wenn auch nicht so einfach. Sie erkennen also die Muster von Bytes und die erwarteten Werte

Madivad
quelle
2

Anstelle von Modbus sollte HDLC in Betracht gezogen werden . Sie erhalten eine Fehlererkennung (was bei gestörten seriellen Leitungen wichtig ist). Die Synchronisation ist robust, die Flucht ist robust.

Ich habe HDLC in RS-485-Netzwerken ohne Probleme verwendet und PPP verwendet es auch.

teambob
quelle
2
Wäre nett, wenn du darauf hinweist, warum du es über Modbus vorschlägst.
Ich habe keine Ahnung, was ich
1

ASCII über den UART ist zum Teil deshalb am beliebtesten, weil:

  • Es ist beim Debuggen von Menschen lesbar (ich habe noch keinen Logikanalysator gesehen, der ASCII nicht decodiert).

  • Die Implementierung ist sehr einfach. Sie haben eine gut standardisierte ASCII-Tabelle über QuickGoogle.

  • Es hat in Synchronisation mit den Start / Stopp-Bits gebaut.

  • Fast die gesamte Hobbyst-Welt hat sich mit ASCII über seriell eingerichtet, daher müssen sich alle neuen Methoden damit befassen, und das ist keineswegs einfach.

Dann geraten Sie in eine Situation, in der Sie mit dem Senden einer bestimmten Codierung beginnen, z. B. das Senden der In-Memory-Darstellung eines Floats im Vergleich zum Konvertieren eines Floats in ASCII, das Senden über eine serielle Schnittstelle, die weit über 4 Byte liegen kann, und das Zurückkonvertieren zu einer In-Memory-Darstellung auf dem Host. Stattdessen senden Sie einfach jedes Mal die 4-Byte-Darstellung. Natürlich können Sie die Codierung selbst vornehmen, aber dann müssen Sie Start- / End-Tags, Reihenfolge usw. einrichten.

Stattdessen können Dinge wie Protobuf verwendet werden. Dies wurde tatsächlich in einem Projekt verwendet, an dem ich gearbeitet habe, und es war äußerst vorteilhaft, es verarbeitet Nachrichten mit variabler Länge, verarbeitet Endian für Sie und ein paar andere coole Funktionen. Die Codegröße ist auch nicht so groß, und Sie können alles angeben, was beim Start statisch zugewiesen werden soll. Sie müssten jedoch selbst eine Prüfsumme eingeben, wenn Sie diese benötigen.

hak8or
quelle