Таймер на миллис

Доброго всем! Есть такой таймер

int8_t SecondCorMs;           	//Коррекция времени
#define MS_IN_SECOND 1000L - SecondCorMs

...........

uint32_t msReset = MS_IN_SECOND;
void TickSecondTimer() {  		//Секундный таймер
  if ((uint32_t)(millis() - msReset >= MS_IN_SECOND)) {
    if (SecondDev >= 86399ul) {
      SecondDev = 0;
      ResetDay();
    } else SecondDev++;
    if (Pump[0].Relay.State) Pump[0].Relay.workTime++;
    if (Pump[1].Relay.State) Pump[1].Relay.workTime++;
    if (Heat.Relay.State) Heat.Relay.workTime++;
    VerifyEditAndSysView();
    isFlash = !isFlash;
    if (LightLCD > 0) LightLCD--;
    do {
      msReset += MS_IN_SECOND;
      if (msReset < MS_IN_SECOND) break;
    } while ((uint32_t)(msReset < (millis() - MS_IN_SECOND))); 
  }
}

Изначально период был 1000. Но таймер “уплывал” причем сильно. Сделал так как сейчас, т.е. с возможностью коррекции в плюс или минус. Но не пойму почему так не стабильно это работает. Если ставлю +7 в SecondCorMs то часы ( SecondDev++;) за пару суток отстают на пару минут. Поставил +8 вроде как вперед начинают бежать… Не получится более менее стабильного времени таким способом сделать? Не пойму, если на 1 мск сократить, то за сутки 86.4 секунды уйдет? Туплю…

Ардуино управляется не атомными часами, а обычным кварцем. У которого есть допустимая погрешность. Точнее, чем есть, не выйдет.

Никто в китайские наны настоящих кварцев не ставит.

ну да, там все кварцы исключиительно китайские :grinning:

Ну почему, случается, что и ставят. А у ненастоящих погрешности еще больше

всё относительно, лет 7 назад я озадачился скетчем со сложной корректировкой времени, был на старом форуме, там и точность хода приводилась

Понял, спасибо… поищу.

а если нужна особая точность, то тут тоже был проект на DS3231 с корректировкой на старение кварца

Часовой кварц здесь ни при чём. Тут важна частота резонатора. Кварцев у китайцев нет - только керамика. Однако, для местных поделок вполне. 2000000 BPS вполне, работает.

С таким кодом - неудивительно. Вы писали? Что, например, означает глубокомысленное преобразование (uint32_t) в восьмой и двадцать второй строках? А что вообще делают строки №№ 19-22? Для чего они?

P.S. Если у Вас есть вопросы, я отвечу, но не быстро, мне ещё три+ часа баранку вертеть и сюда я заглядываю во время перекуров :slight_smile:

Ну нет. Тему нужно держать в курсе.)
А если серьёзно. Иной раз спишь и всё равно тема крутится в голове… Хотя, может я такой впечатлительный…) Поражаюсь тому как жена спит словно убитая…)

1 лайк

Это весьма грубая коррекция.
Считаем:
При добавлении/убавлении 1 мс она прибавляется/убавляется каждую секунду. В сутках 86400 секунд.
В итоге ±1мс коррекции в сутки получаем ±86.4 секунды.

А тут или я дурак или лыжи не едут. Условие же не выполняется, если не считать случаев с переполнениями. Чую здесь потенциальный косяк, который потом сложно будет отладить.

Если бы только здесь. Я уже спросил ТС, что означают эти строки, но он молчит как партизан. Думаю, что это “борьба с переполнениями”.

1 лайк

Код писал я.

Спасибо, что обратили внимание. Да, действительно, сейчас увидел, что это не верно. Ибо я условное выражение ((millis() - msReset >= MS_IN_SECOND)) привожу к uint32_t. Скорее всего у меня была проблема с таймером (возможно другая) и я ее решал по скорому… она решилась (видать другим способом) но этот бред остался. И скорее всего я не логическое выражение хотел привести к uint32_t а (millis() - msReset)… Исправлю, точнее уберу, так как работаю с одинаковыми типами…

Ну да. Где-то у гайвера видел, т.н. этот код(алгоритм таймера) с его сайта.
Еще где-то у него было объяснение данного участка, но так как я не гуру в этом, поверил и оставил… Возможно где-то (с другими типами) это нужно, возможно это совсем не нужно. Тогда это вопрос))

Я тоже к этому пришел. Изначально не задумывался. Думал 1 мкс особой роли не сыграет. Даже изначально -100 … +100 коррекцию делал))) А потом посчитал(к удивлению смог)))) шутка) И понял как важна мск во времени глобальном…

Исправил:

Спойлер uint32_t msReset = MS_IN_SECOND; void TickSecondTimer() { //Секундный таймер if (millis() - msReset >= MS_IN_SECOND) { if (SecondDev >= 86399ul) { SecondDev = 0; ResetDay(); } else SecondDev++; if (Pump[0].Relay.State) Pump[0].Relay.workTime++; if (Pump[1].Relay.State) Pump[1].Relay.workTime++; if (Heat.Relay.State) Heat.Relay.workTime++; VerifyEditAndSysView(); isFlash = !isFlash; if (!LightLCD) LightLCD--; } }

Так правильнее будет?

Ниже по теме код исправлен

Что за переменная в 12 строке и где она используется?
Как по-твоему работает 13 строка?

Конечно же с учетом, что точного времени я таким кодом не добьюсь, ибо 1 мск убавляешь общее время бежит, прибавляешь отстает…
Да и черт с ней, особой точности не нужно в этом устройстве, неприятно, но не смертельно…

На сколько убегает за сутки? На 86 секунд? Ну тогда корректируй эти 86 секунд раз/два в сутки и этого достаточно для сносной точности.