Qt: QTimer create an unwanted loop

77 views Asked by At

I'm reading and plotting data from a serial port using Qt. I'm trying to create a timeout with the QTimer class, who sends in the function "lettura()". It works one time and after creating a loop inside that, is there some way to get out from that loop? I'm a beginner and I don't know how to use thread and qtimer.

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QSerialPort>
#include<QtDebug>
#include<QTimer>
#include <thread>
#include<QSharedPointer>
#include"qcustomplot.h"
QSerialPort *serial;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    //Timer start
      timer.start();
    //Set up form
      ui->setupUi(this);
    //Set up poerta seriale
      serial= new QSerialPort(this);
      serial->setPortName("COM3");
      serial->setBaudRate(QSerialPort::Baud115200);
      serial->setDataBits(QSerialPort::Data8);
      serial->setParity(QSerialPort::NoParity);
      serial->setStopBits(QSerialPort::OneStop);
      serial->setFlowControl(QSerialPort::NoFlowControl);
      serial->open(QIODevice::ReadOnly);
    //Set up grafici
    //Set up del grafico dell'umidità
      ui->plotH->addGraph();
      ui->plotH->graph(0)->setScatterStyle((QCPScatterStyle::ssCircle));
      ui->plotH->graph(0)->setLineStyle(QCPGraph::lsLine);
      ui->plotH->xAxis->setRange(0,8);
      ui->plotH->yAxis->setRange(0,100);
      ui->plotH->xAxis->setLabel("t[h]");
      ui->plotH->yAxis->setLabel("H[RH%]");
   //Set up del grafico della temperatura
      ui->plotT->addGraph();
      ui->plotT->graph(0)->setScatterStyle((QCPScatterStyle::ssCircle));
      ui->plotT->graph(0)->setLineStyle(QCPGraph::lsLine);
      ui->plotT->xAxis->setRange(0,8);
      ui->plotT->yAxis->setRange(-20,50);
      ui->plotT->xAxis->setLabel("t[h]");
      ui->plotT->yAxis->setLabel("T[°C]");
   //Connessione con la funzione principale

   connect(serial, &QSerialPort::readyRead, this, &MainWindow::Reader);


}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::Reader()
{

    QTimer *timer3 = new QTimer(this);
     connect(timer3, &QTimer::timeout, this, QOverload<>::of(&MainWindow::lettura));
     timer3->start(10000);

}



void MainWindow::PLOTTER_H()
{
    ui->plotH->graph(0)->setData(vec_t, vec_H);
    ui->plotH->replot();
    ui->plotH->update();
}

void MainWindow::PLOTTER_T()
{
    ui->plotT->graph(0)->setData(vec_t, vec_T);
    ui->plotT->replot();
    ui->plotT->update();
}

void MainWindow::addPoints(double HUM, double TEMP,double t)
{
    vec_t.append(t);
    vec_H.append(HUM);
    vec_T.append(TEMP);
}



void MainWindow::Clear()
{
vec_t.clear();
vec_T.clear();
vec_H.clear();
}

void MainWindow::on_Clear_clicked()
{
Clear();
PLOTTER_H();
PLOTTER_T();
}

void MainWindow::lettura()
{

    //Letura dei dati
    serial->waitForReadyRead();
    m_readData=serial->QSerialPort::readAll();
    //Sgrossatura dei dati
       inter=QString(m_readData);
      QStringList firstlist2= inter.split("$");
      m_readData2=firstlist2.takeFirst();
      inter2=QString(m_readData2);
      QStringList firstlist3= inter2.split(" ");
      m_readData3=firstlist3.takeFirst();
      H=m_readData3.toDouble();
      QStringList firstlist4=inter2.split(" ");
      m_readData4=firstlist4.takeLast();
      T=m_readData4.toDouble();
      //Ottenere dal timer la variabile tempo
         milli=timer.elapsed();
        double sec=milli/1000;
        min=sec/60;
        double ore=min/60;

        //Creazione dei punti
          addPoints(H,T,min);
          //Aggiunta dei punti ai grafici
            PLOTTER_H();
            PLOTTER_T();
       
            //Programma in stand-by per 5 minuti
          //Sleep(10000);
             // QThread::sleep(10);           //300
 
    }
1

There are 1 answers

0
Nick M. On

First issue is:

void MainWindow::Reader()
{
    QTimer *timer3 = new QTimer(this); <--- The timer is created here
    connect(timer3, &QTimer::timeout, this, QOverload<>::of(&MainWindow::lettura));
    timer3->start(10000);
} <-- and destroyed here.

You need to create the timer3 pointer as a member variable new it in the constructor setup the connect in the constructor, set it to singleshot most likely if you are going to use it this way. and then just call timer3->start(10000)

The other issue is what is

timer.start();

Do you already have a timer? If you do us it instead of the timer3 one

There are other issues with starting the timer on the ReadyRead call from a serial port since it will trigger every time a byte is ready and the timer->start() call will reset the timer each time. But that is a threading question.