Декодер ШИМ на Atmel AVR
М
Мoзгoпрaв и мoзгoвeд©
всем спасибо за подсказки, программу я дописал, и она работает (в железе с реальным источником сигнала).
но, только если выключена оптимизация флаг "-O0". если же её собрать с любой другой оптимизацией, работа прекращается (первая часть, проверочное мигание лампочками работает, а вот дальше фиг знает что там происходит, но явно не то что надо).
как быть? переписывать все на асме? забить на оптимизацию?
Если пользуеш win-avr наиболее рабочий код у мну получался с -O2, -O0 - это без оптимизации
М
Мoзгoпрaв и мoзгoвeд©
Если пользуеш win-avr наиболее рабочий код у мну получался с -O2, -O0 - это без оптимизации
Ну и желательно книжку почитать какую нить, с таймерами может намутил чет... ;-)
t
timsa™
книжку почитать
сами понимаете, лень, некогда да и не зачем. я ж не электронщик, хоть и закончил радиофак когда-то.
в выходные прочитал даташит по диагонали - там все доходчиво, нечего путать.
остальное только с опытом и сотней сделанных проектов придет. а у меня их не будет.
зато задача практически решена. теперь допиливать, вылизывать код. потом все изломать и переделать с нуля по-другому
х
0хCB
таймер то не юзится практически. думается шо компилер при оптимизации while(1) выкинул
попробуй написать for (;;-)
[Сообщение изменено пользователем 24.04.2011 23:10]
попробуй написать for (;;-)
[Сообщение изменено пользователем 24.04.2011 23:10]
Если пользуеш win-avr наиболее рабочий код у мну получался с -O2, -O0 - это без оптимизации
тожэ с -O2 компилил всехда...
правда, предпочитаю avr-gcc
t
timsa™
таймер то не юзится практически. думается шо компилер при оптимизации while(1) выкинул
по вашему, компилятор всегда выкидывает 20+ строк кода если этот код в бесконечном цикле?
и какая связь с таймером?
моё предположение было что при оптимизированном коде частота "кручения цикла" на столько велика, что переполняются счетчики.
но я сделал их unsigned long, а это 4294967295. даже если при частоте 12мгц на каждый такт увеличивать счетчик на единицу, переполнение произойдет через 357,91394125 секунд. так что дело не в этом.
вообще avr-gcc (а я использую его), очень странно оптимизирует код. делает инлайны когда вздумается, выкинул строчку
Исходник:DDRB = 0<<THROTTLE_PWM|0<<STEERING_PWM|0<<GEAR_PWM; |
типа, а фигали, все равно после старта DDRB нулевой!
но я думаю если б я вызвал init() еще раз где-нить, он бы инлайном полноценную версию функции подтянул.
p.s. щас сделаю О2 посмотрю
t
timsa™
p.s. щас сделаю О2 посмотрю
сделал, нифига.
-O0 работает, а 1,2,3,s нет
М
Мoзгoпрaв и мoзгoвeд©
правда, предпочитаю avr-gcc
Дык это он и есть вин авр то :-)
думается шо компилер при оптимизации while(1) выкинул
А с такой буйней я реально встречался в вечном цикле:
while со вложенными скобками, вырезает бывает...
t
timsa™
замена while(1) на for(;;-) результата не дала
t
timsa™
только что опосредованным путем выяснил, что дискретизация распознавания шим крайне низка. в частности трешхолд =100 ломает систему (а я то расчитывал что дискретизация будет исчисляться десятками тысяч)!
отсюда вопрос. я правильно понимаю, что вот такой таймер при тактовой 12МГц
тикает с частотой 10кГц?
отсюда вопрос. я правильно понимаю, что вот такой таймер при тактовой 12МГц
Исходник:TCCR0 = (1<<WGM01)|(1<<CS02); TIMSK = (1<<OCIE0); OCR0 = 5; |
тикает с частотой 10кГц?
х
0хCB
вобще while(dmsec<20000) можно выкинуть, поставить вместо него while(throttle_counter<100 && steering_counter<100) и забить на таймер, ибо в такой реализации не нужен
[Сообщение изменено пользователем 24.04.2011 23:59]
[Сообщение изменено пользователем 24.04.2011 23:59]
х
0хCB
дискретизация распознавания шим крайне низка.
для высокой дискретизации надо юзить ICP, там все будет определяться разрешающей способностью таймера 1, а в текущей реализации этого добится сложновато.
длительность ппм импульса ~800...1600мкс.
собсно если отлавливать с точностью 1мкс будет на выходе 800...1600 дискретов.
а в текущей реализации точность отлова = длительности прохода цикла while,,, чего там win-avr накомплил - хз, но думаю команд 50-100 точно есть
[Сообщение изменено пользователем 25.04.2011 00:11]
t
timsa™
Исходник:TCCR0 = (1<<WGM01)|(1<<CS01); TIMSK = (1<<OCIE0); OCR0 = 150; |
во! ровно 10кГц
t
timsa™
забить на таймер
а это идея! :-)
щас проверим.
p.s. таймер пригодится - еще надо будет поворотником мигать, сейчас он просто горит.
p.p.s. в идеале потом прикрутить плавное включение и выключение всех огней через аппаратный шим :-) но для меня это уже за гранью фантастики.
t
timsa™
щас проверим.
проверка дала неутешительный результат.
по непонятной причине в цикле измерения длины шим очень малые цифры. единицы вместо тысяч :-(
вот кусок кода
Исходник:while(throttle_counter<200) { // крутимся 200 циклов ШИМ // газ if(PWM_PIN & (1<<THROTTLE_PWM)) { // высокий уровнень prev_throttle = 1; throttle_timer++; } else { // низкий уровнень if(prev_throttle == 1) { // это задний фронт prev_throttle = 0; throttle_default += throttle_timer; throttle_counter++; throttle_timer = 0; } } // руль if(PWM_PIN & (1<<STEERING_PWM)) { // высокий уровнень prev_steering = 1; steering_timer++; } else { // низкий уровнень if(prev_steering == 1) { // это задний фронт prev_steering = 0; steering_default += steering_timer; steering_counter++; steering_timer = 0; } } } throttle_default = throttle_default / throttle_counter; steering_default = steering_default / steering_counter; |
выполняется в реальном времени. прерывания запрещены.
на пины THROTTLE_PWM и STEERING_PWM поступают шим с частотой 50гц.
какого чёрта throttle_default и steering_default вместо огромных цифр содержат единицы???
х
0хCB
ловишь просто фронты/спады програмно и с очень большим дискретом, вот единицы и выходят
t
timsa™
очень большим дискретом
12МГц на risc проце это большой дискрет????
даже если на цикл уйдет 1000 тактов (что конечно же не так), то цикл крутится 12000 раз в секунду!
12кГц против 50гц!
я наверно чего то в этой жизни не понимаю
х
0хCB
длительность ппм импульса ~800...1600мкс, ее собсно и считаем. дискрет 1мгц-на выходе значения от 800 до 1600, дискрет 0.1мгц - 80..160 :-)
касаемо 12мгц тактовой частоты: одно действие типа a++ для 32-х разрядного а сожрет на авр 4+3+4=11 комнад(тактов) проверка пина и иф еще такта 4, сложение a+b тактов 20 думаю съест, вот как все просуммируем получим ченить в районе килогерцев, мегеров точно не останется, отсюда такое низкое разрешение.
t
timsa™
низкое разрешение
нашел прогу, которая симулирует сигналы на входе пинов. написал шим последовательность и оттрассировал.
блин грустно... одна милисекунда соответствует 47 оборотам счетчика.
это значит или на асме переписывать (не факт что я смогу переиграть оптимизатор) или AVR унылое говно и даже 50 герцовый шим это предел способностей.
а как же на нем программный USB работает?
пора спать :-)
не факт что я смогу переиграть оптимизатор
запросто. на асме люди сначала думают, потом пишут. а на Си обычно наоборот выходит.
Надо быть проще, сделай замеры пинов тремя отдельными циклами - сначала например steering померяй в течении 10мс, потом throttle и т.п. задержка в 20мс для человека штука незаметная.
Исходник:uint16_t i,thr=0; for(i=(65536-10000);i;i++) { // потому что тупой avr-gcc сам до этого не догадался if(PWM_PIN & (1<<THROTTLE_PWM)) thr++; } |
все это занимает меньше 10мс, при это сделано 10000 замеров.
в итоге у тебя в thr будет сколько ~микросекунд пин был в единице.
х
0хCB
а еще лучше использовать возможности timer capture unit, тада отлавливать фронты/спады сигналов можно с точностью до Fтакт, без особой нагрузки на cpu.
да лан, разбирается на нем этот шим легко и даж время на програмную работу усб остается ;-)
Дык это он и есть вин авр то
а, ну да. просто, я пользовался именно avr-gcc :-) не под виндой.
это значит или на асме переписывать (не факт что я смогу переиграть
оптимизатор) или AVR унылое говно и даже 50 герцовый шим это предел способностей.
ШИМы заводил достаточно шустрые, чото ты делаешь не так. даже трехканальные. частота получалась приличная. точную не помню. какую заводил - на такой и работало, в общем-то. прерывания по переполнению таймера... и заведение его заново...
а делитель тактовой частоты на счет таймера можно любой поставить..
t
timsa™
timer capture unit
а если мне надо 3 сигнала? а этих TCU всего два...
в итоге у тебя в thr будет сколько ~микросекунд пин был в единице.
так то оно так, НО! у меня работа построена на том, что одинаковый цикл для вычисления дефолтного значения и для реальной работы.
я не вычисляю секунды, а просто использую значение счетчика в цикле.
х
0хCB
а вот тут начинается самое интересное :-)
пара вариантов для меги:
1. завести через диоды четные каналы на один icp, нечетные на второй. ну и сидим ловим фронты/спады + анализируем состояние линий:
Фотография из Фотогалереи на E1.ru
по прерываниям от icp0/1 (по изменению, обработчик общий) анализируем линии порта * и считаем шо за время отловили.
2. воткнуть в один icp сигнал поступающий на декодер, сидеть ловить времена фронтов ппм сигнала
[Сообщение изменено пользователем 25.04.2011 13:45]
t
timsa™
четные каналы на один icp, нечетные на второй
а смысл?
тогда уж всё на один icp. по приходу фронта чекаем ноги и определяем где был фронт.
3 или 6 каналов уже не важно
вот только что делать если новый фронт возникает пока старый еще не кончился...
мне то надо длину импульса, значит ловить еще и спад...
Авторизуйтесь, чтобы принять участие в дискуссии.