Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Reading from and writing to the serial port at faster rate using serialPort->waitForReadyRead();
Forum Updated to NodeBB v4.3 + New Features

Reading from and writing to the serial port at faster rate using serialPort->waitForReadyRead();

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 6 Posters 6.8k Views 2 Watching
  • 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.
  • KiraK Offline
    KiraK Offline
    Kira
    wrote on last edited by
    #1

    Hello All,

    I have a program in qt which sends the serial data and read the response that the operation have been performs.

    If i read the response from the readready signal i get the response in nanosec but if i use
    serialPort->waitForReadyRead() the response time increase to 80-100 millisec.

    I cannot use the readready signal as i have to perform the processing in synchronous fashion.

    How can i achieve the same rate for serialPort->waitForReadyRead().

    Also if i specify suppose serialPort->waitForReadyRead(10); I do not get response at the serial port.
    Whereas in case of readready the response is instantaneous.

    J.HilkJ 1 Reply Last reply
    0
    • KiraK Kira

      Hello All,

      I have a program in qt which sends the serial data and read the response that the operation have been performs.

      If i read the response from the readready signal i get the response in nanosec but if i use
      serialPort->waitForReadyRead() the response time increase to 80-100 millisec.

      I cannot use the readready signal as i have to perform the processing in synchronous fashion.

      How can i achieve the same rate for serialPort->waitForReadyRead().

      Also if i specify suppose serialPort->waitForReadyRead(10); I do not get response at the serial port.
      Whereas in case of readready the response is instantaneous.

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #2

      hi @Kira ,

      there's multiple ways you can go here, but you should tell us more about the situation. For example why do you have to do the'processing in synchronous fashion? What is the limiting factor here?

      Simplest sultion here, place your code after waitforReadyRead in its own slot and connect the signal to that. If you're relying on a return value, than better redesign your code :-)

      If you have to, there are some ways to force the event loop to process without exiting a function. (ProcessEvents() QEventLoop) But those should be used rarly, if at all.


      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.

      KiraK 1 Reply Last reply
      1
      • R Offline
        R Offline
        Rondog
        wrote on last edited by Rondog
        #3

        I don't think you can get a response from a serial port anywhere near a nanosecond. If you send a single byte of data you may have a frame size of something like 10 bits. At a baud rate of 256k you are probably looking at something around 40 ns for every byte (assuming a 10 bit frame). This doesn't include whatever is at the other end (it must read, process, and respond).

        I have noticed that the waitForReadyRead() signal can be slow depending on the type of data for some reason. I never figured out why but I suspect it may have something to do with the OS not having a way to signal when new data has arrived (which means Qt must periodically check for new data - ?).

        The serial ports are buffered so writing data can seem instantaneous. In reality the data is slowly be written out the serial port long after the write() function has returned.

        KiraK 1 Reply Last reply
        1
        • Gojir4G Offline
          Gojir4G Offline
          Gojir4
          wrote on last edited by
          #4

          Hello,

          Did you try to use QSerialPort::bytesAvailable() ?
          like:

          while(serial.bytesAvailable() < 1){
              //Data received
          }
          

          I recommend to put some timeout with this way otherwise you can wait indefinitely in case no reply is received.

          I had some issues with waitForReadyRead() on the past, so I reimplemented my own version

          bool MySerialPort::waitForReadyRead(int msecs)
          {
              QElapsedTimer t;
              t.start();
              while(QSerialPort::bytesAvailable() < 1 && t.elapsed() < msecs)
                  QApplication::processEvents();
              return QSerialPort::bytesAvailable() > 0;
          }
          
          KiraK 1 Reply Last reply
          1
          • J.HilkJ J.Hilk

            hi @Kira ,

            there's multiple ways you can go here, but you should tell us more about the situation. For example why do you have to do the'processing in synchronous fashion? What is the limiting factor here?

            Simplest sultion here, place your code after waitforReadyRead in its own slot and connect the signal to that. If you're relying on a return value, than better redesign your code :-)

            If you have to, there are some ways to force the event loop to process without exiting a function. (ProcessEvents() QEventLoop) But those should be used rarly, if at all.

            KiraK Offline
            KiraK Offline
            Kira
            wrote on last edited by
            #5

            @J.Hilk : Here is part of my code:

                           qDebug()<<"Enter the loop";
                           elapsedTimer.start();
                           writeData(QString("X  \n").toUtf8());
                           serialPort->waitForReadyRead();
                           readData = serialPort->readAll();
                           qDebug()<<"Print the response:"<<QString(readData).toUtf8();
                           elapsedTime = elapsedTimer.elapsed();
                           qDebug()<<"Time taken :"<<elasedTimer;
            

            Actually my next program steps are dependent on the previous step of the serial device.
            So i need to wait for the response form the device.
            Can you please explain "place your code after waitforReadyRead in its own slot and connect the signal to that" & "If you have to, there are some ways to force the event loop to process without exiting a function. (ProcessEvents() QEventLoop) ":)

            J.HilkJ 1 Reply Last reply
            0
            • R Rondog

              I don't think you can get a response from a serial port anywhere near a nanosecond. If you send a single byte of data you may have a frame size of something like 10 bits. At a baud rate of 256k you are probably looking at something around 40 ns for every byte (assuming a 10 bit frame). This doesn't include whatever is at the other end (it must read, process, and respond).

              I have noticed that the waitForReadyRead() signal can be slow depending on the type of data for some reason. I never figured out why but I suspect it may have something to do with the OS not having a way to signal when new data has arrived (which means Qt must periodically check for new data - ?).

              The serial ports are buffered so writing data can seem instantaneous. In reality the data is slowly be written out the serial port long after the write() function has returned.

              KiraK Offline
              KiraK Offline
              Kira
              wrote on last edited by Kira
              #6

              @Rondog : Hmm sorry for the typos it was nanosecs :)
              Currently i am working on windows. I have tried the same approach with python on ubuntu there it takes same time.

              1 Reply Last reply
              0
              • Gojir4G Gojir4

                Hello,

                Did you try to use QSerialPort::bytesAvailable() ?
                like:

                while(serial.bytesAvailable() < 1){
                    //Data received
                }
                

                I recommend to put some timeout with this way otherwise you can wait indefinitely in case no reply is received.

                I had some issues with waitForReadyRead() on the past, so I reimplemented my own version

                bool MySerialPort::waitForReadyRead(int msecs)
                {
                    QElapsedTimer t;
                    t.start();
                    while(QSerialPort::bytesAvailable() < 1 && t.elapsed() < msecs)
                        QApplication::processEvents();
                    return QSerialPort::bytesAvailable() > 0;
                }
                
                KiraK Offline
                KiraK Offline
                Kira
                wrote on last edited by Kira
                #7

                @Gojir4 : Sure will try and let u know.
                Can you just share the issue with waitForReadReady() if you don't mind, was it the time taken by the waitForReadReady();

                Hi I tried the first approach and it goes in infinite loop. I let the loop run for 10 sec. but no reply.
                I can try the second approach but don't not sure will the data is available after the specified millisecs because. For the first approach the reply is not coming in seconds. Maybe it is requesting the serial port the data at such a fast rate that is not able to respond.

                1 Reply Last reply
                0
                • KiraK Kira

                  @J.Hilk : Here is part of my code:

                                 qDebug()<<"Enter the loop";
                                 elapsedTimer.start();
                                 writeData(QString("X  \n").toUtf8());
                                 serialPort->waitForReadyRead();
                                 readData = serialPort->readAll();
                                 qDebug()<<"Print the response:"<<QString(readData).toUtf8();
                                 elapsedTime = elapsedTimer.elapsed();
                                 qDebug()<<"Time taken :"<<elasedTimer;
                  

                  Actually my next program steps are dependent on the previous step of the serial device.
                  So i need to wait for the response form the device.
                  Can you please explain "place your code after waitforReadyRead in its own slot and connect the signal to that" & "If you have to, there are some ways to force the event loop to process without exiting a function. (ProcessEvents() QEventLoop) ":)

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #8

                  @Kira said in Reading from and writing to the serial port at faster rate using serialPort->waitForReadyRead();:

                  Actually my next program steps are dependent on the previous step of the serial device.
                  So i need to wait for the response form the device.

                  Well,
                  from the top of my head

                  //this is really just the asynchronous call/react of QIODevice
                  myClass::myClass(QObject *parent) : QObject(parent){
                      connect(serialPort, &QSerialPort::readyRead, this, functionPart2);
                  }
                  
                  functionPart1(){
                      qDebug()<<"Enter the loop";
                      elapsedTimer.start();
                      writeData(QString("X  \n").toUtf8());
                  }
                  
                  functionPart2(){
                       readData = serialPort->readAll();
                       qDebug()<<"Print the response:"<<QString(readData).toUtf8();
                       elapsedTime = elapsedTimer.elapsed();
                       qDebug()<<"Time taken :"<<elasedTimer;
                  }
                  
                  //If you like lambdas
                  {
                      qDebug()<<"Enter the loop";
                      elapsedTimer.start();
                      writeData(QString("X  \n").toUtf8());
                      QMetaObject::Connection myConnection;
                      myConnection = connect(serialPort, &QSerialPort::readyRead, [=]{
                           readData = serialPort->readAll();
                           qDebug()<<"Print the response:"<<QString(readData).toUtf8();
                           elapsedTime = elapsedTimer.elapsed();
                           qDebug()<<"Time taken :"<<elasedTimer;
                           disconnect(myConnection);
                     });
                  }
                  
                  

                  //Above code is untested

                  Can you please explain "place your code after waitforReadyRead in its own slot and connect the signal to that" & "If you have to, there are some ways to force the event loop to process without exiting a function. (ProcessEvents() QEventLoop) ":)

                  the idea would be to run a loop in your function, until the socket emits readyRead. To receive the signal, you event loop mustn't be blocked so you either have to periodically call ProcessEvents() or run a qevent loop.

                  But, again, this is bad code design, and there are better/other options here.


                  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.

                  KiraK 1 Reply Last reply
                  0
                  • J.HilkJ J.Hilk

                    @Kira said in Reading from and writing to the serial port at faster rate using serialPort->waitForReadyRead();:

                    Actually my next program steps are dependent on the previous step of the serial device.
                    So i need to wait for the response form the device.

                    Well,
                    from the top of my head

                    //this is really just the asynchronous call/react of QIODevice
                    myClass::myClass(QObject *parent) : QObject(parent){
                        connect(serialPort, &QSerialPort::readyRead, this, functionPart2);
                    }
                    
                    functionPart1(){
                        qDebug()<<"Enter the loop";
                        elapsedTimer.start();
                        writeData(QString("X  \n").toUtf8());
                    }
                    
                    functionPart2(){
                         readData = serialPort->readAll();
                         qDebug()<<"Print the response:"<<QString(readData).toUtf8();
                         elapsedTime = elapsedTimer.elapsed();
                         qDebug()<<"Time taken :"<<elasedTimer;
                    }
                    
                    //If you like lambdas
                    {
                        qDebug()<<"Enter the loop";
                        elapsedTimer.start();
                        writeData(QString("X  \n").toUtf8());
                        QMetaObject::Connection myConnection;
                        myConnection = connect(serialPort, &QSerialPort::readyRead, [=]{
                             readData = serialPort->readAll();
                             qDebug()<<"Print the response:"<<QString(readData).toUtf8();
                             elapsedTime = elapsedTimer.elapsed();
                             qDebug()<<"Time taken :"<<elasedTimer;
                             disconnect(myConnection);
                       });
                    }
                    
                    

                    //Above code is untested

                    Can you please explain "place your code after waitforReadyRead in its own slot and connect the signal to that" & "If you have to, there are some ways to force the event loop to process without exiting a function. (ProcessEvents() QEventLoop) ":)

                    the idea would be to run a loop in your function, until the socket emits readyRead. To receive the signal, you event loop mustn't be blocked so you either have to periodically call ProcessEvents() or run a qevent loop.

                    But, again, this is bad code design, and there are better/other options here.

                    KiraK Offline
                    KiraK Offline
                    Kira
                    wrote on last edited by
                    #9

                    @J.Hilk : Thanks for the reply its clear enough to explain.

                    Regarding the first part earlier i was trying the same way as they are mentioned in example but i my case i had to search for other option.

                    I just wanted to ask one thing don't know whether its funny :o
                    Can i make my execution wait after writeData() and in the readready() slot can i emit a signal so that waiting code execution can start.
                    See the whole idea is to use signals and slot assuming it would take less time than the waitforReadReady().

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      Hi,

                      As suggested in another thread, you should consider modelling your process using a state machine.

                      That way you can exploit properly Qt's asynchronous mechanism while keeping your sequential logic under control.

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

                      KiraK 1 Reply Last reply
                      0
                      • SGaistS SGaist

                        Hi,

                        As suggested in another thread, you should consider modelling your process using a state machine.

                        That way you can exploit properly Qt's asynchronous mechanism while keeping your sequential logic under control.

                        KiraK Offline
                        KiraK Offline
                        Kira
                        wrote on last edited by
                        #11

                        @SGaist : Thanks for your reply.
                        Can you please explain with just small example how it can be achieved using state machine considering the above use case.

                        1 Reply Last reply
                        0
                        • KiraK Offline
                          KiraK Offline
                          Kira
                          wrote on last edited by
                          #12

                          @J-Hilk @Rondog @SGaist @Gojir4 :

                          Guys a small observation which i made would like to share:
                          I think i issue is not with waitForReadReady() i tried the example by implementing readready() signal but the time required is same.

                          The problem is the request:
                          Please find the code below

                          for (int p = 0; p < 5; p++ ){
                                  writeData(QString("X \n").toUtf8());
                                  serialPort->waitForReadyRead(); 
                                  QByteArray readDataArray;
                                  readDataArray =  serialPort->readAll();
                                  qDebug()<<"Data Received"<<QString(readDataArray).toUtf8();
                                  int elapsedCounter = elapsedTimer.elapsed();
                                  qDebug()<<"Required Time:"<<elapsedCounter;
                                  QTest::qSleep(100) // Sleep After the response
                           }
                          

                          If i put a sleep in the above function all the response comes within 1 -2 millisec.
                          But if i remove the sleep first response comes within 1 millisec and the other responses comes after 100 millisec. approx.
                          Earlier i was thought that putting waitForReadReady() would nullify the execution time of the for loop and request would only be send after we receive a proper response. But it seems that next time the loop executes is giving some issue. Not able to figure out why is it happening. Does serial port requires somewait time after the request.

                          Any one any idea why this situation is occurring and how this can be handled.

                          J.HilkJ 1 Reply Last reply
                          0
                          • KiraK Kira

                            @J-Hilk @Rondog @SGaist @Gojir4 :

                            Guys a small observation which i made would like to share:
                            I think i issue is not with waitForReadReady() i tried the example by implementing readready() signal but the time required is same.

                            The problem is the request:
                            Please find the code below

                            for (int p = 0; p < 5; p++ ){
                                    writeData(QString("X \n").toUtf8());
                                    serialPort->waitForReadyRead(); 
                                    QByteArray readDataArray;
                                    readDataArray =  serialPort->readAll();
                                    qDebug()<<"Data Received"<<QString(readDataArray).toUtf8();
                                    int elapsedCounter = elapsedTimer.elapsed();
                                    qDebug()<<"Required Time:"<<elapsedCounter;
                                    QTest::qSleep(100) // Sleep After the response
                             }
                            

                            If i put a sleep in the above function all the response comes within 1 -2 millisec.
                            But if i remove the sleep first response comes within 1 millisec and the other responses comes after 100 millisec. approx.
                            Earlier i was thought that putting waitForReadReady() would nullify the execution time of the for loop and request would only be send after we receive a proper response. But it seems that next time the loop executes is giving some issue. Not able to figure out why is it happening. Does serial port requires somewait time after the request.

                            Any one any idea why this situation is occurring and how this can be handled.

                            J.HilkJ Offline
                            J.HilkJ Offline
                            J.Hilk
                            Moderators
                            wrote on last edited by
                            #13

                            @Kira

                            I never worked with the synchronous approach of IODevice, but I think, there's a reason, why theres a waitForBytesWritten as well.

                            write the data, call waitForBytes written and time the response after that line. I would imagen, that the response time is continously around the 1-2 miliseconds.


                            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.

                            KiraK 1 Reply Last reply
                            0
                            • J.HilkJ J.Hilk

                              @Kira

                              I never worked with the synchronous approach of IODevice, but I think, there's a reason, why theres a waitForBytesWritten as well.

                              write the data, call waitForBytes written and time the response after that line. I would imagen, that the response time is continously around the 1-2 miliseconds.

                              KiraK Offline
                              KiraK Offline
                              Kira
                              wrote on last edited by Kira
                              #14

                              @J.Hilk : Yes you are correcting but what i mentioned above is same for the asynchronous approach also. In example i have mentioned only the synchronous approach:

                              Please find the results below:
                              Note: Time in Millisecond:
                              Synchronous Approach:
                              Serial Port Outgoing data: "X \n"
                              Data Received "L"
                              Time: 1
                              Serial Port Outgoing data: "X \n"
                              Data Received "L"
                              Time: 99
                              Serial Port Outgoing data: "X \n"
                              Data Received "L"
                              Time: 100
                              Serial Port Outgoing data: "X \n"
                              Data Received "L"
                              Time: 98
                              Serial Port Outgoing data: "X \n"
                              Data Received "L"
                              Time: 99

                              Asynchronous approach:
                              Serial Port Outgoing data: "X \n"
                              Serial Port Outgoing data: "X \n"
                              Serial Port Outgoing data: "X \n"
                              Serial Port Outgoing data: "X \n"
                              Serial Port Outgoing data: "X \n"
                              Serial Port Incoming data: "L"
                              Time: 1
                              Serial Port Incoming data: "L"
                              Time: 102
                              Serial Port Incoming data: "L"
                              Time: 202
                              Serial Port Incoming data: "L"
                              Time: 303
                              Serial Port Incoming data: "L"
                              Time: 403

                              Here Asynchronous approach is taking more time that why i mentioned is there a issue with for loop for any other issues. :)

                              1 Reply Last reply
                              0
                              • KiraK Offline
                                KiraK Offline
                                Kira
                                wrote on last edited by Kira
                                #15

                                Guys figured the issue. Its basically the serial device which is talking the time to respond so the request are being queued. Code is basically fine. I tested with the other device and the output is given within 1 to 2 millisec with synchronous and asynchronous thread.

                                One piece of advice should i delete the thread or mark as solved because the issue does not seem to be of from QT Side.

                                1 Reply Last reply
                                1
                                • aha_1980A Offline
                                  aha_1980A Offline
                                  aha_1980
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #16

                                  @Kira said in Reading from and writing to the serial port at faster rate using serialPort->waitForReadyRead();:

                                  One piece of advice should i delete the thread or mark as solved because the issue does not seem to be of from QT Side.

                                  Just mark it as SOLVED, so others later that have the same problem can follow the instructions.

                                  Thanks

                                  Qt has to stay free or it will die.

                                  1 Reply Last reply
                                  0

                                  • Login

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