Estoy tratando de construir un control remoto IR simple basado en Arduino para un helicóptero de juguete barato controlado por IR (igual que este , se llama "Diamond Gyro" o "Diamond Force"). He decodificado el protocolo IR a excepción de los últimos bits. Estos últimos bits parecen ser un cheque o CRC, pero no he podido "descifrarlo".
Es bastante fácil simplemente repetir un paquete grabado, pero quiero controlar completamente el helicóptero. Eso significa aplicar ingeniería inversa a los bits de control.
(Debo agregar que hago software de día, pero la electrónica es un pasatiempo a veces, así que tal vez me esté perdiendo algo muy básico).
Los detalles del protocolo están en la pregunta y respuesta , pero aquí están los conceptos básicos:
aquí hay un diagrama
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 | C |X|X| CRC?
P: Preamble (always 1), T: Trim, C: Channel,
X: Either part of the channel data or the checksum.
En primer lugar, no estoy seguro de si los X
bits son parte del valor del canal, parte del cheque o algo más. Sin embargo, siempre siguen el valor del canal, por lo que es probable que el valor del canal tenga entre 3 y 4 bits de ancho, aunque 2 bits serían suficientes para los 3 valores de canal posibles.
En segundo lugar, están los últimos 6 bits (marcados CRC?
arriba) que son claramente algún tipo de verificación (y, de hecho, el helicóptero no responde si cambio alguno de esos bits).
Básicamente, hay un paquete de 24 a 26 bits de datos, seguido de 6 a 8 bits de verificación. Y realmente me gustaría descifrar esos bits de verificación para poder componer paquetes yo mismo.
A continuación hay un montón de muestras de los datos binarios que estoy recibiendo. El preámbulo "1" siempre está presente, y no creo que cuente como parte de los datos, pero lo he incluido de todos modos, por si acaso es la clave de todo.
Nuevamente, no sé si los X
bits son parte de los datos o del cheque. Dependiendo de la forma en que se calcule el cheque, es posible que los primeros 1 o 2 bits del cheque simplemente sigan el valor del canal. Pero también es muy posible que el valor del canal tenga una longitud de 4 bits, incorporando los X
bits. O está en el medio, X
siendo un bit parte del canal y el otro parte del control. No sé.
Si alguien sabe qué es ese cheque, o cómo podría averiguarlo, me encantaría saberlo. Me imagino que puedo usar la fuerza bruta, pero incluso si esa es la única opción, me encantaría escuchar algunos consejos sobre cómo hacerlo mejor.
El helicóptero es muy barato, así que dudo que haya algo realmente elegante.
Channel A
P Yaw Throttle Pitch Tr Ch XX Check Description
--------------------------------------------------------------
1 000100 10000100 000000 00 01 01 000101 Left Mid + throttle
1 000000 10000110 010001 00 01 01 010010 Left Max + throttle
1 100001 10000110 000000 00 01 01 100010 Right Mid + throttle
1 100100 10000100 010001 00 01 01 110100 Right Max + throttle
1 010001 00000000 001011 00 01 01 011111 Forward Min
1 010001 00000000 000000 00 01 01 010100 Forward Max
1 010001 00000000 011000 00 01 01 001100 Back Min
1 010001 00000000 100101 00 01 01 110001 Back Max
1 010001 00000000 010001 01 01 01 010101 Left Trim
1 010001 00000000 010001 10 01 01 100101 Right Trim
1 010001 00000011 010001 00 01 01 000110 Throttle 01 (min)
1 010001 00010110 010001 00 01 01 010011 Throttle 02
1 010001 00011111 010001 00 01 01 011010 Throttle 03
1 010001 00101111 010001 00 01 01 101010 Throttle 04
1 010001 00111110 010001 00 01 01 111011 Throttle 05
1 010001 01010101 010001 00 01 01 010000 Throttle 06
1 010001 01011111 010001 00 01 01 011010 Throttle 07
1 010001 01101100 010001 00 01 01 101001 Throttle 08
1 010001 01111010 010001 00 01 01 111111 Throttle 09
1 010001 10000101 010001 00 01 01 000000 Throttle 10 (max)
Channel B
P Yaw Throttle Pitch Tr Ch XX Check Description
--------------------------------------------------------------
1 000000 10000110 010001 00 00 10 010101 Left Max + throttle
1 100100 10000110 010001 00 00 10 110001 Right Max + throttle
1 010001 00000000 001001 00 00 10 011010 Forward Min
1 010001 00000000 000000 00 00 10 010011 Forward Max
1 010001 00000000 010111 00 00 10 000100 Back Min
1 010001 00000000 100110 00 00 10 110101 Back Max
1 010001 00000000 010001 01 00 10 010010 Left Trim
1 010001 00000000 010001 10 00 10 100010 Right Trim
1 010001 00000001 010001 00 00 10 000011 Throttle Min
1 010001 00110100 010001 00 00 10 110110 Throttle Mid
1 010001 01100111 010001 00 00 10 100101 Throttle High
1 010001 10001111 010001 00 00 10 001101 Throttle Max
Channel C
P Yaw Throttle Pitch Tr Ch XX Check Description
--------------------------------------------------------------
1 000000 10000101 010001 00 10 00 011100 Left Max + throttle
1 100100 10000101 010001 00 10 00 111000 Right Max + throttle
1 010001 00000000 001010 00 10 00 010011 Forward Min
1 010001 00000000 000000 00 10 00 011001 Forward Max
1 010001 00000000 010111 00 10 00 001110 Back Min
1 010001 00000000 100110 00 10 00 111111 Back Max
1 010001 00000000 010001 01 10 00 011000 Left Trim
1 010001 00000000 010001 10 10 00 101000 Right Trim
1 010001 00000001 010001 00 10 00 001001 Throttle Min
1 010001 00110100 010001 00 10 00 111100 Throttle Mid
1 010001 01100110 010001 00 10 00 101110 Throttle High
1 010001 10000101 010001 00 10 00 001101 Throttle Max
En primer lugar, está bastante claro que los bits "XX" son parte de la designación del canal, ya que es de lo único que dependen. Los bits "XX" pueden ser simplemente una verificación de los bits "Ch".
Los bits de verificación son un XOR bit a bit simple de 24 de los 26 bits de datos: si toma los 6 bits de guiñada, los 6 LSB del acelerador, los 6 bits de paso y los siguientes 6 bits, y XOR estas cantidades juntas, obtiene los 6 bits de control. Parece que los 2 bits superiores del acelerador no afectan en absoluto a los bits de verificación.
El siguiente script de Perl verifica esto.
#!/usr/bin/perl
# crc.pl - verify decoding of check bits
# On the lines starting with '1', just keep the '0's and '1's in an array.
while (<>) {
my @letters = split '', $_;
next unless $letters[0] eq '1';
@letters = grep /[01]/, @letters;
@letters = @letters[1..32];
$a = string2bin (@letters[0..5]);
$b = string2bin (@letters[8..13]);
$c = string2bin (@letters[14..19]);
$d = string2bin (@letters[20..25]);
$e = string2bin (@letters[26..31]);
$f = $a ^ $b ^ $c ^ $d;
printf "%02X %02X %02X %02X %02X %02X %s\n", $a, $b, $c, $d, $e, $f,
$e == $f ? '-' : '###';
}
sub string2bin {
my $temp = 0;
for (@_) {
$temp = ($temp << 1) + ($_ eq '1' ? 1 : 0);
}
$temp;
}
No veo un patrón inmediatamente obvio, así que atacaría esto más algorítmicamente. Aparentemente, tiene la capacidad de capturar una gran cantidad de paquetes y luego usar alguna forma automatizada para ingresarlos a una computadora. Capturaría un gran número mientras variaba lentamente los controles.
Después de tener una pila de paquetes en un archivo, escriba un código para descifrar el código. Piense en ello como un problema de criptografía. Una de las primeras cosas que haría es buscar pares de paquetes que solo varíen en un bit. Eso debería decirle de inmediato si tiene una suma de verificación simple o algo más complicado como un CRC. Si se trata de una suma de comprobación básica, entonces la suma de comprobación de dichos pares de paquetes solo debería variar si se le suma una potencia de 2. Si un montón de bits varían de manera impredecible, entonces probablemente tenga un CRC.
Si se trata de una suma básica, luego de obtener algunos cambios de un solo bit, debería poder averiguar cómo se agrega cada campo a la suma de verificación. Si parece un CRC, entonces probablemente haría una búsqueda exhaustiva a continuación. Es solo una suma de verificación de 6 bits, por lo que solo hay 64 polinomios posibles. Puede haber hasta 64 valores de inicio diferentes, pero normalmente se inicia un CRC con el conjunto de bits alto y los otros bits en 0. Los nuevos bits se pueden desplazar desde cualquier extremo. Probablemente, al menos si quien diseñó el CRC supiera lo que estaba haciendo, entonces si ejecuta todo el paquete a través del CRC, el resultado debería ser 0. El número de combinaciones es lo suficientemente pequeño como para que una búsqueda exhaustiva por máquina encuentre la respuesta instantáneamente en tiempo humano si realmente es un CRC habitual.
Acabo de ver la respuesta de Dave Tweed donde ha demostrado que esto es incluso más simple que una suma, solo XOR de los campos. Hay muchos ingenieros perezosos por ahí. Hubiera hecho esto con un CRC, que es realmente muy fácil de calcular.
Dejaré mi respuesta aquí como una descripción de cómo atacar algo como esto cuando no ves un patrón por inspección. Si hubiera utilizado este método, habría visto que los cambios de un solo bit en los datos habrían resultado en cambios de un solo bit en la suma de comprobación, lo que habría apuntado inmediatamente a un esquema XOR.
X
. En cuanto a cambiar un solo bit y mirar el cheque, me hubiera gustado intentarlo, pero habría requerido algo de trabajo con este controlador barato. Habría tenido que modificarlo un poco para obtener ese tipo de resolución.Acerca de los XX: como señala Dave, parecen ser parte de la información del canal, ya que siempre son los mismos para un canal determinado. No son realmente necesarios; como dijiste, puedes codificar 3 canales con solo 2 bits, pero los 4 bits dados permiten una distancia de Hamming de 2. Esto significa que los códigos para los canales siempre están separados por al menos 2 bits; cambiar un solo bit no da como resultado un código de canal válido. Junto con la suma de comprobación, esto aumenta la fiabilidad.
Flambino
david tweed
Flambino