Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Изменение текста программы при смене компилятора и чипа
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2, 3, 4, 5, 6, 7
XVR
Цитата(RW6MKA @ Jan 7 2011, 18:54) *
Так и не понял как это сделать в студии. sad.gif
В вашем povorot2.rar файл Povorot2.lss
Цитата
Да, а оптимизация то отключена blink.gif
Видимо эта оптимизация не отключается rolleyes.gif

sigmaN
Во время работы отладчика Vew->Disassembler. А ещё кнопочка соответствующая есть на панели инструментов. Правее брэйкпоинтов...у меня получается предпоследняя
RW6MKA
Когда выполняется if (N > 48) { Povorot = Rstop; и включена кнопка поворота вправо выключается реле, напряжение на датчике пропадает N становится <1,кнопка то по прежнему нажата и реле включается. Все мозги поломал как это обойти. wacko.gif
sigmaN
Ну вы же состояние не выставляете, что уже дальше крутить некуда. Оно должно один раз выставиться и больше на кнопку не реагировать. Только в другую сторону крутить должно.
sigmaN
Блин, надо вам подарок Рождественский сделать ))
RW6MKA
Вот последний результат моего мучения. blush.gif Прогонял всяко разно вроде нигде ошибок не нашел но... Залил в железо. Реле работы включилось сразу(на PIND6 почемуто 0), а при нажатии на поворот влево реле реверса начинает трещать.Нажмите для просмотра прикрепленного файла
RW6MKA
Вот. Свершилось. 08.gif Поменял PIN6 на PIN5(S0 на S1) и после прошивки всё заработало как надо. Видимо во время моих эксперементов лёг пин6 и при его программной замене на пин5 всё нормально отработало. Всем огромное спасибо за оказаное содействие, и отдельный огромный респект sigmaN a14.gif за проявленное долготерпение. На этом, конечно, проект не закрываю, и буду рад подсказкам в его дальнейшем усовершенствовании. Код конечно требует дальнейшей шлифовки(кстати подскажите что в нём можно улучшить), но главная задача на будущее это управление этой схемой через компьютер.(если такое возможно с этим МК).
sigmaN
рад за вас ))
и что, даже нормально отслеживает положение в железе???
что-то я посмотрел на это всё дело по внимательнее...не нравится мне ни функция Analog, ни схема включения конденсатора....
Код
uint16_t Analog(void) {         //используем аналоговый компаратор для замера времени заряда кондёра
        OffBit(DDRB, 0);         //переводим 0 выход порта В в третье состояние
        TCNT0 = 0;              //очистим счётчик-накопитель
        TH = 0;
        OnBit(TCCR0B, CS01);             //включаем таймер0 с пределителем CLK/8
        OnBit(DDRB,7);          //включить транзистор  //КАК ЖЕ ВКЛЮЧИТЬ ТО? ПРОСТО ВЫСТАВИВ НАПРАВЛЕНИЕ ПИНА В OUT??
        while(!(ACSR &(1 << ACO)));//ждём изменения состояния бита АСО на выходе компаратора
        OffBit(TCCR0B, CS01);             //выключаем таймер
        OffBit(DDRB, 7);         //выключаем транзистор //ОПЯТЬ ЖЕ КАК ВЫКЛЮЧИТЬ? ВЫСТАВИВ ПИН В INPUT?
        OnBit(DDRB, 0);          //разряжаем кондёр  // НУ ТУТ ЕЩЁ СОГЛАСЕН
        _delay_ms(2);           //время для разряда кондёра //ЭТО ВРЕМЯ КАЖЕТСЯ МНЕ ОГРОМНЫМ ))
        return(TH << 8 | TCNT0);   //возвращаем результат замера времени
}
И результаты ваши весьма линейные, тоже как-то не дают мне покоя.....


Цитата
(кстати подскажите что в нём можно улучшить)
в качестве Рождественского подарка готовлю вам рабочий пример с той целью, чтобы вы сами посмотрели и поняли разницу ))
sigmaN
может как-то так его подключим??
RW6MKA
Код
...........
        OnBit(DDRB,7);          //включить транзистор  //КАК ЖЕ ВКЛЮЧИТЬ ТО? ПРОСТО ВЫСТАВИВ НАПРАВЛЕНИЕ ПИНА В OUT??
        .........
        OffBit(DDRB, 7);         //выключаем транзистор //ОПЯТЬ ЖЕ КАК ВЫКЛЮЧИТЬ? ВЫСТАВИВ ПИН В INPUT?
        ........
Да, ведь PORTD7 по умолчанию=0 т.е. получается выход с уровнем 0.База на массу и транзистор открывается, убираем массу с базы и транзисторный ключ закрывается. На счёт задержки я с вами согласен, можно обойтись и 1 ms(наше максимальное время заряда а соответственно и разряда 0.544ms)
Цитата
И результаты ваши весьма линейные, тоже как-то не дают мне покоя.....
Мне тоже)), но факты. Я не поленился таки собрал битовый индикатор и на реальной схеме при всех рабочих параметрах посчитал тики.Блин,не может быть но результат линейный.По вращению переменника(его сектор поворота разбил на одинаковые сегменты) индикация тоже равномерно-линейная.
Цитата
в качестве Рождественского подарка готовлю вам рабочий пример с той целью, чтобы вы сами посмотрели и поняли разницу ))
Буду премного благодарен))

