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!