Прошу замечаний по таймеру
- Войдите на сайт для отправки комментариев
Вс, 12/04/2015 - 08:44
if(timeNow<timeOn && timeNow<timeOff) onFlag=1; if(timeNow>=timeOn && timeNow<timeOff) onFlag=1; if(timeNow>=timeOn && timeNow>=timeOff) onFlag=0; if(timeNow<timeOn && timeNow>=timeOff) onFlag=0;
Надо включать в пределах суток релюху. Есть ли в приведённом коде камни, над которыми программа может тупить? Время выключения может быть меньше (абсолютно) чем время включения, то есть наример включить в 10 вечера, выключить в час ночи.
я бы сделал через таймер на убывание... и не парился с сутками. типа нужно во столько то включить на 3 часа. ну вот включил и начал назад 3 часа отсчелкивать.
А тип переменных timeNow,timeOn,timeOff узнать можно? Как они вообще сформированы.
И в этом духе. А тип rtc.xxx() - byte.
Щас кстати лютая магия случилась. Во флеше есть массив с режимом работы на год. Так вот, если читать его в pgm_read(), портится одна из переменных в функции опроса клавиатуры. В результате меню сходит с ума, хаотично мигая экраном. Кнопок пять, и приходится на тройку, которая служит клавишей "налево". Если заменить на скажем 7, то работает как задумано. Но не всплывёт ли оно потом ещё где-то - хз. Свободной памяти 1686, из периферии только кнопки, 1602 и 1307. Как лучше, тут багу описать или отдельную тему сделать? А то клавиатурная функция большая, там прерывание чтобы отличать - когда кнопка нажимается 1 раз, а когда удерживается нажатой долго.
Давай весь код под спойлер, посмотрим
про DEBUG:
закомментированная delay(200) в смене режимов - позволило выяснить, что левая кнопка "залипла".
nKey=7; - лекарство. Была цифра 3.
rtc.adjust() в setup() - пока тестовое время, чтобы держать часы в начале суток.
Новое условие
UPD. не пашет. Сейчас ещё что-нибудь придумаю или AND удалю.
UPD2. Да, всё значительно проще.
Из того, что пока что увидел:
Использование time[7] некрасиво ;) Максимальный индекс равен 6, а не 7. Я тебе потом могу выслать как удобней оформить данные, там сразу многое пишется проще и наглядней, тем более скетч уже слегка немаленький ;)
mode > 0 - не очень хорошо читается, лучше mode != 0, признак того, что режим не Idle. Хотя это философский вопрос.
nKey = 7; - это та же проблема, у тебя был код 3 в комментариях, а в switch везде 7, потому и не работало.
Ну вот и главные "глюки":
Аналогично:
Вот еще переполнение, ищи в тексте все такие операции с переполнением:
О птичках, насколько я понял, в EEPROM хранятся часы и минуты, когда нужно стартовать или остановить, так? Тогда почему
timeNow=(time[4]*60)+time[5];
Это же время в минутах и секундах.timeNow= time[3]; timeNow *= 60; timeNow += time[4];
Было бы больше "к лицу" :) Нет?Щас еще гляжу сравнение.
По поводу сравнения. Тут есть следующие грабли. Если хранить только часы и минуты включения, то:
1. При переходе через 0, будут проблемы.
2. Если добавить день, то будут проблемы при переходе через месяц.
3. Если еще и добавить месяц, то будет проблема при переходе через конец года.
Есть вариант, раз уж есть такая таблица часов:минут старта на год, то хранить время старта, как сейчас есть и хранить время продолжительности, тогда как уже говорили, добавить таймер (можно программный), который будет считать оставшуюся продолжительность и не будет проблем с переходами через 0.
Это один из вариантов, есть и другие.
Спасибо откликнувшимся!
О, действительно в тексте было [7], теперь там [6] :) Это чтобы обнаружить, что изменилась секунда. По этому событию показывается новое время на LCD.
Там просто ещё два режима для "показать", 11-12, в которых надо скрыть курсор. Так что сейчас
Это и есть та самая PFM. Откуда-то мистическим образом kbdMain() возвращает эту тройку, хотя кнопки НЕ нажимаются. То есть гонит в return 3, хотя должен быть ноль. Странно также, что ноль возвращается, по настоящему. Его можно увидеть непосредственно перед кодом кнопки, то есть жмём кнопку, получаем вместо тройки ноль, потом код кнопки, потом через время btnsingthr - код кнопки+10 и так далее. Откуда 3 - непонятно. Если не обращаться к pgm_read(), то вместо 3 нормально - 0.
По поводу переполнения, теперь progmem массив читается в переменную типа int, что делает необязательным разбивание на куски. Переменная tmp остаётся в функциях EEPROM, там где надо отнять. Допустимо ли это:
tmp - byte, offtime - int. Это чтобы получить в tmp правый байт offtime. Вообще, что здесь лучше, highByte()/lowByte, сдвиг или можно оставить так?
Это дебажный zoom, чтобы увидеть весь день за 24 минуты.
Уже обнаружены. Лечение пока такое:
Дня и месяца не будет.
Это и есть та самая PFM. Откуда-то мистическим образом kbdMain() возвращает эту тройку, хотя кнопки НЕ нажимаются. То есть гонит в return 3, хотя должен быть ноль. Странно также, что ноль возвращается, по настоящему. Его можно увидеть непосредственно перед кодом кнопки, то есть жмём кнопку, получаем вместо тройки ноль, потом код кнопки, потом через время btnsingthr - код кнопки+10 и так далее. Откуда 3 - непонятно. Если не обращаться к pgm_read(), то вместо 3 нормально - 0.
Ага, теперь понятно. Значит я не совсем правильно понял. Хотя вроде у меня и с 3 работает нормально (на макетке собрал с Леонардо).
'tmp * 256' переполнится. Можно попробовать tmp = offtime - (int(tmp) * 256);
Впрочем highByte & lowByte будет проще.
Уже обнаружены. Лечение пока такое:
Тут есть хорошая засада, после перехода через 0, timeOn станет другим. Здесь явно лучше хранить режим (включен или нет), если включен, то timeOn не проверять, а проверять только timeOff. И наоборот, если еще не включено, то timeOff не проверять.
Да, високосный год считается по другому, %4 недостаточно ;) В гугле есть примеры. А то потом удивишься :)
В общем решается всё, например, конечным автоматом. Вот вариант для тестирования. Выводит в монитор информацию, нужно нажимать Enter, чтобы сделать следующий шаг. Работает когда в один день оба времени и когда в разные (соседние, конечно). Всё это ограничено условиями твоей задачи, так что скорей всего подойдет: