Alle meine Mikrocontroller-Geräte, die über UART mit dem PC kommunizieren, verwenden ASCII-Strings zum Senden von Befehlen und Empfangen von Daten (wie in Arduino implementiert). Das habe ich gelernt, als ich anfing, mich mit Elektronik zu beschäftigen, und ich fand es immer ausreichend, blanke Saiten zu senden. Mir ist jedoch aufgefallen, dass die meisten Geräte, auf die ich gestoßen bin, hochentwickelte Binärprotokolle verwenden, die Funktionscodes, Adressen und CRC-Fehlerprüfung enthalten.
Wann ist eine einfache ASCII-Kommunikation akzeptabel und wann sollte ich etwas Fortgeschritteneres wie Modbus in Betracht ziehen? Verwenden kommerzielle Geräte ein solches ASCII? Industriell?
ASCII und CRC schließen sich nicht gegenseitig aus. ASCII ist eine Kodierung und CRC dient der Fehlerprüfung.
ALLES kann als ASCII gesendet werden. Wir Alten erinnern uns sicherlich an UUEncoding, das alles in einen ASCII-String verwandelt.
A) Für mich ist es meistens eine Frage der Schnelligkeit und Effizienz. Das Senden einer großen 32-Bit-Zahl per ASCII kann lange dauern, aber es dauert nur 4 Bytes, um sie als Binärdatei über ein serielles Protokoll zu senden.
B) Das Senden von NUMBERS über ASCII bedeutet, dass Sie die Zahl in ASCII konvertieren müssen, was ein klarer zusätzlicher Schritt ist (dies ist Teil dessen, was "printf" tut).
Wenn Sie irgendwie Ihren Platz verlieren, es vermasseln, das Format verlieren, das falsche Endian erhalten usw., kann ein binäres Kommunikationsprotokoll sicherlich vermasseln. Wenn Sie ASCII senden, kann es einfacher sein, sich von Fehlern zu erholen, indem Sie einfach hineingehen und sich den Datenstrom ansehen.
Hier sind einige Gedanken dazu:
Auf der einfachsten Ebene könnte man sagen, dass ein einfaches Kommunikationsprotokoll drei Schichten hat: physisch, Transport und Anwendung. (Es gibt Modelle mit mehr wie OSI mit 7 oder TCP/IP mit 4. Die Anzahl der Schichten ist im Zusammenhang mit dieser Frage nicht besonders wichtig.)
Die Anwendungsschicht ist die Schicht, mit der Sie sich direkt in Ihrem Code befassen, und der Fokus der Frage. Was die Transportschicht betrifft, ist das Byte, das Sie ihr in send_data übergeben haben, nur ein binäres Muster, aber Sie können es in Ihrem Anwendungscode als den Buchstaben „A“ interpretieren. Die CRC- oder Prüfsummenberechnung ist die gleiche, unabhängig davon, ob Sie das Byte als 'A', 0x41 oder 0b01000001 betrachten.
Die Transportschicht ist die Paketebene, auf der Sie Ihre Nachrichtenkopfzeilen und die Fehlerprüfung haben, sei es CRC oder eine einfache Prüfsumme. Im Zusammenhang mit Firmware haben Sie möglicherweise eine Funktion wie send_data, bei der Sie ihr ein zu sendendes Byte übergeben. Innerhalb dieser Funktion wird ein Paket eingefügt, das besagt: "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 physikalischen Schicht werden die Elektronik und die Schnittstelle definiert: Anschlüsse, Spannungspegel, Timing usw. Diese Schicht kann von ein paar Spuren mit TTL-Signalen für einen einfachen UART auf einer Leiterplatte bis zu einem vollständig isolierten Differenzialpaar wie in einigen reichen CAN- Implementierungen.
Am empfangenden Knoten kommt das Paket auf der physikalischen Schicht herein, wird auf der Transportschicht entpackt und Ihr binäres Muster steht dann der Anwendungsschicht zur Verfügung. Es liegt an der Anwendungsschicht des empfangenden Knotens, zu wissen, ob dieses Muster als „A“, 0x41 oder 0b01000001 interpretiert werden soll, und was damit zu tun ist.
Zusammenfassend lässt sich sagen, dass es so ziemlich immer akzeptabel ist, ASCII-Zeichen zu senden, wenn die Anwendung dies erfordert. Das Wichtigste ist, Ihr Kommunikationsschema zu verstehen und einen Fehlerprüfmechanismus einzubauen.
Ein noch nicht erwähnter Punkt ist, dass unabhängig davon, ob Sie ASCII- oder ein Binärprotokoll verwenden, das Senden eines Rubbelzeichens vor jedem Paket sicherstellt, dass selbst dann, wenn Leitungsrauschen oder Framing-Fehler vor dem Start eines Pakets auftreten, alle Zeichen nach dem Rubbelzeichen out wird ohne weiteres Rauschen korrekt gerahmt. Andernfalls, wenn man kontinuierlich Pakete sendet und keine Zeichen enthält, die garantiert eine Resynchronisation erreichen, ist es möglich, dass ein Fehler alles Folgende bis zur nächsten Übertragungspause beschädigt. Das 0xFF-Zeichen ist nett, weil es garantiert, dass jeder Empfänger auf das folgende Zeichen resynchronisieren kann.
(*) 0xFF – Rubout genannt, weil jemand, der ein falsches Zeichen eintippt, während er Daten auf ein Papierband tippt, die Taste „Band rückwärts“ drücken und Rubout drücken kann, um das irrtümlich gestanzte Zeichen durch 0xFF zu ersetzen, was geschieht von den meisten Empfängern ignoriert werden).
Ein Vorteil des Sendens von ASCII-Strings besteht darin, dass die Steuercodes dann verwendet werden können, um den Beginn / das Ende der Nachricht zu signalisieren. zB STX (Zeichen 2) und ETX (Zeichen 3) können den Beginn der Übertragung und das Ende der Übertragung signalisieren. 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 Overhead oder Komplexität), da ein gültiges Datenbyte dasselbe Muster haben kann.
ASCII ist in Ordnung, ich verwende es in fast allen Projekten. Es macht das Debuggen für die Überwachung des Ports viel einfacher und würde nur dann zu einem Problem, wenn viele Daten zu senden wären.
Ein weiterer Bonus: Ich verwende serielle Funkgeräte, um Nachrichten zwischen Arduinos zu erhalten, und ich kann einen an meinen Laptop angeschlossenen seriellen Monitor verwenden und Nachrichten einspeisen, um bestimmte Dinge zu bewirken. Super zum Testen.
Auch das Senden von Dingen als Binärdatei ist nicht unmöglich zu debuggen, und abhängig von Ihren Tools können Sie die Binärdatei extrahieren und in etwas für Menschen Lesbares konvertieren lassen. Oder wenn Sie wissen, wonach Sie suchen, können Sie den Datenstrom visuell inspizieren und Werte dort erkennen, wo sie sein sollten, und Fehler so finden, wenn auch nicht so einfach. dh Sie werden die Muster von Bytes erkennen und die erwarteten Werte erkennen
Anstelle von Modbus ziehen Sie HDLC in Betracht . Sie erhalten eine Fehlererkennung (was bei lauten seriellen Leitungen wichtig ist). Synchronisation ist robust, Escape ist robust.
Ich habe HDLC in RS-485-Netzwerken ohne Probleme verwendet und PPP verwendet es ebenfalls.
ASCII über UART ist unter anderem deshalb am beliebtesten, weil:
Es ist beim Debuggen für Menschen lesbar (ich habe noch keinen Logikanalysator gesehen, der ASCII nicht dekodiert).
Es ist sehr einfach zu implementieren, Sie haben eine ASCII-Tabelle über schnelles Google, die gut standardisiert ist.
Es hat eine eingebaute Synchronisation mit den Start-/Stopp-Bits.
So ziemlich die gesamte Hobbywelt hat sich mit ASCII über Seriell eingerichtet, also müssen alle neuen Methoden damit umgehen, und das ist keineswegs einfach.
Dann geraten Sie in eine Situation, in der Sie beginnen, eine bestimmte Codierung zu senden, z. B. das Senden der In-Memory-Darstellung eines Floats im Vergleich zum Konvertieren eines Floats in ASCII, das Senden über eine serielle Verbindung, die weit mehr als 4 Bytes sein kann, und das dann zurückkonvertieren zu einer In-Memory-Darstellung auf dem Host. Stattdessen senden Sie einfach jedes Mal die 4-Byte-Darstellung. Sicher, Sie können mit der Codierung selbst beginnen, 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 arbeitete, und es war äußerst nützlich, es macht Nachrichten mit variabler Länge, handhabt Endian für Sie und ein paar andere coole Funktionen. Es ist auch nicht so groß in der Codegröße, und Sie können alles so angeben, dass es beim Start statisch zugewiesen wird. Sie müssten jedoch selbst eine Prüfsumme einwerfen, wenn Sie sie brauchen.
Eugen Sch.
Tut
Leichtigkeitsrennen im Orbit