Да,такой вот ещё вопрос.А как можно применить вместо датчика напряжения и компаратора-оптопару и диск с прорезями(ну типа валкодера мышки)?
sigmaN
кстати да, я тут подумал - транзистор же до определенного момента держит ток константой, а на резисторе ток падает по мере заряда кондера.
поэтому хороший кусок получается линейным.
По результатам моделирования в протеусе(с данным типом транзистора) получается линейная характеристика аж до 4.5В

А ещё у меня почему-то в симуляторе ваш кондер вообще не работает. Только после того, как я заменяю его каким-то другим аналогичной ёмкости. Ну или вот этим анимированным вариантом, что на скриншоте в предыдущем посте.

Ладно, в общем разобрался я. Схемотехнику не трогаем. Отличный вариант с транзистором.

Цитата
Да,такой вот ещё вопрос.А как можно применить вместо датчика напряжения и компаратора-оптопару и диск с прорезями(ну типа валкодера мышки)?
не можно, а нужно)))
дохрена готовых продаётся(есть даже по виду как переменный резистор) даже уже с логическим выходом есть. о подключении их к контроллеру тоже много где почитать можно...
RW6MKA
Цитата(sigmaN @ Jan 10 2011, 05:45) *
может как-то так его подключим??

Ну если я не ошибаюсь,этот транзистор здесь при включении разряжает конденсатор, а при отключении не припятствует его зарядке через резистор.Принцип тот же самый, только полевик с изолированным затвором будет включаться при 10-15V на затворевот тут вычитал
sigmaN
Цитата
На счёт задержки я с вами согласен, можно обойтись и 1 ms(наше максимальное время заряда а соответственно и разряда 0.544ms)
разряжаем то ведь не через транзистор, а через порт контроллера. разрядится в общем он, наверно, как минимум раз в 100 быстрее )))

Цитата
Ну если я не ошибаюсь,этот транзистор здесь при включении разряжает конденсатор, а при отключении не припятствует его зарядке через резистор.Принцип тот же самый, только полевик с изолированным затвором будет включаться при 10-15V на затворевот тут вычитал

Полевик этот - N-channel с изолированным затвором и ещё к тому-же Logic level )
И принципе не тот-же самый, что в Вашей схеме. В Вашей схеме зарядка идет ЧЕРЕЗ ТРАНЗИСТОР, а резистор в цепи базы ограничивает максимальный ток коллектора. При этом до тех пор, пока конденсатор, заряжаясь, пытается создать ток больший - транзистор его ограничивает верхним пределом(заданным резистором базы). Это есть его свойство. Биполярный транзистор - токовый прибор и имеет заданное соотношение ток базы/ток коллектора(мало зависящее от напряжения коллектор-эмиттер). Вот поэтому то он и даёт нам линейность, что ток там константный держится.

А так как я предложил подключить - характеристика будет самая что ни на есть нелинейная, что только добавит забот. В топку её кароче))
sigmaN
Как-то что-то я не пойму, оно под отладчиком всегда так странным образом подглючивает индикацию и измеритель положения??

Но если чё будет глючить и в железе - отладим... может чего и я там упустил...
более странными есть глюки индикации, с этим измерением времени там могут быть косяки при работе UART(из за прерываний)
но по идее то прерывание компаратора должно иметь более высокий приоритет, хотя я не уверен есть ли приоритеты в AVR....

ну в общем потестируйте в железе, а там видно будет...

снабжать кода подробными каментами было выше моих сил... может потом.. или сюда вопросы )
RW6MKA
Да-а-а! А стоило ли так всё усложнять? Схема и устройсво в целом не требуют высокой точности и по моему не стоит затрачивать на такое простое устройство столько сил и времени)) Залил я всё в железо, но результат пока нулевой(( Да, я так понял выводы управления реле поменялись? Жаль послезавтра на вахту, возьму с собой все исходники буду курить. Пока на первый взгляд всё непонятно-запутанно, но я думаю всё гораздо проще, чем кажется. UART включили для вывода инфо?Функции сделали самостоятельными и поместили в заголовочные файлы?
sigmaN
Нет там никакого усложнения и особых прямо усилий ) Наоборот - всё наглядно и просто.
Каждый модуль делает своё дело и обеспечивает хотя-бы минимальный уровень абстракции от оборудования.
Выводы поменялись ибо UART занимали.
В общем-то вот этот вариант уже как-то более-менее похож на Си программу.
UART сейчас используется для отладочного вывода + даёт Вам возможность управлять устройством с компьютера.
Причём вы будете приятно удивлены тем, как просто можно его туда добавить при такой структуре проекта.
Также, я думаю нужно добавить таймаут на поворот, чтобы не упереться в упор и не спалить движок.
Т.е. запоминаем время начала движения и если по прошествии определенного времени датчик не отрапортовал о достижении крайнего положения - считать, что мы достигли крайнего положения(и выключать движок) не взирая на показания датчика.

Вы пока смотрите, разбирайтесь и учитесь писать правильные программы, а не быдлокод лепить(гы) )
и не важно маленький это девайсик или огромный проект.

И hwconf.h смотрите. В принципе без паяльника можно обойтись.
В main.с закоментируйте #define USE_UART_DEBUG, а в hwconf.h поставьте старые значения выводов на реле.

А вообще, по хорошему, в железе надо бы подключить UART и откалибровать датчик(он выводит значение в терминал) и подставить эти значения в hwconf.h ибо они, думаю, будут отличаться от симуляторных.

