TimerList от DetSimen - чего-то не догоняю((
- Войдите на сайт для отправки комментариев
Ср, 16/09/2020 - 10:55
Пробема, наверное, пустяковая, но моих скромных познаний в C++ недостаточно для понимания.
В общем, суть в следующем. Делаю неспешно себе часы. В общих чертах они работают уже пару месяцев, но до завершения еще далеко. Попалась мне библиотека от DetSimen для работы с таймерами. А т.к. у меня в коде есть несколько (а будет еще больше) интервалов, которые я отмеряю миллисом, то решил немного упростить себе жизнь, а заодно и код чуть красивше сделать. У меня почти получилось, спасибо тебе, Дед, дай бог тебе и твоему коту здоровья и сытости )))
Но возникло одно но, которого я не понимаю
Работает без нареканий
Работает без нареканий. Знаю, опрашивать можно и реже, но как уж есть ))
Работает без нареканий.
Работает без нареканий.
И вот с ним у меня абсолютное непонимание. Часы зависают в интервале от 20 минут до 2 часов работы после включения. Причем, сама процедура установки яркости старая, раньше работала без нареканий. Если я делаю вот так
То часы опять таки работают без зависаний вне зависимости, работает ли пятый таймер с пустой процедурой или я его вообще отключаю. Т.е. проблема возникает только в случае, если я вызываю процедуру setMatrixIntensity() в таймере.
Попробуй разрешить прерывания перед setMatrixIntensity() в
tmrMatrixIntensity(
void
)
Попробуй разрешить прерывания перед setMatrixIntensity() в
tmrMatrixIntensity(
void
)
Так?
А что это даст?
Шли код на dap68@mail.ru.
Макс число таймеров, которые я использовал, было 8, косяков замечено не было, надо в твоём коде разбираца.
Нет, но я посмотрел код TimerList и прерывания там и так разрешаются перед вызовом фунции из TimerLisr.
Дело в том что эти функции вызываеются в контексте прерывания таймера и, видимо, setMatrixIntensity() не очень хорошо себя чувствует. Вызывай ее из loop() и забей.
PS Кстати, а сколько у тебя свободной памяти остается (dynamic)?
сначала, пропробуй в 127 строчке TimerList.h
убрать комментарий
там, да, мой косяк, Callback вызывается с запрещенными прерываниями, зачем-то.
Пошто я так сделал, счас не упомню. Правильней - прерывания разрешать перед вызовом
сначала, пропробуй в 127 строчке TimerList.h
убрать комментарий
Ох, блин, не заметил что она закоментирована. Ну, тогда разрешение прервываний, скорее всего, поможет.
сначала, пропробуй в 127 строчке TimerList.h
убрать комментарий
ОК, подправил, загрузил, через пару-тройку часов будет видно))
ну, если setMatrixIntensity() память не распахивает, то, наерна, поможет.
я тоже на git-е поправил :) Спасибо.
Нет, но я посмотрел код TimerList и прерывания там и так разрешаются перед вызовом фунции из TimerLisr.
Дело в том что эти функции вызываеются в контексте прерывания таймера и, видимо, setMatrixIntensity() не очень хорошо себя чувствует. Вызывай ее из loop() и забей.
PS Кстати, а сколько у тебя свободной памяти остается (dynamic)?
Наверное, я делаю неправильно, но у меня действо крутится не только в лупе. Все дополнительные экраны - вывод даты, температуры, настройки даты и времени - у меня делаются в отдельных циклах, соответственно, вызов setMatrixIntensity() (и опрос датчика температуры до кучи) нужно пихать в каждый из них. А таймеры это дело решают малой кровью ))
я тоже на git-е поправил :) Спасибо.
Пожалуйста.
Кстати, cli() в
TCounterDown &
operator
--(
int
) особого смысла не имеет. Прерывания и так запрещены в данном месте.
у тя, кста, если ты матрицу использоваешь, должно памяти мало оставаца. Таймеры, оне, с.ка, динамическую память жруть, не менее 110 байт для Atmega328, посмотри, чтоб точно хватало.
Кстати, cli() в
TCounterDown &
operator
--(
int
) особого смысла не имеет. Прерывани и так запрещены в данном месте.
Понимаешь ли. Как написано в описании, TCounterDown это отдельный класс, который может вызываться не только в контексте прерывания от таймера, а и из твоей программы тоже, мануально, в качестве счётчика каких-нить событий. Поэтому, щёччик должен уменьшаться атоммарно, потому и cli();
у тя, кста, если ты матрицу использоваешь, должно памяти мало оставаца. Таймеры, оне, с.ка, динамическую память жруть, не менее 110 байт для Atmega328, посмотри, чтоб точно хватало.
Ага, учту.
я тоже на git-е поправил :) Спасибо.
можно обновить с гита и попробовать мой маячок?
маячок тоже обновил, бери, пробовай
https://github.com/DetSimen/MorzeRepeater
Я примерно до 17 NSK (13 MSK) буду занят, на вопросы потом отвечу, по мере поступления.
Не, все равно зависло((
могу посоветовать только в Callback-е от таймера просто выставлять флаг "запрос обновления матрицы", а вычислять и устанавливать интенсивность уже в loop() по взведенному флагу. Похоже, сётаки, что где-то портица память.
ОК. Есть еще мысль убрать map() и заменить ее прямым вычислением. Будем пробовать ))
Скока у тебе уровней яркости у матрицы? Если 16, как я здесь разглядел
map(analogRead(PHOTORESISTOR_PIN), 0, 1023, 1, 15)
то это лехко переделывается в
Value = (analogRead(PHOTORESISTOR_PIN) >> 6);
Ага, сделал так:
И два часа работало. А вот только что глянул - уже висит. Рано радовался ))
Выходит, что analogRead() пакостит
Выходит, что analogRead() пакостит
Нет.
И два часа работало. А вот только что глянул - уже висит. Рано радовался ))
Выходит, что analogRead() пакостит
analogRead() прост как 3 копейки и пакостить не может. Привел бы полный текст твоего творения, может и посоветовали бы чего.
Привел бы полный текст твоего творения, может и посоветовали бы чего.
Там больше тысячи строк, плюс еще два файла, взять можно здесь
Провел некоторый эксперимент. Строка 85
В таком виде отработало три часа и не зависло. Решил соптимизировать - т.к. (х / 64) * 2 ((x>>6) * 2) эквивалентно x / 32 (x>>5), то заменил такой строкой
И сразу начало зависать. Причем, зависает в дополнительном цикле, стр. 895
где auto_show_timeout - переменная, которая меняется в другом таймере. Просто останавливается после auto_show_timeout == 1, на экране отображается текущий год - и все, никаких реакций. Но при этом яркость экрана регулируется, палец к фоторезистору - экран притухает, палец убираешь - яркость увеличивается. Получается, этот таймер таки работает, но останавливается (останавливается ли?) другой. Который к нему каким боком?
Да и остановкой таймера автопоказа даты тоже ничего не объяснить, т.к. год отображается не нормально, а слегка потрепанными цифрами, как будто данные попытались измениться, но на полпути все замерло. Т.е. останавливается именно цикл while.
Грешным делом подумал, что я ж, идиот, не объявил auto_show_timeout как volatile, полез посмотреть - действительно, не объявил. Но объявление
проблемы не решило, опять зависло на отображении текущего года.
Сейчас опять сделал строку 85
Пока работает.
Как-то запутанно все - стреляет вроде в лоб, а попадает в задницу ))
Ох как все запутано...
Подобавляй в разные места отладочный вывод (Serial.print()) всяких переменных включая аuto_show_timeout причем с указанием функциии откуда печатается . Только скорость поставь 115200
А зачем ты DS18b20 используешь, если в RTC датчик температуры есть?
Ставил. Именно на аuto_show_timeout и ставил. В самом начале, когда грешил именно на этот таймер. И за два часа ни разу не зависло)) Как только сериал убрал - тут же снова начало зависать. Тогда начал откатываться назад и проблемы ушли после отключения таймера настройки яркости. А потом вообще откатывался назад, когда ни одного таймера не было, добавлял только один - с настройкой яркости, и все начинало зависать. И даже если этот таймер оставить включенным, но убрать из него вызов setMatrixIntensity() - все опять же волшебным образом лечится. Т.е. проблема таки в ней ))
А зачем ты DS18b20 используешь, если в RTC датчик температуры есть?
Фигня там, а не датчик. Точность +/- несколько градусов, причем, погрешность плавающая. Я даже коррекцию сделал - но она для разных температур нужна разная.
Ну и все это находится в корпусе, т.е. температуру он выдает внутрикорпусную, а не комнатную ))
А DS18b20 я на заднюю стенку вывел - и порядок
Похоже на проблемы с памятью. Я бы выкинул
Это придется практически с нуля писать
Я с кодом особо не разбирался, но, насколько я увидел, ты ничего особенного с дисплеем не делаешь. Выводишь текст/цифры (в одном размере?) плюс пара спец символов. Все это легко переписывается.
Часы/минуты выводятся своим шрифтом 6х8 с возможностью вывода полужирным начертанием.
Плюс к тому стандартная проблема этих матриц - вывод знаков на матрицу боком. Здесь есть встроенная возможность повернуть как надо, в других библиотеках эту проблему придется решать самому
На самом деле с памятью проблем пока нету - работает же при вызове регулировки яркости из лупа, проблема только в связке с таймером. Да и то последний вариант вроде работает нормально. К утру скажу точно ))
Я бы тебе посоветовал поменять архитектуру своего приложения. :-)
Например, я, своими таймерами в их изначальном виде уже и не пользуюсь. Сначала я отказался от Callback функции, заменив её лямбдой прям в обьявлении.
потом посмотрел, что создание таймеров однотипно, да совсем убрал FCallback из структуры, список теперь сам шлёт сообщения в очередь, если какой-то из таймеров закончился. Во-первых, я тогда не исполняю код в контексте прерывания, во вторых, приложение, которое не ждёт событий, а управляется ими, более устойчиво КМК, ну а в третьих - иканомица память, что на AVR более чем актуально. Теперь у мня структура таймера выглядит так:
Максимальная выдершка, канеш, сократилась до 24,5 суток, но я на таких интервалах не работаю, а сыканомить удалось целый байт на таймер. :)
а обрабатывается это вот всё уже в контексте задачи, в функции Dispatch().
Плюс к тому стандартная проблема этих матриц - вывод знаков на матрицу боком. Здесь есть встроенная возможность повернуть как надо, в других библиотеках эту проблему придется решать самому
этот поворот пишется за 10 минут, проверено лично
Плюс к тому стандартная проблема этих матриц - вывод знаков на матрицу боком. Здесь есть встроенная возможность повернуть как надо, в других библиотеках эту проблему придется решать самому
этот поворот пишется за 10 минут, проверено лично
MD_MAX72xx.h умеет работать с разными вариантами матриц и выводит в нужном направлении, так что и поворота писать не надо. Правда там один шрифт, но кто мешает нужные цифры/буквы самому забитмапить.
Не, не, лень-матушка же ))) Тем более, что необходимость под вопросом. Сейчас убрал вызов setMatrixIntensity() из таймера, и все работает. Таймер теперь просто поднимает флаг, а в setMatrixIntensity() он проверяется и, ежели поднят, считывается датчик и выставляется яркость. Вызываю из лупа. И все работает без сбоев, т.е. проблем с памятью таки нету.
Проблему вызывала именно работа из таймера. Думаю, что таки беда с контроллером матрицы, зависало обычно в одом и том же месте, где кроме отрисовки ничего и не было. Может что в библиотеках, но, видимо, сбоит обмен с контроллером матрицы в условиях манипуляции прерываниями. Однако, переписывать, пока во всяком случае, не буду))
Таймер теперь просто поднимает флаг, а в setMatrixIntensity() он проверяется и, ежели поднят, считывается датчик и выставляется яркость.
И это праильна.
Таймер теперь просто поднимает флаг, а в setMatrixIntensity() он проверяется и, ежели поднят, считывается датчик и выставляется яркость.
И это праильна.
Иеххх, зато теперь яркость регулируется только в основном режиме, в циклах вывода даты или настройках для регулировки тоже вызов надо ставить. Как раньше было. Я-то думал с таймером про это дело ваще забыть )))
А зачем ее постоянно регулировать? Запустил регулировку раз в минуту или там раз в час, запомнил полученное число - и используешь для времени, даты и всего что нужно
Так часы же в комнате стоят. Ладно там в течение дня яркость почти не меняется, но ночью, после выключения света, они должны таки сразу притухнуть. Иначе с регулировкой вообще заморачиваться не стоит ))
Так часы же в комнате стоят. Ладно там в течение дня яркость почти не меняется, но ночью, после выключения света, они должны таки сразу притухнуть. Иначе с регулировкой вообще заморачиваться не стоит ))
так я все равно не понял, в чем проблема. остальные данные. кроме времени - показываются 6 секунд в минуту. Ну эти 6 секунд можно яркость снова и не регулировать. оставить ту. что была 6 сек назад :)
А вообще. если регулировка яркости в лупе - она по идее должна вызываться раз 100 в секунду, как минимум... у вас луп с какой скоростью оборачивается7
Что-то мешает. Через разные промежутки времени, но не более, чем через два часа, все зависает. Только яркость регулируется - таймер продолжает работать. А часы висят. И только при вызове процедуры регулировки из таймера. Остальные четыре таймера проблем не доставляют, а с этим вот такая фигня ))
А вообще. если регулировка яркости в лупе - она по идее должна вызываться раз 100 в секунду, как минимум... у вас луп с какой скоростью оборачивается7
С какой скоростью - не замерял, но вызванная процедура даже не попытается что-то сделать, пока таймер не поднимет флаг. А таймер у меня сейчас работает с интервалом 500 мс
Если хочешь, я опишу архитектуру своих приложений, управляемых событиями, на примере какогонить заоконного термометра с часами. Моя электропочта elf-basic@yandex.ru
Давай, пригодится ))