Results 1 to 6 of 6

Thread: QTimer not working in new project

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default QTimer not working in new project

    I'm having trouble getting QTimer to work in a console (no GUI) application.

    When I start the timer, it goes active, but never times out.

    When I tried using the static QTimer::singleShot method, I get a runtime error:

    QObject::startTimer: QTimer can only be used with threads started with QThread
    I've tried explicitly using Qt::QueuedConnection for the connection to the slot that tries to start the timer, but that makes no difference (and I think that's the default anyway).

    Maybe the signal that's connected to the slot that starts the timer is on a different thread than what instantiated the QObject. The signal is emitted from an interrupt handler registered by the wiringPiISR() function provided by the wiringPi package.

    Here's the code:

    powerControl.h
    Qt Code:
    1. #ifndef POWERCONTROL_H
    2. #define POWERCONTROL_H
    3. #define GPIO3 5
    4. #include <QObject>
    5. #include <QTimer>
    6. #include <QDebug>
    7.  
    8. class PowerControl : public QObject
    9. {
    10.  
    11. Q_OBJECT
    12. public:
    13. explicit PowerControl(QObject *parent = 0);
    14.  
    15. static PowerControl *getInstance() {return instance;}
    16.  
    17. static void handleEdgeBoth(void);
    18.  
    19. virtual void handleIrq(bool afterEdgeState);
    20. ~PowerControl();
    21.  
    22. private:
    23. static PowerControl *instance;
    24. QTimer debounceTimer;
    25. QTimer tapTimer;
    26. QTimer powerOffTimer;
    27. static unsigned long lastTime;
    28.  
    29. signals:
    30. void fallingEdge(void);
    31. void risingEdge(void);
    32. void buttonPushed(void);
    33. void tapDetected(void);
    34. void longPressDetected();
    35.  
    36. public slots:
    37. private slots:
    38. void edgeDetected(bool);
    39. void bounceFinished(void) {qDebug() << "Bounce timeout";}
    40. void tapTimeout(void) {qDebug() << "tap timeout";}
    41.  
    42.  
    43. #define DEBOUNCE_TIME 10
    44. };
    45.  
    46. #endif // POWERCONTROL_H
    To copy to clipboard, switch view to plain text mode 

    powerControl.cpp
    Qt Code:
    1. #include "powercontrol.h"
    2. #include "wiringPi.h"
    3. #include <QDebug>
    4.  
    5. PowerControl *PowerControl::instance;
    6. unsigned long PowerControl::lastTime = 0;
    7.  
    8. PowerControl::PowerControl(QObject *parent) : QObject(parent)
    9. {
    10. debounceTimer.setSingleShot(true);
    11. debounceTimer.setInterval(DEBOUNCE_TIME);
    12. tapTimer.setSingleShot(true);
    13. tapTimer.setInterval(1000);
    14. powerOffTimer.setSingleShot(true);
    15.  
    16. wiringPiISR(3,INT_EDGE_BOTH,handleEdgeBoth);
    17. //wiringPiISR(3,INT_EDGE_RISING,handleEdgeRisingInterrupt);
    18.  
    19. connect(&tapTimer,SIGNAL(timeout()),this,SLOT(tapTimeout(void)),Qt::QueuedConnection);
    20. instance=this;
    21. }
    22. void PowerControl::handleEdgeBoth()
    23. {
    24. PowerControl *pc = getInstance();
    25. unsigned long now = millis();
    26. unsigned long elapsedTime = now - lastTime;
    27. lastTime = now;
    28.  
    29.  
    30. qDebug() << "Elapsed time =" << elapsedTime;
    31.  
    32. if (elapsedTime < DEBOUNCE_TIME)
    33. {
    34.  
    35. qDebug() << "key bounce detected\n";
    36. return;
    37. }
    38. else
    39. emit pc->edgeDetected(digitalRead(3));
    40.  
    41.  
    42.  
    43. }
    44. void PowerControl::handleIrq(bool afterEdgeState)
    45. {
    46. if (afterEdgeState)
    47. qDebug() << "Rising Edge Detected";
    48. else
    49. qDebug() << "Falling Edge Detected";
    50. }
    51. void PowerControl::edgeDetected(bool edge)
    52. {
    53. if (edge)
    54. {
    55. qDebug() << "Rising Edge Detected";
    56. tapTimer.stop();
    57. }
    58. else
    59. {
    60. QTimer::singleShot(1000, this, SLOT(tapTimeout(void)));
    61.  
    62. tapTimer.start();
    63. qDebug() << "Falling Edge Detected, timer isActive = " << tapTimer.isActive();
    64. }
    65. }
    66.  
    67. PowerControl::~PowerControl()
    68. {
    69.  
    70. }
    To copy to clipboard, switch view to plain text mode 

    Hardware is Rpi Zero W, Qt 4.8 running on Stretch Lite

    Thanks!

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QTimer not working in new project

    First comment - if you want PowerControl to be a Singleton, you need to make the constructor and destructor private. Otherwise, anyone can create a new, separate instance of PowerControl simply by using operator new(). And anyone could delete your "instance" simply by calling operator delete() on it, leaving you with a dangling pointer to a deleted object.

    You haven't shown how you are using this class, but my hunch is that you are starting the timer before you have an event loop running (that is, before QApplication::exec() has been called in main()).
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTimer not working in new project

    Thanks for the reply!

    Yes, you are correct about the Singleton. It's ok to be a bit "sloppy" on this project , since it's so simple and I'm the only one who's ever going to work on it. That's my "excuse", but still, there's no reason not to do as you suggest!

    No, the timer doesn't get started before exec is called. It gets started in the "edgeDetected" slot, which gets called as a result of an signal being emitted in the interrupt handler. And, the handler only gets called when I push a hardware button.

    Here's the main.c (and that's ALL the code):

    #include <QCoreApplication>


    #include "powercontrol.h"
    #include "ledcontrol.h"
    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    //QApplication a(argc, argv);

    a.setOrganizationName("Flying Nerd");
    a.setApplicationName("Ipad2GMA");

    wiringPiSetupSys();
    PowerControl pc;
    //LedControl *lc = new LedControl(1000,1000,2,true);


    return a.exec();
    }

  4. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QTimer not working in new project

    If the interrupt fires (expected or unexpected) between line 16 and 19 while your constructor is executing then you can be starting the timer before the event loop is running. At that time, instance will be uninitialized to boot.

    Exactly what debugging output, if any, do you see?

Similar Threads

  1. I am working on a POS project
    By foxrider in forum Newbie
    Replies: 12
    Last Post: 21st April 2014, 14:48
  2. Replies: 7
    Last Post: 24th September 2012, 07:17
  3. Qtimer is not working....
    By k.qasempour in forum Newbie
    Replies: 3
    Last Post: 21st June 2012, 08:16
  4. QTimer - Why this is not working?
    By prasenjit in forum Newbie
    Replies: 2
    Last Post: 17th December 2009, 16:37

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.