Я позволю себе ответить на свой вопрос, поскольку выяснил большую часть его, и это хороший способ поделиться своими выводами. Моя благодарность Олину Латропу за то, что он дал мне место для начала и некоторые идеи, которые нужно опробовать, но в конечном итоге протокол оказался весьма отличным от предположения Олина, поэтому я разместил этот ответ.
Обновление: я отправил дополнительный вопрос относительно последних 8 битов, который я не полностью понял, и Дэйв Твид понял это . Я включу детали здесь, так что этот ответ может работать как полная спецификация протокола, но не забудьте проверить ответ Дэйва.
Мне пришлось попробовать разные вещи, чтобы понять это, но я уверен, что понял. Как ни странно, я не нашел ничего похожего на этот протокол в другом месте, но вполне может быть, что это обычный протокол, о котором я просто не знаю.
Во всяком случае, вот что я нашел:
Протокол / кодирование
Оба импульса и промежутки между ними используются для кодирования данных. Длинный импульс / пробел является двоичным (1), а короткий импульс / пробел - двоичным нулем (0). Импульсы отправляются с использованием стандартной потребительской инфракрасной модуляции 38 кГц при коэффициенте заполнения 50%.
Время импульса / пробела в оригинальном вопросе, но я повторю их здесь для полноты:
Bit Pulse Space
-----+---------+---------
0 | 275µs | 285µs
1 | 855µs | 795µs
Все макс. ± 10 мкс, тип ± 5 мкс. Это основано на выборках, снятых логическим анализатором на частоте 16 МГц; У меня нет осциллографа, поэтому я не знаю точный профиль (то есть время нарастания / спада).
Пакеты повторяются до тех пор, пока применяются управляющие входы, и кажется, что они расположены на расстоянии не менее 100 мс друг от друга.
Передача пакета начинается с преамбулы «импульс 1», которая является фиксированной и не является частью данных. Следующее пространство кодирует первый бит данных пакета, а последний импульс кодирует последний бит.
Каждый пакет имеет длину 32 бита и содержит каждый вход, который может предоставить пульт дистанционного управления. Значения читаются как little-endian, т.е. сначала 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 контрольных битов рассчитываются путем XOR'а всех предыдущих значений. Каждое значение рассматривается как 6 бит. Это означает, что 2 старших бита 8-битного значения газа просто игнорируются. Т.е.
check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel
Практические заметки
Синхронизация сигнала и модуляция не должны быть сверхточными. Даже не совсем точный тайминг моего Arduino работает нормально, несмотря на хитрую модуляцию и небольшую частоту попаданий / пропусков по сравнению с настоящим пультом дистанционного управления.
Я верю - но не проверял - что вертолет просто зафиксируется на канале первого найденного сигнала. Если он остается без сигнала слишком долго (пару секунд), он возвращается в режим «поиска», пока не получит сигнал снова.
Вертолет будет игнорировать значения шага и рыскания, если дроссель равен нулю.
Команды обрезки отправляются только один раз при нажатии кнопки на пульте дистанционного управления. Предположительно, значение триммера просто увеличивает / уменьшает значение в собственном контроллере вертолета; это не то, что отслеживает пульт дистанционного управления. Поэтому любая реализация этого, вероятно, должна придерживаться этой схемы и отправлять только случайное значение усечения влево / вправо, но в противном случае по умолчанию устанавливается нулевое значение усечения в пакетах.
Я рекомендую иметь выключатель, который просто устанавливает газ в ноль. Это приведет к тому, что вертолет упадет с неба, но он получит меньше урона, если не вращает моторы. Поэтому, если вы собираетесь потерпеть крах или что-то ударить, нажмите выключатель, чтобы избежать зацепления шестерен или поломки лезвий.
ИК-светодиоды оригинального пульта дистанционного управления имеют длину волны> 900 нм, но у меня нет проблем с использованием светодиода ~ 850 нм.
ИК-приемник вертолета в порядке, но не сверхчувствительный, поэтому, чем ярче ваш ИК-источник, тем лучше. В пульте дистанционного управления используются 3 светодиода последовательно, которые расположены на шине 9 В вместо шины на 5 В, используемой логикой. Я не очень точно проверил их текущую ничью, но держу пари, что это 50 мА.
Образец данных
Вот несколько пакетов, для всех, кто заинтересован (да, я написал сценарий декодера; я все это не декодировал вручную). Пакеты канала 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 битов пакета все еще остаются загадкой.
Все 4 бита от 23 до 26, похоже, полностью определяются настройкой канала пульта дистанционного управления. Смена канала на пульте дистанционного управления никак не влияет на протокол или модуляцию; это только изменяет эти 4 бита.
Но 4 бита - это в два раза больше, чем нужно для кодирования настроек канала; Есть только три канала, поэтому 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 бит, в зависимости от того, как вы интерпретируете «биты Х», поэтому существует множество способов, которые можно объединить.