Ajuda ou dicas para decodificar um protocolo IR

10

Algum tempo atrás, comprei um pequeno e barato helicóptero de brinquedo controlado por IR (o mesmo que este - chamado "Diamond Gyro" ou "Diamond Force"). Por diversão, eu estive pensando em controlá-lo através de um Arduino.

Atualização: o protocolo foi descoberto; ver resposta

Outroscompartilharam seus resultados ao hackear um helicóptero de brinquedo IR diferente e decodificar seu protocolo de IR. Muito legal, mas infelizmente meu helicóptero usa um protocolo diferente. Um que eu não consigo entender. (Devo acrescentar que a eletrônica é puramente um hobby para mim, por isso posso ter esquecido algo óbvio).

Assim como no segundo link acima, desmontei o controlador, localizei o pino do IC que controla os LEDs (a propósito, as marcações do IC foram apagadas) e liguei um analisador lógico.

Tenho muitos dados bons, mas ainda não consigo descobrir o protocolo. Este site é um ótimo recurso, mas nenhum dos protocolos listados parece se encaixar. E nada mais que encontrei parece se encaixar no sinal que capturei. Eu tenho que imaginar, porém, que é um protocolo simples e pronto para uso, apenas porque é um pequeno brinquedo barato.

Então, eu aprecio qualquer idéia que você possa ter. Talvez eu esteja apenas olhando errado.
(Mais informações abaixo da imagem)

Amostras do canal A

Características do sinal / protocolo

Eu capturei isso em 16MHz com o controlador definido no canal A; deve ser preciso, em termos de tempo. (Você pode escolher 3 canais de infravermelho, mas o uso dos outros dois canais não altera as características, apenas partes do pacote em si.) Os tempos são muito consistentes (+/- 10 µs no máximo). Os pacotes são repetidos com intervalos variados, mas no mínimo estão separados por cerca de 100 ms.

Operadora: 38kHz a 50% de ciclo de trabalho

Baixos:
- Curto: 285µs
- Longo: 795µs

Elevações:
- Curto: 275µs
- Longo: 855µs

Sempre 17 elevações por pacote.

Controles / entradas

O heli possui três controles: "Throttle" (ou seja, velocidade de elevação / rotor), pitch (avanço / retorno) e guinada (rotação ao redor do eixo do rotor), todos controlados com 2 manípulos. Todos eles têm algum tipo de alcance (não apenas liga / desliga) e, até onde eu sei, estão sendo transmitidos em um único pacote. As entradas esquerda / direita são enviadas apenas se outra coisa estiver sendo enviada, então apliquei o acelerador máximo ao amostrar isso. Entrada de aceleração e afinação em seus próprios pacotes de gatilho sendo enviados, assim que você empurra os polegares além de um limite / faixa morta (no gráfico abaixo do rótulo "min" refere-se ao primeiro pacote enviado ao empurrar lentamente um controle além de sua faixa morta).

Também possui botões para aparar a esquerda e a direita, pois o heli não é um instrumento de precisão (de maneira alguma ) e tende a girar lentamente caso contrário. Infelizmente, os botões de ajuste esquerdo / direito não parecem enviar um sinal que está aumentando / diminuindo algo a cada pressionamento (o que seria útil para calcular o protocolo); parece ser apenas um comando, dizendo ao helicóptero para cortar a esquerda / direita e depois o acompanha.

Flambino
fonte
Por que não usar apenas os traços de sinal que você já tem para escrever os pacotes em bruto?
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams Você quer dizer apenas reproduzir os sinais gravados no helicóptero?
Flambino
Certo. Não é como o helicóptero vai ser capaz de dizer a diferença ...
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams É verdade, mas até onde eu sei, o pacote contém todos os 3 controles (acelerador / afinação / guinada) e os controles do heli, pois nenhum é apenas ativado / desativado. Para orientar a coisa por repetir, eu teria que capturar cada configuração única ... Além disso, eu quero entender o protocolo
Flambino
@ IgnacioVazquez-Abrams Opa, de alguma forma eu confundi meu último comentário. Significava dizer: "... o pacote contém todos os 3 controles (acelerador / pitch / guinada) e nenhum deles é apenas ligado / desligado".
Flambino

