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 troubles on Windows 10

QSerialPort troubles on Windows 10

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 4 Posters 3.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.
  • K Offline
    K Offline
    kuzulis
    Qt Champions 2020
    wrote on last edited by
    #5

    @gav007 ,

    Try to do a simple loopback test at first (just connect the RX and TX pins).

    1 Reply Last reply
    1
    • G Offline
      G Offline
      gav007
      wrote on last edited by
      #6

      Unfortunately it did not work under Linux either (Ubuntu 18.04 + Qt 5.9.5). That's weird !
      Error and symptoms are identical.

      1 Reply Last reply
      0
      • K Offline
        K Offline
        kuzulis
        Qt Champions 2020
        wrote on last edited by
        #7

        This means that an issue somewhere in your code or your HW.

        1 Reply Last reply
        0
        • G Offline
          G Offline
          gav007
          wrote on last edited by
          #8

          The trouble appears on 2 different HW. Hence the HW should not be at fault.
          I would rather point the SW. Here is the full class code :

          #ifndef OPLUSCOMM_H
          #define OPLUSCOMM_H
          
          #include <QObject>
          #include <QSerialPort>
          
          
          class OctoPlusComm : public QSerialPort
          {
          
              Q_OBJECT
          
          signals:
          
              void dataRead( const QByteArray & data );
              void dataSent( const QByteArray & data );
          
              void newCommunicationStep( const QString & step );
          
          public:
          
              struct Settings {
                  QString name;
                  qint32 baudRate;
                  QString stringBaudRate;
                  QSerialPort::DataBits dataBits;
                  QString stringDataBits;
                  QSerialPort::Parity parity;
                  QString stringParity;
                  QSerialPort::StopBits stopBits;
                  QString stringStopBits;
                  QSerialPort::FlowControl flowControl;
                  QString stringFlowControl;
                  bool localEchoEnabled;
              };
          
              enum CommunicationStep {
                  IdleStep,
                  StartCommandStep,
                  ROMVersionStep,
                  EEPROMSizeStep,
                  RAMSizeStep,
                  UploadStep
              };
          
              OctoPlusComm(QObject * parent = nullptr);
              virtual ~OctoPlusComm();
          
              bool openPort( const Settings & settings );
          
              static const QString stepText( const CommunicationStep step );
          
          private slots:
          
              void readAll();
          
          private:
          
              void nextStep();
              void setCommunicationStep( const CommunicationStep step );
              bool checkReception();
              bool checkStartCommand();
              bool checkRomVersion( QByteArray & frame );
              bool checkEepromSize( QByteArray & frame );
              bool checkRamSize( QByteArray & frame );
              bool uploadInProgress();
          
          private:
          
              CommunicationStep mCommStep;
          
              QByteArray mReceptionBuffer;
          
          };
          
          #endif // OPLUSCOMM_H
          

          With the implementation :

          OctoPlusComm::OctoPlusComm(QObject * parent) : QSerialPort(parent), mCommStep(IdleStep)
          {
              connect(this, &OctoPlusComm::readyRead, this, &OctoPlusComm::readAll);
          }
          
          OctoPlusComm::~OctoPlusComm() {}
          
          bool OctoPlusComm::openPort( const Settings & settings )
          {
              setPortName(settings.name);
              setBaudRate(settings.baudRate);
              setDataBits(settings.dataBits);
              setParity(settings.parity);
              setStopBits(settings.stopBits);
              setFlowControl(settings.flowControl);
              if ( !open(QIODevice::ReadWrite) ) {
                  setErrorString("Failed to open serial port");
                  emit errorOccurred(QSerialPort::OpenError);
                  return false;
              }
              mCommStep = IdleStep;
              mReceptionBuffer.clear();
              return true;
          }
          
          void OctoPlusComm::readAll()
          {
              qDebug() << "Ready to read";
          
              QByteArray newData = QSerialPort::readAll();
              mReceptionBuffer.append(newData);
          
              emit dataRead( newData );
          
              if ( checkReception() )
              {
                  nextStep();
              }
          }
          
          void OctoPlusComm::nextStep()
          {
              bool bOk = true;
              QByteArray nextFrame;
              nextFrame.clear();
              bOk = checkStartCommand() || checkRomVersion( nextFrame ) || checkEepromSize( nextFrame ) ||
                      checkRamSize( nextFrame ) || uploadInProgress();
              mReceptionBuffer.clear();
              if ( bOk )
              {
                  if ( nextFrame.isEmpty() )
                  {
                      nextFrame.append(COMM_RECEIVE_OK);
                      nextFrame.append(COMM_REC_OK_CHECKSUM);
                      nextFrame.append(COMM_FRAME_END);
                      qDebug() << "Ack reception";
                  }
                  write( nextFrame );
                  emit dataSent( nextFrame );
              }
              else
              {
                  QByteArray request;
                  request.append(mReceptionBuffer.at(1));
                  request.append(mReceptionBuffer.at(2));
                  setErrorString(tr("Unknown request : %1").arg(Utility::displayBuffer(request)));
                  emit errorOccurred(QSerialPort::UnknownError);
              }
          }
          
          void OctoPlusComm::setCommunicationStep( const CommunicationStep step )
          {
              mCommStep = step;
              emit newCommunicationStep( stepText( mCommStep ) );
          }
          
          bool OctoPlusComm::checkReception()
          {
              if (mReceptionBuffer.size() > 0)
              {
                  if ( mReceptionBuffer.endsWith(0x0D) )
                  {
                      qDebug() << "Reception complete";
                      int n = mReceptionBuffer.lastIndexOf('#');
                      if ( n > 0 )
                      {
                          mReceptionBuffer.remove(0, n);
                          qDebug() << "Reception cleaned (" << n << ") : " << Utility::displayBuffer(mReceptionBuffer);
                      }
                      return true;
                  }
          
                  qDebug() << "Reception incomplete";
              }
              else
              {
                  qDebug() << "Empty reception !";
              }
              return false;
          }
          
          bool OctoPlusComm::checkStartCommand()
          {
              if ( mReceptionBuffer.startsWith('#') &&
                   (mReceptionBuffer.indexOf(COMM_START_COMMAND, 1) == 1) )
              {
                  qDebug() << "Start command received";
                  setCommunicationStep( StartCommandStep );
                  return true;
              }
          //    setErrorString(tr("Expect start command, received %1").arg(Utility::displayBuffer(mReceptionBuffer)));
          //    emit errorOccurred(QSerialPort::UnknownError);
              return false;
          }
          
          bool OctoPlusComm::checkRomVersion( QByteArray & frame )
          {
              if ( mReceptionBuffer.startsWith('#') &&
                   (mReceptionBuffer.indexOf(COMM_ROM_VERSION_COMMAND, 1) == 1) )
              {
                  qDebug() << "ROM version request";
                  setCommunicationStep( ROMVersionStep );
          
                  frame.append(COMM_RECEIVE_OK);
                  frame.append(COMM_ROM_VERSION_RESPONSE);
                  frame.append(COMM_FRAME_END);
                  return true;
              }
              return false;
          }
          
          bool OctoPlusComm::checkEepromSize( QByteArray & frame )
          {
              if ( mReceptionBuffer.startsWith('#') &&
                   (mReceptionBuffer.indexOf(COMM_EEPROM_SIZE_COMMAND, 1) == 1) )
              {
                  qDebug() << "EEPROM size request";
                  setCommunicationStep( EEPROMSizeStep );
          
                  frame.append(COMM_RECEIVE_OK);
                  frame.append(COMM_EEPROM_SIZE_RESPONSE);
                  frame.append(COMM_FRAME_END);
                  return true;
              }
              return false;
          }
          
          bool OctoPlusComm::checkRamSize( QByteArray & frame )
          {
              if ( mReceptionBuffer.startsWith('#') &&
                   (mReceptionBuffer.indexOf(COMM_RAM_SIZE_COMMAND, 1) == 1) )
              {
                  qDebug() << "RAM size request";
          
                  setCommunicationStep( RAMSizeStep );
          
                  frame.append(COMM_RECEIVE_OK);
                  frame.append(COMM_RAM_SIZE_RESPONSE);
                  frame.append(COMM_FRAME_END);
                  return true;
              }
              return false;
          }
          
          bool OctoPlusComm::uploadInProgress()
          {
              if ( mReceptionBuffer.startsWith('#') &&
                   (mReceptionBuffer.indexOf(COMM_UPLOAD_COMMAND, 1) == 1) )
              {
                  qDebug() << "Upload data";
          
                  setCommunicationStep( UploadStep );
          
                  return true;
              }
              return false;
          }
          
          const QString OctoPlusComm::stepText( const CommunicationStep step )
          {
              switch ( step )
              {
              case IdleStep:          return tr("Idle");
              case StartCommandStep:  return tr("Start command");
              case ROMVersionStep:    return tr("ROM version check");
              case EEPROMSizeStep:    return tr("EEPROM size check");
              case RAMSizeStep:       return tr("RAM size check");
              case UploadStep:        return tr("Data upload");
              }
              return tr("???");
          }
          

          Does anyone see what I would do wrong ?
          Many thanks for any support.

          1 Reply Last reply
          0
          • K Offline
            K Offline
            kuzulis
            Qt Champions 2020
            wrote on last edited by kuzulis
            #9

            As I sad before, you should to create a simple loopback test at first, to make sure that all data transferred/received. Because nobody will be check your code.

            1 Reply Last reply
            0
            • G Offline
              G Offline
              gav007
              wrote on last edited by
              #10

              I wrote the loopback test. As expected it worked. The reported ticket is related to a timing issue. The loopback test has nothing to do with this. I lost my time.

              I added some delay measurements (OK, it's intrusive but at least, it gives some clues) and observe a delay of about 10 msec between the write operation and the reception of the bytesWritten signal and sometimes a delay of the same level between the readAll call and the write operation. Those delays are observed even if the signals are emitted after the read/write operations.
              If a remove all the emitted signals, those delays are no more observed. The communication is then successful.
              I then check what is done with the dataRead and the dataSent signals : these are only display operations in QPlainTextEdit widget :

              mTextConsole->insertPlainText( QString(data) );
              
              mHexConsole->insertPlainText( QString(data.toHex(' ')) );
              

              This should not justify 10 msec delays.

              So. Since I could not reach a good confidence level with QSerialPort, I abandoned the Qt framework for JAVA. Now I got my solution. In consequence this ticket can be closed for me.

              This is my first disappointing experience with Qt ! Too bad !

              Thanks for the support.
              Best regards.

              J.HilkJ 1 Reply Last reply
              0
              • G gav007

                I wrote the loopback test. As expected it worked. The reported ticket is related to a timing issue. The loopback test has nothing to do with this. I lost my time.

                I added some delay measurements (OK, it's intrusive but at least, it gives some clues) and observe a delay of about 10 msec between the write operation and the reception of the bytesWritten signal and sometimes a delay of the same level between the readAll call and the write operation. Those delays are observed even if the signals are emitted after the read/write operations.
                If a remove all the emitted signals, those delays are no more observed. The communication is then successful.
                I then check what is done with the dataRead and the dataSent signals : these are only display operations in QPlainTextEdit widget :

                mTextConsole->insertPlainText( QString(data) );
                
                mHexConsole->insertPlainText( QString(data.toHex(' ')) );
                

                This should not justify 10 msec delays.

                So. Since I could not reach a good confidence level with QSerialPort, I abandoned the Qt framework for JAVA. Now I got my solution. In consequence this ticket can be closed for me.

                This is my first disappointing experience with Qt ! Too bad !

                Thanks for the support.
                Best regards.

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

                @gav007
                I don't think, that 20 ms to create a QString from raw data and than inserting it to a plain textview + (eventual) repaint of the the ui is totoally unreasonable. Especially, if you're using the old (qt4) styled syntax for QObject::connect. Those come with a noticeable overhead during execution.

                This is the reason why I usually move my IO-communication in its own thread.
                That said, giving your connects a 5th parameter Qt::QueuedConnection may already be enough to make your Qt-solution workable.


                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.

                1 Reply Last reply
                1
                • K Offline
                  K Offline
                  kuzulis
                  Qt Champions 2020
                  wrote on last edited by
                  #12

                  @gav007 said in QSerialPort troubles on Windows 10:

                  observe a delay of about 10 msec between the write operation and the reception of the bytesWritten signal

                  Your words is empty without of a real example. In my case I got an expected delay in this example:

                  #include <QCoreApplication>
                  #include <QSerialPort>
                  #include <QElapsedTimer>
                  #include <QDebug>
                  
                  int main(int argc, char *argv[])
                  {
                      QCoreApplication a(argc, argv);
                  
                      QSerialPort sp("COM1");
                  
                      // it opens with 9600 bauds by default
                      if (!sp.open(QIODevice::ReadWrite))
                          return 0;
                  
                      QElapsedTimer et;
                  
                      auto write = [&]() {
                          et.start();
                          QByteArray ba(256, 0);
                          sp.write(ba);
                      };
                  
                      QObject::connect(&sp, &QSerialPort::bytesWritten, [&](qint64 bytes) {
                          qDebug() << et.elapsed();
                          write();
                      });
                  
                      write();
                  
                      return a.exec();
                  }
                  

                  It printed out:

                  265
                  265
                  266
                  266
                  265
                  

                  that is right, because according to this calculation, the expected delay should be:

                  baudrate = 9600 bits per second
                  bytes per second = 9600 / (1start bit + 8 data bits + 1 stop bit) = 960 bytes per second
                  256 bytes in seconds = 256 / 960 = 0.266(6)

                  • If I try to send ~10 bytes, then I got ~10 msecs. It is true.
                  • if I try to send ~1 byte, then I got ~0-1 msec. It is true.

                  So, I don't know what are you talking about.

                  1 Reply Last reply
                  1
                  • G Offline
                    G Offline
                    gav007
                    wrote on last edited by
                    #13

                    @kuzulis said in QSerialPort troubles on Windows 10:

                    Because nobody will be check your code.

                    @kuzulis said in QSerialPort troubles on Windows 10:

                    Your words is empty without of a real example

                    How surprising you can be !

                    Again, if you read my post, I'm more worried about the 10 msec for 2 insertions in QPlainTextEdit widget than the delay between the write operation and the bytesWritten signal.
                    Where you're right, I did not mention the size of the handled buffer : it varies between 4 and 12 bytes. Not enough to spend 10 msec for sending !

                    So @kuzulis, do not worry about my problem. I'm sure there will be people on this forum willing to help me. Thanks.

                    @J-Hilk ,
                    Thanks for this remark. I would not expect the QSerialPort signals to be managed in the same thread as the GUI elements. Hence using the default AutoConnection type should make the difference. However, I forced all the connections between the QSerialPort object and the GUI elements to be queued and unfortunately the behavior remains the same.

                    Best regards

                    1 Reply Last reply
                    0
                    • K Offline
                      K Offline
                      kuzulis
                      Qt Champions 2020
                      wrote on last edited by kuzulis
                      #14

                      @gav007 said in QSerialPort troubles on Windows 10:

                      it varies between 4 and 12 bytes. Not enough to spend 10 msec for sending !

                      Again, your words is empty. I already have provided the test above, you can try it with your HW, with your baudrate && data length.

                      @gav007 said in QSerialPort troubles on Windows 10:

                      do not worry about my problem

                      I'm do not worry, good luck!

                      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