Me estoy tomando la libertad de responder mi propia pregunta, ya que me di cuenta de la mayoría y esta es una buena manera de compartir mis hallazgos. Le agradezco a Olin Lathrop por darme un lugar para comenzar y algunas ideas para probar, pero en última instancia, el protocolo resultó bastante diferente de lo que suponía Olin, por lo tanto, publiqué esta respuesta.
Actualización: publiqué una pregunta de seguimiento sobre los últimos 8 bits, que no entendí completamente, y Dave Tweed lo descubrió . Incluiré los detalles aquí, por lo que esta respuesta puede funcionar como especificación de protocolo completo, pero ve a ver la respuesta de Dave.
Tuve que probar algunas cosas diferentes para resolver esto, pero estoy bastante seguro de que lo entendí. Curiosamente, no he encontrado nada parecido a este protocolo en otro lugar, pero puede muy bien ser un protocolo común que simplemente no conozco.
De todos modos, esto es lo que he encontrado:
Protocolo / codificación
Tanto los pulsos como los espacios intermedios se utilizan para codificar los datos. Un pulso / espacio largo es binario uno (1), y un pulso / espacio corto es binario cero (0). Los pulsos se envían utilizando una modulación infrarroja de consumo estándar de 38 kHz con un ciclo de trabajo del 50%.
Los tiempos de pulso / espacio están en la pregunta original, pero los repetiré aquí para completar:
Bit Pulse Space
-----+---------+---------
0 | 275µs | 285µs
1 | 855µs | 795µs
Todos ± 10 µs máx., ± 5 µs típ. Esto se basa en muestras capturadas con un analizador lógico a 16MHz; No tengo un osciloscopio, así que no sé el perfil exacto (es decir, tiempos de subida / bajada).
Los paquetes se repiten siempre que se apliquen las entradas de control y parezcan estar separadas por un mínimo de 100 ms.
La transmisión de paquetes comienza con un preámbulo de "pulso 1", que es fijo y no forma parte de los datos. El siguiente espacio codifica el primer bit de datos del paquete, y el último pulso codifica el último bit.
Cada paquete tiene 32 bits de largo y contiene cada entrada que el control remoto puede proporcionar. Los valores se leen como little endian, es decir, MSB primero.
Estructura de datos
A continuación se muestra la estructura básica de los paquetes individuales. Los últimos 8 bits me confundieron, pero eso ya se ha resuelto (ver más abajo).
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
Nota: Los rangos se basan en las lecturas más altas que obtuve. El protocolo es capaz de rangos más grandes, hasta 255 para el acelerador, 63 para cabeceo / guiñada, pero tiene un límite de aproximadamente la mitad.
El valor de tono parece tener una banda muerta de 14-21 (inclusive); solo los valores de arriba o abajo hacen que el helicóptero reaccione. No sé si es lo mismo para el guiñada (difícil de decir, ya que el helicóptero es inestable de todos modos, y puede girar ligeramente por sí solo).
Aquí está en términos gráficos (compárelo con el gráfico en la pregunta original)
Los 6 bits de verificación se calculan haciendo XOR con todos los valores anteriores. Cada valor se trata como 6 bits. Esto significa que los 2 MSB del valor del acelerador de 8 bits simplemente se ignoran. Es decir
check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel
Notas prácticas
Los tiempos de señal y la modulación no necesitan ser súper precisos. Incluso el tiempo no preciso de mi Arduino funciona bien a pesar de la modulación dudosa y un poco de impredecible en las duraciones de pulso / espacio en comparación con el control remoto real.
Creo, pero no he probado, que el helicóptero simplemente se enganchará al canal de la primera señal que encuentre. Si se deja sin señal durante demasiado tiempo (un par de segundos), parece volver a su modo de "búsqueda", hasta que vuelva a adquirir una señal.
El helicóptero ignorará los valores de inclinación y guiñada si el acelerador es cero.
Los comandos de recorte se envían solo una vez por presionar un botón en el control remoto. Presumiblemente, el valor de ajuste simplemente aumenta / disminuye un valor en el propio controlador del helicóptero; no es algo que el control remoto rastrea. Por lo tanto, cualquier implementación de esto probablemente debería apegarse a ese esquema, y solo enviar el valor de recorte ocasional izquierda / derecha, pero por lo demás predeterminado a un valor de recorte cero en los paquetes.
Recomiendo tener un interruptor de apagado que simplemente ponga el acelerador a cero. Esto hará que el helicóptero se caiga del cielo, pero sufrirá menos daño cuando no esté girando sus motores. Entonces, si está a punto de estrellarse o golpear algo, presione el interruptor de matar para evitar pelar los engranajes o romper las cuchillas.
Los LED IR del control remoto original parecen tener una longitud de onda> 900 nm, pero no tengo problemas para usar un LED de ~ 850 nm.
El receptor IR del helicóptero está bien, pero no es muy sensible, por lo que cuanto más brillante sea su fuente IR, mejor. El control remoto utiliza 3 LED en serie, ubicados en el riel de 9V en lugar del riel de 5V utilizado por la lógica. No he verificado su consumo actual con mucha precisión, pero apuesto a que es de 50 mA.
Data de muestra
Aquí hay un montón de paquetes, para cualquier persona interesada (sí, escribí un decodificador; no decodifiqué a mano todo esto). Los paquetes del canal A provienen de las mismas capturas que los gráficos en la pregunta original.
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
Como se mencionó anteriormente, se han descubierto los últimos 8 bits, pero solo para la posteridad, aquí están mis pensamientos originales. Siéntase libre de ignorarlo por completo, ya que estaba bastante equivocado en mis conjeturas.
Los últimos 8 bits
Los últimos 8 bits del paquete siguen siendo un misterio.
Los 4 bits del bit 23 al 26 parecen estar completamente determinados por la configuración del canal del control remoto. Cambiar el canal en el control remoto no altera el protocolo o la modulación de ninguna manera; solo cambia esos 4 bits.
Pero 4 bits es el doble de lo que realmente se necesita para codificar la configuración del canal; solo hay tres canales, por lo que 2 bits es suficiente. Por lo tanto, en la descripción de la estructura anterior, solo he etiquetado los primeros 2 bits como "Canal", y he dejado los otros dos etiquetados como "X", pero esto es una suposición.
A continuación se muestra una muestra de los bits relevantes para cada configuración de canal.
Chan. Bits 23-26
-----+-------------
A | 0 1 0 1
B | 0 0 1 0
C | 1 0 0 0
Básicamente, hay 2 bits más de lo necesario para transmitir la configuración del canal. Tal vez el protocolo tiene 4 bits reservados para permitir más canales más tarde, o para que el protocolo pueda usarse en juguetes completamente diferentes, pero simplemente no lo sé. Para los valores más grandes, el protocolo usa bits adicionales que podrían omitirse (yaw / throttle / pitch podría funcionar con un poco menos cada uno), pero para el ajuste, que también tiene 3 estados, solo se usan 2 bits. Por lo tanto, uno podría sospechar que el canal también tiene solo 2 bits, pero eso deja a los siguientes 2 sin explicar.
La otra posibilidad es que la suma de verificación del paquete tenga 8 bits de largo, comenzando con los "X bits" y, a través de la magia de la suma de verificación, de alguna manera siempre reflejan la configuración del canal. Pero de nuevo: no lo sé.
Y hablando de: no tengo idea de cómo se forman esos bits de verificación. Quiero decir, son bits de verificación, ya que no corresponden a ninguna entrada de control individual, y el helicóptero no parece responder si jugueteo con ellos. Supongo que es un CRC de algún tipo, pero no he podido resolverlo. La verificación tiene una longitud de 6 a 8 bits, dependiendo de cómo interprete los "bits X", por lo que hay muchas formas en que se pueden juntar.