Как принять сигнал с приемника в AVR (PWM|Digital)

Musgravehill
project_Ikar:

Я не знаю за сколько купил мой земляк эту ардуину, но если б я собирал что-то подобное из комплектующих - потратил бы, что-то в районе 6-7$

В глубинке сильно дороже! В местном магазе за эти 7уе можно купить только кусочек текстолита. А еще нужен чип, которые не привозят (что avr, что ftdi за 300р), и обвязка “кондер\резистор по 5 р. за штуку”. Ладно, это решается посылкой (с 11 июля не решается=)

+риск накосячить и спалить.

  • например, мои ЛУТ выглядят страшнее любой готовой Ардуинки. Шелкографии нет, облужено не зеркально, зеленка не нанесена. Да и пайка не идеал.
V_Alex:

Человек не знал, как решить техническую проблему, пришел на Форум и спросил. Респект ему за это. За два дня сам (или с нашей помощью) он разобрался и решил проблему - дважды респект.

Присоединяюсь! Сам следил за этим топиком.

eliash
msv:

Прошу прощения, я понял что нужен генератор группового PPM, а не канального декодированного PWM. Для Вашей задачи особой точности не требуется и код вполне работоспособен… но контроль за переполнением CH1PulseStartTicks я бы все-таки сделал… 😃

что вы имеете ввиду? за переполнением чего сделать контроль? защиту от быстрого дерганья ручки- чтоли? (ну чтоб не завалось по количеству прерываний)
можно немого подробностей?

msv

Да не… все проще…
Просто бросается в глаза, что есть шанс между
CH1PulseStartTicks = micros();
и
Recv = micros() - CH1PulseStartTicks;
внутренняя переменная для функции micros() (наверняка она есть) переполнится и значение которое она вернет в второй строке будет меньше присвоенного в верхней строке. Если там тип long, случиться это не скоро, но я из тех программеров, которые всегда ставят рядом пустой и полный стаканы… Поэтому бы эту ситуацию предусмотрел, тем более что ее можно очень просто разрешить.

eliash
msv:

Да не… все проще…
Просто бросается в глаза, что есть шанс между
CH1PulseStartTicks = micros();
и
Recv = micros() - CH1PulseStartTicks;
внутренняя переменная для функции micros() (наверняка она есть) переполнится и значение которое она вернет в второй строке будет меньше присвоенного в верхней строке. Если там тип long, случиться это не скоро, но я из тех программеров, которые всегда ставят рядом пустой и полный стаканы… Поэтому бы эту ситуацию предусмотрел, тем более что ее можно очень просто разрешить.

ну это даже если произойдет - то всего лишь могут потухнуть огни, до следующей посылки. А посылки идут каждые 20 милисекунд. что-то мне подсказывает, что оно если и моргнет - то никто этого не зметит.
Я ж правильно понимаю, что приемник ретранслирует от передатчика каждую посылку?

msv

Тут такое дело, если Вы оценили вероятность некоторого необработанного события, учли все явные и косвенные последствия, которое оно может вызвать, и что оно не приведет к каким-то фатальным событиям системы (типа деления на ноль, неожиданного ветвления с возможностью переполнения стека итд итп), то конечно можно его игнорировать. Но чаще гораздо проще рядом с полным стаканом поставить пустой из анекдота и быть уверенным, что все предусмотрено на случай если пить не захочется… 😃 Эта мысль не к Вашему конкретному коду, а в принципе, о “культуре” программирования… Типа даже шутка была, что в “хорошей” программе должно быть не меньше 50% кода на обработку ситуаций, которые не случаются никогда. 😃

V_Alex

Вариант “битых” пакетов и полного пропадания сигнала в программе стоит предусмотреть, а сам девайс после изготовления как следует погонять.
В жизни бывает всякое. Например, увлечетесь полетами в сумерках, сядет передатчик, а следом “погаснет” самолет. Обидно…

eliash
msv:

