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

Моргают точки (разделитель в часах) 12:01

Так же как и до этого было if (LightLCD > 0) LightLCD--;. Пока переменная больше нуля, уменьшаем ее… до тех пор пока не станет нолем.

Это для гашения экрана, когда нет действий от энкодера.

Однажды лажонулся с millis():

static uint16_t time;
 while (millis() - time < T_SYS);
 time = millis();

Процесс работал не более минуты. А я в эмуляторе больше и не тыкал.( А у заказчика получился трабл.( Ужас.

Ой ли? В смысле - Так ли это? :slight_smile:

Точно не замечал. Но вариант решения понял… наверное так и сделаю… когда пойму сколько нужно для коррекции…

Вот этот код и верни «взад», если не до конца понимаешь как «отрицание» (!) работает.

Блин точно… Назад все возвращать нет смысла. Нужно так: if (LightLCD) LightLCD--;
Понимаю, просто тороплюсь)) if (!LightLCD) наоборот проверяет, когда LightLCD = 0

И конечно же забыл: msReset += MS_IN_SECOND;

Вот так сделал с учетом двух замечаний:

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--;
    msReset += MS_IN_SECOND;
  }
}

У меня в этом же проекте есть еще и такой таймер:

uint16_t tmr1, PERIOD;
void UpdLCD() {
  uint16_t ms = millis();
  if ((uint16_t)(ms - tmr1) >= PERIOD) {
    FlashParam = !FlashParam;
    if (FlashParam && editParam != 0) PERIOD = 200;
    else PERIOD = 500;
    UpdateScreenData();
    tmr1 = ms;
  }
}

Работает) Но тут как раз без приведения типа не получится…

Кстати тоже можно строку if (FlashParam && editParam != 0) PERIOD = 200; сократить до if (FlashParam && editParam) PERIOD = 200; Но возможно будет читаться (восприниматься) хуже… Хотя, мне вроде понятно…

Как-то так вижу решение;

.....
    if (SecondDev >= 86399ul) {
      SecondDev = 0;
      ResetDay();
    } else  {
        if (newday && !Pump[0].Relay.State && Pump[0].Relay.State && !Heat.Relay.State)  
           {  newday  = false;
              SecondDev +(-)= CorSec;
            } 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++;
......

newday в ResetDay(); возводить…
А коррекцию делать только когда все три устройства, время работы которых считается в этом таймере - выключены…
Понимаю, что если за сутки ни разу не получится (хотя это вряд ли) выключены все три, то время опять уплывет…

Если всё на столько критично, то лучше потрать 100 рублей и купи часы реального времени на DS3231.

Не, вообще не критично… я уже говорил об этом, не смертельно это… Но если малой кровью можно хоть как-то подправить, а мой вариант вроде как раз малой кровью, то почему бы нет… А с DS3231 много переделывать в проекте придется, а он уже практически готовый, да и не нужна супер точность тут. Но как говорил выше просто неприятно))
Ну а то что я предложил (конечно же еще не проверил) имеет место быть? Или как вы видите эту коррекцию времени раз/два в сутки?
В моем случае, я так думаю, что раз в сутки время на экране (хотя у меня секунды не отображаются) возможно скаканет на минуту когда 3 устройства выключены… Это не критично вообще нисколько. Тем более большая часть времени экран выключен…

Вы еще совсем не учитываете эффект от температуры ! Он намного критичнее чем изначальная кривизна кварца !!!

1 лайк

Мне достаточно будет если за месяц уплывет на несколько секунд, за год несколько минут…
А эффект от температуры если еще хуже чем от кварца, тогда нехрен заморачиваться, пусть плывет… что же теперь))) Тут автоматом коррекцию малой кровью не сделаешь…

Мечтать не вредно. А до 30 сек в сутки? Всё корректируется, но стабильности никакой.

Насколько уплывает температура кварца я не знаю, но с математической точки зрения если шаг 1 мс слишком большой, его можно уменьшить. Например если значение поправки для 1 сек рассчитать как float, каждую секунду прибавлять эту поправку к значению требуемой поправки float, целую часть требуемой поправки использовать для коррекции и удалять, а дробную оставлять для следующего цикла.

Без внешнего источника точного времени даже микросхемы часов это просто игрушки !!!
Надо точное время - цепляйтесь к интернет или GPS …

2 лайка

На 100%. Нужен хотя бы резонатор с +/-10 ppm/°C. А попросту, часовой кварц.

Забудьте. Это точность модуля DS3231, на голом кварце такой точности не добиться ))

2 лайка

Ну почему же! У меня комнатная температура, +/- пару градусов. И я корректирую каждые сутки. Почему нет?
Это при том что резонатор нормальный. См. выше.

Можно узнать как?