added: щас глянул вот. да. мотор вращаться не будет. Я там использовал два вывода отдельно: один - крутить вправо, другой - крутить влево, а у вас тут надо одним выводом управлять питанием движка, а вторым выбирать направление.
RW6MKA
Цитата
Также, я думаю нужно добавить таймаут на поворот, чтобы не упереться в упор и не спалить движок.
Упоров нет и никто их не делает, максимум при вращении по кругу намотает антенный кабель на мачту))
Цитата
В main.с закоментируйте #define USE_UART_DEBUG, а в hwconf.h поставьте старые значения выводов на реле.
Всё поменял, реле стали включаться, но видимо данные по тикам не попадают в реальный диапазон(32-272,коэф.деления 4.66 хотя в hwconf.h я выставил эти значения laughing.gif ) и поэтому они включаются не всегда, тем более при включении поворота налево срабатывает реле реверса, а при этом с датчика напряжения то нет(т.е. тики=0). Вообщем надо разобраться с кодом, а потом подправить все значения.
sigmaN
Так так так... без паники ))
1. Правлю код motor_drv.c чтобы он соответствовал Вашей схеме. Как я уже говорил - там есть косяк.
также в Протеусе подписал светодиоды RUN и REV. Во время симуляции видно, что при нажадии кнопки r_key - загорается только RUN, а на l_key и RUN и REV. Т.е. если вместо диодов подключить реле - должно быть всё OK.

2. подключите к девайсу терминал и прямо на компьютере будете наблюдать и за значениями тиков и логику работы программы. Благо для этого уже всё имеется ) Вам только нужен преобразователь уровней(чтобы к COM порту компьютера подключиться) или же используйте какой-нибудь мост USB-UART - там на стороне UART будут TTL уровни.
Можете купить готовый адаптер USBtoCOM - там вы увидите саму микросхему моста USB-UART и преобразователь уровней MAX232. Т.е. из покупного переходника достаточно легко можно сделать и преобразователь уровней и TTL совместимый COM порт(просто подпаять девайс к соответствующим пинам моста USB-UART, а дорожки к MAX232 перерезать или вовсе выпаять микросхему).
Тогда вы сможете видеть реальные заначения тиков и легко подставить их в hwconf.h

3.
Цитата
но видимо данные по тикам не попадают в реальный диапазон(32-272,коэф.деления 4.66 хотя в hwconf.h я выставил эти значения
важно понять, что подставлять нужно только SENSOR_LOW и SENSOR_HIGH. коэфф.деления считается сам. причём с округлением до целого(чтобы потом в программе было целочисленное деление).
Код
#define    SENSOR_POINTS_FOR_ONE_LED    ( (uint8_t)((double)(((SENSOR_HIGH) - (SENSOR_LOW)) / (double)DISPLAY_LED_COUNT + .5f)) )
тут коэффициент вычисляется с плавающей точкой, затем к результату прибавляется 0.5 и значение приводится к целому(дробная часть просто отбрасывается во время этой операции)
Примеры: 4.6 при приведении типа к целому - стало бы просто 4, но благодаря тому, что мы прибавляем 0.5 - выполняется именно округление.
4.6 + 0.5 после приведения к целому станет 5
а вот 4.4 + 0.5 после приведения к целому станет 4
Как мы уже говорили, точность индикации не нужна особая и поэтому такой подход вполне себе имеет право на жизнь ).
Расчёт SENSOR_POINTS_FOR_ONE_LED компилятор делает "в уме", так что в процессе работы микроконтроллер не оперирует числами с плавающей точкой.

4. ну в симуляторе то работает? просто я опасаюсь, что версии протеусов у нас немного разные. у меня в симуляторе всё отлично. И вывод по UART вижу и кнопочки работают и диодеги загараютсо и выключает движок по достижении максимума/минимума.. единственное, подглючивает иногда и выдаёт неправдоподобные значения тиков. Вот это важно выяснить: глюк симулятора или в железе тоже будет такой-же косяк? Это вы должны проверить и сказать мне.
RW6MKA
Приветствую.Вот по приезду сразу занялся кодом и сразу несколько вопросов.В немного изменённом проекте протеуса работа МК сбивается и я не пойму в чём дело(файл проекта выкладываю).Да, значения тиков иногда поражают своим разнообразием и ...отрицательными значениями.)) В железо ещё не кидал. По коду вроде понятно всё,но немного не понятна(или скорее не привычна) структура.Из каких соображений например функция работы компаратора с таймером были разделены? Ведь при отказе работы с компаратором и резисторным датчиком и переходе например на оптопару функцию работы таймера всё равно придётся менять.
sigmaN
Ну надо в железе проверить. То, что они в протеусе скачут я и сам знаю )
Код
Из каких соображений например функция работы компаратора с таймером были разделены?
а из каких соображений они должны быть объединены?
Каждую сущность мы должны по возможности описывать самостоятельно и следить за тем, чтобы внутреннее устройство этой сущности было как можно меньше видно остальным, предоставляя необходимый и достаточный интерфейс для связи этой сущности с другими сущностями.
В проекте есть служба времени, отсчитывающая тики таймера. Ничего более от таймера не требуется. Тогда почему мы должны смешивать его внутреннее устройство(работу с регистрами) с функцией замера времени срабатывания компаратора?
Имеем интерфейс:
инициализация timer0_init() и собственно, функция, позволяющая эти тики получитьtimer0_get_tick_count()
Прерывание, которое мы используем только для расширения разрядности - скрыто внутри модуля timer0.c и это правильно ибо нужно отделять мух от котлет ) Инициализация также сосредоточена в одном месте.
Далее имеем модуль ac.c, в котором реализуется функция замера времени срабатывания компаратора + все телодвижения, необходимые для работы этого узла схемы(управление транзистором, контроль разряда конденсатора...)
И зачем нам здесь таймер? Правильно, чтобы отследить сколько тиков прошло с момента вызова ac_start_comparison(); до срабатывания прерывания компаратора. Что мы для этого делаем? Правильно, засекаем время. Вызываем timer0_get_tick_count(); в начале и запоминаем время старта(в условных тиках, естественно)
Код
//remember comparison start time
    start_time =  timer0_get_tick_count();
