Vor einiger Zeit habe ich einen einfachen und billigen kleinen IR-gesteuerten Spielzeughubschrauber gekauft (genau wie dieser - er heißt "Diamond Gyro" oder "Diamond Force"). Zum Spaß habe ich versucht, es über ein Arduino zu steuern.
Update: Habe das Protokoll herausgefunden; siehe Antwort
Andere haben bereits ihre Ergebnisse zum Hacken eines anderen IR-Spielzeughubschraubers und zum Entschlüsseln seines IR-Protokolls geteilt . Wirklich cool, aber leider verwendet mein Helikopter ein anderes Protokoll. Eine, die ich nicht ganz nachvollziehen kann. (Ich sollte hinzufügen, dass Elektronik für mich nur ein gelegentliches Hobby ist, also habe ich vielleicht etwas Offensichtliches übersehen).
Ähnlich wie im 2. Link oben nahm ich den Controller auseinander, lokalisierte den IC-Pin, der die LEDs steuert (die IC-Markierungen wurden übrigens gelöscht), und schloss einen Logikanalysator an.
Ich habe viele gute Daten, aber ich kann das Protokoll immer noch nicht herausfinden. Diese Seite ist eine großartige Ressource, aber keines der aufgeführten Protokolle scheint zu passen. Und nichts anderes, was ich gefunden habe, scheint auch nicht zu dem Signal zu passen, das ich erfasst habe. Ich muss mir allerdings vorstellen, dass es ein einfaches Standardprotokoll ist, nur weil es ein billiges kleines Spielzeug ist.
Daher wäre ich für jede Idee dankbar. Vielleicht sehe ich es einfach falsch.
(Weitere Infos unter dem Bild)
Ich habe dies bei 16 MHz aufgenommen, wobei der Controller auf Kanal A eingestellt war; sollte zeitlich genau sein. (Es gibt 3 IR-Kanäle, aus denen Sie auswählen können, aber die Verwendung der beiden anderen Kanäle ändert die Eigenschaften nicht, sondern nur Teile des Pakets selbst.) Die Timings sind sehr konsistent (+/- 10 µs max.). Pakete werden mit unterschiedlichen Intervallen wiederholt, aber mindestens sind sie etwa 100 ms voneinander entfernt.
Träger: 38 kHz bei 50 % Einschaltdauer
Tiefen:
- Kurz: 285 µs
- Lang: 795 µs
Höhen:
- Kurz: 275 µs
- Lang: 855 µs
Immer 17 Höhen pro Packung.
Der Heli hat 3 Bedienelemente: „Throttle“ (dh Auftrieb/Rotorgeschwindigkeit), Pitch (vorwärts/zurück) und Yaw (Drehung um die Rotorachse), die alle mit 2 Thumbsticks gesteuert werden. Sie haben alle eine Art Reichweite (nicht nur ein/aus) und werden, soweit ich das beurteilen kann, alle in einem einzigen Paket übertragen. Die linken/rechten Eingänge werden nur gesendet, wenn etwas anderes gesendet wird, also habe ich beim Sampling das maximale Gas gegeben. Gas- und Pitch-Eingabe auf seinen eigenen Trigger-Paketen, die gesendet werden, sobald Sie die Thumbsticks über einen bestimmten Schwellenwert/Totbereich hinaus drücken (in der Grafik unten steht die Bezeichnung „min“ für das erste Paket, das gesendet wird, wenn ein Regler langsam über seinen Totbereich hinaus gedrückt wird).
Es hat auch Knöpfe zum Trimmen nach links und rechts, da der Heli ( überhaupt ) kein Präzisionsinstrument ist und sonst dazu neigt, sich langsam zu drehen. Die linken/rechten Trimmtasten scheinen leider kein Signal zu senden, das bei jedem Drücken etwas erhöht/verringert (was praktisch wäre, um das Protokoll herauszufinden); Es scheint nur ein einziger Befehl zu sein, der dem Hubschrauber sagt, er soll nach links / rechts trimmen, und dann verfolgt er ihn.
Ich erlaube mir, meine eigene Frage zu beantworten, da ich das meiste herausgefunden habe, und dies ist eine gute Möglichkeit, meine Erkenntnisse zu teilen. Mein Dank geht an Olin Lathrop, der mir einen Ausgangspunkt und einige Ideen zum Ausprobieren gegeben hat, aber letztendlich stellte sich heraus, dass das Protokoll ganz anders war als Olins Vermutung, daher poste ich diese Antwort.
Update: Ich habe eine Folgefrage zu den letzten 8 Bits gestellt, die ich nicht ganz verstanden habe, und Dave Tweed hat es herausgefunden . Ich werde die Details hier einfügen, damit diese Antwort als vollständige Protokollspezifikation funktionieren kann, aber sehen Sie sich Daves Antwort an.
Ich musste einige verschiedene Dinge ausprobieren, um das herauszufinden, aber ich bin ziemlich zuversichtlich, dass ich es hinbekommen habe. Seltsamerweise habe ich nirgendwo etwas gefunden, das diesem Protokoll ähnelt, aber es kann sehr gut ein gängiges Protokoll sein, von dem ich einfach nichts weiß.
Wie auch immer, hier ist, was ich gefunden habe:
Sowohl Pulse als auch die Zwischenräume werden zur Codierung der Daten verwendet. Ein langer Impuls/eine lange Pause ist eine binäre Eins (1) und ein kurzer Impuls/eine kurze Pause ist eine binäre Null (0). Die Impulse werden unter Verwendung von Standard-Verbraucher-Infrarot-38-kHz-Modulation bei 50 % Einschaltdauer gesendet.
Die Impuls-/Raumzeiten sind in der ursprünglichen Frage enthalten, aber ich wiederhole sie hier der Vollständigkeit halber:
Bit Pulse Space
-----+---------+---------
0 | 275µs | 285µs
1 | 855µs | 795µs
Alle max. ±10 µs, typ. ±5 µs. Dies basiert auf Abtastwerten, die mit einem Logikanalysator bei 16 MHz erfasst wurden; Ich habe kein Oszilloskop, daher kenne ich das genaue Profil nicht (dh Anstiegs- / Abfallzeiten).
Pakete werden so lange wiederholt, wie die Steuereingänge angelegt werden und einen Abstand von mindestens 100 ms zu haben scheinen.
Die Paketübertragung beginnt mit einer "Puls 1"-Präambel, die fest und nicht Teil der Daten ist. Das folgende Leerzeichen codiert das erste Datenbit des Pakets und der letzte Impuls codiert das letzte Bit.
Jedes Paket ist 32 Bit lang und enthält alle Eingaben, die die Fernbedienung bereitstellen kann. Werte werden als Little Endian gelesen, dh MSB zuerst.
Nachfolgend der grundsätzliche Aufbau der einzelnen Pakete. Die letzten 8 Bits haben mich verwirrt, aber das wurde jetzt herausgefunden (siehe unten).
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
--+---------------------------+-----------+---+-------+-----------
P| Yaw | Throttle | Pitch | T | Chan. | Check
P: Preamble (always a pulse-1), T: Trim, Chan.: Channel
Bit Length Description (see note below)
-----------------------------------------------
0 1 Preamble. High 1
1-6 6 Yaw. Range 0-36 for left-right, 17 being neutral
7-14 8 Throttle. Range 0-134
15-20 6 Pitch. Range 0-38 for forward-back, 17 being neutral
21-22 2 Trim. Left = 1, right = 2, no trim = 0
23-26 4 Channel. A = 5, B = 2, C = 8
27-32 6 Check bits
Hinweis: Die Bereiche basieren auf den höchsten Messwerten, die ich erhalten habe. Das Protokoll ist in der Lage, größere Bereiche zu erreichen – bis zu 255 für Gas, 63 für Nicken/Gieren – aber etwa die Hälfte davon.
Der Tonhöhenwert scheint eine Totzone von 14–21 (einschließlich) zu haben; nur bei Werten darüber oder darunter reagiert der Helikopter tatsächlich. Ich weiß nicht, ob es für das Gieren dasselbe gilt (schwer zu sagen, da der Hubschrauber sowieso instabil ist und sich möglicherweise nur leicht von alleine dreht).
Hier ist es in grafischer Form (vergleiche mit der Grafik in der ursprünglichen Frage)
Die 6 Prüfbits werden durch XOR-Verknüpfung aller vorhergehenden Werte berechnet. Jeder Wert wird als 6 Bit behandelt. Das bedeutet, dass die 2 MSBs des 8-Bit-Drosselwertes einfach ignoriert werden. Dh
check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel
Die Signalzeiten und Modulation müssen nicht supergenau sein. Sogar das überhaupt nicht genaue Timing meines Arduino funktioniert gut, trotz zwielichtiger Modulation und ein bisschen Hit-and-Miss bei den Impuls-/Raumdauern im Vergleich zur echten Fernbedienung.
Ich glaube - habe es aber nicht getestet - dass sich der Hubschrauber einfach an den Kanal des ersten Signals anschließt, das er findet. Wenn es zu lange ohne Signal bleibt (ein paar Sekunden), scheint es in seinen "Suchmodus" zurückzukehren, bis es wieder ein Signal erhält.
Der Helikopter ignoriert Nick- und Gierwerte, wenn das Gas Null ist.
Die Trimmbefehle werden nur einmal pro Tastendruck auf der Fernbedienung gesendet. Vermutlich erhöht/verringert der Trimmwert einfach einen Wert in der Steuerung des Hubschraubers; Es ist nichts, was die Fernbedienung verfolgt. Daher sollte sich jede Implementierung wahrscheinlich an dieses Schema halten und nur gelegentlich den linken/rechten Trimmwert senden, ansonsten aber standardmäßig einen Null-Trimmwert in den Paketen verwenden.
Ich empfehle einen Kill-Switch, der einfach Gas auf Null setzt. Dadurch fällt der Hubschrauber aus dem Himmel, erleidet jedoch weniger Schaden, wenn er seine Motoren nicht dreht. Wenn Sie also kurz davor sind, zu stürzen oder etwas zu treffen, drücken Sie den Kill-Schalter, um zu vermeiden, dass die Zahnräder abisolieren oder die Klingen brechen.
Die IR-LEDs der Originalfernbedienung scheinen eine Wellenlänge von> 900 nm zu haben, aber ich habe keine Probleme mit einer LED von ~ 850 nm.
Der IR-Empfänger des Hubschraubers ist in Ordnung, aber nicht sehr empfindlich. Je heller Ihre IR-Quelle, desto besser. Die Fernbedienung verwendet 3 LEDs in Reihe, die auf der 9-V-Schiene sitzen, anstatt auf der 5-V-Schiene, die von der Logik verwendet wird. Ich habe ihre Stromaufnahme nicht sehr genau überprüft, aber ich würde wetten, dass es 50 mA sind.
Hier sind ein paar Pakete für alle Interessierten (ja, ich habe einen Decoder geschrieben; ich habe das alles nicht von Hand decodiert). Die Pakete von Kanal A stammen aus denselben Aufnahmen wie die Diagramme in der ursprünglichen Frage.
Channel A
Yaw Throttle Pitch Tr Chan Check Description
-----------------------------------------------------------
000100 10000100 000000 00 0101 000101 Left Mid + Throttle
000000 10000110 010001 00 0101 010010 Left Max + Throttle
100001 10000110 000000 00 0101 100010 Right Mid + Throttle
100100 10000100 010001 00 0101 110100 Right Max + Throttle
010001 00000000 001011 00 0101 011111 Forward Min
010001 00000000 000000 00 0101 010100 Forward Max
010001 00000000 011000 00 0101 001100 Back Min
010001 00000000 100101 00 0101 110001 Back Max
010001 00000000 010001 01 0101 010101 Left Trim
010001 00000000 010001 10 0101 100101 Right Trim
010001 00000011 010001 00 0101 000110 Throttle 01 (min)
010001 00010110 010001 00 0101 010011 Throttle 02
010001 00011111 010001 00 0101 011010 Throttle 03
010001 00101111 010001 00 0101 101010 Throttle 04
010001 00111110 010001 00 0101 111011 Throttle 05
010001 01010101 010001 00 0101 010000 Throttle 06
010001 01011111 010001 00 0101 011010 Throttle 07
010001 01101100 010001 00 0101 101001 Throttle 08
010001 01111010 010001 00 0101 111111 Throttle 09
010001 10000101 010001 00 0101 000000 Throttle 10 (max)
Channel B
Yaw Throttle Pitch Tr Chan Check Description
-----------------------------------------------------------
000000 10000110 010001 00 0010 010101 Left Max + Throttle
100100 10000110 010001 00 0010 110001 Right Max + Throttle
010001 00000000 001001 00 0010 011010 Forward Min
010001 00000000 000000 00 0010 010011 Forward Max
010001 00000000 010111 00 0010 000100 Back Min
010001 00000000 100110 00 0010 110101 Back Max
010001 00000000 010001 01 0010 010010 Left Trim
010001 00000000 010001 10 0010 100010 Right Trim
010001 00000001 010001 00 0010 000011 Throttle Min
010001 00110100 010001 00 0010 110110 Throttle Mid
010001 01100111 010001 00 0010 100101 Throttle High
010001 10001111 010001 00 0010 001101 Throttle Max
Channel C
Yaw Throttle Pitch Tr Chan Check Description
-----------------------------------------------------------
000000 10000101 010001 00 1000 011100 Left Max + Throttle
100100 10000101 010001 00 1000 111000 Right Max + Throttle
010001 00000000 001010 00 1000 010011 Forward Min
010001 00000000 000000 00 1000 011001 Forward Max
010001 00000000 010111 00 1000 001110 Back Min
010001 00000000 100110 00 1000 111111 Back Max
010001 00000000 010001 01 1000 011000 Left Trim
010001 00000000 010001 10 1000 101000 Right Trim
010001 00000001 010001 00 1000 001001 Throttle Min
010001 00110100 010001 00 1000 111100 Throttle Mid
010001 01100110 010001 00 1000 101110 Throttle High
010001 10000101 010001 00 1000 001101 Throttle Max
Wie oben erwähnt, wurden die letzten 8 Bits herausgefunden, aber nur für die Nachwelt, hier sind meine ursprünglichen Gedanken. Fühlen Sie sich frei, es vollständig zu ignorieren, da ich mich mit meinen Vermutungen ziemlich geirrt habe.
Die letzten 8 Bits des Pakets sind immer noch ein bisschen mysteriös.
Die 4 Bits von Bit 23 bis 26 scheinen alle vollständig durch die Kanaleinstellung der Fernbedienung bestimmt zu sein. Das Ändern des Kanals auf der Fernbedienung ändert das Protokoll oder die Modulation in keiner Weise; es ändert nur diese 4 Bits.
Aber 4 Bits sind das Doppelte dessen, was tatsächlich benötigt wird, um die Kanaleinstellung zu codieren; Es gibt nur drei Kanäle, also sind 2 Bits genug. Daher habe ich in der obigen Strukturbeschreibung nur die ersten 2 Bits als "Kanal" bezeichnet und die anderen beiden als "X" bezeichnet, aber das ist eine Vermutung.
Nachfolgend finden Sie ein Beispiel der relevanten Bits für jede Kanaleinstellung.
Chan. Bits 23-26
-----+-------------
A | 0 1 0 1
B | 0 0 1 0
C | 1 0 0 0
Grundsätzlich sind es 2 Bits mehr, als zur Übertragung der Kanaleinstellung benötigt werden. Vielleicht hat das Protokoll 4 Bits reserviert, um später mehr Kanäle zu ermöglichen, oder so kann das Protokoll in ganz anderen Spielzeugen verwendet werden, aber ich weiß es einfach nicht. Für die größeren Werte verwendet das Protokoll zusätzliche Bits, die weggelassen werden könnten (Gieren/Gas/Nick könnten mit jeweils etwas weniger auskommen), aber für die Trimmung – die ebenfalls 3 Zustände hat – werden nur 2 Bits verwendet. Man könnte also vermuten, dass der Kanal auch nur 2 Bits hat, aber das lässt die nächsten 2 unberücksichtigt.
Die andere Möglichkeit ist, dass die Prüfsumme des Pakets 8 Bit lang ist, beginnend mit den "X-Bits", und - durch die Prüfsummenmagie - sie zufällig immer irgendwie die Kanaleinstellung widerspiegeln. Aber nochmal: Ich weiß es nicht.
Apropos: Ich habe keine Ahnung, wie diese Prüfbits gebildet werden. Ich meine, das sind Prüfbits, da sie keinem einzelnen Steuereingang entsprechen, und der Helikopter scheint nicht zu reagieren, wenn ich daran herumhantiere. Ich vermute, es ist eine Art CRC, aber ich konnte es nicht herausfinden. Die Prüfung ist 6-8 Bit lang, je nachdem, wie Sie die "X-Bits" interpretieren, es gibt also viele Möglichkeiten, die zusammengesetzt werden könnten.
Das sieht nicht so schlimm aus. Beachten Sie zunächst, dass alle Nachrichten genau 17 Impulse enthalten. Dies gibt uns sofort einen starken Hinweis darauf, dass kurze Leerzeichen innerhalb einer Nachricht irrelevant sind. Es scheint, dass Daten durch Impulse codiert werden, die entweder kurz oder lang sind, und dass ein gewisser Abstandsbereich zwischen diesen Impulsen akzeptabel ist.
Natürlich beginnt jede Nachricht mit einem langen Impuls als Startbit. Das lässt 16 Datenbits. Wahrscheinlich sind einige der frühen Bits ein Opcode, möglicherweise mit variabler Länge. Wenn ich dies tun würde, wären einige der Endbits eine Prüfsumme. Stellen Sie sich vor, die Ingenieure, die die Firmware geschrieben haben, wollten die Dinge für sich einfach halten, also können Sie davon ausgehen, dass irgendwo 8 Datenbits drin sind. Prüfen Sie nun, ob eine der Nachrichten sinnvoll ist.
Nennen wir eine lange eine 1 und eine kurze eine 0. Es könnte auch umgekehrt sein, aber irgendwo müssen wir anfangen. Abstreifen der Startbitblätter:
1010001101011010 min Gas 1010011101011000 maximale Drosselung 1010000001011111 min vorwärts 1010000000011110 max vorwärts 1010000011011101 max zurück 1010000100011010 Minuten zurück 0000010101011100 max links + max Gas 0100010101011110 max rechts + max Gas 1010000101111111 Verkleidung links 1010000101011011 Verkleidung rechts
Ein paar Dinge fallen sofort auf. Offensichtlich ist Bit 0 ein Paritätsbit. Andernfalls scheint es ein 3-Bit-Feld <15:13>, einen 8-Bit-Datenwert <12:5> und ein weiteres 4-Bit-Feld <4:1> zu geben.
Es sieht so aus, als würde der Datenwert in der Reihenfolge der niedrigen bis hohen Bits gesendet, daher ist es wahrscheinlich sinnvoller, die gesamten 16 Bits von dem, was ich zeige, umgedreht zu interpretieren.
Ich habe keine Lust, mehr Zeit damit zu verbringen, aber hoffentlich hat Ihnen das einen Anfang gegeben. Ich würde fortfahren, indem ich die obige Liste neu schreibe, wobei das Paritätsbit entfernt wird, die ganze Zahl von LSB auf MSB umgedreht wird und jedes angenommene Feld separat mit einem Leerzeichen zwischen ihm und dem angrenzenden Feld angezeigt wird. Dadurch kann mehr auf Sie zukommen. Denken Sie auch daran, dass wir möglicherweise den 1/0-Sinn jedes Bits rückwärts haben. Schreiben Sie die neue Tabelle vielleicht in beide Richtungen und sehen Sie, ob etwas auf eine Weise sinnvoller ist.
Ignacio Vazquez-Abrams
Flambino
Ignacio Vazquez-Abrams
Flambino
Flambino