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. QSerialPort - Cannot read more than 64 bytes - Windows - CP2102

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

Scheduled Pinned Locked Moved Solved General and Desktop
qserialportread
7 Posts 5 Posters 1.2k 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.
  • G Offline
    G Offline
    Guillaume Girardot
    wrote on last edited by
    #1

    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
    0
    • KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by KroMignon
      #4

      @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
      4
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #2

        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 Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        G 1 Reply Last reply
        4
        • hskoglundH Offline
          hskoglundH Offline
          hskoglund
          wrote on last edited by hskoglund
          #3

          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
          5
          • KroMignonK Offline
            KroMignonK Offline
            KroMignon
            wrote on last edited by KroMignon
            #4

            @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
            4
            • Christian EhrlicherC Christian Ehrlicher

              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.

              G Offline
              G Offline
              Guillaume Girardot
              wrote on last edited by
              #5

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

              jsulmJ 1 Reply Last reply
              0
              • G Guillaume Girardot

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

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #6

                @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
                0
                • hskoglundH 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 Offline
                  G Offline
                  Guillaume Girardot
                  wrote on last edited by
                  #7

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

                  • Login

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