Solved Howto get one signal per second? myTimer->start(1000); is too slow
-
Hi All,
I am trying to get one signal per second, in order to get a timebase for a measurement system. The below code works, but I see in the application output that the time drifts a bit, so I get fewer than 3600 signals per hour. What can I do about this?
Kind regards,
CedricApplication output:
QDateTime(2016-03-22 09:29:13.918 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:14.934 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:15.947 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:16.962 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:17.976 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:18.990 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:20.003 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:21.017 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 09:29:22.031 W. Europe Standard Time Qt::TimeSpec(LocalTime))Source:
#include <QTime>
QTimer *myTimer;
myTimer = new QTimer();
connect(myTimer,SIGNAL(timeout()),this,SLOT(slotNextSecond()));void MainWindow::slotNextSecond(void)
{
QDateTime now = myQDateTime->currentDateTime();
qDebug() << now;
} -
Hi All, I forgot to mention my versions:
Windows 7 Pro SP1
Qt Creator 3.6.0 Based on Qt 5.5.1 (MSVC 2013, 32 bit) Built on Dec 15 2015 01:01:38 From revision b52c2f91f5Kind regards,
Cedric -
Try setting QTimer::setTimerType to Qt::PreciseTimer.
-
Thanks KeithS, it works almost perfectly. I see now a very small drift, as far as I can tell it's still not 3600 signals per hour, it's a little less, but it's way better than it was.
Therefore my question remains: How can I get 3600 signals per hour? It's ok that there's jitter, but it's not OK to have less than 3600 signals per hour.
For future reference, below is the updated code, and application output:
Kind regards,
CedricSource:
#include <QTime>
QTimer *myTimer;
myTimer = new QTimer();
connect(myTimer,SIGNAL(timeout()),this,SLOT(slotNextSecond()));
myTimer->setTimerType(Qt::PreciseTimer);
myTimer->start(1000);void MainWindow::slotNextSecond(void)
{
QDateTime now = myQDateTime->currentDateTime();
qDebug() << now;
}Application output:
QDateTime(2016-03-22 11:45:24.771 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:25.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:26.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:27.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:28.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:29.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:30.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:31.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:32.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:33.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:34.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:35.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:36.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:37.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:38.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:39.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:40.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:41.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:42.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:43.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:44.772 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:45.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:46.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:47.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:48.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:49.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:50.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:51.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:52.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:53.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:54.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:55.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:56.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:57.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:58.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:45:59.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:00.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:01.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:02.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:03.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:04.773 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:05.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:06.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:07.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:08.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))
QDateTime(2016-03-22 11:46:09.774 W. Europe Standard Time Qt::TimeSpec(LocalTime))Kind regards,
Cedric -
QTimer, according to the docs, is only accurate to 1ms, and:
"All timer types may time out later than expected if the system is busy or unable to provide the requested accuracy. In such a case of timeout overrun, Qt will emit activated() only once, even if multiple timeouts have expired, and then will resume the original interval. "
So the level of accuracy you're seeing is within spec.
-
Any method where you add up intervals will have some kind of drift, because even very small errors start to add up eventually.
An alternative would be to measure relative to a starting point. Start a QElapsedTimer when you start your loop. In each timer event, measure your elapsed time relative to your starting time. If your timer starts to drift, you can correct your interval.
In your above example, the QElapsedTimer would notice that the interval between 11:45:34.772 and 11:45:35.773 is more than 1 second, and would reduce the interval for the next timer by one millisecond. You would still have slight jitters, but they would not add up over time. -
I have solved it. With a high preciseTimer, I get an interval that's within 1 msec acurate, with a normal timer I see about 15msec jitter.
Is the below code expensive, or are modern processors capable of doing this with ease? I am testing on a x86_64 processor, but is it cheap on an Arm cortexA9 AllwinnerA20 processor?Kind regards,
CedricCode:
#include <QTime>
QTimer *myTimer;
myTimer = new QTimer();
connect(myTimer,SIGNAL(timeout()),this,SLOT(slotNextSecond()));
myTimer->setTimerType(Qt::PreciseTimer);
myTimer->start(1000);void MainWindow::slotNextSecond(void)
{
QDateTime now = myQDateTime->currentDateTime();
qint64 delta = now.toMSecsSinceEpoch();
delta %=1000; //change into define
qint64 needed = 1000 - delta; //change into define
qDebug() << delta;
qDebug() << needed;
myTimer->setInterval(needed);
qDebug() << now;
}