timer couldn't work with wiringPiISR (QtQuick application) - c++

I have created a class Capteur_Input and one of the options in the constructor creates an interrupt using wiringPiISR
wiringPiISR(m_pin, INT_EDGE_RISING, isrInput);
my class also has an attribute m_impulsion and I am incrementing this value each time that an interruption happens.
this what my interrupt handler looks like
void Capteur_Input::isrCallback()
{
if(m_pin== Pin_vitesse)
{
increment_impulsion();
emit digital_inputChanged(m_impulsion);
}
else
emit digital_inputChanged(m_value);
}
in my main.cpp I created an instance of this class
static void isrInput_vitesse();
static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);
static void isrInput_vitesse()
{
vitesse.isrCallback();
}
every thing is working fine, the qml and C++ part.
and now I want to calculate the number of impulse detected per second. but I couldn't do it.
my class Capteur_Input also has a timer, I configured it in the constructor
m_timer =new QTimer (this);
m_timer->setTimerType(Qt::PreciseTimer);
connect (m_timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
m_timer->start(500);
and I tried to test in the SLOT onTimeout() someting but this qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse; never shows up. I don't know why maybe because wiringPiISR is a thread and has a higher priority than the timer?
can someone explain to me please, how to make a timer that calculates the exact time and make the interrupt work in the same time?
the timer is working for the other instances of this class that are just inputs no interruptions
void Capteur_Input::onTimeout()
{
qDebug()<<"time is up"<<m_pin;
if(m_pin== Pin_vitesse)
{
qDebug()<<"m_pin== Pin_vitesse";
int vitesse;
vitesse= int (calcul_vitesse/4*2.166);//*0.001/3600;
qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse;
emit vitesse_Changed(vitesse);
qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse;
}
else{
emit digital_inputChanged(readPin());
qDebug()<<"signal DIGITAL emitted m_pin"<<m_pin <<"value"<<readPin();
}
}
actually the slot onTimeout is working for these 2 instances
#define Pin_vitesse 3
#define PinFrein 0
#define PinClignotnat_G 2
Capteur_Input frein(PinFrein,PUD_UP,NO_INTERRUPT);
Capteur_Input clignotant_G(PinClignotnat_G,PUD_DOWN,NO_INTERRUPT);
and is not working for this one which is an interrupt static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);
and this what I got as an output
time is up 0
signal DIGITAL emitted 0 1
time is up 2
signal DIGITAL emitted 2 0
time is up 0
signal DIGITAL emitted 0 1
the timer is working for the other instances and it is not working for the one that is an interrupt

Static QObject instance is not supported in Qt, as stated below (QObject reentrancy section ):
In general, creating QObjects before the QApplication is not supported
and can lead to weird crashes on exit, depending on the platform. This
means static instances of QObject are also not supported. A properly
structured single or multi-threaded application should make the
QApplication be the first created, and last destroyed QObject.
If you need a callback when isr interrupt comes up, a static pointer should work:
static void isrInput_vitesse();
static Capteur_Input *vitesse = nullptr;
static void isrInput_vitesse()
{
if(!vitesse) //not initialized yet
return;
QMetaObject::invokeMethod( vitesse, "isrCallback", Qt::QueuedConnection ); //or blockingQueue if you need to handle it directly in Qt way.
}
The vitesse pointer should be initialized in main() after the initialization of QApplication instance.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//..... your main application body
vitesse = new Capteur_Input(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);
//...
}

Your timeout signal might be interfered or delayed.
You may try to specify a Qt::Connectiontype to force Qt to treat your timeout signal as soon as it is emitted.
QObject::connect(m_timer, &QTimer::timeout, this, &Capteur_Input::onTimeOut, Qt::DirectConnection);
This will deliver the timeout signal to the ontimeOut slot as soon as it is emitted.

Related

Confusing behaviour of signals and slots depending on type of connection