и делаем то-же самое в прерывании компаратора
Код
result = timer0_get_tick_count() - start_time;
в итоге в result имеем время(в тиках) прошедшее с момента запуска сравнения до сработки компаратора.
А теперь Вы скажите мне:
1. исходя из каких соображений мы должны совмещать работу таймера и компаратора в одной функции?
2. как вы в таком случае будете выкручиваться если мы захотим ввести таймаут на поворот. Ну что-то вроде: если мы крутим вправо и на протяжении 3000 тиков не произошла остановка по сигналу от датчика - значит датчик неисправен и нужно останавливать движок.
При моём подходе - всё просто. Я засеку время начала поворота в какой-нибудь локальной переменной
Код
rotation_start_time =  timer0_get_tick_count();
а в конце основного цикла управления буду просто проверять не вышла ли разница timer0_get_tick_count() - rotation_start_time; за дозволенные приделы(3000). Я обойдусь буквально пятью строчками в программе для реализации этого функционала.
Сколько строк потратите вы для такой доработки при Вашем подходе?
3. зачем что-то менять в таймере при переходе на оптопару?

Хотите научиться программировать? Учитесь мыслить структурно и автоматно что-ли...
Предыдущий вариант этого проекта занимал меньше строк, но внесение каких-либо изменений или отладка такого проекта на практике оказывается очень сложной. Хотя... это не самый подходящий вариант для иллюстрации...проект действительно очень простой и даже в случае полнейшего быдлокодерства, всё-таки как-то можно напрячь мозК и отладить...
Попробовали бы вы написать в таком стиле проектик раз в пять масштабнее, а потом резко попытаться внести в него изменения/доработки.
Всегда помните о том, что набыдлокодить легче, чем продумать хотя-бы элементарный дизайн, но потом это обязательно обернется Вам геморроем в дальнейшем.

Знаете как легко в мой вариант проекта прикрутить управление с ПК? строчек в 20 обойдется "со всеми пирогами".
А теперь я бы хотел увидеть сколько вы промучаетесь с добавкой управления с ПК в ваш код )
В чем разница? Ведь оба проекта делают тоже самое... а разница именно в дизайне. а на сколько легче дышать потом в итоге.
RW6MKA
Да, учится мне ещё и учится. Воощем я понимаю логичность такого деления на независимые оконченые модули, просто сам ещё не в состоянии определить что нужно вынести в отдельный модуль а что нет. Видимо это вырабатывается при длительной практике построения структур программ. Что ж будем работать. rolleyes.gif
_Pasha
Цитата(RW6MKA @ Feb 3 2011, 20:35) *
просто сам ещё не в состоянии определить что нужно вынести в отдельный модуль а что нет.

Не переживайте, этого никто не может сделать. Все равно будут иррегулярности и некрасивости, в той или иной степени. И придется расплачиваться либо оверхедом либо переписыванием.
RW6MKA
Вот изменённый проект протеусаНажмите для просмотра прикрепленного файла Сегодня подкорректировал железо под новую распиновку и подгрузил код. Конечно же вылезли результаты которых в студии не было. Кнопка поворота срабатывает, но тут же отключается. С реверсом получше,но индикации практически нет ни в том, ни в другом случае. Только в момент включения реле происходит смена индикации. В общем всё что происходило в протеусе происходит и в железе.
sigmaN
А зачем нам измененный проект протеуса?

Цитата
Конечно же вылезли результаты которых в студии не было. Кнопка поворота срабатывает, но тут же отключается. С реверсом получше,но индикации практически нет ни в том, ни в другом случае. Только в момент включения реле происходит смена индикации.

Ну так в протеусе индикация работала вполне сносно и проблема была по сути только с некорректной работой датчика положения.

Попробуйте пожалуйста ещё собрать проект с закомментированной строкой
Код
#define USE_UART_DEBUG
, чтобы UART не мешал жить и испытать его в железе....

Сейчас ещё попробую погонять в протеусе ваш первоначальный вариант. вроде как делалось всё по нему. в общем нИзачОт мне ))
ну посмотрим...
sigmaN
Порядок в проекте начинается с порядка в именах файлов и папок.... то у вас Povorot, то Povorot2 теперь уже протеусовский проект называется Povorot2.
Я вынужден распаковывать и переименовывать всё это. Ужас! )
RW6MKA
Цитата
А зачем нам измененный проект протеуса?
Дело в том, что в проекте со светодиодами напряжение поступающее с датчика присутствует постоянно и всё может прекрасно работать,а в реальности будут проблемы.
Цитата
Ну так в протеусе индикация работала вполне сносно и проблема была по сути только с некорректной работой датчика положения.
При включении реверса-да, индикация работает, а вот при включении RUN возникают проблемы.
Цитата
Попробуйте пожалуйста ещё собрать проект с закомментированной строкой

В железе побывал и этот вариант кода, результат тот же.
У меня вопрос такого плана.Есть индикатор жк wm-1611-62c можно ли на него вывести данные uart?
sigmaN
В ближайшие два-три дня посмотрю что там к чему.....

