Прерывания по таймеру
- Войдите на сайт для отправки комментариев
Добрый день, корифеи
Освоившись с отказом от delay и переходом на millis сваял скетч (все работало как надо, ничего не напрягало, благо задачи не ресурсоемкие), но попался на глаза материал про прерывания по таймеру, и понеслось ))) Прошу глянуть код - не слишком ли тяжелым для прерывания получился код? С одной стороны прерывание вызывается раз в 4 секунды и выполняя расчеты раз в 4 секунды, а не при каждом проходе loop процессор разгружается для выполнения других задач (конечно в моем случае для простоя он разгружается), плюс отказался от нескольких unsigned long переменных, что также должно положительно сказаться на быстродействии. А с другой стороны - не слишком ли долго процессор теперь засиживается в прерывании? Визуально все работает так же, как и в варианте с millis, но гложет удав сомнения...
ISR (TIMER1_COMPA_vect) // функция вызываемая таймером-счетчиком T1 { // дезинфекция if ((PumpWaterState) && UvLampTime > 0 ) { // если включена помпа и установлено время работы УФ лампы timerPumpUV = (timerPumpUV + 4); // увеличиваем время таймера (+4) if (timerPumpUV > PumpWaterWorkTime && (!UvLampState)) { // если время работы помпы превысило пороговое значение и УФ лампа выключена uvStart(); // включаем УФ лампу } if (timerPumpUV > (PumpWaterWorkTime + UvLampTime) && (UvLampState)) { // если время работы УФ лампы превысило пороговое значение и УФ лампа включена uvStop(); // включаем УФ лампу timerPumpUV = 0; // сбрасываем переменную } } // таймер выключения if (TimerSet > 0) { // если время таймера не истекло TimerSet = (TimerSet - 4); // уменьшаем время таймера (-4 сек) if (TimerSet <= 0) { // если время таймера истекло PowerOnTask = 0; // выдаем задание на выключение питания TimerSet = 0; // сбрасываем таймер, а то мало ли - может в минут натикал if (DEBUG == 1) { beep(); Serial.println("таймер кончился"); } } else { // если время таймера не истекло if (DEBUG == 1) { TimerCoundownNew = ceil(TimerSet / 10.0); // получаем в десятках секунд время до отключения таймера (для индикации) if (TimerCoundownNew != TimerCoundownOld) { // если требуется обновить индикацию таймера coundownLed(3, TimerCoundownNew); // передаем в функцию номер светодида, который нужно зажечь TimerCoundownOld = TimerCoundownNew; // запоминаем значение } } else { TimerCoundownNew = ceil(TimerSet / 3600); // получаем в часах время до отключения таймера if (TimerCoundownNew != TimerCoundownOld) { // если требуется обновить индикацию таймера coundownLed(3, TimerCoundownNew); // передаем в функцию номер светодида, который нужно зажечь TimerCoundownOld = TimerCoundownNew; // запоминаем значение } } } } // таймер опроса DHT timerDHT = (timerDHT + 4); // увеличиваем время таймера (+4) // таймер расчета скорости вентилятора timerFan = (timerFan + 4); // увеличиваем время таймера (+4) // таймер отображения целевой влажности if (timerHum > 0) { // если время таймера не истекло timerHum = (timerHum - 2); // уменьшаем время таймера (-0.5 сек) } }
Для того, что является "слишком", а что - нет, должны быть какие-то критерии.
В принципе, критерии могут быть такими:
1. Интервал между пользовательскими прерываниями должен быть строго больше, чем длительность прерывания. Т.е. чтобы следующее прерывание не наезжало на предыдущее.
2. Длительность пользовательского прерывания желательно, чтобы была меньше, чем интервал между системными прерываниями.
Системнве прерывания выполняются примерно 1 раз в мс. Значит, желавтельно, чтобы пользовательское прерывангие было короче 1 мс.
Лично я в setup() перед тем, как включать прерывание вызываю его как функцию, измеряю время его работы, вывожу это время на печать, и только потом включаю прерывание. Даже если контроллер намертво зависнет, в консорли у меня будет цифра, облегчающая диагностику.
Спасибо за критерии оценки - подозревал что они должны быть, вот теперь появились количественные ориентиры. По проверке длительности прерывания тоже все понял, еще раз спасибо.
Здравствуйте, это упрощенный пример, чтобы многие поняли суть вопроса Прерывание настроено на таймере 1 с интервалом 1 секунду. Мне нужно, чтобы по нажатию кнопки запускался таймер и начинался отсчет времени именно в момент нажатия а не по ходу программы как в данном случае. Догадываюсь что нужно запретить прерывание пока находимся в теле функции loop() и разрешить в момент нажатия таким образом чтобы не затронуть работу millis() и других завязанных на timer 0. Может есть способ по лучше.
Возможно функцию LCD_update_time() потребуется вызывать как это сделано в конструкции с millis() и не нужно запрещать прерывание а завести переменные либо отсчитывать время в обработчике по разрешению и завести флаг
Пока в уме только это