Страница 1 из 1
Таймер Т1 в ATmega8515L
Добавлено: Вт фев 24, 2009 23:24:03
DrWatson
Уважаемые КОТоварищи! У меня такая проблемка: задумал я часы с таймером и датчиками температуры. Схему собрал, все красиво, НО: часы при запуске(или работе) таймера отстают, да походу дела еще и датчик температуры на DS1820 их тоже притормаживает.
Расклад такой: контроллер ATmega8515, кварц на 4,096МГц, датчики LM75AD - домашняя температура, DS1820 - уличная, часы реального времени на таймере Т1 (предделитель 1024, режим нормал, сброс по совпадению с OCR1A=4000дес, плюс прерывания на OCR1A - отсчет времени, OCR1B=2000дес - для мигания двоеточия часы:минуты), таймер Т0 - генерация звуков и опрос кнопок (3 кнопки на одном порту) (предделитель 1024, режим нормал, перекидывание выхода в противоположное состояние при генерации звука 2048Гц), програмлю на CVAVR, работа с датчиками и индикатором из стандартных его библиотек (от Pavel Haiduk). Да, еще индикатор WH1602. Обновление индикации раз в минуту с опросом датчиков (через стандартные библиотеки), каждые полсекунды по Т1 (А и В) мигает двоеточие и обновляются секунды таймера (если таймер запущен) на экране. Есть подозрение, что считывание датчика DS1820 заставляет пропускать прерывание Т1, либо Т0 заставляет пропускать его. В даташите на таймеры я так и не понял пропускается ли прерывание от таймера, когда прерывания запрещены или ставится в очередь. Исходник прилагаю.
Добавлено: Ср фев 25, 2009 09:05:14
asteroid7
На таймере тяжело получить точные часы. У Вас много прерываний. Каждое из них может тормозить. В m8515 нет асинхронного таймера с ногами TOSCx. Это плохо. Обычно на него вешают кварц 32768 и он работает независимо от программы.
По Ds1820 – нечего сказать. Нет исходников.
А что в программе делают sleep_enable(), idle() и sleep_disable()? Они точно нужны?
Как вариант повышения точности:
В программе должно быть только одно прерывание по таймеру. Оптимально 1000Hz (1ms). В прерывании никаких ветвлений и лишнего кода, только инкрементируется большая переменная. Это тики. В основной программе идёт вся обработка. Никаких CLI и SEI.
А может проще поставить внешнюю м/с часов?
В любом случае, придётся ввести переменную корректировки хода в час/в день.
Добавлено: Ср фев 25, 2009 10:22:22
smac
asteroid7 писал(а):На таймере тяжело получить точные часы.
Не совсем так, не очень тяжело.
asteroid7 писал(а):
А что в программе делают sleep_enable(), idle() и sleep_disable()? Они точно нужны?
Резонно, действительно при некоторых режимах можент останавливаться таймер, но в idle вроде не останавливается.
asteroid7 писал(а):В программе должно быть только одно прерывание по таймеру. Оптимально 1000Hz (1ms). В прерывании никаких ветвлений и лишнего кода, только инкрементируется большая переменная. Это тики. В основной программе идёт вся обработка. Никаких CLI и SEI.
Тоже не совсем, прерывания от таймера ставятся в очередь, поэтому все-равно будут обрабатываться, главное - чтобы следующее прерывание от таймера не пришло до того как начало обрабатываться предыдущее.
asteroid7 писал(а):
В любом случае, придётся ввести переменную корректировки хода в час/в день.
Здесь скорее всего так, ибо кварцы тоже разные бывают
DrWatson Если вы думаете что у вас пропускаются прерывания то нужно сделать так, чтобы они не были запрещены длительное время (более чем период срабатывания таймера), при этом нужно учесть, что при обработке прерываний от др. источников прерывания тоже глобально запрещаются. В принципе советы
asteroid7 приведут к результату. От себя добавлю что копать надо в сторону DS1820, насколько я знаю, ф-и работы с 1-wire запрещают прерывания на длительное время.
Добавлено: Ср фев 25, 2009 21:30:39
DrWatson
Вот и я думаю, что 1-wire тормозит, плюс индикатор, да И2С (программный), в сумме походу и набегает больше секунды, первый и третий точно запрещают прерывания, программную коррекцию времени планирую конечно, если только переход на зимнее-летнее время реализую (иначе нет смысла, все равно два раза в год переводить часы, а точность до 30 секунд в год - не криминал:))
А может проще поставить внешнюю м/с часов?
Была мысля, но в корпусе уже места практически нет, хотя СМД влезет, но платы делаю маркером, для ЛУТа возможностей нет, кроме того создавать кучу новых компонентов в роутере - времени больше уйдет чем от руки рисовать. Да еще у нас тут два отдела одного магазина на весь город - не все есть, и стоит DS1307 около 150р. (И так уже вся конструкция вышла больше 500), а с таким раскладом жаба начинает душить интерес к самоделанию)))) - китайские поделки почему-то стоят зачастую дешевле.
Тем более в основном платы делаю под корпус, а не корпус под плату)))
Резонно, действительно при некоторых режимах можент останавливаться таймер, но в idle вроде не останавливается.
Иначе часы вообще стояли бы, так как большую часть времени у меня контроллер спит.
Да в прилепленном исходнике уже изменения были для попытки решить эту проблему, разносом обращений к датчикам во времени:
Код: Выделить всё
if(Sec==50) GetHomeTemp(); // За 10 секунд до обновления получаем темп. в доме
if(Sec==55) GetStreetTemp(); // За 5 сек. до обновления получаем темп. на улице
раньше все происходило в 0 секунд вместе с обновлением информации на индикаторе, пока правда не проверил как будет работать.
Добавлено: Ср фев 25, 2009 22:05:00
asteroid7
smac писал(а):asteroid7 писал(а):На таймере тяжело получить точные часы.
Не совсем так, не очень тяжело.
Аргументы гдее?!