Цитата
Есть индикатор жк wm-1611-62c можно ли на него вывести данные uart?
запрограммировать ещё один микроконтроллер, который будет принимать данные по UART и выводить их на LCD )

Я уже рассказывал Вам как можно подключить UART к ПК. Думаю это самый легкий и быстрый вариант.
RW6MKA
Тут, по ходу пьесы возникли небольшие вопросы. Впринципе я нутром чую что так правильнее, а мозга отстаёт))
Код
      dev_state.r_key = !GPIO_READ_PIN(KEYPAD_PORT, KEY_R);
dev_state.l_key = !GPIO_READ_PIN(KEYPAD_PORT, KEY_L);
//key is pressed?
if( !dev_state.r_key && !dev_state.l_key )
Почему переменной присваиваем инвертируемое значение пина?

Код
motordrv_forward(255)
Я так понимаю что это значение тоже нужно менять на реальное 262?

Вы всё таки вводите понятие гистерезиса в проект, но я не до конца понимаю зачем? 48 светодиодов на 360градусов вращения дают примерно 7градусов между позициями сведодиодов(для 4м антенны типа 2хквадрат это даст смещение конца бума примерно на 1м) и при скорости вращения 3-4об/мин я думаю эта опция будет лишней. Просто смена положений датчика происходит настолько плавно, что программа будет прогонять несколько циклов проверки положения датчика, преже чем это положение сменится на 1.

Про UART-COM.Можно ли для этой цели использовать телефонный COM-шнур?COM для Siemens Ведь разница в уровнях сигналов телефона и девайса не так уж велика.
sigmaN
Цитата
Почему переменной присваиваем инвертируемое значение пина?
потому что кнопка включена "об землю" и если она нажата - пин читается как 0. Мы же хотим абстрагироваться от этого факта и поля dev_state.l_key и r_key хранят true - если кнопка нажата и false - если отпущена.
Это добавляет логичности и удобочитаемости последующему коду.

Цитата
Я так понимаю что это значение тоже нужно менять на реальное 262?
там параметр 8бит, поэтому больше 255 не возьмет.
параметр сделан с запасом на будущее и типа указывает скорость вращения двигателя. в данной реализации он игнорируется. туда можно хоть 0 вписать.

Цитата
COM для Siemens
так в принципе наверно тоже работать будет, но можно ведь не мудрить и собрать как положено - на max232. рассыпухи даже меньше будет! другое дело, если этот уже собран и работает....

гистерезис убрать дело не хитрое, ежели чего.... но в том, что он в таких вещах он необходим для стабильной работы и "по науке" это правильно - я более чем уверен. хотя и не смогу объяснить ничего, кроме как на пальцах.


Цитата
что программа будет прогонять несколько циклов проверки положения датчика, преже чем это положение сменится на 1.
просто всё дело в том, что гистерезис и управление идёт не по диодам, а по тикам с таймера ) и настроить можно будет значительно точнее, чем на 1 диод... диоды там вообще так..просто показометр для приблизительного ориентирования что к чему....
RW6MKA
Вот, собрал я переходник UART-USB и теперь вижу всё онлайн, но ясности это в картинку не добавило. Я тут файлик прицеплю, а в двух словах... включаешь кнопку влево или вправо может сработает реле, а может и нет. Индикация вообще практически нулевая. Короче всё как в протеусе(( В общем буду ковырять код))
Цитата
просто всё дело в том, что гистерезис и управление идёт не по диодам, а по тикам с таймера )
но округляем то мы по одному из 48 положений датчика или я не прав?
sigmaN
Лично у меня в протеусе проблема только одна - иногда ловит неправильное значение датчика и либо срабатывает "упор" и реле отключается, либо(в другую сторону когда крутим) это даёт глюк индикации. С этим делом я разберусь. У меня и тогда(сразу после написания кода) были сомнения, поэтому я и попросил Вас проверить всё в железе.
Цитата
sensor_position: -17198

огого! такого даже в протеусе не было )))))

Даа, блин, судя по файлику - в реальной жизни всё на много хуже, чем в протеусе.
Накосячил я где-то..
sigmaN
что ж, похоже надо у народа спросить. Как-то похоже на то, что таймер прерывание проскакивает blink.gif
В общем расклад такой:
таймер отсчитывает тики:
Код
oid timer0_init(void)
{
    TIMSK = 0x2;
    TCCR0B = TMR_DIVIDER;
}

uint16_t timer0_get_tick_count(void)
{
    return (ticks << 8 | TCNT0);
}

ISR(TIMER0_OVF_vect)
{                      
        ticks++;
}


компаратор отмеряет этими тиками время заряда конденсатора(до срабатывания прерывания)
CODE
void ac_init(void)
{
//see ATtiny2313 datasheet page 150 Table 62
ACSR = (1 << ACIS1) | (1 << ACIS0);
//transistor pin is always output
GPIO_SET_DIR_OUT(AC_PORT, AC_TRANSISTOR);
//sensor pin(AIN1) is always input
GPIO_SET_DIR_IN(AC_PORT, AC_SENSOR);
//turn off pull-up
GPIO_SET_LOW(AC_PORT, AC_SENSOR);
//and even disable digital input buffer for this pin ))
//datasheet page 150, DIDR register description
// DIDR |= (1 << AIN1D);
//keep capacitor discharged all time
capacitor_discharge();
}

