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 Startplatz und einige Ideen zum Ausprobieren gegeben hat, aber letztendlich hat sich das Protokoll als ganz anders herausgestellt als Olins Vermutung, weshalb ich diese Antwort gepostet habe.
Update: Ich habe eine Folgefrage zu den letzten 8 Bits gepostet , die ich nicht vollständig 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 schauen Sie sich Daves Antwort an.
Ich musste einige verschiedene Dinge ausprobieren, um das herauszufinden, aber ich bin ziemlich zuversichtlich, dass ich es verstanden habe. Seltsamerweise habe ich an keiner anderen Stelle etwas gefunden, das diesem Protokoll ähnelt, aber es kann durchaus ein allgemeines Protokoll sein, von dem ich einfach nichts weiß.
Wie auch immer, hier ist was ich gefunden habe:
Protokoll / Codierung
Beide Impulse und die Zwischenräume werden zum Codieren der Daten verwendet. Ein langer Impuls / Raum ist eine binäre Eins (1) und ein kurzer Impuls / Raum ist eine binäre Null (0). Die Impulse werden unter Verwendung einer Standard-Consumer-Infrarot-38-kHz-Modulation bei einem Tastverhältnis von 50% gesendet.
Die Puls- / Raum-Timings sind in der ursprünglichen Frage enthalten, aber ich werde sie hier der Vollständigkeit halber wiederholen:
Bit Pulse Space
-----+---------+---------
0 | 275µs | 285µs
1 | 855µs | 795µs
Alle ± 10µs max., ± 5µs typ. Dies basiert auf Proben, die mit einem Logikanalysator bei 16 MHz aufgenommen wurden; Ich habe kein Oszilloskop, daher kenne ich das genaue Profil nicht (dh Anstiegs- / Abfallzeiten).
Pakete werden wiederholt, solange die Steuereingaben angewendet werden und einen Abstand von mindestens 100 ms zu haben scheinen.
Die Paketübertragung beginnt mit einer Präambel "Impuls 1", die fest und nicht Teil der Daten ist. Der folgende Raum codiert das erste Datenbit des Pakets und der letzte Impuls codiert das letzte Bit.
Jedes Paket ist 32 Bit lang und enthält jeden Eingang, den die Fernbedienung bereitstellen kann. Die Werte werden als Little Endian gelesen, dh zuerst als MSB.
Datenstruktur
Nachfolgend finden Sie die Grundstruktur der einzelnen Pakete. Die letzten 8 Bits hatten 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 Pitch / Yaw -, aber bei etwa der Hälfte.
Der Tonhöhenwert scheint eine Totzone von 14-21 (einschließlich) zu haben; Nur Werte von oben oder unten lassen den Hubschrauber tatsächlich reagieren. Ich weiß nicht, ob es beim Gieren dasselbe ist (schwer zu sagen, da der Hubschrauber sowieso instabil ist und sich von selbst nur leicht drehen kann).
Hier ist es grafisch (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. Dies bedeutet, dass die 2 MSBs des 8-Bit-Drosselklappenwerts einfach ignoriert werden. Dh
check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel
Praktische Hinweise
Die Signalzeiten und die Modulation müssen nicht sehr genau sein. Sogar das ungenaue Timing meines Arduino funktioniert trotz zwielichtiger Modulation und ein bisschen Hit and Miss bei der Puls- / Raumdauer im Vergleich zur echten Fernbedienung einwandfrei.
Ich glaube - aber noch nicht getestet -, dass der Hubschrauber einfach am Kanal des ersten Signals einrastet, das er findet. Wenn es zu lange (einige Sekunden) ohne Signal bleibt, scheint es in den "Such" -Modus zurückzukehren, bis es wieder ein Signal empfängt.
Der Hubschrauber ignoriert Nick- und Gierwerte, wenn der Gashebel 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 nicht etwas, was die Fernbedienung verfolgt. Daher sollte sich jede Implementierung davon wahrscheinlich an dieses Schema halten und nur gelegentlich den linken / rechten Trimmwert senden, andernfalls wird standardmäßig ein Trimmwert von Null in den Paketen verwendet.
Ich empfehle einen Kill-Schalter, der einfach den Gashebel auf Null stellt. Dadurch fällt der Hubschrauber vom Himmel, erleidet jedoch weniger Schaden, wenn er seine Motoren nicht dreht. Wenn Sie also kurz vor dem Absturz stehen oder etwas treffen, drücken Sie den Kill-Schalter, um zu vermeiden, dass Sie 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 der Verwendung einer ~ 850 nm-LED.
Der IR-Empfänger des Hubschraubers ist in Ordnung, aber nicht sehr empfindlich. Je heller Ihre IR-Quelle, desto besser. Die Fernbedienung verwendet 3 in Reihe geschaltete LEDs, die auf der 9-V-Schiene anstelle der von der Logik verwendeten 5-V-Schiene sitzen. Ich habe ihre aktuelle Auslosung nicht sehr genau überprüft, aber ich würde wetten, dass es 50 mA sind.
Beispieldaten
Hier sind ein paar Pakete für alle Interessierten (ja, ich habe einen Decoder geschrieben; ich habe das alles nicht von Hand dekodiert). Die Kanal-A-Pakete stammen aus denselben Erfassungen 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 in meinen Vermutungen ziemlich falsch lag.
Die letzten 8 Bits
Die letzten 8 Bits des Pakets sind immer noch ein bisschen rätselhaft.
Die 4 Bits von Bit 23 bis 26 scheinen alle vollständig durch die Kanaleinstellung der Fernbedienung bestimmt zu sein. Durch Ändern des Kanals auf der Fernbedienung wird das Protokoll oder die Modulation in keiner Weise geändert. es ändert nur diese 4 Bits.
Aber 4 Bits sind doppelt so viel, wie tatsächlich zum Codieren der Kanaleinstellung benötigt wird. Es gibt nur drei Kanäle, also sind 2 Bits ausreichend. Daher habe ich in der obigen Strukturbeschreibung nur die ersten 2 Bits als "Kanal" bezeichnet und die anderen beiden als "X" bezeichnet, aber dies ist eine Vermutung.
Unten 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 gibt es 2 Bits mehr als nötig, um die Kanaleinstellung zu übertragen. Vielleicht hat das Protokoll 4 Bits beiseite gelegt, 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 / Pitch könnte mit jeweils etwas weniger auskommen), aber für das Trimmen - das ebenfalls 3 Zustände hat - werden nur 2 Bits verwendet. Man könnte also vermuten, dass der Kanal auch nur 2 Bits ist, aber die nächsten 2 bleiben unberücksichtigt.
Die andere Möglichkeit besteht darin, dass die Prüfsumme des Pakets, beginnend mit den "X-Bits", 8 Bit lang ist und - durch die Magie der Prüfsumme - zufällig immer die Kanaleinstellung widerspiegelt. Aber nochmal: Ich weiß es nicht.
Apropos: Ich habe keine Ahnung, wie diese Prüfbits gebildet werden. Ich meine, es handelt sich um Prüfbits, da sie keinem einzelnen Steuereingang entsprechen und der Hubschrauber nicht zu reagieren scheint, wenn ich mit ihnen herumspiele. Ich vermute, es ist eine Art CRC, aber ich konnte es nicht herausfinden. Die Prüfung dauert 6 bis 8 Bit, je nachdem, wie Sie die "X-Bits" interpretieren. Es gibt also viele Möglichkeiten, die zusammengestellt werden können.