Qt Forum

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

    Update: Forum Guidelines & Code of Conduct

    Solved QSerialPort - Cannot read more than 64 bytes - Windows - CP2102

    General and Desktop
    qserialport read
    5
    7
    540
    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.
    • G
      Guillaume Girardot last edited by

      Hi,

      I am developing a communication interface for an industrial device using Qt.

      I have following problem :

      • I send from my PC a request to my embedded device (no problem here)
      • When receiving the request, the embedded device sends to the PC 77 bytes that holds its configuration.
      • With Qt, I receive 64 bytes only instead of the 77 expected.
      • I made a Python script and with it, I do receive the 77 bytes so I believe the problem comes from my Qt code.

      Here is my Qt code :

      #include <QCoreApplication>
      #include <QSerialPort>
      #include <QDebug>
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          //
          // Serial port object.
          //
          QSerialPort *port = new QSerialPort();
      
          //
          // Prepare the port.
          //
          port->setPortName("COM8");
          qDebug() << "setBaudRate   " << port->setBaudRate(921600);
          qDebug() << "setDataBits   " << port->setDataBits(QSerialPort::Data8);
          qDebug() << "setParity     " << port->setParity(QSerialPort::NoParity);
          qDebug() << "setStopBits   " << port->setStopBits(QSerialPort::OneStop);
          qDebug() << "setFlowControl" << port->setFlowControl(QSerialPort::NoFlowControl);
          qDebug() << "open          " << port->open(QIODevice::ReadWrite);
      
          //
          // Send the request.
          //
          const char request[4] = { 0x06, 0x00, 0x02, 0x10 };
          qDebug() << "";
          qDebug() << "write" << port->write(request, 4);
          qDebug() << "waitForBytesWritten" << port->waitForBytesWritten(1000); // milliseconds
      
          //
          // Read the port.
          //
          qDebug() << "";
          qDebug() << "waitForReadyRead" << port->waitForReadyRead(1000); // milliseconds
          char answer[77];
          qint64 bytesReceived = port->read(&answer[0], 77);
      
          //
          // Close the port.
          //
          port->close();
      
          //
          // Print data.
          //
          QList<quint8> quint8Array;
          for (quint16 i = 0; i < bytesReceived; ++i)
          {
              quint8Array.append((quint8)(answer[i]));
          }
      
          qDebug() << "";
          qDebug() << "Received" << bytesReceived << "bytes";
          qDebug() << quint8Array;
      
          return a.exec();
      }
      

      The result is :

      qt_result.png

      Now, here is the Python code that works well:

      # Imports
      import sys, serial
      
      # Serial object
      ser = serial.Serial()
      
      # Configuration
      ser.port     = "COM8"
      ser.baudrate = 921600
      ser.bytesize = serial.EIGHTBITS
      ser.parity   = serial.PARITY_NONE
      ser.stopbits = serial.STOPBITS_ONE
      ser.timeout  = 1.0 # seconds
      
      # Try to open the port
      try:
          ser.open()
          is_ser_open = True
      except Exception as e:
          print ("The COM Port \"" + COM_PORT + "\" cannot be opened!")
          print ("Fix the issue and try again.")
          sys.exit()
      
      # Write
      ser.write([0x06, 0x00, 0x02, 0x10])
      
      # Read
      data = ser.read(77)
      
      # Close the port
      ser.close()
      
      # Print
      txt = "["
      for i in range(0, len(data) - 1):
          txt += str(int(data[i])) + ", "
      txt = txt[:-2] + "]"
      
      print("Received " + str(len(data)) + " bytes.")
      print(txt)
      

      And the Python result:

      python_result.png

      My embedded device uses a MCU together with a USB Bridge from Silicon Lab :
      https://www.silabs.com/interface/usb-bridges/usbxpress/device.cp2102n-gqfn28

      I am using Qt Creator with the kit Desktop Qt 5.14.1 MinGW 32 bits on a Windows 10 PC.

      Can you help me with that?

      Thank in advance,

      Guillaume

      1 Reply Last reply Reply Quote 0
      • KroMignon
        KroMignon last edited by KroMignon

        @Guillaume-Girardot said in QSerialPort - Cannot read more than 64 bytes - Windows - CP2102:

        //
        // Read the port.
        //
        qDebug() << "";
        qDebug() << "waitForReadyRead" << port->waitForReadyRead(1000); // milliseconds
        char answer[77];
        qint64 bytesReceived = port->read(&answer[0], 77);
        

        If you want to do it in pooling mode, I would suggest you to change the code as follow:

            //
            // Read the port.
            //
            QElaspedTimer t;
            t.start();
            QByteArray reply;
            while(repy.size() < 77 && !t.hasExpired(2000)) {
                if(port->waitForReadyRead(100))
                    reply.append(port->readAll());
            }
        
        

        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

        1 Reply Last reply Reply Quote 4
        • Christian Ehrlicher
          Christian Ehrlicher Lifetime Qt Champion last edited by

          Use signals / slots instead waitForReadyRead() - there is no guarantee that when waitForReadyRead() finishes all of your data is already there. It my work but must not.

          Qt has to stay free or it will die.

          G 1 Reply Last reply Reply Quote 4
          • hskoglund
            hskoglund last edited by hskoglund

            Just guessing but it looks like those last 13 bytes are lost because you began reading too fast, so you only get the first USB packet of 64 bytes.

            So either do as @Christian-Ehrlicher says above (best solution), or as a test/short-term solution, try doing a 2nd waitForReadyRead(1000) after the first, i.e. after you've printed (qdebug()) out the first 64 bytes.

            G 1 Reply Last reply Reply Quote 5
            • KroMignon
              KroMignon last edited by KroMignon

              @Guillaume-Girardot said in QSerialPort - Cannot read more than 64 bytes - Windows - CP2102:

              //
              // Read the port.
              //
              qDebug() << "";
              qDebug() << "waitForReadyRead" << port->waitForReadyRead(1000); // milliseconds
              char answer[77];
              qint64 bytesReceived = port->read(&answer[0], 77);
              

              If you want to do it in pooling mode, I would suggest you to change the code as follow:

                  //
                  // Read the port.
                  //
                  QElaspedTimer t;
                  t.start();
                  QByteArray reply;
                  while(repy.size() < 77 && !t.hasExpired(2000)) {
                      if(port->waitForReadyRead(100))
                          reply.append(port->readAll());
                  }
              
              

              It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

              1 Reply Last reply Reply Quote 4
              • G
                Guillaume Girardot @Christian Ehrlicher last edited by

                @Christian-Ehrlicher thanks for the help!
                Which signal(s) do you recommend to use? From the IODevice class (on which is based QSerialPort) I can see the readyRead signal, and my understanding is that the waitForReadyRead function is actually waiting for that signal. Are they other signals?
                The readyRead is triggered once data is available, but we do not know how much (that was my problem actually).

                jsulm 1 Reply Last reply Reply Quote 0
                • jsulm
                  jsulm Lifetime Qt Champion @Guillaume Girardot last edited by

                  @Guillaume-Girardot said in QSerialPort - Cannot read more than 64 bytes - Windows - CP2102:

                  The readyRead is triggered once data is available, but we do not know how much

                  That's why you need to read every time readyRead is triggered and accumulate the data in a buffer, until you got everything.

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply Reply Quote 0
                  • G
                    Guillaume Girardot @hskoglund last edited by

                    @hskoglund thanks for the help! I did not try your solution, but I guess it should work because the solution from @KroMignon works and you have the same diagnostic.

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