void ac_start_comparison(void)
{
//we don't start new comparison until previous is done or aborted
if( state != AC_NORESULT)
return;
//first of all discharge capacitor.
capacitor_discharge();
//we need tho things to set AIN0 to hi-z state
//1. set pin as input
//2. disable internal pull-up resistor
GPIO_SET_DIR_IN(AC_PORT, AC_CAPACITOR);
GPIO_SET_LOW(AC_PORT, AC_CAPACITOR);
//clear Analog Comparator Interrupt Flag(if any)
ACSR |= (1 << ACI);
//enable comparator interrupt
ACSR |= (1 << ACIE);
//remember comparison start time
start_time = timer0_get_tick_count();
state = AC_INPROGRESS; //уже даже state обновляю сразу после засечки времени
//turn on transistor(charging started)
GPIO_SET_LOW(AC_PORT, AC_TRANSISTOR);
//
//now we can exit this routine and wait for interrupt...
}

void ac_abort_comparison(void)
{
state = AC_NORESULT;
//disable comparator interrupt
ACSR &= ~(1 << ACIE);
capacitor_discharge();
}

uint16_t ac_get_comparison_time(void)
{
if( state == AC_READY )
{
state = AC_NORESULT;
return result;
}
else
return 0xFFFF;//not ready or in progess
}


ISR(ANA_COMP_vect)
{
//disable further interrupts(if any)
ACSR &= ~(1 << ACIE);
if( state == AC_INPROGRESS)
{//end_time и start_time - глобальные для отладки.
end_time = timer0_get_tick_count();
result = end_time - start_time;
state = AC_READY;
}
}


в основном цикле что-то вроде
CODE

//поехали...
ac_start_comparison();
for( i = 0; i < 47; i++)
{
uart_puts_P("disp_led_turn_on(i++)\r\n");
disp_led_turn_on(i);

_delay_ms(200);
sensor_position = ac_get_comparison_time();

if( sensor_position != 0xFFFF )
{
char digits[8];


itoa(start_time, &digits[0], 10);
uart_puts_P("start_time: ");
uart_puts(&digits[0]);
uart_puts_P(" ");

itoa(end_time, &digits[0], 10);
uart_puts_P("end_time: ");
uart_puts(&digits[0]);
uart_puts_P("\r\n");

itoa(sensor_position, &digits[0], 10);
uart_puts_P("sensor_position: ");
uart_puts(&digits[0]);
uart_puts_P("\r\n");
//чтобы не полагаться на флаги - начинаю следующий замер только по окончании предыдущего.
ac_start_comparison();

}
}


И вот такая бывает лажа
start_time: 11143 end_time: 11011
sensor_position: -132
т.е. каким-то образом start_time получился меньше end_time
Эти тики состоят из старшего байта = кол-во переполнений таймера(ticks) и младшего( текущее значение TCNT0 )
На банальный "перекрут" счётчика ticks это не похоже ибо отличаются только младшие байты.
Я бы сказал, что это больше похоже на "недокрут" старшего байта. т.е. на пропуск прерывания таймера.
Это очень странно ибо в проекте нигде нет глобальных запрета прерываний (искал cli прям в листинге после компилятора).
Или же я чего-то ещё не доглядел.... всё вроде работает, но иногда спотыкается...... как-то непонятно однако...

доработал даже немного
Код
uint16_t timer0_get_tick_count(void)
{
    //we have owerflow flag, but interrupt is not executed yet
    //this can take a place when we call timer0_get_tick_count from interrupt handler
    //so TIMER0_OVF_vect interrupt can't be executed, but owerflow is occured
    //we have have to take care about this
    if( TIFR & (1 << TOV0) )
    {
        //clear TOV0 in software and do ticks++;
        TIFR |= (1 << TOV0);
        ticks++;        
    }
    return (ticks << 8 | TCNT0);
}

всё равно не помогло.

и да, volatile на ticks, state, start_time, end_time и result - присутствуют....
sigmaN
Предыдущие вопросы снимаются. Разглючил сам )

На данный момент остался один единственный глюк: всё-таки прерывание компаратора иногда проскакивает. вывел на осциллограф в протеусе все входы-выходы, в прерывании дёргаю пин для отладки.. прерывание нигде не запрещаю(ни глобально ни конкретно по компаратору) а он отработает когда 10, когда 20, а когда 40 прерываний и затыкается. видно на осциллографе, что порог превышен более чем в два раза и должен был давно сработать, а не срабатывает. Никаких других прерываний, кроме коротенького таймерного ticks++; нет, а он всё равно заглючивает.
Но тут уж я буду на протеус опять грешить )) надо в железе проверять.

По поводу реле и подачи напряжения на датчик.... сейчас посмотрел... первые три-четыре замера конечно же идут неправильными потому, что там ведь фильтр L8 L1 C7 и, понятное дело, всё это имеет свою постоянную времени. Поэтому измерения начинаются с 10 - 11, а потом доходят до положенных 125(в протеусе при данном положении переменника)... тут и без фильтров никак, ибо двигатель... и с этим делом по идее бороться проще всего в лоб: пропустить первые три-пять значений от датчика )

дальше по коду. в main.c есть #define WALKING_LED_TEST
раскомменитровав его вы активируете тест, который гоняет диодик туда-сюда и непрерывно выводит значения sensor_position: по uart. в протеусе, как я говорил, эта зараза глючит. давайте проверим в железе. питание, естественно, на датчик нужно подать перемычкой или каким-то иным способом.
Также в протеусе оочень редко, но подглючивает индикация(загорается два диода, вместо одного). нужно это тоже внимаетльно протестировать именно в железе.
RW6MKA
Так, чисто познавательные вопросы.
Код
#define    SENSOR_POINTS_FOR_ONE_LED    ( (uint8_t)((double)(((SENSOR_HIGH) - (SENSOR_LOW)) / (double)DISPLAY_LED_COUNT + .5f)) )
Не совсем понимаю использования типа double вместо float и совсем запутался в скобках)) Да, ещё не совсем понятно .5f так вроде понимаю что это для округления, но само выражение незнакомо.