(из анекдота про еврейскую шапочку в прорубе)
smac писал(а):asteroid7 писал(а):В программе должно быть только одно прерывание по таймеру. Оптимально 1000Hz (1ms). В прерывании никаких ветвлений и лишнего кода, только инкрементируется большая переменная. Это тики. В основной программе идёт вся обработка. Никаких CLI и SEI.
Тоже не совсем, прерывания от таймера ставятся в очередь, поэтому все-равно будут обрабатываться, главное - чтобы следующее прерывание от таймера не пришло до того как начало обрабатываться предыдущее.
При постановке прерывания в очередь и ожидании его набегает погрешность. За несколько часов - секунда запросто...
Добавлено: Ср фев 25, 2009 22:10:06
DrWatson
Пока прерывания запрещены таймер-то тикает, запрет его не останавливает, так что если прерывания не пропускать, то все будет точно (в пределах точности кварца).
Добавлено: Ср фев 25, 2009 23:14:28
DrWatson
Кстати, а может чтение ЕЕПРОМа тормозить все это дело, что-то я не помню про это?
Добавлено: Ср фев 25, 2009 23:20:37
smac
asteroid7 писал(а):
Аргументы гдее?!

(из анекдота про еврейскую шапочку в прорубе)
Давайте не будем меряться пиписьками. Для меня не сложно, если вы в своих силах сомневаетесь, то я в своих нет.
asteroid7 писал(а):Пока прерывания запрещены таймер-то тикает, запрет его не останавливает, так что если прерывания не пропускать, то все будет точно (в пределах точности кварца).
Как вам уже ответили, если таймер работает в режиме автоматического перезапуска при совпадении (СТС), то главное, чтобы не было пропусков обработки прерывания, а с какой задержкой (в разумных пределах естественно т. е. например до 1 с) они будут обрабатываться - не суть важно.
Т. е я хочу сказать, что практически для любого кварца можно пообрать режим работы таймера такой, чтобы погрешность (неточность хода) часов зависела только от кварца.
Погрешность инидикации - переключение секунд на индикаторе при при нормально написанной програме не будет превышать нескольких милисекунд, но это не в принципе к часам имеет сильно опосредованное отношение.
Добавлено: Ср фев 25, 2009 23:39:11
smac
DrWatson писал(а):Кстати, а может чтение ЕЕПРОМа тормозить все это дело, что-то я не помню про это?
Чтение вряд-ли оно не очень много занимает (2 или 4 такта контроллера) а вот запись может тормозить на несколько милисекунд (около 4 мс) если криво организована.
Добавлено: Чт фев 26, 2009 00:14:33
DrWatson
Ладно, потестирую сутки, в пятницу отпишусь, спасибо за советы.
Добавлено: Чт фев 26, 2009 05:33:57
MOHOXPOM
Возможно избежать убегание / отставание хотя бы даже видимого в сутки, если поставить запись нового значения таймера первым в процедуре переполнения таймера. У меня работает. В моем проекте. С ЖК 12864, DS1820 и кнопками
Добавлено: Чт фев 26, 2009 08:50:11
asteroid7
smac писал(а):
...
если таймер работает в режиме автоматического перезапуска при совпадении (СТС)
...
Согласен. Используя 16-ти битный таймер с CTC режимом можно приблизиться к неплохой точности.
В коде
DrWatson используется 8-и битный таймер по переполнению. С ним то и тяжело что либо получить.
P.S. "пиписьками меряться" – мы, вроде, не в детском саду...