I have the following snippet
#include <QObject>
#include <QtConcurrent>
class Foo : public QObject {
Q_OBJECT
public:
explicit Foo(QObject *parent = nullptr) : QObject(parent) {
connect(this, &Foo::signal, this, &Foo::slot, ConnectionType);
}
void startBlockingMap() {
qDebug("startBlockingMap");
slot_counter = 0;
std::atomic_int signal_counter = 0;
QtConcurrent::blockingMap(nums, [&](auto &&num) {
++signal_counter;
emit signal();
});
qDebug("result: %d signals, %d slots", int(signal_counter), int(slot_counter));
slot_counter = 0;
}
public slots:
void slot() { ++slot_counter; }
signals:
void signal();
private:
std::atomic_int slot_counter = 0;
std::vector<int> nums{1, 2, 5, 8};
};
#include "main.moc"
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
Foo *foo = new Foo(&app);
QTimer::singleShot(10, foo, [foo, &app]() {
foo->startBlockingMap();
app.quit();
});
return app.exec();
}
It produces different results depending on what connection type is passed to connect.
When ConnectionType is Qt::DirectConnection output is
startBlockingMap
result: 4 signals, 4 slots
Which is clear.
When ConnectionType is Qt::QueuedConnection output is
startBlockingMap
result: 4 signals, 0 slots
Which is not. I thought, slots would be executed after startBlockingMap is finished, but they are not executed at all. Why? What happened?
At last, results when ConnectionType is Qt::AutoConnection are surprising. I expected they would be the same as for Qt::DirectConnection or Qt::QueuedConnection (as documentation states) but they are different:
startBlockingMap
result: 4 signals, x slots
Where x varies from 0 to 4 depending on… something. Apparently, there is some data race (?). I don't know.
Why are slots not executed with Qt::QueuedConnection?
Why output when connection type is Qt::AutoConnection differs from output when connection type is direct and when it is queued? Why is it so random?
Edit:
With help of this answer, I see that to execute slots connected via queued connection right after blockingMap, event loop should be continued explicitly via calling qApp->processEvents().
Which is not. I thought, slots would be executed after maps are finished, but they are not executed at all. Why? What happened?
The slots gets executed when the control get back to the event loop, but here the startBlockingMap function gets called from the event loop, so the slots gets executed when the startBlockingMap function returns and the control get back to the event loop.
Why output when connection type is Qt::AutoConnection differs from output when connection type is direct and when it is queued? Why is it so random?
The blockingMap function use different threads to call your lambda, sometimes a thread from a threadpool, sometimes the thread that executes the blockingMap function(here the 'main' thread). You can check that by adding the line qDebug() << this->thread() << ' ' << QThread::currentThread(); into the lambda. Now the emit slot() gets executed sometimes from a function that is not the owner of the object, so the signal gets queued, sometimes from the 'main'-thread that is the owner of the object, so the slot gets executed directly and you can see the increase in the console.

QT - Mainwindow doesn't update unless it's closed

