How implement serial delay
-
I have a send function and now I need a delay of 2 ms after I send a byte. If I send quicker than these 2 ms the receiving end will miss the data.
void MainWindow::send(QString c) { serial->write(c.toLatin1()); QString cAsHex = QString("%1").arg(c, 0, 16); qDebug() << cAsHex << " >>"; }
I was wondering what the most efficient way would be to do this. I don't know whether I can use some fancy serial function of which I don't know about yet or if I should pause the entire application using a QThread delay.
It is not big deal if the program freezes temporarily.
-
This
void MainWindow::send(QString c) { QTimer::singleShot(2, this, SLOT(timeOut())); timer = true; serial->write(c.toLatin1()); QString cAsHex = QString("%1").arg(c, 0, 16); qDebug() << cAsHex << " >>"; while (timer == true) {;} } void MainWindow::timeOut() { timer = false; }
is not working. The idea is that timeOut gets called 2ms after a byte has been send so the program can escape the while loop.
Why is this not working??
EDIT:
does not matter I used a different approach with a timer object and ->start(2) and -> stop() functions. This works ;) -
And what ever you do, please dont use QThread delay. :)
-
@jsulm said in How implement serial delay:
@bask185 Just use QTimer
Thank you. I will try it out ;)
@mrjj said in How implement serial delay:
And what ever you do, please dont use QThread delay. :)
You cannot say something like that if you don't provide the 'why' argument with it. This is just like saying: "never use global variables" or "always use 'private' and 'public'".
If I say: "jump in the ditch", how likely will it be that you will actually do it? But if I say: "Jump in the ditch, because there is a person drowning in it" than it is more likely that you will actually jump in the ditch. I said in the OP that it would not be a big deal if my program would freeze temporarily during a data transfer so I am not even remotely getting why I should not use a QThread delay??? If my push buttons would be disabled, it would actually be better because no user can accidently send a 'false' byte.
-
This
void MainWindow::send(QString c) { QTimer::singleShot(2, this, SLOT(timeOut())); timer = true; serial->write(c.toLatin1()); QString cAsHex = QString("%1").arg(c, 0, 16); qDebug() << cAsHex << " >>"; while (timer == true) {;} } void MainWindow::timeOut() { timer = false; }
is not working. The idea is that timeOut gets called 2ms after a byte has been send so the program can escape the while loop.
Why is this not working??
EDIT:
does not matter I used a different approach with a timer object and ->start(2) and -> stop() functions. This works ;) -
Fair enough, please don't use QThread delay for any kind of pausing in a main thread as it also strangulate the
event/signal processing and can lead to all sort of odd behaviors. Its simply a wrong solution to the requirements.Your buttons are not really disabled, they simply not getting the click event ( or some might) so using
delay is just bad design in 99% of all cases in regards to the main thread.
To disable, there is a function for just that. -
@bask185 Well, this just cannot work as your while loop blocks the event loop which breaks signals/slots.
Why did you put the loop there?void MainWindow::send(QString c) { QTimer::singleShot(2, this, SLOT(timeOut())); serial->write(c.toLatin1()); QString cAsHex = QString("%1").arg(c, 0, 16); qDebug() << cAsHex << " >>"; } void MainWindow::timeOut() { // Here send the rest of the data }
-
I would suggest something like this:
//Member variables: QTimer *timer; QList<QString> dataToSend; /*Timer event*/ timer = new QTimer(this); connect(timer, &QTimer::timeout, timer, [=]{ if(dataToSend.size() > 0){ send(dataToSend.first()); dataToSend.removeFirst(); } if(dataToSend.isEmpty()) timer->stop(); }); /*Start send*/ ... dataToSend.append(newData); if(!timer->isRunning()) timer->start(2);
-
I now use:
void MainWindow::send(QString c) { timer->start(2); serial->write(c.toLatin1()); QString cAsHex = QString("%1").arg(c, 0, 16); qDebug() << cAsHex << " >>"; while (Timer == true) {;} } void MainWindow::timeOut() { Timer = false; timer->stop(); }
and it works like a charm