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
#ifndef POWERCONTROL_H
#define POWERCONTROL_H
#define GPIO3 5
#include <QObject>
#include <QTimer>
#include <QDebug>
class PowerControl
: public QObject{
Q_OBJECT
public:
explicit PowerControl
(QObject *parent
= 0);
static PowerControl *getInstance() {return instance;}
static void handleEdgeBoth(void);
virtual void handleIrq(bool afterEdgeState);
~PowerControl();
private:
static PowerControl *instance;
static unsigned long lastTime;
signals:
void fallingEdge(void);
void risingEdge(void);
void buttonPushed(void);
void tapDetected(void);
void longPressDetected();
public slots:
private slots:
void edgeDetected(bool);
void bounceFinished(void) {qDebug() << "Bounce timeout";}
void tapTimeout(void) {qDebug() << "tap timeout";}
#define DEBOUNCE_TIME 10
};
#endif // POWERCONTROL_H
#ifndef POWERCONTROL_H
#define POWERCONTROL_H
#define GPIO3 5
#include <QObject>
#include <QTimer>
#include <QDebug>
class PowerControl : public QObject
{
Q_OBJECT
public:
explicit PowerControl(QObject *parent = 0);
static PowerControl *getInstance() {return instance;}
static void handleEdgeBoth(void);
virtual void handleIrq(bool afterEdgeState);
~PowerControl();
private:
static PowerControl *instance;
QTimer debounceTimer;
QTimer tapTimer;
QTimer powerOffTimer;
static unsigned long lastTime;
signals:
void fallingEdge(void);
void risingEdge(void);
void buttonPushed(void);
void tapDetected(void);
void longPressDetected();
public slots:
private slots:
void edgeDetected(bool);
void bounceFinished(void) {qDebug() << "Bounce timeout";}
void tapTimeout(void) {qDebug() << "tap timeout";}
#define DEBOUNCE_TIME 10
};
#endif // POWERCONTROL_H
To copy to clipboard, switch view to plain text mode
powerControl.cpp
#include "powercontrol.h"
#include "wiringPi.h"
#include <QDebug>
PowerControl *PowerControl::instance;
unsigned long PowerControl::lastTime = 0;
{
debounceTimer.setSingleShot(true);
debounceTimer.setInterval(DEBOUNCE_TIME);
tapTimer.setSingleShot(true);
tapTimer.setInterval(1000);
powerOffTimer.setSingleShot(true);
wiringPiISR(3,INT_EDGE_BOTH,handleEdgeBoth);
//wiringPiISR(3,INT_EDGE_RISING,handleEdgeRisingInterrupt);
connect(&tapTimer,SIGNAL(timeout()),this,SLOT(tapTimeout(void)),Qt::QueuedConnection);
instance=this;
}
void PowerControl::handleEdgeBoth()
{
PowerControl *pc = getInstance();
unsigned long now = millis();
unsigned long elapsedTime = now - lastTime;
lastTime = now;
qDebug() << "Elapsed time =" << elapsedTime;
if (elapsedTime < DEBOUNCE_TIME)
{
qDebug() << "key bounce detected\n";
return;
}
else
emit pc->edgeDetected(digitalRead(3));
}
void PowerControl::handleIrq(bool afterEdgeState)
{
if (afterEdgeState)
qDebug() << "Rising Edge Detected";
else
qDebug() << "Falling Edge Detected";
}
void PowerControl::edgeDetected(bool edge)
{
if (edge)
{
qDebug() << "Rising Edge Detected";
tapTimer.stop();
}
else
{
QTimer::singleShot(1000,
this,
SLOT(tapTimeout
(void)));
tapTimer.start();
qDebug() << "Falling Edge Detected, timer isActive = " << tapTimer.isActive();
}
}
PowerControl::~PowerControl()
{
}
#include "powercontrol.h"
#include "wiringPi.h"
#include <QDebug>
PowerControl *PowerControl::instance;
unsigned long PowerControl::lastTime = 0;
PowerControl::PowerControl(QObject *parent) : QObject(parent)
{
debounceTimer.setSingleShot(true);
debounceTimer.setInterval(DEBOUNCE_TIME);
tapTimer.setSingleShot(true);
tapTimer.setInterval(1000);
powerOffTimer.setSingleShot(true);
wiringPiISR(3,INT_EDGE_BOTH,handleEdgeBoth);
//wiringPiISR(3,INT_EDGE_RISING,handleEdgeRisingInterrupt);
connect(&tapTimer,SIGNAL(timeout()),this,SLOT(tapTimeout(void)),Qt::QueuedConnection);
instance=this;
}
void PowerControl::handleEdgeBoth()
{
PowerControl *pc = getInstance();
unsigned long now = millis();
unsigned long elapsedTime = now - lastTime;
lastTime = now;
qDebug() << "Elapsed time =" << elapsedTime;
if (elapsedTime < DEBOUNCE_TIME)
{
qDebug() << "key bounce detected\n";
return;
}
else
emit pc->edgeDetected(digitalRead(3));
}
void PowerControl::handleIrq(bool afterEdgeState)
{
if (afterEdgeState)
qDebug() << "Rising Edge Detected";
else
qDebug() << "Falling Edge Detected";
}
void PowerControl::edgeDetected(bool edge)
{
if (edge)
{
qDebug() << "Rising Edge Detected";
tapTimer.stop();
}
else
{
QTimer::singleShot(1000, this, SLOT(tapTimeout(void)));
tapTimer.start();
qDebug() << "Falling Edge Detected, timer isActive = " << tapTimer.isActive();
}
}
PowerControl::~PowerControl()
{
}
To copy to clipboard, switch view to plain text mode
Hardware is Rpi Zero W, Qt 4.8 running on Stretch Lite
Thanks!
Bookmarks