I'm trying to update the main window by calling updateGUI function in a thread every 500 ms. The window is displayed but not updated with the new values unless I close the window. When I do so, a new window is opened with the new value. I found this question but it didn't answer my question. I knew that (as stated in qt documentation)
QApplication::exec enters the main event loop and waits until
exit() is called.
I tried to use processEvents() but the main window is opened and closed repeatedly and very fast that I can't even see it. Here is my code:
float distanceToObject;
bool objectDetected;
Modes currentMode;
void timerStart(std::function<void(void)> func, unsigned int interval)
{
std::thread([func, interval]()
{
while (true)
{
auto x = std::chrono::steady_clock::now() + std::chrono::milliseconds(interval);
func();
std::this_thread::sleep_until(x);
}
}).detach();
}
int updateGUI(void)
{
int argc = 0;
char **argv = NULL;
QApplication a(argc, argv);
MainWindow w;
// Set text of a label
w.setDistance(QString::number(distanceToObject));
// Also update objectDetected and currentMode values
w.show();
//a.processEvents();
return a.exec();
}
void sendMsg(void)
{
// Send heartbeat signal to another device
}
void receiveMsg(void)
{
// Read messages from the other device and update the variables
// These two values change continuously
objectDetected = true;
distanceToObject = 5.4;
}
void decide(void)
{
// The core function of the program. Takes relatively long time
// Run a decision-making algorithm which makes decisions based on the values received from the other device.
// Update some variables according to the made decisions
currentMode = Auto;
// Execute functions according to the made decisions.
setMode(currentMode);
}
int main(void)
{
timerStart(updateGUI, 500);
timerStart(sendMsg, 1000);
timerStart(receiveMsg, 10);
timerStart(decide, 500);
}
How can I update the main window with the variables' values correctly?
Your thread does not update the MainWindow, but it does create an entirely new QApplication and MainWindow on every iteration. Your thread should be stuck inside QApplication::exec until you quit the application (e.g. by closing the window). Only then should your thread's loop make further progress.
In general, you must be very careful when doing updates from outside the main thread, since typically GUI operations must be performed inside the main thread.
Think about using QThread, which already comes with its own event loop, which you can use to notify/update your window using a respective slot.
Without further details about what you are actually trying to achieve, it is not possible to give you further direction. I, at least, recommend that you create your QApplication and MainWindow inside the main thread (e.g. main). Then it depends what you are trying to 'update'. If you need to progress some data, then you can do that within your second thread and send the results to your MainWindow instance using signal-slot. If you need to draw onto the window, then this either has to be done in the main thread directly, or you might find a way to render into a separate buffer (i.e. QImage) from within your thread and then send this buffer to the main thread for drawing it into the window.
I try to sketch how something like this can be done. Notice, however, that this it neither complete nor compilable, but merely an outline.
First, you have your MainWindow and add to it a signal, that notifies all observers to start doing their work (will become clear in a moment). Furthermore, you add slots that will be invoked whenever one of your values changes. Those slots run in the main thread (and are members of the MainWindow) and thus can update the window however they need to:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
// constructors and stuff
void startWorking()
{
emit startWorkers();
}
public slots:
void onModeChanged(Modes m)
{
// update your window with new mode
}
void onDistanceChanged(float distance)
{
// update your window with new distance
}
signals:
void startWorkers();
};
Next, you build a Worker class, that encapsulates all the 'background work' you like to do (basically what your thread did in your original code):
class Worker : public QObject
{
Q_OBJECT
public:
// constructors and stuff
public slots:
void doWork()
{
while(!done)
{
// do stuff ...
Modes m = // change mode
emit modeModified(m);
// do stuff ...
float distance = // compute distance
emit distanceModified(distance);
// do stuff ...
}
}
signals:
void modeModified(Modes m);
void distanceModified(float distance);
};
Note, that Worker must inherit QObject and that your doWork method must be a public slot. Furthermore, you add a signal for each of the values you like your MainWindow to be informed about. No implementation for them is needed, since it is generated by the Qt MOC (Meta Object Compiler). Whenever one of the respective values changes, simply emit the corresponding signal and pass the new value.
Lastly, you put everything together:
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow window;
// create a worker object
Worker* worker = new Worker;
// connect signals and slots between worker and main window
QObject::connect(worker, &Worker::modeModified,
&window, &MainWindow::onModeChanged);
QObject::connect(worker, &Worker::distanceModified,
&window, &MainWindow::onDistanceChanged);
QObject::connect(&window, &MainWindow::startWorkers,
worker, &Worker::doWork);
// create a new thread
QThread* thread = new QThread;
// send worker to work inside this new thread
worker->moveToThread(thread);
thread->start();
// show window and start doing work
window.show();
window.startWorking();
// start main loop
int result = app.exec();
// join worker thread and perform cleanup
return result;
}
Alright, let's go through it. First, you create your QApplication and MainWindow inside your main thread. Next, create an instance of your Worker object (could create multiple here). Then you connect the signals of the worker to the slots of the window and vice versa. Once these connections are established, whenever you emit a signal, the connected slot is invoked by Qt (and passed values are transmitted). Notice, that this connection works across thread boundaries. Whenever a signal is emitted from a thread different then the receiving object's thread, Qt will send a message, which is processed in the receiving object's thread.
Then you tell Qt that you want your worker to live inside another thread using QObject::moveToThread. See here for a very detailed explanation of how to correctly use QThread and objects inside it.
The rest is then simple. show your window and start processing. Here different ways are possible. I just call the startWorking method here, which then emits the startWorkers signal, which is connect to the worker's doWork method, such that doWork will start executing after this signal is received by the other thread.
You then call QApplication::exec which runs the main thread's event loop, where all these signals are processed by Qt. Once your application is closed (e.g. by calling quit or closing the main window) the exec method returns and you are back in main. Notice, that you need to correctly close the thread (e.g. by sending an addition signal that stops the while loop) and join it. You also should delete all the allocated objects (worker, thread). I omitted this here for simplicity of the code example.
Answering your Question
I have many functions, e.g., updateClips and mavReceive that should be called periodically and run independently from each other. I should create a different Worker class for each function, as each has different signals, and a QThread object for each of these functions, right? I don't need startTimer() anymore? If yes, how can I control the calling interval for each function (used to be done in startTimer()
from the comment:
The answer greatly depends on what exactly you mean by "should be called periodically". Who is supposed to call them? The user? Or should they just be executed periodically?
So in principle, you can have multiple workers in one thread. However, if they are supposed to do work all the time (spin in a while loop) it does not make sense, since one is running and all others are blocked. In that case you would have one thread for each worker.
If I understand you correctly, you are interested in updating something periodically (e.g. every 500ms). In that case I highly recommend using the QTimer. You can set an interval and then start it. The timer will then periodically emit the timeout signal, which you can connect to whatever function (more precisely slot) you want to have executed.
An updated version of the Worker could look like this:
class Worker : public QObject
{
Q_OBJECT
public:
Worker()
{
QObject::connect(&modeTimer_, &QTimer::timeout,
this, &Worker::onModeTimerTimeout);
QObject::connect(&distanceTimer_, &QTimer::timeout,
this, &Worker::onDistanceTimerTimeout);
modeTimer_.start(500); // emit timeout() every 500ms
distanceTimer_.start(100); // emit timeout() every 100ms
}
public slots:
void onModeTimerTimeout()
{
// recompute mode
Modes m = // ...
emit modeModified(m);
}
void onDistanceTimerTimeout()
{
// recompute distance
float distance = // ...
emit distanceModified(distance);
}
signals:
void modeModified(Modes m);
void distanceModified(float distance);
private:
QTimer modeTimer_;
QTimer distanceTimer_;
};
Notice, the connections established in the constructor. Whenever one of the timers times out, the connected slot is invoked. This slot then may compute whatever it needs to and afterwards send the result back to the MainWindow in the main thread using the same signal as before.
So, as you see, you can have multiple timers / re-computations / update signals within one Worker (and thus, one thread). However, the crucial point for an implementation is, how long the computations take. If they take very long (e.g. nearly as long as the intervals) then you should think about using multiple threads to speed up the computation (meaning: perform one computation in each thread). As I slowly seem to get a clearer picture of what you want to achieve, I am wondering whether it is only about these periodic updates that you 'misused' the thread for in your question. If this is indeed the case, then you do not need that thread and Worker at all. Then simply add the timers to your MainWindow and connect their timeout signal to the respective slot of the MainWindow directly.

