Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt Serial Read data missing Issue



  • Hi i am new to Qt Serial port. I am trying to communicate with two com ports on my laptop. i have written the code as below. When i click start button the data is written from first port but the second port does not receive the data being sent from port 1 for two iterations. From third iteration the data read is also not proper. Kindly help mw understand what is happening here.

    I am sharing the screenshot for reference. and also the Code

    Screenshot (9).png

    Code:

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    openSerial();
    

    }

    void MainWindow::on_pushButton_clicked()
    {
    communicate();
    }

    void MainWindow::openSerial()
    {

    serial_1->setPortName("COM14");
    serial_1->setBaudRate(QSerialPort::Baud9600);
    serial_1->setDataBits(QSerialPort::Data8);
    serial_1->setParity(QSerialPort::NoParity);
    serial_1->setStopBits(QSerialPort::OneStop);
    serial_1->setFlowControl(QSerialPort::NoFlowControl);
    
    serial_2->setPortName("COM13");
    serial_2->setBaudRate(QSerialPort::Baud9600);
    serial_2->setDataBits(QSerialPort::Data8);
    serial_2->setParity(QSerialPort::NoParity);
    serial_2->setStopBits(QSerialPort::OneStop);
    serial_2->setFlowControl(QSerialPort::NoFlowControl);
    

    }

    void MainWindow::communicate()
    {
    if ((serial_1->open(QIODevice::ReadWrite)) && (serial_2->open(QIODevice::ReadWrite)))
    {

        while(serial_2->isOpen() && (serial_2->isOpen()))
        {
    
            QApplication::processEvents(QEventLoop::AllEvents);
    
            serial_1->write("Hi Hello");
            ui->textBrowser->append("Data written From Serial-1");
            serial_2_receive = serial_2->readAll();
            qDebug()<<"Data Received at Serial-2 : "<<serial_2_receive;
            ui->textBrowser->append(serial_2_receive);
            QApplication::processEvents();
    
        }
    
    }
    
    else
    {
        qDebug()<<" SERIAL Open Fail ";
    }
    

    }

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

    void MainWindow::on_pushButton_2_clicked()
    {
    serial_2->close();
    serial_1->close();
    }

    void MainWindow::on_pushButton_3_clicked()
    {
    ui->textBrowser->clear();
    }



  • @Rajesh-Panati Yes this will never work, because you are give QSerialPort the opportunity to do his work (sending data for serial 1 and receiving data for serial2):

        while(serial_2->isOpen() && (serial_2->isOpen()))
        {
            serial_1->write("Hi Hello");
            serial_1->waitForBytesWritten();
            ui->textBrowser->append("Data written From Serial-1");
            serial_2->waitForReadyRead(500);
            serial_2_receive = serial_2->readAll();
            qDebug()<<"Data Received at Serial-2 : "<<serial_2_receive;
            ui->textBrowser->append(serial_2_receive);
            QApplication::processEvents();
        }
    
    


  • @KroMignon

    Hi @KroMignon Thank you for your quick response. As shown in the above screenshot i am receiving the message "Hi Hello" written from port-1 on port-2 after second iteration. My assumption is when the serial port-1 writes and by the time it goes to port-2 read the data is missing (timing issue), am i right or is that a wrong assumption from me. I had even added WaitForReadReady() before reading but not working.



  • @KroMignon

    To make my question clear. i am connecting the two ports using two USB to serial converters and establishing the physical connection.


  • Lifetime Qt Champion

    Hi,

    Please take a look at the QSerialPort examples, especially the terminal example.

    Make use of QSerialPort asynchronous nature.



  • @Rajesh-Panati said in Qt Serial Read data missing Issue:

    while(serial_2->isOpen() && (serial_2->isOpen()))

    and what's this about? Typo?



  • @SGaist

    Hi @SGaist, Thanks for your reply. Sorry for the long reply. I had gone through the terminal example. In terminal example the communication is done using single port, but for example if we want to communicate between two ports of same system with physical connection established, you need to open two terminal example application with different ports settings (Ex: COM1 as Port-1 in terminal 1 app and COM 2 as Port-2 in terminal 2 app) only then you will be able to communicate with each other. In my case i will be communicating with both the ports from same app. I am able to communicate with the ports but the data is not read at port 2 for two iterations as shown in the screenshot above. Is it wrong logic or timing issue i am not understanding.



  • @Kent-Dorfman

    Hi, Thanks for the reply. I have seen it, its mistake from me. Here i am checking if both the ports are open only then i am communicating (.ie read and write). it should be while(serial_1->isOpen() && (serial_2->isOpen())) but this does'nt make a difference i have changed and checked.


  • Lifetime Qt Champion

    @Rajesh-Panati said in Qt Serial Read data missing Issue:

    @SGaist

    Hi @SGaist, Thanks for your reply. Sorry for the long reply. I had gone through the terminal example. In terminal example the communication is done using single port, but for example if we want to communicate between two ports of same system with physical connection established, you need to open two terminal example application with different ports settings (Ex: COM1 as Port-1 in terminal 1 app and COM 2 as Port-2 in terminal 2 app) only then you will be able to communicate with each other. In my case i will be communicating with both the ports from same app. I am able to communicate with the ports but the data is not read at port 2 for two iterations as shown in the screenshot above. Is it wrong logic or timing issue i am not understanding.

    The fact that the data comes from an external device, a different application or a different part of the same application plays no role here.

    You should in any case treat these two as separate entities and as already suggested, use the asynchronous nature of QSerialPort. There's no need for a while loop at all. There's one thing that is guaranteed to not be guaranteed when using serial port is that you will always received all the data in one go. That's not how it works. It's your duty to establish a clear protocol to detect when you can a complete "frame" of data that you can process. The technique is always the same: cumulate the data received in a buffer, check it the "frame complete" conditions are met, extract and process the frame and then continue.


  • Lifetime Qt Champion

    @Rajesh-Panati

    Don't use waitForBytesWritten()/waitForBytesReceived()/processEvents().

    Use signals and slots, they are designed for such things.

    Connect a slot to the readyRead() signal of serial_2 and read the data there.

    Regards



  • @SGaist Thank you. Ok i will try it.



  • @Rajesh-Panati said in Qt Serial Read data missing Issue:

    Hi @KroMignon Thank you for your quick response. As shown in the above screenshot i am receiving the message "Hi Hello" written from port-1 on port-2 after second iteration. My assumption is when the serial port-1 writes and by the time it goes to port-2 read the data is missing (timing issue), am i right or is that a wrong assumption from me. I had even added WaitForReadReady() before reading but not working.

    If you want to use QSerialPort in polling mode (not signals/slots based), you have to use waitForBytesWritten() and waitForReadyRead() to ensure QSerialPort can do his job.

    But, those functions only tells you all data have been sent or data are available (which does not mean "all data you have sent" are available). It is up to you to handle this, by nature serial interfaces are asynchronous!

    One way is to add a "special symbol" like "carriage return" or "line feed", or to way until no more data available for a given time:

    while(serial_2->isOpen() && (serial_2->isOpen()))
    {
        serial_1->write("Hi Hello");
        serial_1->waitForBytesWritten();
        ui->textBrowser->append("Data written From Serial-1");
        QApplication::processEvents();
        serial_2_receive.clear();
        while(serial_2->waitForReadyRead(500))
        {
            serial_2_receive.append(serial_2->readAll());
        }
        qDebug()<<"Data Received at Serial-2 : "<<serial_2_receive;
        ui->textBrowser->append(serial_2_receive);
        QApplication::processEvents();
    }
    


  • @aha_1980 Thank you. i have tried all these but still missing data for two iterations. I am checking other ways too.



  • @KroMignon Thank you for the reply. I will try with this and see.


  • Lifetime Qt Champion

    @Rajesh-Panati please show your code



  • @aha_1980 Hi, here is the code after making changes you had asked for. But still the data is missing for first two iterations. Screenshot attached for your reference and code below.

    Screenshot:

    Screenshot (11).png

    Code:

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    connect(serial_2, &QSerialPort::readyRead, this, &MainWindow::readData);
    
    openSerial();
    

    }

    void MainWindow::on_pushButton_clicked()
    {

    communicate();
    

    }

    void MainWindow::openSerial()
    {

    serial_1->setPortName("COM13");
    serial_1->setBaudRate(QSerialPort::Baud9600);
    serial_1->setDataBits(QSerialPort::Data8);
    serial_1->setParity(QSerialPort::NoParity);
    serial_1->setStopBits(QSerialPort::OneStop);
    serial_1->setFlowControl(QSerialPort::NoFlowControl);
    
    serial_2->setPortName("COM14");
    serial_2->setBaudRate(QSerialPort::Baud9600);
    serial_2->setDataBits(QSerialPort::Data8);
    serial_2->setParity(QSerialPort::NoParity);
    serial_2->setStopBits(QSerialPort::OneStop);
    serial_2->setFlowControl(QSerialPort::NoFlowControl);
    

    }

    void MainWindow::communicate()
    {
    if ((serial_1->open(QIODevice::ReadWrite)) && (serial_2->open(QIODevice::ReadWrite)))
    {

        while(serial_1->isOpen() && (serial_2->isOpen()))
        {
    
            QApplication::processEvents(QEventLoop::AllEvents);
    
            QThread::msleep(1000);
    
            serial_1->write("Hi Hello");
            ui->textBrowser->append("Data written From Serial-1\n");
    
        }
    
    }
    
    else
    {
        qDebug()<<" SERIAL Open Fail ";
    }
    

    }

    void MainWindow::readData()
    {
    serial_2_receive = serial_2->readAll();
    qDebug()<<"Data Received at Serial-2 : "<<serial_2_receive;
    ui->textBrowser->append("Data Received at Serial 2 : "+serial_2_receive+"\n");
    }

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

    void MainWindow::on_pushButton_2_clicked()
    {
    serial_2->close();
    serial_1->close();
    }

    void MainWindow::on_pushButton_3_clicked()
    {
    ui->textBrowser->clear();
    }



  • @Rajesh-Panati said in Qt Serial Read data missing Issue:

    while(serial_1->isOpen() && (serial_2->isOpen()))
    {

        QApplication::processEvents(QEventLoop::AllEvents);
    
        QThread::msleep(1000);
    
        serial_1->write("Hi Hello");
        ui->textBrowser->append("Data written From Serial-1\n");
    
    }
    

    So you are only processing Qt events at a rate of once per second? Don't you think that might cause syncronization problems?

    Instead of communicate() create a QTimer handler when the communicate button is pressed then have its body send the data out and concatenate to your UI every time the timer expires.

    Trying to do sequential programming event loops for asynchonous I/O is very error prone. You should use the Qt tools and do it in an event driven manner.


  • Qt Champions 2019

    @Rajesh-Panati "i have tried all these" - you did not. You're still not using asynchronous nature of QSerialPort and you still use a while loop...



  • @jsulm Thank you for the suggestion after removing the while and as you and @Kent-Dorfman suggested i removed QProccessEvents and now its able to receive. Thank you very much.



  • @Kent-Dorfman Thank you for the suggestion. Its working now.


Log in to reply