Код
//clear Analog Comparator Interrupt Flag(if any)
    ACSR |= (1 << ACI);
    //enable comparator interrupt
    ACSR |= (1 << ACIE);
Здесь не совсем понимаю почему разрешены прерывания по любому изменению сигнала на выходе компаратора. Логичней,по моему, было бы установить ACIS1 и ACIS2 что бы прерывания происходили только при установлении на выходе компаратора 1. Да и нужно ли здесь использовать прерывания?

Цитата
По поводу реле и подачи напряжения на датчик.... сейчас посмотрел... первые три-четыре замера конечно же идут неправильными потому, что там ведь фильтр L8 L1 C7 и, понятное дело, всё это имеет свою постоянную времени. Поэтому измерения начинаются с 10 - 11
Но в моём варианте кода такое ведь не наблюдалось?
sigmaN
Цитата
Не совсем понимаю использования типа double вместо float и совсем запутался в скобках)) Да, ещё не совсем понятно .5f
ну дабл типа круче )) компилятор же всё равно в уме считает это дело ) .5f = 0.5 f - эт типа float. зачем добавлять 0.5 уже писал, перечитайте.

Цитата
Здесь не совсем понимаю почему разрешены прерывания по любому изменению сигнала на выходе компаратора. Логичней,по моему, было бы установить ACIS1 и ACIS2 что бы прерывания происходили только при установлении на выходе компаратора 1
там закоментированы ACIS1 и ACIS2... я что-то там экспериментировал с этим делом и забыл... дело то ночью было)
От повторной сработки прерывания при разряде кондера спасали запрет прерывания компаратора в самом прерывании компаратора + по состоянию(переменная state) прерывание имеет значение только когда inprogress.
Это всё уже пофиксено в последней версии.

Нужны ли прерывания? ну для чего-то же они существуют) значит нужны wink.gif

Цитата
Но в моём варианте кода такое ведь не наблюдалось?
думаю в вашем варианте кода были охренительные задержки везде и потому первый замер ваш код делал уже тогда, когда напряжение на датчике стабилизировалось.
Вы даже можете подключить осциллограф к выходу датчика и увидите как напряжение там возрастает и фронт там далеко не самый крутой )


А по моему варианту кода там ещё осталось оптимизировать disp_led_turn_on(uint8_t led) ибо там остаток от деления влеплен по быстряку )

Сейчас WALKING_LED_TEST погоняйте в железе. если всё хорошо - проблему с двумя-тремя левыми замерами мы решим очень быстро.
RW6MKA
Значит так. Нажмите для просмотра прикрепленного файлаэтот файл работа железа с #define WALKING_LED_TEST Визуально это зажигание светодиодов по кругу.Нажмите для просмотра прикрепленного файлавторой файл это // #define WALKING_LED_TEST Если питание на датчик подаем отдельно, то кнопки работают но на весь диапазон вращения датчика смена позиции светодиодов 3-4.Если питание через реле,то после вкл уходит в затуп(позиция 10) ну и соответственно работать не желает.
sigmaN
ну CAPTURE.TXT мне нравится. левых замеров не наблюдается.

Цитата
кнопки работают но на весь диапазон вращения датчика смена позиции светодиодов 3-4

ну тут уж видимо нужно подставлять реальные SENSOR_LOW и SENSOR_HIGH
а посему Задача номер 2 вам :
подаёте на датчик отдельное питание
включаете WALKING_LED_TEST
и крутите переменный резистор от минимума до максимума, замечая каким значениям датчика эти положения соответствует. минимум и максимум подставим потом в SENSOR_LOW, SENSOR_HIGH и должно работать.
На сколько я понял, WALKING_LED_TEST не даёт отрицательных значений и других аномалий при неподвижном переменном резисторе. Это так?

А заодно и подольше погоняйте WALKING_LED_TEST. не бывает ли такого, что диодики перестают бегать, а по uart выводится только disp_led_turn_on(i++) или disp_led_turn_on(i--) ? ну т.е. без значений сенсора.
это тоже очень важный тест.
RW6MKA
Вот читаю код, а врубится до конца не могу как происходит взаимодействие ас с таймером???((Кстати так и не увидел где установлены ACIS1 и ACIS2?А вот это
Код
if( TIFR & (1 << TOV0) )
    {
        //clear TOV0 in software and do ticks++;
        TIFR |= (1 << TOV0);
        ticks++;        
    }
    return (ticks << 8 | TCNT0);
вообще не пойму

На мой неопытный взгляд всё слишком замудрёно и трудночитаемо))
sigmaN
Ладно, потом разбираться будем.
Давайте добьёмся работоспособности для начала )

ACIS1 и ACIS2 устанавливаются при инициализации компаратора. т.е. в ac init мотреть.
RW6MKA
Ну ёлы-палы, в тот раз хоть с трудом но удалось установить коннект, сейчас курсор вообще сошел с ума. Я вот не пойму,это помеха такая идёт или програмно что то лезет в комп?

