Страница 1 из 1

_isTimer нежданчики

Добавлено: 12 июн 2021, 10:34
Sancho
И вновь о функции

Код: Выделить всё

bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
Вновь возвращаюсь к многократно обсуждаемой теме, а именно функции таймера.
Для начала давайте отойдём от 4 байтных значений, и уменьшим до одного байта. Смысла это не меняет, от слова совсем.
Допустим, сейчас функция вернула нам значение 253, а мы вызвали таймер с параметрами 250 и 20, т.е еще 17 милс осталось.
Что происходит в нашем случае?
Ответ для : if (currentTime>= startTime) {return (currentTime>=(startTime + period));}
Подставляем: if (253>= 250) {return (253>=(250 + 20));}, а т.к. 250 + 20 = 14, 253>=14, то мы получим истину!!! хотя время ещё не прошло!!!!
Вот именно здесь и происходит злая шутка с переходом через максимум!!!!
Ну нельзя прибавлять в ситуациях, когда число не бесконечно.
Как проверяют пройденное расстояние по простому одометру ? правильно, от того, сколько сейчас,
отнять сколько было при старте. даже если перед этим были все 9, кроме последней!
Просто единицу, которая "невидима" в "старшем" разряде мы игнорируем при подведении итога!
Возьмём альтернативу, которой я всегда заменяю штатную функцию.

Код: Выделить всё

 bool _isTimer(unsigned long startTime, unsigned long period )
  {
	unsigned long currentTime = millis();
	return (period <=(currentTime - startTime));
  }
пробуем для байта: 20 <= 253 - 250 - false
далее, через некоторое время, когда прошло "переполнение"
20 <= 10 - 250 - false, т.к. 10-250= 16!!!!
для неверующих приводил примеры, даже для ардуино скетч. попробуйте на win каркуляторе в режиме програмист, наконец.
Неужели я долбоящер? Если да, то нечего мне тут делать, наверное...

_isTimer нежданчики

Добавлено: 12 июн 2021, 10:42
rw6cm
Нам без граблей ни как :smile390: иначе мы теряем бдительность )))

_isTimer нежданчики

Добавлено: 12 июн 2021, 13:40
ecoins
Поднятый вопрос интересен... Пока без комментариев...
А как Вы оцениваете проблему - при переполнении возможен один пропуск события?

_isTimer нежданчики

Добавлено: 12 июн 2021, 14:08
Sancho
ecoins писал(а): 12 июн 2021, 13:40 А как Вы оцениваете проблему - при переполнении возможен один пропуск события?
всё зависит от момента вызова.
повторяемость редкая, для мс, и не очень для мкс. при подходе к макс значениям.
данный момент легко повторить, удалив старшие три байта у millis() и создав простой проект для теста.
Это не фишка, это баг.

_isTimer нежданчики

Добавлено: 12 июн 2021, 20:33
ecoins
Уточню вопрос - при переполнении и уже прошедшего времени = period, функция может не вернуть значение равно 1?
А в следующем периоде уже вернёт 1?
То есть возможен пропуск одного события при переполнении (46 дней для ms)?

_isTimer нежданчики

Добавлено: 13 июн 2021, 10:14
Sancho
при достижении момента, когда Ваши данные, а именно сумма периода и запомненного времени превышают значение переполнения, Вы будете получать 1 при каждом вызове функции при недостижении этого времени пока значение millis не переполнится

Отправлено спустя 1 минуту 55 секунд:
это редко для мс, но это имеет место быть!

_isTimer нежданчики

Добавлено: 13 июн 2021, 13:02
ecoins
Строка unsigned long currentTime = millis() с некоторым смыслом?
Или можно проще ?
bool _isTimer(unsigned long startTime, unsigned long period ) {return (period <=(millis() - startTime));}

_isTimer нежданчики

Добавлено: 14 июн 2021, 09:30
Sancho
ecoins писал(а): 13 июн 2021, 13:02 Строка unsigned long currentTime = millis() с некоторым смыслом?
Или можно проще ?
bool _isTimer(unsigned long startTime, unsigned long period ) {return (period <=(millis() - startTime));}
Конечно можно.
Просто, как мне кажется, всё равно создаётся временная переменная под то, что возвращает функция.
А в приведённом примере именно для наглядности.
Но, надеюсь, Вы уловили суть нежданчика.

_isTimer нежданчики

Добавлено: 28 июл 2021, 13:09
Labu559
Sancho писал(а): 14 июн 2021, 09:30 ... надеюсь, Вы уловили суть нежданчика...
...для неверующих приводил примеры, даже для ардуино скетч. попробуйте на win каркуляторе в режиме програмист, наконец...
Да, [ref=#ff8000]Sancho[/ref], ув. Александр уловили и шишки набили! Я минимум 2 года как ощутил и говорю об ущербности _isTimer() на millis() и micros() :) . Увидеть один раз лучше чем 100 раз услышать? Тогда [spoiler title= умеющий смотреть узрит:]
16bitOverflow_02_2.ino
16b_OverflowMicrosErrors.pdf
32bitOverflow_02_2b.ino
32b_OverflowMicrosErrors.pdf
Изучения функций проводили онлайн совмесно с ув.Sancho для , 16-, 32- битых значений и 8-бит для ресурсоограниченных ATTiny для 3-х и 2-х значений времени старта функций с основным циклом длительностью 11 мкс с отслеживанием временных интервалов в 41 мкс. [/spoiler]
Это скетчи демонстрации отрабатывания базовой isTimer() функций в реализациях FLProg, Sancho и моей, а также логи вывода в терминал. Смотрите, сравнивайте, опровергайте, или продолжайте при каждом вызове функции суммировать и сравнивать 32-битные переменные, особенно с micros(), который почему-то не ждёт даже пока его скопируют в другую переменную и кратен 4-м и получать гарантированные сбои при каждом переполнении аппаратного таймера с разной степенью "тяжести". Всем удачи!

_isTimer нежданчики

Добавлено: 28 июл 2021, 17:54
Sancho
Об использовании таймера для генерации точных промежутков времени, например часах, писал тут.