PDA

View Full Version : Qtimer accuracy



bollibompa
12th April 2011, 09:15
Hi
My app is controlling two pumps via RS-232 (qextserialport). The pumps should be updated with a new rate every second. It works fine but when I compare the elapsed time in my qt-app with an accurate stop-watch it differs approximately 1 second per minute. The Qtimer seems to be slower than the stop-watch.

It is even worse (slower) when I controll two pumps from the same app so I need to controll each pump from one software each. Having two apps open is not a big problem the biggest problem is that the pumps are running for about 24-48 hours before stop and adding all differences in Qtimer means that after 24 hours the app has only pumped for about 23.5 hours whilst the timer says 24 h. Are there any Qtimer with more accuracy or depends this problem on the machine (HP-Laptop quite new)

Thanksfor any help!
Thomas

JohannesMunk
12th April 2011, 09:58
Hello Thomas!

It could be related to system timer resolution, which is only set to a high setting, when you use intervals below 20ms. Try this:



YourClass::YourClass(..)
{
QTimer* timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(doSometh ing());
timer->start(10);
}

void YourClass::doSomething()
{
static int counter = 1;
if (counter == 100)
{
// do your stuff here..

counter = 1;
} else {
++counter;
}
}


HIH

Johannes

MarekR22
12th April 2011, 10:04
Probably your problem is caused by noneffective code. Remember that timer event is processed only when event loop is reached, so your code must often return control to event loop. From time event to time event you can have small inaccuracies caused by this and they can accumulate to bigger differences.
If you need long term accuracy I wouldn't depend on QTimer only. Maybe you should try to use QTime::elapsed or QElapsedTimer to be able to compensate that differences.

Lesiok
12th April 2011, 13:44
First : from QTimer doc : Timers will never time out earlier than the specified timeout value and they are not guaranteed to time out at the exact value specified. In many situations, they may time out late by a period of time that depends on the accuracy of the system timers.

Second : Windows is not real time OS.
You must remember this and, I think, redesign application.

P.S. How did You measure time with QTimer ?

squidge
12th April 2011, 14:21
Windows does have high resolution timers available but using them will vastly increase your CPU usage.

A better idea would be to query the system time say once a minute and recalibrate your application based on the result.

JohannesMunk
13th April 2011, 15:02
@squidge: Out of curiosity: What sort of timers are you talking about?

And how do they affect CPU usage? I have heard about this, but never saw any increase in CPU load.

Joh

squidge
13th April 2011, 19:19
Basically, the timer you are using now lets your process go to sleep and lets it wake up when its time to process messages. Your timer will be one of these messages.

If you use the high resolution timers such as QueryPerformanceCounter(), then you need to busy loop to get the best results, and so your CPU usage goes through the roof compared to the message based approach.

What you could do as a half/half solution would be use the message based timers, and then when you get a time update, figure out the time difference between two calls to QueryPerformanceCounter() and use that as the actual increment.

Note that you'll also need to use QueryPerformanceFrequency() in your application initialisation as QueryPerformanceCounter() only works in counts.

JohannesMunk
13th April 2011, 22:39
Ah. I'm quite familiar with performance counter, and especially the very inaccurate QueryPerformanceFrequency. If you call this on two computers they will probably return the same nominal frequency, but can deviate a lot in actual counts. I just wouldn't call it a timer. Thats why I asked.

Joh

squidge
14th April 2011, 00:15
Theres always multimedia timers, too, but for a lot of projects, combining message-based timers with high resolution timers is a better approach.

Have a look at CreateTimerQueueTimer()