Не все китайские вертолеты одинаково полезны. Разбор протокола передачи данных от ir пульта.
- Войдите на сайт для отправки комментариев
Использование ИК пульта от мини вертолета
Как говорится Доброго времени суток.
Был у меня когда-то мини вертолет название не вспомню вид приблизительно такой
Он благополучно сломался а пульт управления остался. Спустя время я решил сделать ардуино машинку управляемую с пульта. Долго размышлял ка прицепить дуалшок от ps3 но там заморочки с протоколом. Нестандартный протокол и описание его я не смог найти. И по этому выбор пал на IR пульт от вертолета. Найдя единственную статью размноженную десятки раз с описанием протокола связи сел за паяльник и начал ваять. Но не тут то было оказалось что не все китайские вертолеты «одинаково полезны». Протокол описанный в статье https://habr.com/ru/post/189248/ не подошел к моему пульту.
С этого и начались мои исследования.
Во первых в отличии от пульта описанного в выше упомянутой сатье цитата « кодируются длительностью паузы между сигналами: логический ноль — это 600 микросекунд, логическая единица — 1200 микросекунд.»
В моем пульте кодировка идет не только паузами между сигналами но и длительностью сигнала.
Помог маленький китайский осциллограф. Данные идут с промежутком в ~18000мс
Первый стартовый сигнал в районе 3000мс. потом пакет данных 32 сигнала и 32 промежутка между сигналами итого 64 бита но используются не все. Логический ноль до 700 мс. логическая единица до 1300 мс. значения приблизительные разбег бывает в пару сотен мс. (погрешность измерений).
Подключил к ардуино уно ir приемник написал небольшую программу для передачи данных в порт на компьютер. не судите строго программа писалось методом проб и ошибок.
01 | #define IN_PIN 2 // входной пин |
02 |
03 |
04 | uint32_t us[4],com[2]; // us масив с зашифрованным сигналом. 0 и 1 значение временные в которых записываются комманды в процессе получения |
05 | //us[2и3] записываются во время паузы между командами иначе команды будут прииходить частично измененные так как частота сигнала меньше частоты процессора |
06 | int tim_pause = 5000; // минимальная задержка между командами если пауза дольше этого значения счетчики обнуляются и ждем новой команды |
07 |
08 | uint32_t prevUs; //переменная для хранения времени предыдущего срабатывания |
09 | int count = 0; //счетчик сигналов |
10 | bool first, prevS, flag = 0; |
11 | byte bit1, bit2 ; |
12 | void setup () { |
13 | Serial .begin(115200); |
14 | delay(100); |
15 |
16 | pinMode(IN_PIN, INPUT_PULLUP); |
17 |
18 | attachInterrupt(0, preriv, CHANGE); //инициалилируем прерывание на изменение состояние пина 2 |
19 | } |
20 |
21 | void loop (){ |
22 | if ( (us[2]!=com[0])||(us[3]!=com[1])){ // для того чтоб в мониторе порта не выводились повторные значения завел еще 2 переменных для контроля изменений |
23 | com[0]=us[2]; |
24 | com[1]=us[3]; |
25 | for ( int j=31; j>=0; j--) { //выводим их со страршего бита |
26 | Serial .print(bitRead(us[2], j)); //если старшие биты равны нулю то при обычном выводе они не покажутся для этого делаем цикл с условием если бит раве1 то выводит 1 если нулю |
27 | // Serial.print(";"); //выводим между значениями ; для того чтоб при открытии екселем разделять значения в разные колонки. |
28 | |
29 | |
30 | } |
31 | //Serial.print(us[2], BIN);// способ не работает пропускает старшие нули |
32 | Serial .print( " " ); //промежуток между переменными легче ориентироваться. |
33 | for ( int i=31; i>=0; i--) { //здесь все тоже самое |
34 | Serial .print(bitRead(us[3], i)); |
35 | //Serial.print(";"); |
36 | //Serial.println(us[3], BIN); |
37 | |
38 | } |
39 | Serial .println(); |
40 | } |
41 | } |
42 |
43 | void comand() { |
44 | |
45 | |
46 | } |
47 | void preriv() { |
48 | // читаем время |
49 | uint32_t now = micros(); |
50 | |
51 | if ((now - prevUs)>tim_pause) { //если время с последнего срабатывания превышает tim_pause обнуляем счетчики |
52 | us[2]=us[0]; //записываем временные переменные в постоянное место переменная полностью изменилась |
53 | us[3]=us[1]; |
54 | flag=0; |
55 | count=0; |
56 | bit1=0; |
57 | bit2=0; |
58 | } |
59 | if (!flag) { // триггер (первое срабатывание) |
60 | flag = 1; // запомнили |
61 | prevUs = now; // время первого |
62 | } else { // измеряем следующие |
63 | if (count>0) { //пропускаем второе срабатывание так как это был стартовый сигнал |
64 | if (count<33){ //так как максимальная (стабильно работающая)переменная uint32_t содержит 32 бита а у нас их 64 делим данные на 2 переменных |
65 | bitWrite(us[0] ,(31-bit1), ((now - prevUs)>800)) ; //если время предыдущего срабатывания минус текущее время больше 800 мс записываем 1 иначе 0 в соответствующий бит |
66 | bit1++; //добавляем в счетчик битов 1 |
67 | } else { |
68 | if (count<64){ //проделываем тоже самое для второй переменной |
69 | bitWrite(us[1] ,(31-bit2), ((now - prevUs)>800)); |
70 | bit2++; |
71 | } |
72 | } |
73 | } |
74 | prevUs = now; // запомнили время |
75 | count++; |
76 | } |
77 | } |
скетч с подробными коментариями: https://github.com/GodVine/ir_verto
Данные из порта перекинул в таблицы мукрасофта. если когото интересует исходник таблицы вот он https://disk.yandex.ru/i/rE-yVP3jagg8ug . В итоге получилось такая картина:
с 63 по 57 биты это акселиратор скорость вращения несущих винтов (номирация идет с младшего бита и с нуля как все в ардуино)
с 54 по 51 биты это в лево в право 50 бит направление 0 в лево 1 в право
56 и 47 биты ререключение режимов(или устройств)
с 45 по 43 калибровка вращения главных винтов 42 бит направление калибровки
с 28 по 25 вперед назад 24 бит направление 0 назад 1 вперед
теперь осталось взять эти биты (например с 63 по 57) и перевезти его в отдельную переменную акселиратор изменяестя от 12 до 100 почему не с 1 не знаю возможно дефект потенциометра в пульте.
также передаются контрольные суммы и еще какие-то данные которые мне не удалось расшивровать.
Как я "приделал" этот пульт к своим самоделкам смотрите в следующей части.
коментариями
когото
акселиратор
номирация
в лево ...в право ...в лево ...в право
акселиратор
я указал только систематические ошибки, явные опечатки пропустил. Запятые, которые сэкономлены, явно проданы на привозе! ;))
Код я конечно не стал читать. Кровь из глаз мешает. ;))
Тоже "мёртвую петлю" делал?
я указал только систематические ошибки, явные опечатки пропустил. Запятые, которые сэкономлены, явно проданы на привозе! ;))
запятые ладно... а вот то, что ТС, описывая таймслоты протокола(то есть то, в чем собственно самая соль его сообщения), систематически путает МИКРОсекунды и МИЛЛИсекунды - никуда не годится.
Да ладно, разберёмся мы с этими микросекундами
Код я конечно не стал читать. Кровь из глаз мешает. ;))
Немного потерял.
Это один из многочисленных кодов, которые вроде и работают, но иногда (причём, нерегулярно, а время от времени, без видимых причин) глючат. Понятное дело, что в самом-то коде всё правильно, просто плата китайская :-(
Понял, принял. Следующую статью буду писать академическим слогом.
Понятное дело, что в самом-то коде всё правильно, просто плата китайская :-(
вот вот обидно, что иногда такой код используют в своих библиотеках и, более 20 таких нашёл
Следующую статью буду писать академическим слогом.
может не надо? а то..."академическим виделся текст, а на поверку про..." )))
PS я не настоящий сталевар ежели что, просто сегодня пятница, здесь по пятницам так принято, сломать не смог решил возглавить )))