Ayuda o sugerencias para decodificar un protocolo IR

10

Hace algún tiempo compré un pequeño y barato helicóptero de juguete controlado por IR (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 al piratear un helicóptero de juguete IR diferente y decodificar 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 solo un pasatiempo para mí, por lo que puede haber pasado por alto algo obvio).

Al igual que en el segundo enlace anterior, desarmé el controlador, ubiqué el pin IC que controlaba los LED (por cierto, las marcas del IC se borraron) y conecté un analizador lógico.

Obtuve muchos datos buenos, pero aún no puedo entender 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 mirando mal.
(Más información debajo de la imagen)

Muestras del canal A

Características de señal / protocolo

Capturé esto a 16MHz con el controlador configurado en el canal A; debe ser preciso, en cuanto al tiempo. (Puede elegir entre 3 canales IR, 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 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 máximos por paquete.

Controles / entradas

El heli tiene 3 controles: "Acelerador" (es decir, velocidad de elevación / rotor), inclinación (avance / retroceso) y guiñada (rotación alrededor del eje del rotor), todo controlado con 2 barras de control. 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. El acelerador y la entrada de tono en sus propios paquetes de activación que se envían, tan pronto como empuje los thumbsticks más allá de algún umbral / banda muerta (en el gráfico debajo de 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, de lo contrario, tiende a girar lentamente. Desafortunadamente, los botones de ajuste izquierdo / derecho no parecen enviar una señal que incremente / disminuya algo por cada pulsación (lo que sería útil para calcular el protocolo); parece ser solo un comando, diciéndole al helicóptero que recorte a la izquierda / derecha, y luego lo rastrea.

revs Flambino
fuente
¿Por qué no usar las trazas de señal que ya tiene para escribir los paquetes sin procesar?
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams ¿Quieres decir simplemente reproducir las señales grabadas en el helicóptero?
Flambino
Seguro. No es que el helicóptero pueda notar la diferencia ...
Ignacio Vázquez-Abrams
@ IgnacioVazquez-Abrams Es cierto, pero por lo que puedo decir, el paquete contiene los 3 controles (acelerador / cabeceo / guiñada) y los controles del heli, ninguno está activado / desactivado. Para dirigir la cosa repitiendo, tendría que capturar cada configuración ... Además, quiero entender el protocolo
Flambino
@ IgnacioVazquez-Abrams Vaya, de alguna manera confundí mi último comentario. Significaba decir: "... el paquete contiene los 3 controles (acelerador / cabeceo / guiñada) y ninguno de ellos solo está activado / desactivado".
Flambino

Respuestas:

8

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)

estructura de paquete

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.

Flambino
fuente
6

Esto no se ve tan mal. Primero observe que todos los mensajes contienen exactamente 17 pulsos. Esto inmediatamente nos da una pista fuerte de que los espacios cortos dentro de un mensaje son irrelevantes. Parece que los datos están codificados por pulsos 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 son un código de operación, posiblemente de longitud variable. Si estuviera haciendo esto, algunos de los bits finales serían una suma de comprobación. Calcule que los ingenieros que escribieron el firmware querían mantener las cosas simples para sí mismos, por lo que puede comenzar asumiendo que hay 8 bits de datos en algún lugar. Ahora vea si alguno de los mensajes tiene sentido.

Llamemos un largo a 1 y un corto a 0. Podría ser al revés, pero tenemos que comenzar en alguna parte. Eliminando el bit de inicio deja:

1010001101011010 acelerador mínimo
1010011101011000 acelerador máximo
1010000001011111 min adelante
1010000000011110 max adelante
1010000011011101 max espalda
1010000100011010 min de vuelta
0000010101011100 max izquierda + max acelerador
0100010101011110 max derecho + max acelerador
1010000101111111 moldura izquierda
1010000101011011 moldura derecha

Algunas cosas salen 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 está enviando en orden de bits bajo a alto, por lo que probablemente tenga más sentido interpretar los 16 bits enteros invertidos de lo que muestro.

No tengo ganas de pasar más tiempo en esto, pero espero que esto te haya dado un comienzo. Continuaría reescribiendo la lista anterior con el bit de paridad eliminado, el número entero volcó 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. También tenga en cuenta que podemos tener el sentido 1/0 de cada bit al revés. Quizás escriba la nueva tabla en cada sentido y vea si algo tiene más sentido en un sentido.

Olin Lathrop
fuente
¡Gracias, esto es excelente! Me pondré en ello y veré qué encuentro. Después de mirar otros protocolos, comencé a pensar que tal vez los espacios eran irrelevantes, pero como tenían dos tiempos muy consistentes, no estaba tan seguro. Pensé que variarían más si no fueran importantes. De todos modos, lo intentaré. Gracias de nuevo
Flambino
Huh ... por lo que puedo decir, los espacios son importantes. Me concentré en el acelerador y capturé algunas muestras más en 10 posiciones diferentes del acelerador. Excluir espacios no me dio números significativos, independientemente de cómo hice las conversiones. Pero incluirlos como long = 1, short = 0 produce una progresión suave del valor del acelerador de 1 a 134 (little endian). Todavía
estoy
Tengo el protocolo entendido casi por completo, pero todavía hay un poco de misterio. Agregué un montón de cosas a mi pregunta, si quieres darle un giro. De todos modos, ¡gracias por tu ayuda hasta ahora! Me hizo trabajar en la dirección correcta.
Flambino
@Flambino: Parece que estás muy por delante de lo que hice para comenzar, que resultó ser una suposición errónea en retrospectiva. Leí tu pregunta actualizada pero todavía no entiendo cómo se usa exactamente la longitud de los espacios. ¿Fue solo una coincidencia que todos los patrones que mostraste tenían exactamente 17 pulsos y que el último indicaba paridad si solo los pulsos se toman como 0 o 1?
Olin Lathrop
Honestamente, fue principalmente prueba y error de mi parte. Dado que los 2 tiempos utilizados para los espacios son tan exactos como los tiempos de pulso, pensé que podrían ser significativos. Y, al ignorar los espacios no produjo datos binarios útiles, simplemente asumí pulso largo = 1 y espacio largo = 1 (y espacio corto / pulso = 0), lo que inmediatamente me dio datos muy útiles. Entonces, el primer espacio después del pulso del preámbulo es el primer bit (el gráfico de aceleración máxima derecha + máxima muestra un "espacio 1" como primer bit) seguido de 16 pulsos, con 15 espacios más en el medio; 32 bits
Flambino