QEventLoop for synchronous wait for signal

I'm using Qt5, QCoreApplication.
In order to allow for readable and easy to maintain code, I need to write a blocking method in a class/thread A that will emit a signal, connected to a slot in a different thread B, and then wait for an answer or a timeout to occur asynchronously in thread B.
I have first been thinking about what felt like a natural solution: let thread B reply with a signal connected to a slot in thread A, and somehow wait for it. It seems QEventLoop can do that for me. But I keep reading contradictory statements: that's the pattern but avoid it if you can :-).
I'm pretty sure I could achieve my purpose by blocking A on a 0 QSemaphore that B would release when ready. The code would probably not be much more complex that way.
What do you experienced Qt developers think?
Is there a good solution or do you find some symptoms of flawed analysis in my description (i.e. do you think I should never ever need to do something like that? :-))?
The key ingredient you can leverage is the Qt::BlockingQueuedConnection.
This connection type lets you pass return value from a slot. You can use it in a signal-slot connection. You can also directly invoke the slot without using a signal through the QMetaMethod::invoke / QMetaObject::invokeMethod mechanism.
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
class Master : public QObject {
Q_OBJECT
public:
Q_SIGNAL bool mySignal();
Q_SLOT void process() {
if (mySignal()) { // this can be a blocking call
qDebug() << "success!";
}
thread()->quit();
}
};
class Slave : public QObject {
Q_OBJECT
public:
Q_SLOT bool mySlot() {
// do whatever processing is needed here
// It's OK to call QCoreApplication::processEvents here
return true;
}
};
int main(int argc, char** argv) {
QCoreApplication app(argc, argv);
QThread masterThread, slaveThread;
Master master;
Slave slave;
master.moveToThread(&masterThread);
slave.moveToThread(&slaveThread);
slave.connect(&master, SIGNAL(mySignal()), SLOT(mySlot()),
Qt::BlockingQueuedConnection);
masterThread.start();
slaveThread.start();
QMetaObject::invokeMethod(&master, "process");
masterThread.wait();
slaveThread.quit();
slaveThread.wait();
return 0;
}
#include "main.moc"
if you just want to emit a signal in your thread, which means your main thread will have a slot to connect you thread signal, it is simple, just emit it.
but if you want a slot in your thread, and receive signal and so something in your thread, you have to use QEventloop in you run method.
usually, I will just use QThread::wait to wait for other thread end.
be careful here, some Qt objects cannot work across the thread like QSql* and QTcpSocket....

Qt Slot not being Called

