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 3 Jun 2020, 17:13 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
    • K Offline
      K Offline
      KroMignon
      wrote on 4 Jun 2020, 06:40 last edited by KroMignon 6 Apr 2020, 06:40
      #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
      • C Online
        C Online
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on 3 Jun 2020, 17:20 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 Jun 2020, 07:31
        4
        • H Offline
          H Offline
          hskoglund
          wrote on 3 Jun 2020, 17:48 last edited by hskoglund 6 Mar 2020, 18:03
          #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 4 Jun 2020, 07:55
          5
          • K Offline
            K Offline
            KroMignon
            wrote on 4 Jun 2020, 06:40 last edited by KroMignon 6 Apr 2020, 06:40
            #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
            • C Christian Ehrlicher
              3 Jun 2020, 17:20

              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 4 Jun 2020, 07:31 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).

              J 1 Reply Last reply 4 Jun 2020, 07:38
              0
              • G Guillaume Girardot
                4 Jun 2020, 07:31

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

                J Offline
                J Offline
                jsulm
                Lifetime Qt Champion
                wrote on 4 Jun 2020, 07:38 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
                • H hskoglund
                  3 Jun 2020, 17:48

                  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 4 Jun 2020, 07:55 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

                  4/7

                  4 Jun 2020, 06:40

                  • Login

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