帮助或提示解码红外协议


10

不久前,我买了一架简单而便宜的红外遥控小玩具直升机(与架直升机相同-叫做“钻石陀螺”或“钻石部队”)。为了娱乐,我一直在研究通过Arduino控制它。

更新:弄清楚了协议;看答案

其他人已经分享了他们的成果,他们可以入侵另一架红外玩具直升机并对其红外协议进行解码。真的很酷,但不幸的是我的直升机使用了不同的协议。我不太清楚的一个。(我应该补充一点,对我来说,电子产品纯粹是一种业余爱好,因此我可能忽略了一些显而易见的东西)。

就像上面的第二个链接一样,我将控制器拆开了,找到了控制LED的IC引脚(顺便说一下,IC的标记已被擦除),并连接了一个逻辑分析仪。

有很多好的数据,但是我仍然无法弄清楚协议。该站点是一个很好的资源,但是列出的协议似乎都不适合。我发现的其他任何东西似乎都不适合我捕获到的信号。不过,我不得不想象这是一个简单的现成协议,只是因为它是一种便宜的小玩具。

因此,如果您有任何想法,我将不胜感激。也许我只是看错了。
(图片下方的更多信息)

来自频道A的样本

信号/协议特征

我在控制器设置为通道A的情况下以16MHz的频率捕获了该信号。应该准确,及时。(您可以选择3个IR通道,但使用其他两个通道不会改变特性,仅改变数据包本身的一部分。)时序非常一致(最大+/- 10µs)。数据包以不同的间隔重复,但至少相距约100毫秒。

载波:38kHz @ 50%占空比

最低:
-短:285µs-
长:795µs

高:
-短:275µs-
长:855µs

每包始终为17高。

控制/输入

直升机的3个控件:“油门”(即升/转子速度),俯仰(前/后)和偏航(绕转子轴旋转)均由2个指尖控制。它们都有一定的范围(不仅仅是开/关),据我所知,它们都是在单个数据包中传输的。左/右输入仅在发送其他内容时发送,因此我在采样时应用了最大油门。一旦您将指尖推过某个阈值/死区,便发送了自己的触发数据包上的油门和俯仰输入(在“ min”标签下方的图形中,是将控件缓慢推过其死区时发送的第一个数据包)。

它还有用于左右修剪的按钮,因为直升机完全不是一种精密仪器否则会缓慢旋转。不幸的是,向左/向右修剪按钮似乎并没有发送每次增加或减少某些东西的信号(这对于确定协议很方便)。它似乎只是一个命令,告诉直升机向左/向右修剪,然后跟踪它。


为什么不仅仅使用已经必须写出原始数据包的信号走线呢?
伊格纳西奥·巴斯克斯

@ IgnacioVazquez-Abrams您的意思是只重播记录到直升机的信号吗?
Flambino

当然。并不是说直升飞机能够分辨出不同...
Ignacio Vazquez-Abrams 2013年

@ IgnacioVazquez-Abrams是的,但是据我所知,该数据包包含所有3个控件(油门/俯仰/偏航)和直升机的控件,没有一个只是打开/关闭。要通过重放来引导事物,我必须捕获每个单独的配置...除了我想了解协议之外
Flambino 2013年

@ IgnacioVazquez-Abrams糟糕,我在某种程度上混淆了我的最后评论。意思是说:“ ...该数据包包含所有3个控件(油门/俯仰/偏航),并且没有一个仅处于打开/关闭状态”。
Flambino

Answers:


8

我已经很自由地回答我自己的问题,因为我已经弄清了大部分问题,这是分享我的发现的一种好方法。感谢Olin Lathrop给我一个起点,并尝试了一些想法,但是最终,该协议与Olin的猜测完全不同,因此我发布了这个答案。


更新:我发布有关后8位的后续问题,我没有完全理解,然后Dave Tweed弄清楚了。我将在此处提供详细信息,因此该答案可以作为完整的协议规范使用,但是请务必查看Dave的答案。


我必须尝试一些不同的事情才能弄清楚这个问题,但是我很自信我明白了。奇怪的是,我没有在其他地方找到任何类似于此协议的东西,但这很可能是我不知道的常见协议。

无论如何,这就是我所发现的:

协议/编码

脉冲和两者之间的空格均用于编码数据。长脉冲/空格为二进制一(1),短脉冲/空格为二进制零(0)。使用标准的消费者红外38kHz调制@ 50%占空比发送脉冲。

脉冲/空间时序是原始问题,但是为了完整起见,我将在这里重复它们:

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

所有最大值为±10µs,典型值为±5µs。这是基于逻辑分析仪在16MHz频率下捕获的样本。我没有示波器,所以我不知道确切的轮廓(即上升/下降时间)。

只要应用了控制输入,数据包就会重复,并且看起来至少间隔100毫秒。

数据包传输以“脉冲1”前导开始,该前导是固定的,不是数据的一部分。接下来的空间编码数据包的第一个数据位,最后一个脉冲编码最后一个位。

每个数据包长32位,并包含遥控器可以提供的每个输入。值读为小端,即MSB在前。

数据结构

以下是各个数据包的基本结构。最后8位让我感到困惑,但是现在已经知道了(请参阅下文)。

 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

注意:范围基于我得到的最高读数。该协议具有更大的范围-节气门最大255,俯仰/偏航最大63-但上限仅为该范围的一半。
音高值似乎具有14-21(含)的死区;只有高于或低于此值才能使直升机做出反应。我不知道偏航是否相同(很难说,因为直升机无论如何都是不稳定的,可能会自行稍微旋转)。

这是图形形式的(与原始问题中的图形相比)

包结构

6个校验位是通过对所有先前值进行异或运算而得出的。每个值均视为6位。这意味着将仅忽略8位调节值的2个MSB。即

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

实用笔记

信号时序和调制不需要非常精确。与真正的遥控器相比,即使我的Arduino的计时精度也不尽如人意,尽管调制方式比较笨拙,而且脉冲/空间持续时间有些打不上。

我相信-但尚未经过测试-直升机只会将其锁定在找到的第一个信号通道上。如果没有信号的时间过长(几秒钟),它似乎会回到“搜索”模式,直到再次获取信号为止。

如果油门为零,则直升机将忽略俯仰和偏航值。

修整命令仅在遥控器上每按一次按钮发送一次。推测调整值只是在直升机自己的控制器中增加/减少了一个值。遥控器无法跟踪。因此,此方法的任何实现都应遵循该方案,并且仅发送偶尔的修剪左/右值,否则默认将数据包中的修剪值设为零。

我建议您使用一个扼杀开关,将油门简单地设置为零。这将导致直升机掉出天空,但在不旋转电机时会受到较小的损害。因此,如果您要坠毁或撞到某些东西,请按一下kill开关,以免剥落齿轮或损坏刀片。

原始遥控器的IR LED似乎具有大于900nm的波长,但使用〜850nm LED时我没有任何问题。

直升机的红外接收器还可以,但不是超级敏感,因此红外光源越亮越好。遥控器使用3个串联的LED,它们位于9V导轨上,而不是逻辑电路使用的5V导轨上。尚未非常精确地检查其电流消耗,但我敢打赌它是50mA。

样本数据

对于有兴趣的人,这是一堆数据包(是的,我为解码器编写了脚本;我没有手工解码所有这些内容)。通道A数据包来自与原始问题中的图形相同的捕获。

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

如上所述,已经确定了最后8位,但仅出于后人考虑,这是我最初的想法。随意完全忽略它,因为我的猜测几乎是错误的。

最后8位

数据包的最后8位仍然是个谜。

从位23到26的4位似乎完全由遥控器的通道设置确定。更改遥控器上的频道不会以任何方式改变协议或调制方式。它只会更改这4位。

但是4位是编码通道设置实际需要的两倍。只有三个通道,所以2位就足够了。因此,在上面的结构描述中,我仅将前2位标记为“通道”,而将其余2位标记为“ X”,但这是一个猜测。

以下是每个通道设置的相关位示例。

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

基本上,传输通道设置所需的位数比需要的多2位。也许协议保留了4位以供以后使用更多通道,或者该协议可用于完全不同的玩具中,但我只是不知道。对于较大的值,协议确实使用了可能被忽略的额外位(偏航/节气门/节距可能少了一点),但是对于微调(也具有3种状态),仅使用了2位。因此,人们可能会怀疑该通道也只有2位,但是接下来的2位却没有得到说明。

另一种可能性是,数据包的校验和是8位长,从“ X位”开始,并且-通过校验和魔术,它们恰好总是以某种方式反映了通道设置。但是,再次:我不知道。

谈到:我不知道这些校验位是如何形成的。我的意思是,它们校验位,因为它们不与任何单个控制输入相对应,并且如果我摆弄它们,直升机似乎也没有响应。我猜这是某种类型的CRC,但我无法弄清楚。支票的长度为6-8位,具体取决于您解释“ X位”的方式,因此有很多方法可以组合在一起。


6

看起来还不错。首先请注意,所有消息都恰好包含17个脉冲。这立即为我们提供了一个强有力的线索,即消息中的短空格无关紧要。看来数据是通过短脉冲或长脉冲来编码的,并且这些脉冲之间的一定间隔范围是可以接受的。

显然,每个消息都以一个长脉冲作为起始位开始。剩下16个数据位。早期的一些比特可能是操作码,可能是可变长度的。如果我这样做的话,那么其中的一些结束位将是一个校验和。如图所示,编写固件的工程师想要使事情简单一些,因此可以从假设某处有8个数据位开始。现在,看看是否有任何消息有意义。

让我们将long称为1,将short称为0。这可能是相反的,但是我们必须从某个地方开始。剥离起始位将留下:

1010001101011010分钟油门
1010011101011000最大油门
1010000001011111分钟向前
1010000000011110最大前进
1010000011011101最大返回
1010000100011010分钟后
0000010101011100最大左+最大油门
0100010101011110最大右+最大油门
1010000101111111修剪左
1010000101011011修剪右

一些事情马上弹出。显然,位0是奇偶校验位。否则,将出现一个3位字段<15:13>,一个8位数据值<12:5>和另一个4位字段<4:1>。

看起来数据值是按照从低到高的位顺序发送的,因此解释从我所显示的内容中翻转过来的整个16位可能更有意义。

我不想花更多的时间在此上,但是希望这可以给您一个开始。我将重新编写上面的列表,其中删除奇偶校验位,将整数从LSB翻转到MSB,并在每个假定的字段与邻接字段之间分别留一个空格。那可能会让更多的人冒出来。还要记住,我们可能对每一位都有1/0的感觉。也许以每种方式写出新表,然后看一看是否更有意义。


谢谢你,太好了!我将继续进行下去,然后看看我发现了什么。在查看了其他协议之后,我确实开始认为这些空间可能无关紧要,但是由于它们有两个非常一致的时间安排,所以我不太确定。我认为如果它们不重要,它们的差异会更大。无论如何,我会尝试一下。再次感谢
Flambino 2013年

嗯...据我所知,空间确实很重要。我专注于油门,并在10个不同的油门位置上捕获了更多样本。不管我如何进行转换,排除空格都不会提供有意义的数字。但是,如果将它们包括为long = 1,short = 0,则会使油门值从1平滑过渡到134(小端)。仍在处理其他参数
Flambino 2013年

我已经几乎完全弄清了协议,但是还有一些神秘之处。如果您想解决这个问题,请在我的问题中添加很多内容。无论如何,谢谢您到目前为止的帮助!让我朝着正确的方向工作。
Flambino 2013年

@Flambino:看来您比我刚开始做的要好得多,事实证明,事后看来这主要是错误的猜测。我阅读了您更新的问题,但仍然不知道如何正确使用空格的长度。仅仅是因为您所显示的所有模式都恰好有17个脉冲,而仅将脉冲取为0或1,最后一个恰好表示奇偶校验,这是否只是偶然?
Olin Lathrop 2013年

老实说,这主要是我的尝试和错误。由于用于空格的2个时序与脉冲时序一样精确,因此我认为它们可能是有意义的。而且,当忽略空格并不能产生有用的二进制数据时,我只是假设long pulse = 1 long space = 1(以及short space / pulse = 0),这立即给了我非常有用的数据。因此,前导脉冲之后的第一个空格是第一位(最大右+最大油门图显示“空格1”作为第一位),后跟16个脉冲,中间还有15个空格;32位。
Flambino
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.