I got a program in which I connect with a QSignalMapper multiple signal from object to a slot in the main program:
class A()
{
private:
QSignalMapper * signalMapperRead_;
std::vector<Service*> services_;
public:
void initConnection()
{
signalMapperRead_ = new QSignalMapper();
connect(signalMapperRead_, SIGNAL(mapped(int)), this, SLOT(readyToSendToService(int)));
for ( size_t i = 0 ; i < services_.size() ; ++i )
{
connect(services_.at(i), SIGNAL(readyToSendToServer()), signalMapperRead_, SLOT(map()));
signalMapperRead_->setMapping(services_.at(i), (int)i);
}
}
int run()
{
initConnection();
for(;;)
{
//do stuff;
}
}
};
int main()
{
QApplication app(argc, argv);
A * a = new A();
a->run();
return app.exec
}
then, as the program is a kind of server i make him loop, and waiting for new client, ...
But the slot is never called. I am thinking that maybe it's because the program is always in the loop and never check if a signal has been emitted.
Can you please help me
Don't use your own loop, create a QApplication and call its exec() method.
You have to call QApplication::exec() for Qt to deliver signals.
Edit for changed code: Just remove the for(;;)-Loop, it's uneccessary. QApplication::exec() has its own loop.
But the slot is never called.
The Qt documentation about QApplication::exec says:
Enters the main event loop and waits until exit() is called [...].
It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. [...]
Generally, no user interaction can take place before calling exec(). [...]
This means that it's the exec method that takes care of the signal-slot system. You are calling A::run (before the exec function) which contains an for(;;) infinite loop which will block the real loop from being executed leading to your signals to be lost.
I have found a work-around. Beside I am not sure it's very efficient, my solution is to start a QEventLoop at every cycle of my for(;;) loop, and I made this QEventLoop quit on a QTimer timeout

Connect all of an objects signals to a single slot

Been looking around a bit and people seem to have a similar issue but with multiple signals from different sources etc. My situation is that I have a object that signals if it succeded, failed or got canceled. These signals are passed along to another class and are'nt connected to a slot, just a signal. Now I would like to fix so that no matter what signal the object sends (failed, succeded, canceled) a slot will be called that will delete the object. In short, I want a way of connecting every signal of an object to a slot.
Want to do something like this:
connect(myObject, allSignals, this, handleObjectDone());
void handleObjectDone() {
myObject->deleteLater();
}
Is there any way of doing this? Or should I just pass two signals everytime it does something, for example emit readyToBeDeleted() and emit succeded()?
Thanks!
Setting aside any qualms about whether connecting all the signals in one object to a single slot in another object is actually a wise thing to do, below is a function that does that, along with a unit test to verify that it works.
If you watch stdout while you run this, you will see it print out all the connections it is making. When it runs, clicking on the QLineEdit will cause the QLineEdit to emit a signal, which will (of course) cause the QApplication::quit() slot to be called, so the application will exit.
#include <stdio.h>
#include <QApplication>
#include <QLineEdit>
#include <QMetaMethod>
#include <QMetaObject>
void ConnectAllSignalsToSlot(QObject * sourceObject, QObject * targetObject, const char * slotName)
{
const QMetaObject * mo = sourceObject->metaObject();
if (mo)
{
int numMethods = mo->methodCount();
int firstMethod = mo->methodOffset(); // set to 0 instead if you want to connect signals from superclasses too
for (int i=firstMethod; i<numMethods; i++)
{
QMetaMethod mm = mo->method(i);
if (mm.methodType() == QMetaMethod::Signal)
{
QString signalString = QString("2") + mm.signature();
printf("Connecting up signal [%s] on object %p to slot [%s] on object %p\n", signalString.toUtf8().constData(), sourceObject, slotName, targetObject); // just so we can see what it's doing
QObject::connect(sourceObject, signalString.toUtf8().constData(), targetObject, slotName);
}
}
}
else printf("Error, sourceObject has no QMetaObject????\n");
}
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
QWidget * testSource = new QLineEdit;
testSource->show();
ConnectAllSignalsToSlot(testSource, &app, SLOT(quit()));
return app.exec();
}
You can connect any number of signals to any number of slots (as well as other signals). It makes perfect sense to connect the signals to two slots for this purpose. The slots are called in the order they are connected. Emitting two signals consecutively is perfectly reasonable as well. Of course readyToBeDeleted() should be emitted after succeeded() so that the object isn't deleted before emitting its result signal.
Unless I'm misunderstanding you, it's that simple.