Kommunikationsprotokoll Basis (Spezifikation)
Hi!
Das freut mich sehr, dass Ihr dabei seid
! Hatte am Anfang gedacht, das Hardware und Software für die Meisten eher nichts ist aber ich finde es schön, dass sich hier selbst dafür jemand interessiert
.
OK, also kommen wir auch gleich zum Thema. Ich habe ein Kommunikationsprotokoll spezifiziert als Basis für die Kommunikation zwischen Fernsteurung und Copter und die möchte ich hier dokumentieren.Mit anderen Worten: Jetzt kommt richtig schön trockener theoretischer Stoff :-D.
Normalerweise müsste ich an dieser Stelle zuerst ein wenig auf die Einstellungsmöglichkeiten des DNT24P Funkmoduls eingehen aber dazu hab ich grad keine Lust. Das hole ich in einem anderen Beitrag nach. Wichtig zu wissen ist eigentlich erstmal nur, dass ich die Funkmodule als "Kabelersatz" (Cable Replacement) verwenden möchte. Das bedeutet, die Daten, die man auf der einen Seite (z.B. Fernsteuerung) reinschiebt, bekommt man auf der anderen Seite (z.B. Copter) genauso wieder raus. So als ob man ein RS232 Kabel zwischen zwei Geräten angeschlossen hat und Daten austauscht.
Die kleinste zu Übertragende Dateneinheit bei einem UART (Universal Asynchronouse Receiver Transmitter, über diese Schnittstelle werden die DNT24P Module an dem ATXMega128 angeschlossen) ist ein Byte (8 Bit). Sprich, wenn man ein Byte mit dem Wert 3 in der Funke zum Funkmodul über den UART sendet, wird ein Byte mit dem Wert 3 im Copter über den UART, an den das Funkmodul angeschlossen ist, empfangen. Bild 1 veranschaulicht diese grobe Kommunikation.
Angenommen man ginge naiv an so eine Kommunikation heran und überträgt einfach nacheinander die vier wichtigen Steuerkanäle (Speed [Gas], Rudder [Drehen], Elevator [Pitch] und Aileron [Roll]) zyklisch. In einer Idealen Wert wäre alles in Ordnung, alle Daten kämen perfekt beim Copter an und alles könnte perfekt interpretiert werden. Leider befinden wir uns nicht in einer perfekten Welt, denn:
* Über die Kommunikationsstrecke (sei es Kabel oder Funk) können die Daten verfälscht werden.
* Einzelne Bits können kippen.
* Bits können falsch erfasst werden vom Sender.
* Andere Funksignale können die Übertragung stören und verfälschen.
* Die UARTs könnten wegen ihrer assynchronheit zeitliche Fehler verursachen
* ... usw.
Aus diesen Gründen ist für eine sichere Datenkommunikation ein
Übertragungsprotokoll erforderlich. Kommunikatiojnsprotokolle haben üblicherweise eine Startkennung (Zum Erkennen, wann ein Datenpaket anfängt) und eine Checksumme (Checksum, zum Überprüfen, ob der Paketinhalt korrekt empfangen worden ist). Im Falle des Kommunikationsprotokolles für meinen Copter habe ich ein einfaches Basisprotokoll spezifiziert (wie in Bild 2 zu sehen). Dabei habe ich mir überlegt, was für die Steuerung eines Copters am wichtigsten ist: Die vier Steuerwerte:
* Speed
* Rudder
* Eleveator
* Aileron
Daher wollte ich diese vier Werte innerhalb eines einzelnen Paketes übertragen können und zwar mit einer ausreichenden Genauigkeit. Ich wählte den Datentyp "signed short", er ist zwei Byte lang und hat einen Wertebereich von -32768 bis 32767 (2 hoch 16). Das ist mehr als Ausreichend. Mit den ADC des ATXMega128 kann ohnehin nur ein Wertebereich von 12 Bit (2 hoch 12 = 0 bis 4096) erfasst werden. Ein Byte für jeden Wert reicht leider nicht, da dann nur ein Wertebercih von -128 bis 128 möglich wäre (2 hoch 8). Eine weitere wichtige Anfordeung für mich ist, dass ein Paket immer die gleiche Länge hat. Das Problem hier ist, dass wenn die Startkennung eines Paketes innerhab der Datenbytes entahlten ist, würde dies als Paketanfang erkannt werden und das eigentliche Paket wäre verloren. Daher versucht man die Starterkennung innerhalb der Datenbytes während der Übertragung zu vermeiden durch Byte Stuffing. Leider wird ein Paket dadurch größer, was für eine Echtzeitkommunikation für den RC Modellbau nicht praktikabel ist.
Ich habe mir daher ein eigenes Konzept überlegt mit dem kleine Datenmengen ohne Paketverlängerung übertragen werden können und bei dem die Startkennung nicht innerhalb der Datenbytes auftauchen kann.
Dazu definierte ich ein Byte mit dem Wert 01XXXXXX(binär) als Startkennung. Die X stehen dabei für irrelevante Bits. Die sechs X dieser Startkennung können also genutzt werden, um einzelne Datenbytes innerhalb des Paketes zu maskieren (sollten diese in den ersten beiden Bit den Wert "01" haben). Da die vier Steuerwerte + der Checksumme insgesamt 9 Byte sind und nur sechs Byte der Startkennung genutzt werden können habe ich kurzerhand entschieden, zwei Byte mit der Startkennung zu verwenden, im Falle eines Paketes mit den Haupt Steuerdaten. Bild 2 zeigt wie die Bits und Bytes verwendet werden.
Desweiten habe ich einen Pakettyp definiert, welcher nur mit einem Byte Startkennung auskommt, um 0 bis 4 Nutzbytes zu übertragen. Der Identifier spezifiziert dabei den Inhalt des Pakets (z.B. AKKU Spannung, GPS Koordinaten, Befehl zum halten der aktuellen GPS Position, usw.). Die Länge gibt an, wieviele Nutzbytes im Paket enthalten sind. Die genaue Interpretation dieser Werte wird von einer darüberliegenden Schicht übernommen und spielt für das Baisprotokoll keine Rolle. Hier sind sozusagen nur die Haupt Steuer Daten Pakete und Pakete für das Übertragen generelleler Daten spezifiziert. Als spezielles Paket kann das "Acknowledge Paket" betrachtet, werden, welches den Empfang eines generellen Datenpaketes anhand des Identifiers bestätigen soll. Das ist wichtig für Befehle wie "Aktuelle GPS Position halten". Denn stellt man sich vor, man betätigt an der Funke den Knopf für das "Halten der aktuellen GPS Position" und das Paket ist nicht korrekt vom Copter empfangen worden, dann würde weiterhin die Funkensteuerung aktiv sein, der Pilot denkt aber der Copter hält sich nun automatisch. Das wäre fatal. Daher müssen einige Pakettypen bestätigt werden. Die Logik dafür muss allerdings eine übergeordnete Auswertungsschicht übernehmen.
In Bild 2 sind alle Pakettypen beschrieben. Ich hoffe das evtl. der ein oder andere das alles versteht und wenn nicht ist es auch nicht schlimm
. Dann hab ich wenigstens meine Doku hier
.
Viele Grüße,
Markus
Kleiner Nachtrag:
Sicher fragen sich nun einige: "Was passiert eigentlich, wenn ein wichtiges Datenpaket mit den Hauptsteuerdaten nicht richtig empfangen worden ist?". Das ist eine gute Frage. Also: Ich plane die Hauptsteuertdaten mit 50Hz zu übertragen, sprich: Die Hauptsteuerdaten werden 50 Mal in einer Sekunde übertragen. Das ist etwa doppelt soviel wie es nötig wäre, denn der Mensch ist träge und kann ohnehin nicht mehr als 25 Änderungen in einer Sekunde wahrnehmen (Wie beim TV Bild). Angenommen ein Steuerdatenpaket wird nicht korrekt empfangen, dann gibt es zwei Möglichkeiten.
Erstens: Das Paket könnte neu angefordert werden. Allerdings würde das den Kommunikationsfluss behindern, denn nachfolgende Pakete mit neuen wichtigen Steuerdaten müssten sich hinten anstellen. Ausserdem: Was soll der Copter mit "alten" Daten anfangen. Er könnte sich höchsten sagen: "Tja, vor XXX Millisekunden hätte ich eigentlich in die und die Position fliegen sollen..." aber das Hilft ihm dann auch nicht mehr
.
Zweitens: Ein nicht korrekt empfangenes Paket wird einfach ignoroert und das nächste aktuelle Paket wird ausgewertet. Diese Möglichkeit macht mehr Sinn, denn alte Pakete sind nicht mehr anzuwenden. Die Copterregelung kann auch ohne Probleme eine geringe Anzahl fehlerhaft empfangener Pakete verkraften. In dieser Zeit wird einfach der zuletzt korrekt empfangene Wert verwendet. Wichtig ist aber, dass ein FailSafe eingebaut wird, sollte die Kommunikation über eine gewisse Zeit nicht mehr gegen sein. In diesem Fall sollte der Copter so intelligent sein und seine aktuelle Position einfach anhand von GPS Daten halten oder besser noch zu seinem Startpunkt automatisch zurückkehren. Aber das ist ein anderes Thema und wird in einem späteren Beitrag behandelt (Jahaaaa, ich glaube das wird mein Lieblingsspruch... "Wird in einem anderen Beitrag behandelt..."
). Wenn man so darüber nachdenkt wird einem erst klar, was alles in so einem Projekt drin steckt und was beachtet werden muss. Ich denke vielen sind die Hintergründe gar nicht klar, wenn man die Steuerplatinen einfach kauft.