Je prends la liberté de répondre à ma propre question car j'ai compris l'essentiel et c'est un bon moyen de partager mes résultats. Mes remerciements à Olin Lathrop pour m'avoir donné un point de départ et quelques idées à essayer, mais en fin de compte, le protocole s'est avéré assez différent de la supposition d'Olin, donc j'ai posté cette réponse.
Mise à jour: J'ai posté une question de suivi concernant les 8 derniers bits, que je ne comprenais pas complètement, et Dave Tweed l'a compris . Je vais inclure les détails ici, donc cette réponse peut fonctionner comme une spécification de protocole complète, mais allez vérifier la réponse de Dave.
J'ai dû essayer différentes choses pour comprendre cela, mais je suis assez confiant de l'avoir compris. Curieusement, je n'ai rien trouvé de semblable à ce protocole ailleurs, mais il pourrait très bien s'agir d'un protocole commun que je ne connais tout simplement pas.
Quoi qu'il en soit, voici ce que j'ai trouvé:
Protocole / encodage
Les impulsions et les espaces intermédiaires sont utilisés pour coder les données. Une impulsion / espace long est un binaire (1), et une impulsion / espace court est un zéro binaire (0). Les impulsions sont envoyées en utilisant une modulation infrarouge standard grand public de 38 kHz à un rapport cyclique de 50%.
Les temps d'impulsion / espace sont dans la question d'origine, mais je vais les répéter ici pour être complet:
Bit Pulse Space
-----+---------+---------
0 | 275µs | 285µs
1 | 855µs | 795µs
Tous ± 10µs max., ± 5µs typ. Ceci est basé sur des échantillons capturés avec un analyseur logique à 16 MHz; Je n'ai pas d'oscilloscope, donc je ne connais pas le profil exact (c'est-à-dire les temps de montée / descente).
Les paquets sont répétés tant que les entrées de contrôle sont appliquées et semblent espacées d'au moins 100 ms.
La transmission des paquets commence par un préambule "impulsion 1", qui est fixe et ne fait pas partie des données. L'espace suivant code le premier bit de données du paquet et la dernière impulsion code le dernier bit.
Chaque paquet a une longueur de 32 bits et contient toutes les entrées que la télécommande peut fournir. Les valeurs sont lues comme peu endiennes, c'est-à-dire MSB en premier.
Structure de données
Vous trouverez ci-dessous la structure de base des paquets individuels. Les 8 derniers bits m'ont confondu, mais cela a été compris maintenant (voir ci-dessous).
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
Remarque: les plages sont basées sur les lectures les plus élevées que j'ai obtenues. Le protocole est capable de plus grandes gammes - jusqu'à 255 pour les gaz, 63 pour le tangage / lacet - mais plafonne à environ la moitié.
La valeur de hauteur semble avoir une zone morte de 14 à 21 (inclus); seules les valeurs supérieures ou inférieures font réellement réagir l'hélicoptère. Je ne sais pas si c'est la même chose pour le lacet (difficile à dire, car l'hélicoptère est instable de toute façon, et peut juste tourner légèrement tout seul).
Ici, c'est en termes graphiques (comparer avec le graphique de la question d'origine)
Les 6 bits de contrôle sont calculés en XOR 'toutes les valeurs précédentes. Chaque valeur est traitée comme 6 bits. Cela signifie que les 2 MSB de la valeur de limitation à 8 bits sont simplement ignorés. C'est à dire
check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel
Notes pratiques
Les timings et la modulation du signal n'ont pas besoin d'être super précis. Même le timing pas du tout précis de mon Arduino fonctionne très bien malgré une modulation douteuse et un peu de coups et échecs sur les durées d'impulsion / espace par rapport à la vraie télécommande.
Je crois - mais je n'ai pas testé - que l'hélicoptère se verrouillera simplement sur le canal du premier signal qu'il trouvera. S'il est laissé sans signal trop longtemps (quelques secondes), il semble revenir à son mode "recherche", jusqu'à ce qu'il acquière à nouveau un signal.
L'hélicoptère ignorera les valeurs de tangage et de lacet si la manette des gaz est nulle.
Les commandes de trim ne sont envoyées qu'une seule fois par pression sur un bouton de la télécommande. On peut supposer que la valeur de trim augmente / diminue simplement une valeur dans le propre contrôleur de l'hélicoptère; ce n'est pas quelque chose que la télécommande garde en mémoire. Donc, toute implémentation de ceci devrait probablement s'en tenir à ce schéma, et envoyer uniquement la valeur de trim occasionnelle gauche / droite, mais sinon, la valeur par défaut est zéro dans les paquets.
Je recommande d'avoir un kill switch qui met simplement l'accélérateur à zéro. Cela entraînera la chute de l'hélicoptère du ciel, mais il subira moins de dommages lorsqu'il ne fait pas tourner ses moteurs. Donc, si vous êtes sur le point de vous écraser ou de heurter quelque chose, appuyez sur le bouton d'arrêt pour éviter de démonter les engrenages ou de casser les lames.
Les LED IR de la télécommande d'origine semblent avoir une longueur d'onde> 900 nm, mais je n'ai aucun problème à utiliser une LED ~ 850 nm.
Le récepteur IR de l'hélicoptère est correct, mais pas super sensible, donc plus votre source IR est lumineuse, mieux c'est. La télécommande utilise 3 LED en série, reposant sur le rail 9V au lieu du rail 5V utilisé par la logique. Je n'ai pas vérifié leur tirage actuel très précisément, mais je parierais que c'est 50mA.
Exemples de données
Voici un tas de paquets, pour toute personne intéressée (oui, j'ai écrit un décodeur; je n'ai pas décodé tout cela à la main). Les paquets du canal A proviennent des mêmes captures que les graphiques de la question d'origine.
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
Comme mentionné ci-dessus, les 8 derniers bits ont été compris, mais juste pour la postérité, voici mes pensées originales. N'hésitez pas à l'ignorer complètement, car j'avais à peu près tort dans mes suppositions.
Les 8 derniers bits
Les 8 derniers bits du paquet sont encore un peu mystérieux.
Les 4 bits du bit 23 à 26 semblent tous être entièrement déterminés par le réglage du canal de la télécommande. Changer le canal sur la télécommande ne modifie en rien le protocole ou la modulation; cela ne change que ces 4 bits.
Mais 4 bits est le double de ce qui est réellement nécessaire pour coder le paramètre de canal; il n'y a que trois canaux, donc 2 bits suffisent. Par conséquent, dans la description de la structure ci-dessus, je n'ai étiqueté que les 2 premiers bits comme "Canal", et laissé les deux autres étiquetés "X", mais c'est une supposition.
Vous trouverez ci-dessous un échantillon des bits pertinents pour chaque paramètre de canal.
Chan. Bits 23-26
-----+-------------
A | 0 1 0 1
B | 0 0 1 0
C | 1 0 0 0
Fondamentalement, il y a 2 bits de plus que nécessaire pour transmettre le paramètre de canal. Peut-être que le protocole a 4 bits mis de côté pour permettre plus de canaux plus tard, ou alors le protocole peut être utilisé dans des jouets entièrement différents, mais je ne sais tout simplement pas. Pour les valeurs plus grandes, le protocole utilise des bits supplémentaires qui pourraient être laissés de côté (lacet / accélération / tangage pourraient se débrouiller avec un peu moins chacun), mais pour le trim - qui a également 3 états - seuls 2 bits sont utilisés. Donc, on pourrait soupçonner que le canal n'est également que de 2 bits, mais cela laisse les 2 suivants disparus.
L'autre possibilité est que la somme de contrôle du paquet soit de 8 bits, en commençant par les "X bits", et - grâce à la magie de la somme de contrôle - ils se trouvent toujours refléter le réglage du canal. Mais encore une fois: je ne sais pas.
Et en parlant de: je n'ai aucune idée de la façon dont ces bits de contrôle sont formés. Je veux dire, ce sont des bits de contrôle, car ils ne correspondent à aucune entrée de commande unique, et l'hélicoptère ne semble pas répondre si je les tripote. Je suppose que c'est une sorte de CRC, mais je n'ai pas pu le comprendre. La vérification est longue de 6 à 8 bits, selon la façon dont vous interprétez les «X bits», il existe donc de nombreuses façons de les assembler.