Hace algún tiempo compré un pequeño y simple helicóptero de juguete controlado por infrarrojos (igual que este , se llama "Diamond Gyro" o "Diamond Force"). Por diversión, he estado buscando controlarlo a través de un Arduino.
Actualización: tengo el protocolo resuelto; Ver respuesta
Otros ya han compartido sus resultados sobre la piratería de un helicóptero de juguete IR diferente y la decodificación de su protocolo IR. Realmente genial, pero desafortunadamente mi helicóptero usa un protocolo diferente. Uno que no puedo entender. (Debo agregar que la electrónica es puramente un pasatiempo ocasional para mí, por lo que es posible que haya pasado por alto algo obvio).
Al igual que en el segundo enlace anterior, desmonté el controlador, localicé el pin del IC que controla los LED (por cierto, las marcas del IC se han borrado) y conecté un analizador lógico.
Tengo muchos buenos datos, pero todavía no puedo descifrar el protocolo. Este sitio es un gran recurso, pero ninguno de los protocolos enumerados parece encajar. Y nada más que he encontrado parece encajar con la señal que he capturado tampoco. Sin embargo, tengo que imaginar que es un protocolo simple y listo para usar, solo porque es un pequeño juguete barato.
Así que agradecería cualquier idea que pueda tener. Tal vez solo lo estoy viendo mal.
(Más información debajo de la imagen)
Capturé esto a 16 MHz con el controlador configurado en el canal A; debe ser preciso, en cuanto al tiempo. (Hay 3 canales IR entre los que puede elegir, pero el uso de los otros dos canales no cambia las características, solo partes del paquete en sí). Los tiempos son muy consistentes (+/- 10 µs máx.). Los paquetes se repiten con intervalos variables pero, como mínimo, están separados por unos 100 ms.
Portador: 38kHz @ 50% ciclo de trabajo
Bajos:
- Corto: 285µs
- Largo: 795µs
Máximos:
- Corto: 275µs
- Largo: 855µs
Siempre 17 colmos por paquete.
El heli tiene 3 controles: "acelerador" (es decir, elevación/velocidad del rotor), cabeceo (adelante/atrás) y guiñada (rotación alrededor del eje del rotor), todos controlados con 2 palancas de mando. Todos tienen algún tipo de rango (no solo encendido/apagado) y, por lo que puedo decir, todos se transmiten en un solo paquete. Las entradas izquierda/derecha solo se envían si se envía algo más, por lo que apliqué el acelerador máximo al muestrear eso. Acelerador y entrada de tono en sus propios paquetes de activación que se envían, tan pronto como empuje las palancas de mando más allá de algún umbral/banda muerta (en el gráfico a continuación, la etiqueta "min" es para el primer paquete enviado cuando empuja lentamente un control más allá de su banda muerta).
También tiene botones para recortar a izquierda y derecha, ya que el heli no es un instrumento de precisión ( en absoluto ) y tiende a girar lentamente de lo contrario. Desafortunadamente, los botones de recorte izquierdo/derecho no parecen enviar una señal que incremente/reduzca algo con cada pulsación (lo que sería útil para calcular el protocolo); parece ser solo un comando único, que le dice al helicóptero que se ajuste a la izquierda/derecha, y luego lo sigue.
Me tomo la libertad de responder mi propia pregunta, ya que tengo la mayor parte descifrada y esta es una buena manera de compartir mis hallazgos. Agradezco a Olin Lathrop por brindarme un punto de partida y algunas ideas para probar, pero, en última instancia, el protocolo resultó bastante diferente de la suposición de Olin, por lo que publiqué esta respuesta.
Actualización: publiqué una pregunta de seguimiento con respecto a los últimos 8 bits, que no entendí completamente, y Dave Tweed lo resolvió . Incluiré los detalles aquí, por lo que esta respuesta puede funcionar como una especificación de protocolo completa, pero consulte la respuesta de Dave.
Tuve que probar algunas cosas diferentes para resolver esto, pero estoy bastante seguro de que lo conseguí. Curiosamente, no he encontrado nada parecido a este protocolo en ningún otro lugar, pero es muy posible que sea un protocolo común que simplemente no conozco.
De todos modos, esto es lo que he encontrado:
Tanto los pulsos como los espacios intermedios se utilizan para codificar los datos. Un pulso/espacio largo es un uno binario (1), y un pulso/espacio corto es un cero binario (0). Los pulsos se envían usando una modulación de 38 kHz de infrarrojos de consumo estándar al 50 % del ciclo de trabajo.
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
Todo ±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 separados 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 una longitud de 32 bits y contiene todas las entradas que puede proporcionar el control remoto. Los valores se leen como little endian, es decir, MSB primero.
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 aceleración, 63 para cabeceo/guiñada, pero alcanza aproximadamente la mitad de eso.
El valor de tono parece tener una banda muerta de 14 a 21 (inclusive); solo los valores por encima o por debajo hacen que el helicóptero reaccione. No sé si es lo mismo para la 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 en todos los valores anteriores. Cada valor se trata como 6 bits. Esto significa que los 2 MSB del valor de aceleración de 8 bits simplemente se ignoran. Es decir
check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel
Los tiempos y la modulación de la señal no necesitan ser muy precisos. Incluso la temporización nada precisa de mi Arduino funciona bien a pesar de la modulación dudosa y un poco de imprecisión en las duraciones de pulso/espacio en comparación con el control remoto real.
Creo, pero no lo 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 vuelve a adquirir una señal.
El helicóptero ignorará los valores de cabeceo y guiñada si el acelerador es cero.
Los comandos de recorte se envían solo una vez por cada botón que se presiona en el control remoto. Presumiblemente, el valor de compensación simplemente incrementa/disminuye un valor en el propio controlador del helicóptero; no es algo de lo que el control remoto realiza un seguimiento. Por lo tanto, cualquier implementación de esto probablemente debería apegarse a ese esquema, y solo enviar el valor de recorte izquierdo/derecho ocasional, pero de lo contrario, de forma predeterminada, 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 caiga del cielo, pero sufrirá menos daño cuando sus motores no estén girando. Entonces, si está a punto de estrellarse o golpear algo, presione el interruptor de apagado para evitar dañar los engranajes o romper las cuchillas.
Los LED IR del control remoto original parecen tener una longitud de onda de >900 nm, pero no tengo problemas para usar un LED de ~850 nm.
El receptor de infrarrojos del helicóptero está bien, pero no es muy sensible, por lo que cuanto más brillante sea la fuente de infrarrojos, mejor. El control remoto usa 3 LED en serie, ubicados en el riel de 9V en lugar del riel de 5V que usa la lógica. No he comprobado su consumo actual con mucha precisión, pero apuesto a que son 50 mA.
Aquí hay un montón de paquetes, para cualquier persona interesada (sí, escribí un decodificador; no decodifiqué todo esto a mano). 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 resuelto 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 del paquete siguen siendo un poco misteriosos.
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 son suficientes. Por lo tanto, en la descripción de la estructura anterior, solo etiqueté los primeros 2 bits como "Canal" y dejé los otros dos etiquetados como "X", pero esto es una suposición.
A continuación se muestra una muestra de los bits relevantes para la configuración de cada 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 los necesarios para transmitir la configuración del canal. Tal vez el protocolo tiene 4 bits reservados para permitir más canales más tarde, o el protocolo se puede usar 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ían funcionar con un poco menos cada uno), pero para el recorte, que también tiene 3 estados, solo se usan 2 bits. Entonces, uno podría sospechar que el canal también tiene solo 2 bits, pero eso deja a los siguientes 2 sin contabilizar.
La otra posibilidad es que la suma de verificación del paquete tenga una longitud de 8 bits, comenzando con los "bits X" 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 única, y el helicóptero no parece responder si juego con ellos. Supongo que es un CRC de algún tipo, pero no he podido descifrarlo. La verificación tiene una longitud de 6 a 8 bits, dependiendo de cómo interprete los "X bits", por lo que hay muchas formas de combinarlos.
Esto no se ve tan mal. Primero observe que todos los mensajes contienen exactamente 17 pulsos. Esto nos da inmediatamente una fuerte pista de que los espacios cortos dentro de un mensaje son irrelevantes. Parece que los datos están codificados por pulsos que son cortos o largos, y que es aceptable cierto rango de espacio entre estos pulsos.
Obviamente, cada mensaje comienza con un pulso largo como bit de inicio. Eso deja 16 bits de datos. Probablemente algunos de los primeros bits sean un código de operación, posiblemente de longitud variable. Si estuviera haciendo esto, algunos de los bits finales serían una suma de verificación. Imagínese que los ingenieros que escribieron el firmware querían mantener las cosas simples para ellos, por lo que puede comenzar suponiendo que hay 8 bits de datos en alguna parte. Ahora vea si alguno de los mensajes tiene sentido.
Llamemos 1 a un largo y 0 a un corto. Podría ser al revés, pero tenemos que empezar por alguna parte. Quitando las hojas de bits de inicio:
1010001101011010 minutos del acelerador 1010011101011000 aceleración máxima 1010000001011111 min adelante 1010000000011110 máx adelante 1010000011011101 máximo atrás 1010000100011010 minutos atrás 0000010101011100 máx. izquierda + aceleración máx. 0100010101011110 máx derecho + acelerador máx. 1010000101111111 moldura izquierda 1010000101011011 ajuste derecho
Algunas cosas saltan de inmediato. Obviamente, el bit 0 es un bit de paridad. De lo contrario, parece haber un campo de 3 bits <15:13>, un valor de datos de 8 bits <12:5> y otro campo de 4 bits <4:1>.
Parece que el valor de los datos se envía en orden de bits de menor a mayor, por lo que probablemente tenga más sentido interpretar los 16 bits completos invertidos de lo que muestro.
No tengo ganas de dedicar más tiempo a esto, pero espero que esto te haya dado un comienzo. Procedería reescribiendo la lista anterior con el bit de paridad quitado, el número completo cambiado de LSB a MSB, y cada campo asumido se muestra por separado con un espacio entre él y el campo contiguo. Eso puede permitir que te salgan más cosas. También tenga en cuenta que podemos tener el sentido 1/0 de cada bit al revés. Tal vez escriba la nueva tabla en cada sentido y vea si algo tiene más sentido de una forma.
Ignacio Vázquez-Abrams
Flambino
Ignacio Vázquez-Abrams
Flambino
Flambino