QTimer not accurate?



  • I am building a real time application that shows a graph in real time.

    The graph shows a workout that will last for X minutes.
    When X minutes are done, the workout is completed.

    So let say I launch a 5min workout.
    I start a timer so that after 5min the workout automatically stop
    Using this :
    connect(timer_workoutEnded, SIGNAL(timeout()), this, SLOT(workoutFinished()));

    The timer is properly initialized with :
    timer_workoutEnded->start(this->workout->getTotalLength() 601000);
    TotalLength is the length of the workouts in minutes so I have to convert in ms.
    I have tried printing a few variable and I haven't figured why the timer stop before 5min.

    Here is a screenshot of it :
    https://www.dropbox.com/s/06rxql98dh09pk4/workout.png

    Thanks!


    Log:
    "TOTAL LENGTH WORKOUT : 5"
    "TOTAL LENGTH WORKOUT SEC : 300000"

    "04:55"
    STOPPING WORKOUT // Should stop at 5:00!


  • Moderators

    Hi,

    How does your application determine that 4:55 has passed? The recommended way to measure is to use QElapsedTimer.

    It looks like you're using different timers to measure workout duration and to signal the end of a workout. Did you start both timers at the same time?

    As for generating timeout events, the QTimer has "3 levels of precision":http://qt-project.org/doc/qt-5.1/qtcore/qt.html#TimerType-enum which you can set by calling QTimer::setTimerType() before you call QTimer::start(). All 3 types are precise enough for your app.

    • Qt::PreciseTimer: About 1 ms resolution on Windows
    • Qt::CoarseTimer (default): About 15 ms resolution on Windows
    • Qt::VeryCoarseTimer: 1000 ms resolution on all platforms

    Also, timer accuracy is affected by the busy the thread is. However, a heavily-loaded thread should only cause timer delays, not early timeouts.



  • Hi

    [quote author="JKSH" date="1380159000"]Hi,
    As for generating timeout events, the QTimer has "3 levels of precision":http://qt-project.org/doc/qt-5.1/qtcore/qt.html#TimerType-enum which you can set by calling QTimer::setTimerType() before you call QTimer::start().[/quote]
    Just a note, this is Qt 5... (I have the same problem in 4.8 and can's switch yet)

    From my experience if you want real time or semi real time, Widows (OS) is not the best option, rather use Linux or a real time OS.



  • I don't believe the timer or the timer level of precision are to blame. If you want 5 minutes you will get 5 minutes (plus/minus a couple of msec).
    It's absolutely better to utilize the QElapsedTimer class to do this for protection against timer changes (system clock etc) by the user.
    However the QElapsedTimer does not have signals, so you need to implement your timerEvent and check it there to emit the required signal.
    You already have a timer, so overwriting the timerEvent might not be a bad thing. (I always overwrite the timerEvent when I use more the 1 timer in a class).



  • [quote author="JKSH" date="1380159000"]Hi,
    How does your application determine that 4:55 has passed? The recommended way to measure is to use QElapsedTimer.
    [/quote]

    Thanks for your insight.
    I'm using 3 different QTimer on this window.
    -1 for updating the time shown (1sec timeout that call a method)
    -1 for updating the graph curves (each 5sec)
    -1 for ending the workout.

    For showing the time, the method I use is probably not right.
    I initialize a "QTime(0,0,0,0)" and every 1sec my QTimer increase QTime by 1sec
    I'll have a look at QElapsedTimer and report back
    Thank you


  • Moderators

    You're welcome :)

    [quote author="maximus" date="1380195467"]
    For showing the time, the method I use is probably not right.
    I initialize a "QTime(0,0,0,0)" and every 1sec my QTimer increase QTime by 1sec[/quote]That method causes errors to keep growing over time. The QTimer isn't going to fire exactly every 1000 ms, especially if you're using a coarse timer.

    If every time your QTimer fires it's off by 15 ms, then after 5 minutes (300 seconds) you could have an accumulated error of 300*15 ms = 4500 ms



  • [quote author="JKSH" date="1380196428"]You're welcome :)
    That method causes errors to keep growing over time. The QTimer isn't going to fire exactly every 1000 ms, especially if you're using a coarse timer.

    If every time your QTimer fires it's off by 15 ms, then after 5 minutes (300 seconds) you could have an accumulated error of 300*15 ms = 4500 ms[/quote]

    Yes you were right, I tried with "Qt::PreciseTimer" and it stop right on 5min, so that must be the problem (this machine is on Windows)
    However I can't use this method as I want this application multiplatform and free. I'll see if QElapsedTimer can do the same work



  • It seem QElapsedTimer will not be suitable in my use-case, because the timer sometime needs to be stopped (pause the workout)
    So I guess I'll have to use QTimer.
    Is there a reliable timer for Mac/Linux, like Qt::PreciseTimer is for Windows?
    I could check the OS and set the timerType accordingly.

    Anyone know if I would have this problem with Java and Timer? I'm not 100% sure i'll use QT over Java.
    Thank you.


  • Moderators

    [quote author="maximus" date="1380203827"]It seem QElapsedTimer will not be suitable in my use-case, because the timer sometime needs to be stopped (pause the workout)[/quote]You can record the elapsed time when the user stops the timer. Then, when the user starts the timer again, add the previous record to to the new timer's values.

    [quote]Is there a reliable timer for Mac/Linux, like Qt::PreciseTimer is for Windows?
    I could check the OS and set the timerType accordingly.[/quote]Qt is cross-platform. Qt::PreciseTimer exists on all supported platforms, including Mac and Linux.

    I only mentioned Windows because I tested the timers on Windows. But, it's often said Qt;:CoarseTimer is more accurate on Linux than on Windows.

    [quote]Anyone know if I would have this problem with Java and Timer? I'm not 100% sure i'll use QT over Java. [/quote]I don't use Java, so I don't know the answer to that. But, like Qt, it probably depends on the OS and hardware.

    What are your plans for you application?



  • [quote author="JKSH" date="1380205541"]You can record the elapsed time when the user stops the timer. Then, when the user starts the timer again, add the previous record to to the new timer's values.[/quote]

    Good idea!

    [quote]I don't use Java, so I don't know the answer to that. But, like Qt, it probably depends on the OS and hardware.[/quote]

    I was asking because I think Timer in Java will use the appropriate timer depending on your OS.

    [quote]What are your plans for you application?[/quote]

    Why I chose QT: Ease of developing interface, cross-platform and faster execution than Java, Con: i'm kind of new to C++
    As for Java I just have more experience, and the deployment is easier

    I want to develop something similar to :
    http://www.trainerroad.com/
    but cross-platform and no fee

    Thanks for your time :)



  • Just an update,
    since the timer was not precise enough in Windows only,
    I added the specific code and it fix the problem :

    #ifdef WIN32
    timer_1sec->setTimerType(Qt::PreciseTimer);
    #endif

    On other platform the standard timer type seem accurate enough for my need.
    Thanks everyone


  • Moderators

    [quote]I was asking because I think Timer in Java will use the appropriate timer depending on your OS.[/quote]What's "appropriate" depends on your use case too -- the programming framework doesn't know your plans so it can't make decisions for you.

    High-precision timers have more overhead. You probably won't notice the overhead in you app, but generally it's good practice to use the cheapest option available that meets your requirements. No point using something expensive that you don't need.

    [quote]since the timer was not precise enough in Windows only,
    I added the specific code and it fix the problem :
    #ifdef WIN32 timer_1sec->setTimerType(Qt::PreciseTimer);
    #endif
    On other platform the standard timer type seem accurate enough for my need.[/quote]Another way to reduce risk of your app stopping at "4:99" or "5:01": Instead of using a separate timer to signal the end of the workout, just add another check after you measure your elapsed time: If elapsed time >= 300000 (or if your clock says "5:00"), then stop the session.

    [quote]Why I chose QT: Ease of developing interface, cross-platform and faster execution than Java, Con: i'm kind of new to C++
    As for Java I just have more experience, and the deployment is easier

    I want to develop something similar to :
    http://www.trainerroad.com/
    but cross-platform and no fee
    [/quote]A very good cause. All the best!

    If you plan to make more apps in the future (and especially if you plan to target different mobile platforms), it's definitely worth investing time in Qt :) Here's an overview of all features in Qt, which is a lot more than GUI development: http://doc-snapshot.qt-project.org/qt5-stable/qtmodules.html



  • [quote]Another way to reduce risk of your app stopping at "4:99" or "5:01": Instead of using a separate timer to signal the end of the workout, just add another check after you measure your elapsed time: If elapsed time >= 300000 (or if your clock says "5:00"), then stop the session.
    [/quote]

    Yes now I only use one timer and assume it's right, all actions come from it, safer this way.

    [quote]
    A very good cause. All the best!

    If you plan to make more apps in the future (and especially if you plan to target different mobile platforms), it's definitely worth investing time in Qt :) Here's an overview of all features in Qt, which is a lot more than GUI development: http://doc-snapshot.qt-project.org/qt5-stable/qtmodules.html[/quote]

    Thanks for you support! the community seems really nice and great support with tutorials, etc.
    I guess the hard part for me will be to compile a version of my app for all platform. I would like to support Mac/Linux/Windows, for android and IOs, is it possible also? I use the latest qt5.1 with a qwt plugin. right now I just use qtcreator in ubuntu and it compiles and works fine. Is it possible to do a setup so I can build/compile/deploy all OS version on a single machine? I'll go read more on this sorry for the newbie questions.

    Have a great night,
    Max


  • Moderators

    [quote author="maximus" date="1380241996"]
    Thanks for you support! the community seems really nice and great support with tutorials, etc.[/quote]You're most welcome. :) Yes, I've learnt lots from this community too. If you have any more questions, just start a new post.

    [quote]I guess the hard part for me will be to compile a version of my app for all platform. I would like to support Mac/Linux/Windows, for android and IOs, is it possible also? I use the latest qt5.1 with a qwt plugin. right now I just use qtcreator in ubuntu and it compiles and works fine. Is it possible to do a setup so I can build/compile/deploy all OS version on a single machine? I'll go read more on this sorry for the newbie questions.[/quote]Using one platform to build programs for a different platform is called "cross-compiling", and Qt Creator has some built-in support for that.

    Android and iOS support is in "Technology Preview" mode at the moment. Full support will come in November when Qt 5.2 is released.

    On your development PC, you'll need compiled Qt libraries for each platform that you're targetting.

    MinGW is a very solid toolchain for producing Windows executables; you can use this to create a Windows .exe from Ubuntu. It seems harder to target Mac though; I found this but it doesn't sound very robust: http://stackoverflow.com/questions/2786240/how-to-compile-intel-mac-binaries-on-linux

    But anyway, this is a different topic now. It's best to start a new post if you have more questions about cross-compiling.

    Again, good luck.



  • Just to keep you guys updated, I found a good solution with QwtSystemClock (use QElapsedTimer internally).

    I used the method similar to the example oscilloscope in qwt/example
    Variable used:

    @ int d_timerId;
    QwtSystemClock d_clock;
    int lastSecond;
    double timeElapsed_sec;
    double timePaused_sec;
    double resumeActivated_time_sec;
    double pauseActivated_time_sec;@

    code :

    @void WorkoutDialog::startWorkout() {

    d_clock.start();
    d_timerId = startTimer( 1 );  //check ElapsedTime every 1ms! Is there a better way to monitor Elapsed time? can Elapsedtime trigger an event every 1sec without the need to monitor it with a non-reliable timer??
    

    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// timerEvent
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void WorkoutDialog::timerEvent( QTimerEvent *event ) {

    if ( event->timerId() == d_timerId && !isWorkoutPaused ) {
    
        timeElapsed_sec = d_clock.elapsed() / 1000.0 - timePaused_sec;
    

    // qDebug() << "time Elapsed:" << d_clock.elapsed() / 1000.0;
    // qDebug() << "Total time paused:" << timePaused_sec;
    // qDebug() << "Resulting true Elapsed time" << timeElapsed_sec;
    // qDebug() << "----------------------------";

        int currentSecond = ((int)timeElapsed_sec) % 10;
        //        qDebug() << "currentSecond : " << currentSecond;
    
        // 1 sec has passed
        if (currentSecond != lastSecond) {
            update1sec();
        }
        lastSecond = currentSecond;
    }
    

    }@

    I just did a test and on a 4hours workout, I lost 2 seconds in precision, pretty good.
    The lost come from :
    int currentSecond = ((int)timeElapsed_sec) % 10;
    that removes over time a fraction on a second
    Maybe I could improve it even more by calculating an acceptable interval instead of casting?
    Like :
    if (timeElapsed_sec - ((int) timeElapsed_sec) < 0,001)
    so close it counts as a second...

    Let me know if you have ideas
    Thanks!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.