Communicating with multiple serial port simultaneously



  • Hey There, I am trying to communicate with multiple serial port and read sensor data simultaneously , I need to draw graph from sensor data.

    my mainwindow.cpp is a main UI in that I am just creating a dummy live graph, and I am getting total number of serial port available (total attached port with device) and I am setting the Port name in combobox.

    on selection of portname from combobox ,I am calling Graph1.cpp class in which I am connecting with serial port and fetching sensor data and plotting graph using QcustomChart.

    Problem --
    for first time when Graph1.cpp loads (I mean for first selection of portname) it works fine, but when I click on second option of Port Name then Graph1.cpp loads for second time and is start fetching data and plot graph accordingly but for first window (Already opened) data got stuck I mean grpah showing nothing.

    ** I need to call Graph1.cpp when someone select PortName from combobox, and it calling can be 10 times or more than that

    here is my source code

    MainWindow.h file

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QtCore>
    #include "qcustomplot.h"
    #include "graph1.h"
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    private slots:
        void realtimedata();
        void switchcall(int);
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
        QTimer Timer;
    };
    
    class NewWindow
    {
     //   NewWindow *nw = new NewWindow();
    };
    
    #endif // MAINWINDOW_H
    

    MainWindow.cpp file

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QSerialPort>
    #include <QScrollArea>
    
    #include <QSerialPortInfo>
    #include <QComboBox>
    
    //QSerialPort *serial;
    //QString comportname="";
    //char buffer[2];
    QString SerialPortName;
    QStringList totalPorts;
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
            {
            ui->comboBox->addItem(serialPortInfo.portName());
            totalPorts<<serialPortInfo.portName();
            }
    
        qDebug() << SerialPortName;
    
      //  connect(ui->comboBox,SIGNAL(activated(int)),this,SLOT(clickedaction(int)));
        connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(switchcall(int)));
    
        ui->plotdisplaymain->addGraph(); // blue line
        ui->plotdisplaymain->graph(0)->setPen(QPen(Qt::blue));
        ui->plotdisplaymain->graph(0)->setBrush(QBrush(QColor(240, 255, 200)));
        ui->plotdisplaymain->graph(0)->setAntialiasedFill(false);
    //    ui->plotdisplaymain->addGraph(); // red line
    //    ui->plotdisplaymain->graph(1)->setPen(QPen(Qt::red));
    //    ui->plotdisplaymain->graph(0)->setChannelFillGraph(ui->plotdisplaymain->graph(1));
    
        ui->plotdisplaymain->addGraph(); // blue dot
        ui->plotdisplaymain->graph(1)->setPen(QPen(Qt::blue));
        ui->plotdisplaymain->graph(1)->setLineStyle(QCPGraph::lsNone);
        ui->plotdisplaymain->graph(1)->setScatterStyle(QCPScatterStyle::ssDisc);
    //    ui->plotdisplaymain->addGraph(); // red dot
    //    ui->plotdisplaymain->graph(3)->setPen(QPen(Qt::red));
    //    ui->plotdisplaymain->graph(3)->setLineStyle(QCPGraph::lsNone);
    //    ui->plotdisplaymain->graph(3)->setScatterStyle(QCPScatterStyle::ssDisc);
    
        ui->plotdisplaymain->xAxis->setTickLabelType(QCPAxis::ltDateTime);
        ui->plotdisplaymain->xAxis->setDateTimeFormat("hh:mm:ss");
        ui->plotdisplaymain->xAxis->setAutoTickStep(false);
        ui->plotdisplaymain->xAxis->setTickStep(2);
        ui->plotdisplaymain->axisRect()->setupFullAxesBox();
    
        // make left and bottom axes transfer their ranges to right and top axes:
        connect(ui->plotdisplaymain->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->plotdisplaymain->xAxis2, SLOT(setRange(QCPRange)));
        connect(ui->plotdisplaymain->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->plotdisplaymain->yAxis2, SLOT(setRange(QCPRange)));
    
        // setup a timer that repeatedly calls MainWindow::realtimeDataSlot:
        connect(&Timer, SIGNAL(timeout()), this, SLOT(realtimedata()));
        Timer.start(0); // Interval 0 means to refresh as fast as possible
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::switchcall(int)
    {
        graph1* grapher = new graph1();
    
        // Be sure to destroy you window somewhere
        grapher->init(totalPorts[ui->comboBox->currentIndex()],ui->comboBox->currentIndex());
        grapher->setModal(false);
        grapher->show();
           //grapher-exec();
    }
    
    void MainWindow::realtimedata()
    {
      // calculate two new data points:
    
      double key = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
    
      static double lastPointKey = 0;
      if (key-lastPointKey > 0.01) // at most add point every 10 ms
      {
        double value0 = tan(key);  //qSin(key); //sin(key*1.6+cos(key*1.7)*2)*10 + sin(key*1.2+0.56)*20 + 26;
    //    double value1 = -tan(key); //qCos(key); //sin(key*1.3+cos(key*1.2)*1.2)*7 + sin(key*0.9+0.26)*24 + 26;
        // add data to lines:
        ui->plotdisplaymain->graph(0)->addData(key, value0);
     //   ui->plotdisplaymain->graph(1)->addData(key, value1);
        // set data of dots:
        ui->plotdisplaymain->graph(1)->clearData();
        ui->plotdisplaymain->graph(1)->addData(key, value0);
    //    ui->plotdisplaymain->graph(3)->clearData();
    //    ui->plotdisplaymain->graph(3)->addData(key, value1);
        // remove data of lines that's outside visible range:
        ui->plotdisplaymain->graph(0)->removeDataBefore(key-7);
    //    ui->plotdisplaymain->graph(1)->removeDataBefore(key-8);
        // rescale value (vertical) axis to fit the current data:
        ui->plotdisplaymain->graph(0)->rescaleValueAxis();
    //    ui->plotdisplaymain->graph(1)->rescaleValueAxis(true);
        lastPointKey = key;
      }
      // make key axis range scroll with the data (at a constant range size of 8):
      ui->plotdisplaymain->xAxis->setRange(key+0.25, 8, Qt::AlignRight);
      ui->plotdisplaymain->replot();
    
      // calculate frames per second:
    //  static double lastFpsKey;
      static int frameCount;
      ++frameCount;
    //  if (key-lastFpsKey > 2) // average fps over 2 seconds
    //  {
    //    ui->statusBar->showMessage(
    //          QString("%1 FPS, Total Data points: %2")
    //          .arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
    //          .arg(ui->plotdisplaymain->graph(0)->data()->count()+ui->plotdisplaymain->graph(0)->data()->count())
    //          , 0);
    //    lastFpsKey = key;
    //    frameCount = 0;
    //  }
    }
    

    Graph1.h file

    #ifndef GRAPH1_H
    #define GRAPH1_H
    
    #include <QDialog>
    #include "qcustomplot.h"
    #include <QStatusBar>
    
    namespace Ui {
    class graph1;
    }
    
    class graph1 : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit graph1(QWidget *parent = 0);
        void init(QString portName, int index);
        ~graph1();
        void closeEvent(QCloseEvent *event);
    
    
    private slots:
       //  void realtime();
         void recieveddata();
    
    private:
        Ui::graph1 *ui;
        QTimer Timer;
    };
    
    #endif // GRAPH1_H
    

    Graph1.cpp file

    #include "graph1.h"
    #include "ui_graph1.h"
    #include <QSerialPort>
    #include <QSerialPortInfo>
    #include <QString>
    #include <QTextCodec>
    #include <stdio.h>
    #include <iostream>
    
    
    QSerialPort *serial;
    
    char buffer[2];
    
    graph1::graph1(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::graph1)
    {
        ui->setupUi(this);
    }
    
    void graph1::init(QString portName, int index)
    {
    
        qDebug()<<"Data from main "<<portName;
    
        serial = new QSerialPort(this);
    
        serial->setPortName(portName);
        serial->open(QIODevice::ReadWrite);
        serial->setBaudRate(QSerialPort::Baud9600);
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);
        serial->ReadOnly;
        connect(serial,SIGNAL(readyRead()),this,SLOT(recieveddata()));
    
    
        ui->plotdisplay->addGraph(); // blue line
        ui->plotdisplay->graph(0)->setPen(QPen(Qt::blue));
        ui->plotdisplay->graph(0)->setBrush(QBrush(QColor(240, 255, 200)));
        ui->plotdisplay->graph(0)->setAntialiasedFill(false);
    
        ui->plotdisplay->addGraph(); // red line
        ui->plotdisplay->graph(1)->setPen(QPen(Qt::red));
        ui->plotdisplay->graph(0)->setChannelFillGraph(ui->plotdisplay->graph(1));
    
        ui->plotdisplay->addGraph(); // blue dot
        ui->plotdisplay->graph(2)->setPen(QPen(Qt::blue));
        ui->plotdisplay->graph(2)->setLineStyle(QCPGraph::lsNone);
        ui->plotdisplay->graph(2)->setScatterStyle(QCPScatterStyle::ssDisc);
    
        ui->plotdisplay->addGraph(); // red dot
        ui->plotdisplay->graph(3)->setPen(QPen(Qt::red));
        ui->plotdisplay->graph(3)->setLineStyle(QCPGraph::lsNone);
        ui->plotdisplay->graph(3)->setScatterStyle(QCPScatterStyle::ssDisc);
    
        ui->plotdisplay->xAxis->setTickLabelType(QCPAxis::ltDateTime);
        ui->plotdisplay->xAxis->setDateTimeFormat("hh:mm:ss");
        ui->plotdisplay->xAxis->setAutoTickStep(false);
        ui->plotdisplay->xAxis->setTickStep(2);
        ui->plotdisplay->axisRect()->setupFullAxesBox();
    
        // make left and bottom axes transfer their ranges to right and top axes:
        connect(ui->plotdisplay->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->plotdisplay->xAxis2, SLOT(setRange(QCPRange)));
        connect(ui->plotdisplay->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->plotdisplay->yAxis2, SLOT(setRange(QCPRange)));
    
    }
    
    
    graph1::~graph1()
    {
        serial->close();
        delete serial;
        delete ui;
    
    }
    
    void graph1::recieveddata()
    {
    
        QString stringer;
        QByteArray datas = serial->readAll();
    
         stringer = QString::fromStdString(datas.toStdString());
    
         double recievedSerialData = stringer.toDouble();
    
         qDebug() << "dbl:[" << recievedSerialData << "]";
        qDebug() <<stringer;
    
        QString numr = QString::fromStdString(stringer.toStdString());
    
        int nummer =  numr.toInt();
    
        double y = recievedSerialData+10;
    
    
    
    
        double key = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
        static double lastPointKey = 0;
        if (key-lastPointKey > 0.01) // at most add point every 10 ms
        {
        ui->plotdisplay->graph(0)->addData(key, recievedSerialData);
        ui->plotdisplay->graph(1)->addData(key, y);
        // set data of dots:
        ui->plotdisplay->graph(2)->clearData();
        ui->plotdisplay->graph(2)->addData(key, recievedSerialData);
        ui->plotdisplay->graph(3)->clearData();
        ui->plotdisplay->graph(3)->addData(key, y);
        // remove data of lines that's outside visible range:
        ui->plotdisplay->graph(0)->removeDataBefore(key-8);
        ui->plotdisplay->graph(1)->removeDataBefore(key-8);
        // rescale value (vertical) axis to fit the current data:
        ui->plotdisplay->graph(0)->rescaleValueAxis();
        ui->plotdisplay->graph(1)->rescaleValueAxis(true);
        lastPointKey = key;
    
    }
    
        // make key axis range scroll with the data (at a constant range size of 8):
        ui->plotdisplay->xAxis->setRange(key+0.25, 8, Qt::AlignRight);
        ui->plotdisplay->replot();
    }
    
    void graph1::closeEvent(QCloseEvent *event)
    {
        serial->close();
        delete serial;
    //    if (maybeSave()) {
    
    //        event->accept();
    //    } else {
    //        event->ignore();
    //    }
    }
    

    Note: If you want to test my code please add qcustomPlot.h and QcustomPlot.cpp

    ![alt text](C:\Users\raghu\Desktop\MainWindow ui.png)


  • Moderators

    @Raghvendra

    I have added code tags to your post. Please code tags next time. They are ensuring a better readability of your code sections.

    At the end of your post you like to show a pciture, but there is only a local path in your computer in there. Therefore, nobody will be able to the png file.


  • Lifetime Qt Champion

    Hi,

    You're using a static QSerialPort pointer which is a bad idea in any case, make it a member of your class.

    To add to @koahnig, if you really want that someone take on his own free time to analyse your code and even try to build it then provide a complete buildable project through e.g. BitBucket, GitLab, GitHub etc.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.