Добавлено: Чт фев 26, 2009 09:03:44
asteroid7
DrWatson
Так Вы код на ds1820 и не показали.
Если в нём и правда запрещаются прерывания, то можно его код вынести и подкорректировать под себя, убрав все CLI и SEI. Но это стоит делать только при считывании из датчика.
Запустили преобразование термометра и вышли. Через секунду считываем из термометра. Если на каком этапе вклинится прерывание и 1-wire даст сбой, просто повторить. При корректном CRC результат считать истинным. И опрашивать датчик можно постоянно, а не раз в минуту.
Добавлено: Чт фев 26, 2009 09:55:27
smac
asteroid7 писал(а): Согласен. Используя 16-ти битный таймер с CTC режимом можно приблизиться к неплохой точности.
В коде DrWatson используется 8-и битный таймер по переполнению. С ним то и тяжело что либо получить.
В первом посте написано, что для часов используется таймер 1 в режиме CTC, восьмибитный таймер (T0) используется для опроса кнопок и звуковой индикации.
Добавлено: Чт фев 26, 2009 21:48:48
asteroid7
smac писал(а):
В первом посте написано, что...
Упсс... Совсем невнимательным стал.
Нужно срочно брать отпуск.

Добавлено: Пт фев 27, 2009 05:38:29
MOHOXPOM
asteroid7 писал(а):DrWatson
Если в нём и правда запрещаются прерывания, то можно его код вынести и подкорректировать под себя, убрав все CLI и SEI. Но это стоит делать только при считывании из датчика.
Только вопрос возникает, будет ли работать. У нас не многозадачная операционка, а 8 битный МК. Нужно четко разграничивать тайминги процессов, особенно когда это касается 1-wire
Добавлено: Пт фев 27, 2009 09:00:41
asteroid7
Будет работать. А куда он денется. Для примера, в одном из девайсов, я использую 9 прерываний. Два постоянно работающих UARTа, SPI, 4 таймера и ещё внешние INT. Логгирую температуру ds1820 раз в минуту с самым низким приоритетом. В среднем, из 30 измерений, в одном битое CRC. Тут же перезапустив преобразование, через секунду получаю верный результат.
Добавлено: Пт фев 27, 2009 13:12:35
DrWatson
asteroid7 писал(а):DrWatson
Так Вы код на ds1820 и не показали.
Если в нём и правда запрещаются прерывания, то можно его код вынести и подкорректировать под себя, убрав все CLI и SEI. Но это стоит делать только при считывании из датчика.
Запустили преобразование термометра и вышли. Через секунду считываем из термометра. Если на каком этапе вклинится прерывание и 1-wire даст сбой, просто повторить. При корректном CRC результат считать истинным. И опрашивать датчик можно постоянно, а не раз в минуту.
Код показать не смогу - сам не нашел - стандартная библиотека КодВижина АВР, но с 1-Wire полюбому должны запрещаться. Скорее всего ждет окончания преобразования, задержка где-то с полсекунды. Поставил повтор отсчета времени в прерывании по совпадению с OCR1B, если по OCR1А будет пропущено прерывание.
Вчера погонял - после разноса во времени опроса датчиков и индикации - отставание часов составило за сутки около 1 секунды.
Может дело в кварце (Усеченный такой непонятно чьего производства). хотя маркировка 4,096 МГц может указывать на погрешность около 0,005%, тогда отставание на 1 секунду в сутки - норма для такой погрешности. Надо ставить подстроечный кондер, так как программно с прерываниями раз в секунду можно реализовать подгонку только за год или месяц.
И еще вопрос немного не по теме: сдуру поставил датчик температуры в доме внутрь корпуса, а там трансформатор и 7805 стоят и довольно теплые во время работы (хотя общее потребление схемы не превышает 50мА), при этом после прогрева показания завышены где-то на 3,5 градуса, поставил в коде коррекцию (вычитаю 3,5 градуса из считанных с него показаний). Сам вопрос: при изменениях температуры в доме на +-5град. врать будет также (на 3,5 град.) или разница сильно изменится?