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

Timer неправильно отрабатывает по OnTimer заданный Interval

СообщениеДобавлено: 14.09.2013 02:04:08
DropSoft
Нужно 20 раз в секунду посылать в СОМ-порт набор данных
Установил на форму таймер Timer1
Enabled = true
Interval = 50
По событию OnTimer посылаю в СОМ-порт посылку, считываю текущее время DecodeTime( Now, Hour, Min, Sec, MSec );
и в Memo1 вывожу время и код посылки. Я был уверен, что среднее время между посылками будет 50 мс, с колебаниями в обе стороны около этого значения из-за многозадачности.
Однако, судя по выводимому MSec, время между посылками увеличивается в большую сторону.
Вот реальный пример временной разницы между посылками, в миллисекундах:
62 63 62 63 62 78 47 78 47 63 62 63 62 63 62 63 62 63 218 63 62 63 62
То есть среднее время 62,5 мс вместо установленных 50. Да еще один скачек на 218. Почему так, кто-нибудь может объяснить?

Re: Timer неправильно отрабатывает по OnTimer заданный Inter

СообщениеДобавлено: 14.09.2013 04:31:36
B4rr4cuda
Потому что данный таймер не держит столь малое значение (точнее официально должен держать 50, но на практике этого не бывает). В случае, если необходим высокоточный таймер, используют мультимедийный таймер, на винде по крайней мере. Либо делается обработка в потоке, с собственноручным вычислением интервалов и тд...

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

Re: Timer неправильно отрабатывает по OnTimer заданный Inter

СообщениеДобавлено: 14.09.2013 05:05:29
DropSoft
Дык я не требую строго по 50 мс между посылками, мне необходимо, чтобы ВСРЕДНЕМ было 20 посылок в секунду.
Таймер на то и таймер, что аппаратно отщелкивает заданные 50мс и посылает системное сообщение. Пусть оно обрабатывается с разной задержкой, но если я установил 50 мс, значит за секунду я должен получить 20 сообщений, за 10 секунд 200 сообщений. А у меня получается за 10 секунд только около 160 сообщений, т.е. в среднем 62,5 мс между событиями.
Как будто после прихода от системы сообщения WM_TIMER добавляется случайное время до его обработки (что понятно) и только потом начинается новый отсчет 50мс, а это случайное время в среднем 12,5мс. Бред же?
Я под Lazarus недавно начал писать, до этого микроконтроллеры программировал, что такое аппаратный таймер представляю хорошо.

Добавлено спустя 15 минут 7 секунд:
Re: Timer неправильно отрабатывает по OnTimer заданный Interval
Так, кажется я понял. У меня квант времени операционки получается около 15,625 мс. И 62,5 мс - это 4 кванта. Т.е система время Timer1 Interval отмеряет не по аппаратному таймеру, а квантами со значением, ближайшим большим к запрашиваему.
Тогда все сходится. Хотя могли бы сделать апроксимацию с учетом накопления ошибки. В общем, надо копать в сторону мультимедийного таймера. Да, у меня винда. Надо, чтоб работало на ХР,Висте и 7.

Re: Timer неправильно отрабатывает по OnTimer заданный Inter

СообщениеДобавлено: 14.09.2013 16:34:44
serg_iv
То есть среднее время 62,5 мс вместо установленных 50. Да еще один скачек на 218. Почему так, кто-нибудь может объяснить?

у вас прибавляется время, необходимое на работу с железом, посылка пакета туда обратно. Новый цикл 50 мс начинается после выхода из процедуры onTimer.
Скачок времени, это скорее всего битый пакет, система его ожидает некоторое заданное вами время.

Re: Timer неправильно отрабатывает по OnTimer заданный Inter

СообщениеДобавлено: 14.09.2013 18:09:52
mse
MSEgui has such a timer.
Windows:
Код: Выделить всё
******************* start
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m
63.0000m 47.0000m 47.0000m 47.0000m 46.0000m

------------------ stop n: 70 interval: 50.0000m

With application.beginhighrestimer() (uses mmtimer):
Код: Выделить всё
******************* start
51.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 50.0000m 50.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 50.0000m 50.0000m 49.0000m 51.0000m
50.0000m 49.0000m
------------------ stop n: 67 interval: 50.0000m

Linux:
Код: Выделить всё
******************* start
50.1220m 50.1800m 49.7930m 50.0100m 50.1960m
49.8560m 50.1420m 50.0360m 49.8410m 50.0430m
49.9340m 49.9530m 50.1320m 50.1140m 49.9560m
49.8140m 50.1800m 50.0360m 49.9690m 49.8540m
50.0170m 49.9930m 50.1300m 50.0370m 49.9680m
50.0030m 49.8780m 49.9840m 50.0730m 49.8500m
50.0340m 49.9770m 50.1960m 50.0390m 49.9680m
50.0020m 49.8170m 49.9730m 50.2290m 49.9470m
49.9020m 50.1530m 49.9780m 49.8620m 50.0020m
49.9970m 50.0100m 50.1520m 49.9720m 49.8740m
49.9730m 50.1830m 49.9740m 49.7970m 49.9970m
49.9960m 50.0560m 50.1760m 49.9780m 50.0190m
49.9790m 50.0300m 49.9700m 50.0310m 49.9780m
49.9950m 49.9950m 50.0310m 49.9730m 50.0220m
49.8640m
------------------ stop n: 71 interval: 50.0027m

Implementation is here:
http://gitorious.org/mseide-msegui/mseide-msegui/source/886f809787c4a95e3d9d63c93122cc9c848287e5:lib/common/kernel/msetimer.pas
Test application:
http://gitorious.org/mseuniverse/mseuniverse/source/7882ddd6c0c54dd9abc8a8c9b3c8fbde8559b9bd:testcase/timer/resolution