_isTimer нежданчики

функция таймера.

В данный форум Вы можете заносить найденные Вами ошибки.При добавления ошибки пожалуйста приложите файлик error.log который находится в папке с установленной программой
Ответить
Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

_isTimer нежданчики

#1

Сообщение Sancho » 12.06.2021{, 10:34}

И вновь о функции

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

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 каркуляторе в режиме програмист, наконец.
Неужели я долбоящер? Если да, то нечего мне тут делать, наверное...
мой ник в нете и почте omelchuk890, если что. запомните на всякий. многие знают номер тлф.

Аватара пользователя
rw6cm
Полковник
Сообщения: 2283
Зарегистрирован: 06.09.2015{, 20:25}
Репутация: 334
Имя: Владимир

_isTimer нежданчики

#2

Сообщение rw6cm » 12.06.2021{, 10:42}

Нам без граблей ни как :smile390: иначе мы теряем бдительность )))
Win10-64, FLProg (portable)

ecoins
Полковник
Сообщения: 2926
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 453
Откуда: Шатура
Имя: Энвер

_isTimer нежданчики

#3

Сообщение ecoins » 12.06.2021{, 13:40}

Поднятый вопрос интересен... Пока без комментариев...
А как Вы оцениваете проблему - при переполнении возможен один пропуск события?

Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

_isTimer нежданчики

#4

Сообщение Sancho » 12.06.2021{, 14:08}

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

ecoins
Полковник
Сообщения: 2926
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 453
Откуда: Шатура
Имя: Энвер

_isTimer нежданчики

#5

Сообщение ecoins » 12.06.2021{, 20:33}

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

Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

_isTimer нежданчики

#6

Сообщение Sancho » 13.06.2021{, 10:12}

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

Отправлено спустя 1 минуту 55 секунд:
это редко для мс, но это имеет место быть!
мой ник в нете и почте omelchuk890, если что. запомните на всякий. многие знают номер тлф.

ecoins
Полковник
Сообщения: 2926
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 453
Откуда: Шатура
Имя: Энвер

_isTimer нежданчики

#7

Сообщение ecoins » 13.06.2021{, 13:02}

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

Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

_isTimer нежданчики

#8

Сообщение Sancho » 14.06.2021{, 09:30}

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

Labu559
Лейтенант
Сообщения: 359
Зарегистрирован: 25.01.2018{, 22:23}
Репутация: 95
Откуда: Bukovyna
Имя: Василий

_isTimer нежданчики

#9

Сообщение Labu559 » 28.07.2021{, 13:09}

Sancho писал(а):
14.06.2021{, 09:30}
... надеюсь, Вы уловили суть нежданчика...
...для неверующих приводил примеры, даже для ардуино скетч. попробуйте на win каркуляторе в режиме програмист, наконец...
Да, Sancho, ув. Александр уловили и шишки набили! Я минимум 2 года как ощутил и говорю об ущербности _isTimer() на millis() и micros() :) . Увидеть один раз лучше чем 100 раз услышать? Тогда
умеющий смотреть узрит:Показать
16bitOverflow_02_2.ino
Тестовый скетч 16-битной версии
(5.9 КБ) 11 скачиваний
16b_OverflowMicrosErrors.pdf
Вывод в терминал 16-битной версии
(125.87 КБ) 15 скачиваний
32bitOverflow_02_2b.ino
Тестовый скетч 32-битной версии
(5.47 КБ) 9 скачиваний
32b_OverflowMicrosErrors.pdf
Вывод в терминал 32-битной версии
(15.36 КБ) 15 скачиваний
Изучения функций проводили онлайн совмесно с ув.Sancho для , 16-, 32- битых значений и 8-бит для ресурсоограниченных ATTiny для 3-х и 2-х значений времени старта функций с основным циклом длительностью 11 мкс с отслеживанием временных интервалов в 41 мкс.

Это скетчи демонстрации отрабатывания базовой isTimer() функций в реализациях FLProg, Sancho и моей, а также логи вывода в терминал. Смотрите, сравнивайте, опровергайте, или продолжайте при каждом вызове функции суммировать и сравнивать 32-битные переменные, особенно с micros(), который почему-то не ждёт даже пока его скопируют в другую переменную и кратен 4-м и получать гарантированные сбои при каждом переполнении аппаратного таймера с разной степенью "тяжести". Всем удачи!
Последний раз редактировалось Labu559 04.08.2021{, 16:17}, всего редактировалось 3 раза.

Аватара пользователя
Sancho
Полковник
Сообщения: 4066
Зарегистрирован: 25.12.2015{, 17:32}
Репутация: 590
Откуда: Ярославль.
Имя: Александр
Контактная информация:

_isTimer нежданчики

#10

Сообщение Sancho » 28.07.2021{, 17:54}

Об использовании таймера для генерации точных промежутков времени, например часах, писал тут.
мой ник в нете и почте omelchuk890, если что. запомните на всякий. многие знают номер тлф.

Ответить

Вернуться в «Новые»