Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Unsolved QTSerialPort Read/Write doesn't properly work on Windows

    QML and Qt Quick
    qt 5.4 qtserialport
    5
    10
    3106
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      canerbldk last edited by

      Hello, I'm trying to write a code for my application. My goal is to write a bunch of bits to the serial port and in this time read the serial port for a reply from the connected device. While I'm writing to the serial port and reading from the serial port, also I want to measure elapsed time. I'm not really experience with QT and I'm facing with some problems.

      I started from a basic application which read serial port, but it's not working as it's supposed to work. I tested my code in Linux machine, it's work flowless, but in windows, it's not reading serial port.

      In Linux, when I run the code, it listens until i close the program. Whatever I sent from serial port, It directly print to the terminal. But in windows, it just waits and doesn't read anything. I also set my buffer to smaller but that's also didn't work. But when I uncomment that //selectedPort->waitForReadyRead(5000); part in windows, It works and read serial port for 5 sec. Then it's idle without reading anything.

      On the other hand, I want to measure the time elapsed during writing and reading. I'm trying to write 1MB of data, with 115200baudrate which is around 11,25kb/sec as my calculation. But when I try with my code it returns 1-2ms which seems wrong. I created 16kb of data with a for-loop. I suppose to take more than 1sec but my code returns 0ms. I think, I don't know how to make it properly. Also i need this kind of stuff also for reading.

      I'm looking for any kind of suggestion for my application. Sorry for my mistakes.

      myserial.cpp

      MySerial::MySerial(QString portn, uint32_t baudrate){
          selectedPort = new QSerialPort;
          this->baudrate = baudrate;
          selectedPort->setPortName(portn);
          selectedPort->setBaudRate(static_cast<qint32>(baudrate));
          selectedPort->open(QIODevice::ReadWrite);
          connect(selectedPort, SIGNAL(readyRead()),this, SLOT(MyReadyRead()));
          //selectedPort->waitForReadyRead(5000);
      
      }
      
      void MySerial::MyReadyRead()
      {
          QByteArray myData = selectedPort->readAll();
          std::cout << myData.toStdString();fflush(stdout);
      }
      
      
      void MySerial::startWrite(QByteArray myData){
          myTime.start();
          for(long i=0; i<1024;i++){ // 16byte -> 16kb
              selectedPort->write(myData);
          }
          std::cout << "Time elapsed(in ms):" <<myTime.elapsed()<<std::endl;
      }
      
      

      main.cpp

      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
          MySerial *s0 = new MySerial("COM6",115200);
          QByteArray testData = "1111111111111111";//
                                // 16 char = 16byte of data
      
          s0->startWrite(testData);
      
      
          return a.exec();
      }
      
      
      aha_1980 JonB 2 Replies Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi and welcome to devnet,

        You should check whether your open call is successful. Then you should also check for errors in your code.

        Are you sure that you are opening the correct com port ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        C 1 Reply Last reply Reply Quote 2
        • aha_1980
          aha_1980 Lifetime Qt Champion @canerbldk last edited by

          @canerbldk and to add to @sgaist, which Qt version are you using? there has been a bug recently which influenced the receiving of characters.

          Regards

          Qt has to stay free or it will die.

          1 Reply Last reply Reply Quote 2
          • C
            canerbldk @SGaist last edited by canerbldk

            @SGaist with //selectedPort->waitForReadyRead(5000); i'm able to read correctly and i also tested my open function seems correct.

                if(selectedPort->open(QIODevice::ReadWrite))
                std::cout << "Port " << portn.toStdString() << "is open" << std::endl;
            
            

            @aha_1980 I'm using Qt 5.13.1 (MSVC 2017, 32 bit)

            I also created 2 virtual serial comm. port to test everything. I connected one port to Docklight and the other one to my code, I received and delivered everything correctly.

            J.Hilk 1 Reply Last reply Reply Quote 0
            • JonB
              JonB @canerbldk last edited by JonB

              @canerbldk

              std::cout << myData.toStdString();fflush(stdout);

              Why use fflush(stdout), are you sure std::cout is using the stdout buffer like that? Prefer

              cout.flush();
              //  or
              cout << ... << flush;
              
              

              Next:
              In startWrite() you time QSerialPort::write() operations. I am not an expert on serial I/O, but in general that returns immediately only guaranteeing to queue the output, not execute it. You have signals like QIODevice::bytesWritten or function QSerialPort::waitForBytesWritten() for that. Also you do not check the return result from QSerialPort::write(), it might be returning less bytes than you sent or even -1 for error. And you don't have any calls to QSerialPort::flush() or handler for QSerialPort::errorOccurred, just in case. @SGaist mentioned this.

              The above two might behave differently on Windows vs Linux, so worth just checking.

              C 1 Reply Last reply Reply Quote 3
              • C
                canerbldk @JonB last edited by

                @JonB I modified my code a bit as much as what I understood. I added an error handler and I modified fflush(stdout). Nothing changed. I don't get any error. I'm still not able to read without //selectedPort->waitForReadyRead(5000);. Also, I have the same problem for bytesWritten. I have to add //selectedPort->waitForBytesWritten(3000); to trigger MyBytesWritten() function.

                On the other hand, although I run the same code twice, I'm getting different outputs, in terms of elapsed time. My guess, I'm measuring data write time to write-buffer, instead of write time to the serial port.

                I still need some help to figure out how to measure the time elapsed correctly. Thank you for your help.

                main.cpp

                int main(int argc, char *argv[])
                {
                    QCoreApplication a(argc, argv);
                
                    MySerial *s0 = new MySerial("COM6",115200);
                    QByteArray testData = "1111111111111111";//
                                          // 16 char = 16byte of data
                
                    s0->startWrite(testData);
                    s0->startListen();
                    s0->startWrite("C");
                
                    return a.exec();
                }
                

                myserial.cpp

                #include "myserial.h"
                #include <stdio.h>
                #include <iostream>
                #include <unistd.h>
                #include <QCoreApplication>
                #include <QObject>
                
                
                MySerial::MySerial(QString portn, uint32_t baudrate)
                {
                    selectedPort = new QSerialPort;
                    this->baudrate = baudrate;
                    selectedPort->setPortName(portn);
                    selectedPort->setBaudRate(static_cast<qint32>(baudrate));
                    if(selectedPort->open(QIODevice::ReadWrite))
                    std::cout << "Port " << portn.toStdString() << " is open" << std::endl;
                
                    connect(selectedPort, &QSerialPort::errorOccurred, this, &MySerial::handleError);
                    connect(selectedPort, SIGNAL(readyRead()),this, SLOT(MyReadyRead()));
                    connect(selectedPort,SIGNAL(bytesWritten(qint64)),this,SLOT(MyBytesWritten(qint64)));
                
                    myTime.start();
                }
                
                void MySerial::MyReadyRead()
                {
                    QByteArray myData = selectedPort->readAll();
                    std::cout << myData.toStdString();
                    std::cout.flush()<<std::endl;
                }
                
                void MySerial::MyBytesWritten(qint64){
                    selectedPort->flush();
                    std::cout << "MyBytesWritten(in ms):" <<myTime.elapsed()<<std::endl;
                }
                
                MySerial::~MySerial(){
                    selectedPort->close();
                    selectedPort->disconnect();
                }
                
                void MySerial::startWrite(QByteArray myData){
                    std::cout << "Time elapsed(in ms):" <<myTime.elapsed()<<std::endl;
                    myTime.restart();
                    for(long i=0; i<1024;i++){ // byte -> kilobyte
                        selectedPort->write(myData);
                    }
                    selectedPort->waitForBytesWritten(3000);
                    myTime.restart();
                }
                
                void MySerial::startListen()
                {
                     while(selectedPort->waitForReadyRead(3000)){
                         std::cout << "Read Data" <<myTime.elapsed()<<std::endl;
                         MyReadyRead();
                     }
                }
                
                void MySerial::handleError(QSerialPort::SerialPortError serialPortError)
                {
                    if (serialPortError == QSerialPort::ReadError) {
                          m_standardOutput << QObject::tr("An I/O error occurred while reading "
                                                          "the data from port %1, error: %2")
                                              .arg(selectedPort->portName())
                                              .arg(selectedPort->errorString())
                                           << endl;
                        QCoreApplication::exit(1);
                    }
                }
                

                output1

                Port COM6 is open
                Time elapsed(in ms):0
                MyBytesWritten(in ms):606
                ----o Ping
                ----o Ping
                Time elapsed(in ms):3001
                MyBytesWritten(in ms):27
                

                output2

                Port COM6 is open
                Time elapsed(in ms):0
                MyBytesWritten(in ms):644
                ----o Ping
                ----o Ping
                Time elapsed(in ms):3001
                MyBytesWritten(in ms):28
                
                1 Reply Last reply Reply Quote 0
                • J.Hilk
                  J.Hilk Moderators @canerbldk last edited by

                  @canerbldk said in QTSerialPort Read/Write doesn't properly work on Windows:

                  I'm using Qt 5.13.1 (MSVC 2017, 32 bit)

                  jepp, IIRC that's one of the versions where the signals are not emitted correctly.
                  5.13.2 should be out and it should work there, if I'm not mistaken. @aha_1980 should be able to correct me if I'm wrong :)

                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct

                  Qt Needs YOUR vote: https://bugreports.qt.io/browse/QTQAINFRA-4121


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  aha_1980 C 2 Replies Last reply Reply Quote 3
                  • aha_1980
                    aha_1980 Lifetime Qt Champion @J.Hilk last edited by

                    @J-Hilk you're correct:

                    https://bugreports.qt.io/issues/?filter=21665&jql=project %3D QTBUG AND issuetype %3D Bug AND resolution in (Done%2C Fixed) AND fixVersion %3D 5.13.2 AND component %3D "Serial Port" ORDER BY priority DESC%2C status ASC%2C labels ASC

                    Qt has to stay free or it will die.

                    1 Reply Last reply Reply Quote 3
                    • C
                      canerbldk @J.Hilk last edited by

                      @J-Hilk OH my god! I'm trying to fix that problem for a week. I tried lots of things to understand why it's not working correctly on windows, but I never think about QT version :( Thanks a lot for your help !!!

                      But, I'm still looking for a suggestion for read-write timing measurement. As I stated before I'm thinking that I'm measuring write-to-buffer time while I need write-to-serial timing. Thanks in advance

                      aha_1980 1 Reply Last reply Reply Quote 2
                      • aha_1980
                        aha_1980 Lifetime Qt Champion @canerbldk last edited by

                        @canerbldk said in QTSerialPort Read/Write doesn't properly work on Windows:

                        As I stated before I'm thinking that I'm measuring write-to-buffer time while I need write-to-serial timing.

                        That is hardly possible, as there are many buffers involved: in your app, in Qt, in the OS, in the driver, ...

                        What you can do is to time the round trip i.e. send a command and measure the time until the answer comes back.

                        Regards

                        Qt has to stay free or it will die.

                        1 Reply Last reply Reply Quote 2
                        • First post
                          Last post