millis() переполнение (новичок)

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
Подскажите...
C++:
void loop() {
  if (millis() - timer_1 > 5000) {    // условие таймера
    timer_1 = millis();                   // сброс таймера
Я конечно могу ошибаться но чисто теоретически давайте представим что МК включен непрерывно больше чем значение может считать таймер millis() 50 дней. Меня интересует итерация цикла в конце переполнения. Когда переменной timer_1 будет присваивается значение OVER большое а сам millis() будет обновляется и начинать отсчет с 0. Следующее условие будет в теории выполнятся через 50 дней или вообще не когда.
Объясните как в таких случаях поступают?
 

rkit

★★★✩✩✩✩
5 Фев 2021
510
127
В какой теории? Сколько будет (unsigned long)0 - 5000? Раз уж ты такой теоретик
 

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
@rkit, Раскрой ответ пожалуйста, я же написал что новичок в этом...
0-5000>5000 условие будет выполнятся только когда разность будет больше 5000... т.е вместо 0 мы должны подождать когда в милесе натикает 10000 ..
Если это так работает что последняя итерация переполнения присваивает таймеру значение OVER9999 а милес обновляется до 0 и что получается
0-OVER9999>5000 Это сколько я должен ждать ???
 
Изменено:

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
@bort707, Без рофлов если.. Почему именно так? Милес обновился и начал с 0,переменной присвоено большое значение... Это надо ждать когда милес дотикает до этого большого значения? Кто переменную перезапишет?
 

poty

★★★★★★✩
19 Фев 2020
3,261
948
Пример с 0 и 5000 для типа unsigned long неудачен, поскольку условие выполнится задолго до переполнения. Но если применять правильные значения, то @bort707 прав.
 

Сотнег

★★★★★★★
15 Янв 2020
4,446
1,520
@_Quasar_, в вычислении millis() - timer_1
тоже происходит переполнение.
И оно беззнаковое.
Поэтому значение нормализуется.
 

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
@Сотнег,
timer_1 присвоено значение 4,294,967,000 из возможных 4,294,967,295 то милес обновился и начал набирать с 0 а условие продолжает сравнивать разность с присвоенным значением 4,294,967,000 ...
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,272
1,303
Москва
Я вроде уже это где то разжевывал.
Для примера возьму uint16_t=(0..65535) и интервал 1000
при timer_1 2000 ждем когда будет
millis()-timer_1 >1000 , т.е.3001-2000>1000 - подходит!

при timer_1 65000 все интереснее. Подходить должно 66001, но т.к. это больше максимума, то миллис выдаст 466
Проверяем 466-65000= вроде как получается отрицательное число -64534, но т.к. отрицательных чисел для данного типа нет. то оно будет 1001 , что опять же выдаст нужный результат.
 
  • Лойс +1
Реакции: Tiolaris

bort707

★★★★★★✩
21 Сен 2020
3,067
915
timer_1 присвоено значение 4,294,967,000 из возможных 4,294,967,295 то милес обновился и начал набирать с 0 а условие продолжает сравнивать разность с присвоенным значением 4,294,967,000 ...
вы исходите из того, что результат выражения (0 - 4,294,967,000) - это большое отрицательное число, правильно?
Но ведь вычисления-то ведутся в беззнаковых числах! И никаких отрицательных результатов быть не может.

Хороший пример счетчика с переполнением - время на часах.
Часы изменяются от 0..1..2..3....22..23..0..1...2..
Чтобы отмерить интервал в 2 часа, вы вычитаете из 15 часов 13. = получается 2
И между 22 и 20 часами - тоже 2 часа
В полночь наступает "переполнение".
Но между 01 часом ночи и предыдущими 23 часам - опять два часа, а вовсе не -22!
Точно так же и тут. Между значением миллис() =0 и 0xFFFFFFFF- ровно 1 миллисекунда, а не огромное отрицательное число!

Я вам выше написал - не верите, проверьте.
Запишите такой кусок в скетч, прошейте в ардуину и посмотрите результат
C++:
uint32_t t1 = 0xffffffff;
uint32_t t2 =0;
uint32_t t3 = t2 -t1;
Serial.println(t3);
 
  • Лойс +1
Реакции: _Quasar_

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
52
0
при timer_1 65000 все интереснее. Подходить должно 66001, но т.к. это больше максимума, то миллис выдаст 466
Проверяем 466-65000= вроде как получается отрицательное число -64534, но т.к. отрицательных чисел для данного типа нет. то оно будет 1001 , что опять же выдаст нужный результат.
1 момент не понятен... Перезапись значения timer_1 происходит только после выполнения условия равного значению разности больше 5000... Если в одной из итерации присвоено значение timer_1 = 65000 то дальше милес обновляется так как досчитывает придел uint16_t ... А дальше как???
 

bort707

★★★★★★✩
21 Сен 2020
3,067
915
@bort707, Вот теперь более менее понятно стало СПАСИБО
ну раз понятно, то теперь я вам добавлю тумана
имейте в виду, что это чудесное правило работает только через вычитание
то есть вот это вот - правильно:
C++:
if (millis() - prev_timer > 5000) {    // верное условие таймера
а вот так РАБОТАТЬ НЕ БУДЕТ!
C++:
if (millis() > prev_timer + 5000) {    // НЕПРАВИЛЬНОЕ условие таймера
 
  • Лойс +1
Реакции: _Quasar_

Сотнег

★★★★★★★
15 Янв 2020
4,446
1,520
Лучше сказать, что будет работать, пока в какой-то момент не заглючит (не зависнет) на значениях prev_timer+5000 близких к максимально возможным.
 
  • Лойс +1
Реакции: _Quasar_

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@_Quasar_, года 2-3 назад я так же тупил, точно с таки же вопросом правда немного в другом форуме, думаю выше все всё уже сказали! В этом форуме люди явно добрее! Удачи в изучении Ардуино!