Переполнение millis()

Тема в разделе "Arduino & Shields", создана пользователем yden, 25 авг 2016.

  1. ostrov

    ostrov Гуру

    Верный способ пользования millis() для предотвращения проблемы 2000 переполнения такой:
    Код (C++):
    if(millis() - lastTime > interval)
    {
      lastTime = millis();
    ....
    }
    А вообще, неплохо бы передергивать контроллер хотя бы раз в месяц, хотя бы программно.
     
  2. Unixon

    Unixon Оракул Модератор

    Навскидку приходят два решения:
    1) для длинных интервалов времени (больше максимального значения millis) - замена простого счетчика millis на RTC-подобную структуру с функциями для работы над интервалами времени;
    2) для коротких (меньше максимального значения millis) - принудительное обнуление счетчика millis в начале главного цикла или перед началом измерения интервала, если значение не было сохранено еще в какой-нибудь переменной для последующего сравнения.
     
  3. UnSstrennen

    UnSstrennen Нерд

    Позвольте изложить свой метод.
    Пусть у нас есть переменная lastTime и interval = millis() - lastTime
    Вот проблема
    Если millis() сбросились, то разница стала отрицательной.
    Почему бы не писать что-то типа такого:
    Код (C++):
    if (abs(millis() - lastTime) > interval) {
      lastTime = millis();
    }
    Проблема вроде как отпадает, пусть lastTime = 78479, а миллис сбросились в 0. Тогда интервал станет очень большим и сработает условие if. Кажется, этот метод тоже прост и хорош. Раз в 50 дней а большинстве проектов можно пожертвовать однократным несоблюдением интервала.
     
  4. ostrov

    ostrov Гуру

    Просто вычитать из millis() засеченное время и сравнивать с интервалом. Если переменная времени unsigned long, как и должно быть, то при сбросе таймера сразу сработает условие без всяких abs.

    Если работа таймера точно не превышает переполнения, то в переменную можно вставлять сумму таймера с интервалом и сравнивать потом с таймером же. На целую операцию за сравнение короче. )
     
    Последнее редактирование: 22 авг 2018
  5. DIYMan

    DIYMan Guest

    Нет. Потому что это БЕЗЗНАКОВАЯ арифметика. Если millis сбросилась, то конструкция
    Код (C++):
    millis() - lastTime
    ВСЕГДА вернёт ПРАВИЛЬНОЕ ПОЛОЖИТЕЛЬНОЕ значение, потому что арифметика - беззнаковая. Можно просто в гугле вбить фразу - и почитать, что это такое.

    Проблемы переполнения и сброса milis - просто не существует, есть проблема с людьми, которые не знают, что такое беззнаковая арифметика. Надо просто запомнить одну вещь: единственная правильная конструкция для проверки на интервал между двумя беззнаковыми переменными (а у millis тип возвращаемого значения unsigned long) - это

    Код (C++):
    if( current - last > interval)
    Если будете прибавлять, а не вычитать - будут косяки при переполнении millis. Если будете вычитать - проблемы нет, в принципе.