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. Setup QSerialPort in a different thread with a timer
QtWS25 Last Chance

Setup QSerialPort in a different thread with a timer

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 4 Posters 1.4k 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.
  • C Offline
    C Offline
    Clarck_D
    wrote on last edited by
    #1

    Hello everyone,

    I've been working to set my QSerial port in a separated thread so that my main program to keep it isolated from the GUI processing delay.

    Here is the link to the stackoverflow post i made with my code :

    https://stackoverflow.com/questions/53341179/setup-qthread-with-qtimer-and-qserial

    I tried to put exec() in my ValidationCommunication::run(), put it did not behaved as i expected.. I saw in Qt doc that it is supposed to start event loop, but once started it never go back to my run().

    Is this the right way to handle a QSerialPort ?

    I've been learning Qt by my own so maybe there is some concepts that I misunderstood.

    Thanks !

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      I saw your code in StackOverflow. Did you consider QSerialPort class for this purpose. Which function to be executed in thread ? You are calling start function same thread object again and again. Why are you calling it so many times ?

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      C 1 Reply Last reply
      0
      • dheerendraD dheerendra

        I saw your code in StackOverflow. Did you consider QSerialPort class for this purpose. Which function to be executed in thread ? You are calling start function same thread object again and again. Why are you calling it so many times ?

        C Offline
        C Offline
        Clarck_D
        wrote on last edited by
        #3

        @dheerendra Thanks for your answer.
        Yes I've considered QSerialPort but when I tried my GUI was very slow so I thought it could be good to use a different thread. And actually, I don't really know how this is usually done so i tried this way.
        The function to execute in the thread are reception/transmission of data on ComPort. I'm calling the start function multiple times because it is the only way I've managed to make it run forever in a non-blocking way.

        C aha_1980A 2 Replies Last reply
        0
        • C Clarck_D

          @dheerendra Thanks for your answer.
          Yes I've considered QSerialPort but when I tried my GUI was very slow so I thought it could be good to use a different thread. And actually, I don't really know how this is usually done so i tried this way.
          The function to execute in the thread are reception/transmission of data on ComPort. I'm calling the start function multiple times because it is the only way I've managed to make it run forever in a non-blocking way.

          C Offline
          C Offline
          Clarck_D
          wrote on last edited by Clarck_D
          #4

          Please guys, I really need help on this one

          1 Reply Last reply
          0
          • dheerendraD Offline
            dheerendraD Offline
            dheerendra
            Qt Champions 2022
            wrote on last edited by
            #5

            Just start experimenting now with SerialPort communication in thread. Sub class Thread and reimplement the run method. Try to open the serial Port functions through run() methods. Let me know how it goes.

            Dheerendra
            @Community Service
            Certified Qt Specialist
            http://www.pthinks.com

            1 Reply Last reply
            0
            • C Clarck_D

              @dheerendra Thanks for your answer.
              Yes I've considered QSerialPort but when I tried my GUI was very slow so I thought it could be good to use a different thread. And actually, I don't really know how this is usually done so i tried this way.
              The function to execute in the thread are reception/transmission of data on ComPort. I'm calling the start function multiple times because it is the only way I've managed to make it run forever in a non-blocking way.

              aha_1980A Offline
              aha_1980A Offline
              aha_1980
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @Clarck_D said in Setup QSerialPort in a different thread with a timer:

              es I've considered QSerialPort but when I tried my GUI was very slow so I thought it could be good to use a different thread.

              QtSerialPort is asynchronous, so if your GUI got slow you did something wrong, like using the waitForReadyXxx methods. It is possible to do the communication in a thread, but I don't think it's needed. Threading has it's own implications, so I'm not sure you're taking the easier way now.

              Regards

              Qt has to stay free or it will die.

              C 1 Reply Last reply
              2
              • aha_1980A aha_1980

                @Clarck_D said in Setup QSerialPort in a different thread with a timer:

                es I've considered QSerialPort but when I tried my GUI was very slow so I thought it could be good to use a different thread.

                QtSerialPort is asynchronous, so if your GUI got slow you did something wrong, like using the waitForReadyXxx methods. It is possible to do the communication in a thread, but I don't think it's needed. Threading has it's own implications, so I'm not sure you're taking the easier way now.

                Regards

                C Offline
                C Offline
                Clarck_D
                wrote on last edited by
                #7

                @aha_1980 Thanks guys, I tried to go back to my old code without using blocking methods and I'm able to receive data async but when I try to write data more than once I get this error : "QSerialPort::SerialPortError(ResourceError)" ..

                aha_1980A 1 Reply Last reply
                0
                • C Clarck_D

                  @aha_1980 Thanks guys, I tried to go back to my old code without using blocking methods and I'm able to receive data async but when I try to write data more than once I get this error : "QSerialPort::SerialPortError(ResourceError)" ..

                  aha_1980A Offline
                  aha_1980A Offline
                  aha_1980
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @Clarck_D Please show your code ;)

                  Qt has to stay free or it will die.

                  C 1 Reply Last reply
                  0
                  • aha_1980A aha_1980

                    @Clarck_D Please show your code ;)

                    C Offline
                    C Offline
                    Clarck_D
                    wrote on last edited by
                    #9

                    @aha_1980

                    bool Validation_Board::sendValid(FrameFormat frame)
                     {
                    QByteArray txFrame;
                    bool ackReceptionStatus, eventReceptionStatus, resultsStatus, cmdStatus;
                    
                    /* Clear before sending command */
                    _comPort->clear();
                    
                    /* Get command name */
                    _curCmdName = dataCheck.getCmdName(frame.chipId, frame.msgId);
                    
                    /* Add command name to text printed in console */
                    _testText->append("Command name : \n" + _curCmdName.toUpper() + "\n" );
                    
                    /* List number of events for this command */
                    _listEvents.clear();
                    listCmdEvents();
                    _nbEvent = _listEvents.size();
                    
                    /* Set Timeout value */
                    _timeout = frame.timeout;
                    
                    /* Check if there is commands to send */
                    if (frame.commandToSend)
                    {
                        /* Sending command */
                        txFrame = convertFrameToArray(frame);
                        sendCommand(txFrame);
                    
                        /* Receive command Ack */
                       // ackReceptionStatus = receiveAck(txFrame);
                    }
                    /* Clear before sending next command */
                      _comPort->clear();
                     }
                    
                    
                     void Validation_Board::openSerialPort(QString comPort, int portSpeed)
                    {
                        _comPort = new ComPort(comPort, portSpeed);
                    _comPort->openSerialPort();
                    connect(_comPort, SIGNAL(dataReceived(QByteArray)), this, SLOT(receptionValid(QByteArray)));
                    connect(this, SIGNAL(writeValid(QByteArray)), _comPort, SLOT(write(QByteArray)));
                    }
                    
                            void Validation_Board::closeSerialPort()
                     {
                       _comPort->closeSerialPort();
                     }
                    
                        void ComPort::closeSerialPort()
                     {
                    qDebug() << "CLOSE :" << _portName;
                    if (_serialPort && _serialPort->isOpen())
                    {
                        _serialPort->clear();
                        _serialPort->close();
                    }
                    _isOpen = false;
                     }
                    
                      void ComPort::openSerialPort()
                     {
                    _serialPort = new QSerialPort(this);
                    connect(_serialPort, SIGNAL(readyRead()), this, SLOT(readyRead()));
                    connect(_serialPort, &QSerialPort::bytesWritten,
                            this, &ComPort::handleBytesWritten);
                    connect(_serialPort, &QSerialPort::errorOccurred,
                            this, &ComPort::handleError);
                    _serialPort->setPortName(_portName);
                    _serialPort->setBaudRate(_baudRate);
                    _serialPort->setDataBits(QSerialPort::Data8);
                    _serialPort->setParity(QSerialPort::NoParity);
                    _serialPort->setStopBits(QSerialPort::OneStop);
                    _serialPort->setFlowControl(QSerialPort::NoFlowControl);
                    if (_serialPort->open(QIODevice::ReadWrite))
                    {
                        qDebug() << "Connected :" << _portName;
                        _isOpen = true;
                    }
                    else
                    {
                        qWarning() << "Error while opening" << _portName <<":" << _serialPort->errorString();
                        closeSerialPort();
                    }
                    }
                    
                     void ComPort::handleBytesWritten(qint64 bytes)
                     {
                    qDebug() << "Bytes_written";
                    m_bytesWritten += bytes;
                    if (m_bytesWritten == m_writeData.size()) {
                        m_bytesWritten = 0;
                        qDebug() << "Data successfully sent to port" << _serialPort->portName();
                        //  qDebug() << m_standardOutput;
                        //  QCoreApplication::quit();
                    }
                    }
                    
                    
                     void ComPort::handleError(QSerialPort::SerialPortError serialPortError)
                    {
                    qDebug() << "Error : " << serialPortError;
                    if (serialPortError == QSerialPort::WriteError) {
                        qDebug() << "An I/O error occurred while writing the data to port" <<  _serialPort->portName()
                                 << "error: " <<  _serialPort->errorString();
                        // qDebug() << m_standardOutput;
                        //  QCoreApplication::exit(1);
                    }
                    }
                    
                    void ComPort::write(QByteArray data)
                    {
                    if (_serialPort)
                    {
                        qCritical() << "TEST";
                        qint64 res = _serialPort->write(data.data(), data.length());
                        _serialPort->flush();
                        if (res <= 0)
                            qDebug() << _serialPort->errorString();
                    }
                    }
                    
                    J.HilkJ 1 Reply Last reply
                    0
                    • C Clarck_D

                      @aha_1980

                      bool Validation_Board::sendValid(FrameFormat frame)
                       {
                      QByteArray txFrame;
                      bool ackReceptionStatus, eventReceptionStatus, resultsStatus, cmdStatus;
                      
                      /* Clear before sending command */
                      _comPort->clear();
                      
                      /* Get command name */
                      _curCmdName = dataCheck.getCmdName(frame.chipId, frame.msgId);
                      
                      /* Add command name to text printed in console */
                      _testText->append("Command name : \n" + _curCmdName.toUpper() + "\n" );
                      
                      /* List number of events for this command */
                      _listEvents.clear();
                      listCmdEvents();
                      _nbEvent = _listEvents.size();
                      
                      /* Set Timeout value */
                      _timeout = frame.timeout;
                      
                      /* Check if there is commands to send */
                      if (frame.commandToSend)
                      {
                          /* Sending command */
                          txFrame = convertFrameToArray(frame);
                          sendCommand(txFrame);
                      
                          /* Receive command Ack */
                         // ackReceptionStatus = receiveAck(txFrame);
                      }
                      /* Clear before sending next command */
                        _comPort->clear();
                       }
                      
                      
                       void Validation_Board::openSerialPort(QString comPort, int portSpeed)
                      {
                          _comPort = new ComPort(comPort, portSpeed);
                      _comPort->openSerialPort();
                      connect(_comPort, SIGNAL(dataReceived(QByteArray)), this, SLOT(receptionValid(QByteArray)));
                      connect(this, SIGNAL(writeValid(QByteArray)), _comPort, SLOT(write(QByteArray)));
                      }
                      
                              void Validation_Board::closeSerialPort()
                       {
                         _comPort->closeSerialPort();
                       }
                      
                          void ComPort::closeSerialPort()
                       {
                      qDebug() << "CLOSE :" << _portName;
                      if (_serialPort && _serialPort->isOpen())
                      {
                          _serialPort->clear();
                          _serialPort->close();
                      }
                      _isOpen = false;
                       }
                      
                        void ComPort::openSerialPort()
                       {
                      _serialPort = new QSerialPort(this);
                      connect(_serialPort, SIGNAL(readyRead()), this, SLOT(readyRead()));
                      connect(_serialPort, &QSerialPort::bytesWritten,
                              this, &ComPort::handleBytesWritten);
                      connect(_serialPort, &QSerialPort::errorOccurred,
                              this, &ComPort::handleError);
                      _serialPort->setPortName(_portName);
                      _serialPort->setBaudRate(_baudRate);
                      _serialPort->setDataBits(QSerialPort::Data8);
                      _serialPort->setParity(QSerialPort::NoParity);
                      _serialPort->setStopBits(QSerialPort::OneStop);
                      _serialPort->setFlowControl(QSerialPort::NoFlowControl);
                      if (_serialPort->open(QIODevice::ReadWrite))
                      {
                          qDebug() << "Connected :" << _portName;
                          _isOpen = true;
                      }
                      else
                      {
                          qWarning() << "Error while opening" << _portName <<":" << _serialPort->errorString();
                          closeSerialPort();
                      }
                      }
                      
                       void ComPort::handleBytesWritten(qint64 bytes)
                       {
                      qDebug() << "Bytes_written";
                      m_bytesWritten += bytes;
                      if (m_bytesWritten == m_writeData.size()) {
                          m_bytesWritten = 0;
                          qDebug() << "Data successfully sent to port" << _serialPort->portName();
                          //  qDebug() << m_standardOutput;
                          //  QCoreApplication::quit();
                      }
                      }
                      
                      
                       void ComPort::handleError(QSerialPort::SerialPortError serialPortError)
                      {
                      qDebug() << "Error : " << serialPortError;
                      if (serialPortError == QSerialPort::WriteError) {
                          qDebug() << "An I/O error occurred while writing the data to port" <<  _serialPort->portName()
                                   << "error: " <<  _serialPort->errorString();
                          // qDebug() << m_standardOutput;
                          //  QCoreApplication::exit(1);
                      }
                      }
                      
                      void ComPort::write(QByteArray data)
                      {
                      if (_serialPort)
                      {
                          qCritical() << "TEST";
                          qint64 res = _serialPort->write(data.data(), data.length());
                          _serialPort->flush();
                          if (res <= 0)
                              qDebug() << _serialPort->errorString();
                      }
                      }
                      
                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #10

                      @Clarck_D
                      I'm not sure, but I think it may be your clear() command. That clears the internal class buffers and the UART (driver) buffers. I think, you actually wanted to call flush()?


                      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.

                      C 1 Reply Last reply
                      4
                      • J.HilkJ J.Hilk

                        @Clarck_D
                        I'm not sure, but I think it may be your clear() command. That clears the internal class buffers and the UART (driver) buffers. I think, you actually wanted to call flush()?

                        C Offline
                        C Offline
                        Clarck_D
                        wrote on last edited by
                        #11

                        @J.Hilk Omg.. I removed it and it works !
                        No, I do wanted to clear my ComPort twice, before and after send, to be perfectly sure that there in no unwanted data.. Thanks alot !! :)

                        1 Reply Last reply
                        1

                        • Login

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