Respostas:

8

Estou tendo a liberdade de responder à minha própria pergunta, conforme descobri a maior parte e essa é uma boa maneira de compartilhar minhas descobertas. Meus agradecimentos a Olin Lathrop por me dar um lugar para começar e algumas idéias para experimentar, mas, em última análise, o protocolo ficou bem diferente do palpite de Olin, por isso, eu postando esta resposta.


Atualização: postei uma pergunta de acompanhamento referente aos últimos 8 bits, que não entendi completamente, e Dave Tweed descobriu . Vou incluir os detalhes aqui, para que esta resposta possa funcionar como a especificação completa do protocolo, mas consulte a resposta de Dave.


Eu tive que tentar algumas coisas diferentes para descobrir isso, mas estou bastante confiante de que entendi. Estranhamente, não encontrei nada parecido com este protocolo em outro lugar, mas pode muito bem ser um protocolo comum que simplesmente não conheço.

Enfim, aqui está o que eu encontrei:

Protocolo / codificação

Os pulsos e os espaços intermediários são usados ​​para codificar os dados. Um pulso / espaço longo é um binário (1) e um pulso / espaço curto é zero binário (0). Os pulsos são enviados usando a modulação infravermelha padrão do consumidor de 38kHz a 50% do ciclo de trabalho.

Os tempos de pulso / espaço estão na pergunta original, mas vou repeti-los aqui para completar:

 Bit    Pulse     Space
-----+---------+---------
  0  |  275µs  |  285µs
  1  |  855µs  |  795µs

Todos os ± 10µs máx., ± 5µs tip .. Isso é baseado em amostras capturadas com um analisador lógico em 16MHz; Não tenho um osciloscópio, portanto não conheço o perfil exato (ou seja, os tempos de subida / descida).

Os pacotes são repetidos desde que as entradas de controle sejam aplicadas e pareçam espaçadas a um mínimo de 100ms.

A transmissão de pacotes começa com um preâmbulo "pulso 1", que é fixo e não faz parte dos dados. O espaço a seguir codifica o primeiro bit de dados do pacote e o último pulso codifica o último bit.

Cada pacote tem 32 bits e contém todas as entradas que o controle remoto pode fornecer. Os valores são lidos como pouco endian, ou seja, MSB primeiro.

Estrutura de dados

Abaixo está a estrutura básica dos pacotes individuais. Os últimos 8 bits me confundiram, mas isso já foi descoberto (veja abaixo).

 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: As faixas são baseadas nas leituras mais altas que obtive. O protocolo é capaz de faixas maiores - até 255 para acelerador, 63 para afinação / guinada -, mas alcança cerca de metade disso.
O valor do pitch parece ter uma faixa morta de 14 a 21 (inclusive); somente valores acima ou abaixo fazem o helicóptero reagir. Não sei se é o mesmo para a guinada (difícil dizer, já que o helicóptero é instável de qualquer maneira e pode girar um pouco por conta própria).

Aqui está em termos gráficos (compare com o gráfico na pergunta original)

estrutura de pacotes

Os 6 bits de verificação são calculados com XOR em todos os valores anteriores. Cada valor é tratado como 6 bits. Isso significa que os 2 MSBs do valor do acelerador de 8 bits são simplesmente ignorados. Ou seja,

check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel

Notas práticas

Os tempos e a modulação do sinal não precisam ser super precisos. Até o tempo não exato de meu Arduino funciona bem, apesar da modulação desonesta e de um pouco de acerto e falha nas durações de pulso / espaço em comparação com o controle remoto real.

Acredito - mas ainda não testei - que o helicóptero simplesmente trava no canal do primeiro sinal encontrado. Se ficar sem sinal por muito tempo (alguns segundos), ele parece voltar ao modo "pesquisa", até adquirir um sinal novamente.

O helicóptero ignorará os valores de inclinação e guinada se o acelerador for zero.

Os comandos de corte são enviados apenas uma vez por pressionar o botão no controle remoto. Presumivelmente, o valor de compensação simplesmente aumenta / diminui um valor no próprio controlador do helicóptero; não é algo que o controle remoto controla. Portanto, qualquer implementação disso provavelmente deve se ater a esse esquema e enviar apenas o valor ocasional de ajuste esquerdo / direito, mas, por outro lado, é padrão para um valor de ajuste zero nos pacotes.

Eu recomendo ter um interruptor de interrupção que simplesmente ajuste o acelerador para zero. Isso fará com que o helicóptero caia do céu, mas sofrerá menos danos quando não estiver girando seus motores. Portanto, se você estiver prestes a bater ou bater em alguma coisa, pressione o botão de matar para evitar arrancar as engrenagens ou quebrar as lâminas.

Os LEDs IR do controle remoto original parecem ter um comprimento de onda> 900nm, mas não tenho problemas ao usar um LED ~ 850nm.

O receptor de infravermelho do helicóptero está ok, mas não é super sensível, portanto, quanto mais brilhante sua fonte de infravermelho, melhor. O controle remoto usa 3 LEDs em série, posicionados no trilho de 9V em vez do trilho de 5V usado pela lógica. Ainda não checamos o draw atual com muita precisão, mas aposto que é 50mA.

Dados de amostra

Aqui estão alguns pacotes para qualquer pessoa interessada (sim, escrevi um decodificador; não decodifiquei tudo isso à mão). Os pacotes do canal A são provenientes das mesmas capturas que os gráficos da pergunta 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 mencionado acima, os últimos 8 bits foram descobertos, mas apenas para a posteridade, aqui estão os meus pensamentos originais. Sinta-se livre para ignorá-lo completamente, pois eu estava quase errado em minhas suposições.

Os últimos 8 bits

Os últimos 8 bits do pacote ainda são um pouco misteriosos.

Todos os 4 bits do bit 23 a 26 parecem ser inteiramente determinados pela configuração do canal do controle remoto. Alterar o canal no controle remoto não altera o protocolo ou modulação de forma alguma; apenas altera esses 4 bits.

Mas 4 bits é o dobro do que é realmente necessário para codificar a configuração do canal; existem apenas três canais, então 2 bits é suficiente. Portanto, na descrição da estrutura acima, eu apenas rotulei os 2 primeiros bits como "Canal" e deixei os outros dois rotulados como "X", mas isso é um palpite.

Abaixo está uma amostra dos bits relevantes para cada configuração de canal.

Chan.   Bits 23-26
-----+-------------
  A  |  0  1  0  1
  B  |  0  0  1  0
  C  |  1  0  0  0

Basicamente, existem 2 bits a mais do que o necessário para transmitir a configuração do canal. Talvez o protocolo tenha 4 bits reservados para permitir mais canais posteriormente, ou então o protocolo possa ser usado em brinquedos completamente diferentes, mas eu simplesmente não sei. Para valores maiores, o protocolo usa bits extras que podem ser deixados de fora (guinada / acelerador / afinação podem passar um pouco menos cada), mas para trim - que também tem 3 estados - apenas 2 bits são usados. Portanto, pode-se suspeitar que o canal também tenha apenas 2 bits, mas isso deixa os 2 próximos não contabilizados.

A outra possibilidade é que a soma de verificação do pacote tenha 8 bits de comprimento, começando com os "X bits" e - através da mágica da soma de verificação - eles apenas refletem de alguma forma sempre a configuração do canal. Mas novamente: eu não sei.

E por falar em: não tenho idéia de como esses bits de verificação são formados. Quero dizer, são bits de verificação, pois não correspondem a nenhuma entrada de controle e o helicóptero não parece responder se eu mexer com eles. Acho que é algum tipo de CRC, mas não consegui descobrir. A verificação tem duração de 6 a 8 bits, dependendo de como você interpreta os "bits X", portanto, existem várias maneiras que podem ser reunidas.

Flambino
fonte
6

Isso não parece tão ruim. Primeiro observe que todas as mensagens contêm exatamente 17 pulsos. Isso imediatamente nos dá uma forte pista de que espaços curtos em uma mensagem são irrelevantes. Parece que os dados são codificados por pulsos, sendo curtos ou longos, e que algum intervalo de espaçamento entre esses pulsos é aceitável.

