Problems with RTS management with QtSerialPort



  • Hi all.

    I am implementing a communicatin protocol over RS485 and I am having problems with the RTS management.
    I am QSerialPort class in Qt 5.6.1.

    I put UP the RTS when I am going to trasnmit a frame data and when the "bytesWritten" signal is received I put it DOWN in the connected slot.
    If I have no answer to the above sent frame, I retransmit it. But in the retranmission (in the same slot as above) the RTS signal is put down before all the data have been retransmitted.

    The up and down of the signal is done with the method "setRequestToSend".

    This is the code the mos relevant related code:

    Port configuration
    if(mSerialPort->open(QIODevice::ReadWrite)){
    currentTxId = 0;
    mSerialPort->setBaudRate(QSerialPort::Baud115200);
    mSerialPort->setDataBits(QSerialPort::Data8);
    mSerialPort->setFlowControl(QSerialPort::NoFlowControl);
    mSerialPort->setStopBits(QSerialPort::OneStop);
    mSerialPort->setParity(QSerialPort::NoParity);

        mSerialPort->setDataTerminalReady(true);       
    
        bool rtsUP = mSerialPort->isRequestToSend();
        mSerialPort->setRequestToSend(!rtsUP);
    
       connect(mSerialPort, SIGNAL(readyRead()), this, SLOT(onDataAvailable()));
       connect(mSerialPort, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
    

    }

    Send Data and RTS Up
    bool AppProtocolHandler::sendFrameWithACK(const QByteArray frame)
    {
    QByteArray txframe = frame;
    txframe.push_front(flag_STX);
    txframe.push_front(flag_DLE);
    txframe.push_back(flag_DEL);
    txframe.push_back(flag_ETX);

     //Start frame retransmission Timer
    m_txTimer->start(FRAME_RETRANSMISION_TIME);
    
    bool rtsUP = mSerialPort->isRequestToSend();
    if (rtsUP){
        mSerialPort->setRequestToSend(false);
    }
    
    qint64 frameLenght = static_cast<qint64> (frame.at(0));
    qint64 txlen = mSerialPort->write(txframe, frameLenght);
    
    if (mSerialPort->waitForBytesWritten(500)){
        m_txframe = frame;
        m_pendingFrames.insert(static_cast<int>(txframe.at(5)), static_cast<t_prot_cmd>(txframe.at(6)));
         return true;
    }
    else
    {
        qDebug()<< "AppProtocolHandler::sendFrameWithACK waitForBytesWritten(500) = FALSE";
        mSerialPort->setRequestToSend(true);
        return false;
    }
    

    }

    End Send Data and RTS Down
    void AppProtocolHandler::onBytesWritten(qint64 nBytes)
    {
    qint64 frameLenght = static_cast<qint64> (m_txframe.at(0));

    if (nBytes == frameLenght)
    {
        bool rtsUP = mSerialPort->isRequestToSend();
        if (!rtsUP){
            mSerialPort->setRequestToSend(true);
        }
    }
    

    }

    Any help or experience would be appreciated.
    Thanks!!


  • Qt Champions 2017

    Hi @iaguirre,

    on which platform are you?

    I guess your problem is most likely, that onBytesWritten is called when QSerialPort has written the data to the operating system (which has it's own buffers), but that does not mean the data is actually (completely) written on the serial line (and therefore not completely received from the other side).

    We had a problem like this some month ago, where a Linux flush call helped; I just don't find it now :(

    In any case, this will mean you have to block your program so it should preferable be done in a thread.

    Edit: found it: https://forum.qt.io/topic/83399/qtserialport-blocking-write-in-raspberry-pi-raspbian-pixel



  • We are running the program on Linux.

    When you say Linux flush call, you mean QtSerialPort flush method?

    Thanks again.


  • Qt Champions 2017

    Hi @iaguirre,

    We are running the program on Linux.

    Good. The solution I have for you is not portable...

    When you say Linux flush call, you mean QtSerialPort flush method?

    The guy in the other thread cleared both the QtSerialPort (with flush) and Kernel buffers (with tcdrain) and it worked for him. Please see: https://forum.qt.io/topic/83399/qtserialport-blocking-write-in-raspberry-pi-raspbian-pixel/7

    As said, keep in mind that it will block your program for the time it takes to write the bytes.



  • Thanks for your answer.
    It doesn´t work for me.


  • Qt Champions 2017

    Hi @iaguirre,

    How did you implement it?
    How did you check that it does not work as expected?



  • Hi again.

    The best solution has been to enable RTS after open the port, following the instructions readed here:
    https://github.com/torvalds/linux/blob/master/Documentation/serial/serial-rs485.txt

    You should verify if your linux kernel driver supports it.

    Regards


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.