Тут такое дело, если Вы оценили вероятность некоторого необработанного события, учли все явные и косвенные последствия, которое оно может вызвать, и что оно не приведет к каким-то фатальным событиям системы (типа деления на ноль, неожиданного ветвления с возможностью переполнения стека итд итп), то конечно можно его игнорировать. Но чаще гораздо проще рядом с полным стаканом поставить пустой из анекдота и быть уверенным, что все предусмотрено на случай если пить не захочется… 😃 Эта мысль не к Вашему конкретному коду, а в принципе, о “культуре” программирования… Типа даже шутка была, что в “хорошей” программе должно быть не меньше 50% кода на обработку ситуаций, которые не случаются никогда. 😃

Согласен полностью!

V_Alex:

Вариант “битых” пакетов и полного пропадания сигнала в программе стоит предусмотреть, а сам девайс после изготовления как следует погонять.
В жизни бывает всякое. Например, увлечетесь полетами в сумерках, сядет передатчик, а следом “погаснет” самолет. Обидно…

О, а вот над этим действительно надо поработать… как то ушло из виду такое поедение!

1 month later
RL2000

Здравствуйте! Тожа заинтересован в считывания сигнала PWM с помощью ATmega. Прерывания по rise/fall, расчет числа тиков, но ведет себя странно. С приемника/серво-тестера сигнал ни в какую не считывает (подтягивающий резистор и включал, и выключал). А вот если завести PWM-сигнал с меги, то все прекрасно считывается, да и при обычной коммутации на +5В тоже все работает. Может, кто подкинет идею, в чем причина такой ерунды? Заранее спасибо!

V_Alex

Уровень сигнала с сервотестера может быть мал. Если в нем стоит стабилизатор на 3,3 В, а на внешнем проце 5 В, то система может глючить. Нужно согласовать уровни сигналов, например через транзисторный каскад.
Или попробуйте завести сигнал с сервотестера на вход аналогового компаратора Меги, а второй вход компаратора кинуть на внутренний опорник. В этом случае амплитуды входного сигнала должно хватить.

harrystar

Для начала напишите маленькую проверочную прогу, которая считывает состояние ноги к которой подключен сигнал и это же состояние выставляет на другой ноге. Соотв. у вас должен получиться программный “повторитель”. На вход подаете сигнал с сервотестера, на выход вешаете серву. Если все работает, значит все соединено правильно, все уровни совпадают и все подтяжки выставлены тоже правильно. Дальше уже можно писать код. Вместо сервы можно подключить резистор со светодиодом. Различие 1 мс импульсов от 2 мс импульсов видно на глаз (по изменению яркости).

RL2000

Добрый вечер! Спасибо за советы! Внезапно разобрался во всем сам. Не тот порт заткнул, когда все прояснилось - цифры на LCD стали показывать правильные длительности импульса. Правда, при попытке выдать принятый PWM на выход (через 16-битный таймер, т.к. основная программа занята), серва дергается. Дискретизация по времени приема PWM с сервотестера - порядка 52мкс, если ставить больше, как писали - 2000 тиков таймера на 2мс, то на основную программу просто не остается тактов процессора. Вообще, все это нужно чтобы в полете в какой-то момент отобрать управление у приемника и заставить серву исполнять сигнал по программе процессора. Может, лучше поставить транзистор, который будет закрывать путь для прохода PWM-сигнала с приемника по команде процессора?

Aleksey_Gorelikov
RL2000:

Может, лучше поставить транзистор, который будет закрывать путь для прохода PWM-сигнала с приемника по команде процессора?

Не проще запретить внешнее прерывание?

Петруччо

Коллеги, позвольте задать дилетантский вопрос:

сейчас встала необходимость принять на мегу сигнал с приемника, на этом канале висит несколько серв. Идея такая:

  1. Принимаем сигнал на ICP, меряем длительность импульса счетчиком.
  2. Значение длины полученного импульса программно корректируется, т.е. от него либо отнимается время, либо сколько-то прибавляется.
  3. формируется новый импульс заданной длинны на соответствующем PWM пине проца.

Таким образом имея 1 вход можно на него через проц повесить 2-3-4 серво в режиме секвенсора.

