Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QTSerialPort Read/Write doesn't properly work on Windows
QtWS25 Last Chance

QTSerialPort Read/Write doesn't properly work on Windows

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
qt 5.4qtserialport
10 Posts 5 Posters 5.6k Views
  • 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 Offline
    C Offline
    canerbldk
    wrote on last edited by
    #1

    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_1980A JonBJ 2 Replies Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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
      2
      • C canerbldk

        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_1980A Offline
        aha_1980A Offline
        aha_1980
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @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
        2
        • SGaistS SGaist

          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 ?

          C Offline
          C Offline
          canerbldk
          wrote on last edited by canerbldk
          #4

          @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.HilkJ 1 Reply Last reply
          0
          • C canerbldk

            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();
            }
            
            
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @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
            3
            • JonBJ 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 Offline
              C Offline
              canerbldk
              wrote on last edited by
              #6

              @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
              0
              • C 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.HilkJ Offline
                J.HilkJ Offline
                J.Hilk
                Moderators
                wrote on last edited by
                #7

                @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


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

                aha_1980A C 2 Replies Last reply
                3
                • J.HilkJ J.Hilk

                  @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 :)

                  aha_1980A Offline
                  aha_1980A Offline
                  aha_1980
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @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
                  3
                  • J.HilkJ J.Hilk

                    @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 :)

                    C Offline
                    C Offline
                    canerbldk
                    wrote on last edited by
                    #9

                    @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_1980A 1 Reply Last reply
                    2
                    • C canerbldk

                      @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_1980A Offline
                      aha_1980A Offline
                      aha_1980
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @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
                      2

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved