Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

Setup QSerialPort in a different thread with a timer



  • 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 !


  • Qt Champions 2017

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



  • Please guys, I really need help on this one


  • Qt Champions 2017

    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.


  • Lifetime Qt Champion

    @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



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


  • Lifetime Qt Champion

    @Clarck_D Please show your code ;)



  • @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();
    }
    }

  • Moderators

    @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()?



  • @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 !! :)


Log in to reply