Obviamente, toda mensagem começa com um pulso longo como um bit de início. Isso deixa 16 bits de dados. Provavelmente, alguns dos bits iniciais são um código de operação, possivelmente com comprimento variável. Se eu estivesse fazendo isso, alguns dos bits finais seriam uma soma de verificação. Imagine que os engenheiros que criaram o firmware queriam manter as coisas simples para si mesmos, para que você possa começar assumindo que existem 8 bits de dados em algum lugar. Agora veja se alguma das mensagens faz sentido.

Vamos chamar um longo de 1 e um curto de 0. Pode ser o contrário, mas temos que começar de algum lugar. Retirar o bit inicial deixa:

1010001101011010 aceleração mínima
1010011101011000 acelerador máximo
1010000001011111 min para a frente
1010000000011110 max forward
1010000011011101 max voltar
1010000100011010 min de volta
0000010101011100 max esquerda + aceleração máxima
0100010101011110 max direita + aceleração máxima
1010000101111111 guarnição esquerda
1010000101011011 aparar à direita

Algumas coisas saem imediatamente. Obviamente, o bit 0 é um bit de paridade. Caso contrário, parece haver um campo de 3 bits <15:13>, um valor de dados de 8 bits <12: 5> e outro campo de 4 bits <4: 1>.

Parece que o valor dos dados está sendo enviado em ordem de baixa a alta, então provavelmente faz mais sentido interpretar os 16 bits inteiros lançados do que mostro.

Não me apetece gastar mais tempo com isso, mas espero que isso tenha lhe dado um começo. Eu continuaria reescrevendo a lista acima com o bit de paridade retirado, o número inteiro invertido LSB para MSB, e cada campo assumido mostrado separadamente com um espaço entre ele e o campo adjacente. Isso pode permitir que mais surjam em você. Lembre-se também de que podemos ter o sentido 1/0 de cada bit para trás. Talvez escreva a nova tabela de cada lado e veja se algo faz mais sentido de uma maneira.

Olin Lathrop
fonte
Obrigado, isso é excelente! Vou direto ao assunto e ver o que encontro. Depois de examinar outros protocolos, comecei a pensar que talvez os espaços fossem irrelevantes, mas como eles tinham dois tempos muito consistentes, eu não tinha tanta certeza. Imaginei que eles variariam mais se não fossem importantes. Enfim, eu vou experimentar. Obrigado novamente
Flambino
Huh ... até onde eu sei, os espaços são importantes. Eu me concentrei no acelerador e capturei mais algumas amostras em 10 posições diferentes do acelerador. A exclusão de espaços não me deu números significativos, independentemente de como eu fiz as conversões. Mas incluí-los como long = 1, short = 0 produz uma progressão suave do valor do acelerador de 1 para 134 (little endian). Ainda trabalhando nos outros parâmetros
Flambino
Eu tenho o protocolo quase totalmente descoberto, mas ainda há um pouco de mistério. Adicionou uma tonelada de coisas à minha pergunta, se você quiser dar uma guinada nela. De qualquer forma, obrigado por sua ajuda até agora! Me fez trabalhar na direção certa.
Flambino
@Flambino: Parece que você está bem à frente do que eu fiz para começar, o que acabou sendo um palpite errado em retrospectiva. Li sua pergunta atualizada, mas ainda não entendo como exatamente o comprimento dos espaços é usado. Foi apenas coincidência que todos os padrões mostrados tivessem exatamente 17 pulsos e que o último acontecesse para indicar paridade se apenas os pulsos fossem considerados 0 ou 1?
Olin Lathrop
Honestamente, foi principalmente tentativa e erro da minha parte. Como os 2 tempos utilizados para os espaços são tão exatos quanto os tempos de pulso, achei que eles poderiam ser significativos. E, quando ignorar os espaços não produziu dados binários úteis, apenas assumi pulso longo = 1 e espaço longo = 1 (e espaço curto / pulso = 0), o que imediatamente me deu dados muito úteis. Portanto, o primeiro espaço após o pulso do preâmbulo é o primeiro bit (o gráfico de aceleração máxima à direita + aceleração mostra um "espaço 1" como o primeiro bit) seguido de 16 pulsos, com mais 15 espaços no meio; 32 bits.
Flambino