Вопрос собсно такой: принять и обсчитать импульс это не проблема, новый тоже сформировать нет, но насколько я понимаю пока проц будет “думать” над текущим обрабатываемым импульсом в это время на ICP будет тикать новый и его мега не успеет уже принять и обработать. Т.е. если я правильно понимаю как минимум будет запаздывание в 1 цикл ШИМ от приёмника. Можно как-то решить эту проблему или дело настолько серьезно, что напрашивается RTOS?
Для справки, JR matchbox выполняет именно такую ф-ию, но в руках не держал, не разбирал… Если я прав, то это в принципе можно реализовать на 2-3-4 независимых камнях типа тиньки25 или 13, у которой есть входы ICP.

Частота 4 МГц, камень ATMega32…пока. На нем отрабатываются узлы, потом все переезжает в 128ю.

Буду признателен за любые подсказки.С Уважением.

V_Alex

Маскимальная длительность пришедшего с приемника импульса - 2 миллисекунды. Такт поступления импульсов - 20 миллисекунд. Итого остается 18 милисекунд.
На последовательную генерацию трех импульсов (максимум те-же 2 миллисекунды каждый) уйдет 6 миллисекунд. Итого, на все расчетные удовольствия остается 12 миллисекунд.
Вторичные импульсы есс-но будут отставать от исходного, но все будут сгенерированы до прихода следующего импульса с приемника.

Петруччо

Благодарю!
Т.е. генерация новых “обсчитанных” импульсов идет в процессоре в фоновом режиме, в то время как проц обрабатывает новые входящие, правильно?
Извините за нескромность, у Вас часом нет этого куска кода? Мне хоть посмотреть в какую сторону бежать…😊

V_Alex

Камень - тини 13А, частота внутреннего RC-генератора 9,6 МГц. Импульс снимается в прямом цикле без прерываний с 4 входа порта В. После метки main10 в регистрах Delay находится разность между 2,2 мс и фактической длиной импульса. Импульс меряется тактами по 6 тиков в каждом. Принцип последующей генерации выходных импульсов после обсчета - такой-же.
=============================================
;********** переопределям регистры ***********************
.def Delay_L = R19 ; задержка (младший байт)
.def Delay_H = R20 ; задержка (старший байт)

;********* задаем константы (9,6 МГц, 6 тактов) **********
.equ VRRST = 3520 ; верхний порог (2,200 мс)

;********** обработка импульса ********************************
ldi Delay_L,Low(VRRST) ; начинаем обработку импульса
ldi Delay_H,High(VRRST); загружаем 2,2 мс в регистры задержки
pul_3: sbis PinB, 4
rjmp main10 ; выходим, если импульс закончился
subi Delay_L, 1
sbci Delay_H, 0
brcc pul_3
main10: …
=======================================
Сразу предупреждаю, что в плане ассемблера я “начинающий” программист.
Возможно кто-то из гуру расщедрится на более грамотное решение.

Петруччо

Спасибо! 😃
Ну, я “сишник”, за ассемблером к отцу пойду, он у меня спец по нему. В принципе всё понятно, попробую это на си портировать, но чувствуется без прерывания не обойтись.

V_Alex

Код делался под примитивную задачу, хотелось обойтись без прерываний.

Петруччо

Александр, а не поясните пжлст: что значит

V_Alex:

Импульс снимается в прямом цикле

? Т.е. как я понимаю программа в бесконечном цикле (jmp loop) проверяет изменение сигнала на входе (1 или 0) и уже потом обрабатывает его?

RL2000
Aleksey_Gorelikov:

Не проще запретить внешнее прерывание?

Такой способ не подойдет, задумал вообще не считывать PWM-сигнал с приемника. Сразу с приемника на сервопривод, а в нужный момент отобрать линию у приемника. Разве что ставить дополнительную микросхему и передавать тщательно вычисленную длительность через UART или еще как.

Петруччо
RL2000:

Сразу с приемника на сервопривод

RL2000:

отобрать линию у приемника

RL2000:

дополнительную микросхему и передавать тщательно вычисленную длительность через UART

это как??😃 В любом случае придется процессор в разрыв тогда ставить.