Ну ёлы-палы, в тот раз хоть с трудом но удалось установить коннект, сейчас курсор вообще сошел с ума. Я вот не пойму,это помеха такая идёт или програмно что то лезет в комп?
sigmaN
Наверное это ещё от того, что тактируется мк от внутреннего RC генератора(у него большая нестабильность по температуре + возможно и у вас там что-то с проводами/разводкой т.д.
Параметры порта, надеюсь, правильно стоят? Двигатель не включайте вообще пока что - он источник помех неплохой....
От моста USB-UART больше никуда UART не идёт, кроме как на контроллер? Ну там может у Вас ещё MAX232 прикручена? нет?
RW6MKA
Фу, заработала. Пока без сбоев но крайние положения показывает 38 и 49, а этого не может быть. Я делал замеры с битовым индикатором у меня получилось 32 и 273 тика. вот свежак Нажмите для просмотра прикрепленного файла
sigmaN
Цитата
Пока без сбоев
означает, что ничего из этого
Цитата
На сколько я понял, WALKING_LED_TEST не даёт отрицательных значений и других аномалий при неподвижном переменном резисторе. Это так?

А заодно и подольше погоняйте WALKING_LED_TEST. не бывает ли такого, что диодики перестают бегать, а по uart выводится только disp_led_turn_on(i++) или disp_led_turn_on(i--) ? ну т.е. без значений сенсора.
это тоже очень важный тест.
мы не наблюдаем? Правильно я понимаю? А то Вы так отвечаете, что толком не разберешь. А ведь это важно, чтобы определиться какие подсистемы работают хорошо, а какие нет.

Цитата
но крайние положения показывает 38 и 49
это ВЕСЬМА странные и сомнительные результаты ибо метод измерения, код и железо осталось без изменений(относительно Вашего первоначального варианта). Кроме того, моделирование в протеусе работает и замеры проходят правильно.

Для проверки можно сделать следующее:
1. Конечно же сперва замерять мультиметром напряжение на входе компаратора при вращении переменника. Может быть там какая аппаратная хрень закралась... Номиналы кондера, транзистора и резистора те-же? Фьюзы не перепутаны(частота я имею ввиду). хотя нет, UART же работает вроде как....
2. Самым сильным решением, конечно же, была бы заливка Вашего варианта прошивки и проверка, так сказать, боем )
RW6MKA
Да-а-а, дело было не в бобине... krapula.gif Вообщем я дико извиняюсь, всё дело было в железе. Мало того что я подстраивая железо под нужные пины перепутал реле RUN и REV(понятно что при таком раскладе напряжение с датчика будет только при вкл обоих реле), так ещё и стабилитрон датчика накрылся и вместо 0.5-4.5в он давал 0.55-0.65в. Вот файлы с обновлёнными данными.Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла Нумерация та же. Коротко о работе железа. Ну в первом случае понятно, во втором случае включение влево работает когда захочет, вправо почти чётко работает, но иногда при сбоях в показаниях датчика тоже тупит(ну это всё видно из файла) Индикация практически никакая. Мерцание двух с.д. и скачки через несколько с.д. т.е. нет четкой ,плавной смены одного с.д. на другой.
sigmaN
очень хорошо.
Пока поработаем только с WALKING_LED_TEST. То, что без него у нас пока глюки я уже понял и даже понял где их ловить. Индикация на WALKING_LED_TEST работает исправно всегда? Если диодик бегает слишком быстро, добавьте задержку вот тут
Код
uart_puts_P("disp_led_turn_on(i++)\r\n");                        
            ac_start_comparison();
            _delay_ms(200);
можете просто скопировать и вставить строку _delay_ms(200); ещё раз ниже. то-же самое в цикле ниже, после
Код
uart_puts_P("disp_led_turn_on(i--)\r\n");
и внимательно посмотрите сбоит ли индикация или имеем исправное движение по кругу туда-сюда.
И очень важно мне знать
Цитата
не бывает ли такого, что диодики перестают бегать, а по uart выводится только disp_led_turn_on(i++) или disp_led_turn_on(i--) ? ну т.е. без значений сенсора.


А дальше основоной код я подправлю и всё заработает как швейцарские часы ))
RW6MKA
Индикация на WALKING_LED_TEST работает нормально. Смена светодиодов проходит по порядку, без скачков или двойной индикации. Сбоев в индикации нет, гонял часа два, аж голова закружилась)) в UART отображается disp_led_turn_on(i++) и sensor_position: ххх. Так что я думаю здесь глюков нет.

sigmaN
Вот это самое главное. Сейчас вставлю пару костылей в основной код и дело пойдет как надо.

А глюк протеуса таки подтвержден! При симуляции даже WALKING_LED_TEST глючит с индикацией и проскакивают прерывания компаратора( со временем начинает выводитт только disp_led_turn_on(i++) без sensor_position: ххх )

Так что вывод один: в топку протеус.
Из симуляторов можно более-менее нормально использовать только симуляторы ядра(в студии например или аналогичные для других процов).
ILYAUL
Цитата(sigmaN @ Feb 9 2011, 22:53) *
...проскакивают прерывания компаратора....

А Вы его запретили в начале программы , он по умолчанию включен всегда после сброса
sigmaN
Цитата
А Вы его запретили в начале программы , он по умолчанию включен всегда после сброса
включен сам компаратор, но не прерывание. и у нас в железе всё работает, а в протеусе проскакивает )

вот новая, надеюсь окончательно рабочая версия
если в железе при включении таки будут проскакивать неправдоподобно малые значения - увеличить SENSOR_FILTER_TIME_CONSTANT в файле hwconf.h
накидывайте по 10ms не ошибетесь....
RW6MKA
Ну, к сожалению это не последняя версия кода)) Вот что получилось Нажмите для просмотра прикрепленного файла
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.