QSerialPort High Speed Serial Reading from board and Logging



  • Hi everyone , i'm newbie to QT. Just struggled with QT about 2 months but i got basic informations about my project. I tried to explain my issue in the best way. Sorry for writing errors. :)

    Here is the deal. I'm trying to get sensor values from T.I instruments' Hercules Board which have TMS570LS1227 microcontroller. Main purpose is getting the desired packages from sensor which is connected to board and log it to text file. I managed sending or receiving , logging tasks. But i read so much about QSerialPort losing data and etc. topics. I couldn't figure it out.

    For testing the data i'm getting from board i'm only sending 5 byte short number. 1st byte is TypeCheck ( float,decimal and bla bla) for parsing the received package. 2nd and 3rd byte is the short value ( have a union struct no error about it) and the other 2 bytes is CRC(Cyclic Redundancy Check) value of the package.
    This was just an information about what i'm trying to do.

    I'm sending an counter variable to QT. Sending frequency have to be 10kHz. Means that 10000*5(bytes)*8(bit) = 400000 bit baudrate i should have. I searched forums about QT and it's saying that baudrate 600000 is available in QT. So i set my serial port according to that.

    The struggle is that : When i'm getting data from board, first package is not coming like just "5 bytes to read". Incoming bytes in internal serial read buffer showing sometimes 10, sometimes 35, sometimes 500, it depends on how fast i'm doing the job on QT. I managed it with using a Circular Buffer to keep data without losing any of it. E.g: With debugging i saw that; when first package came to QT i'm getting let's say 50 bytes. I'm checking the values of the buffer and it's true.( in this case 50/5=10; last sended number i have to receive is 10). But then second package is coming and i'm checking the received buffer and first 5 byte didn't equal to "11". It can be "45". Then it follows "45,46,47.." .

    This means i'm losing data. Why i'm struggling with that ? Is QT doesn't support higher baudrate in QSerialPort ?

    I wanted to give the codes as well. You guys can check anything about it. Feel free to critisize my coding as well i wanted my skills to developed :).

    ReadyRead Signal is connected to the slot like that.

    serial = new QSerialPort(this);
        connect(serial,SIGNAL(readyRead()),this,SLOT(toReadThePort()),Qt::QueuedConnection);
    

    Initializing Serial Port code:

    void MyObject::InitSerialPort()
    {
                /*Circular Buffer Initializing*/
    
        CircularBufferManager_ApiInit(&SerialCircularBufferManager_s,
                                      &SerialBuffer[0],
                                      1,
                                      3000);
    
                //Configure Port Settings;
    
        static bool PortIsOpen;
        serial->setPortName("COM7");
        serial->setBaudRate(600000); // 460800
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);
        serial->setReadBufferSize(400);
    
            if(!serial->isOpen())
            {
                PortIsOpen = serial->open(QIODevice::ReadWrite); // Open the Port;
                if(PortIsOpen == 1)
                    qDebug()<<"Port Has Opened !";
            }
        serial->clear(QSerialPort::AllDirections);
    
    
        LogData(GonnaBeWrittenFile,StrBuffer); // Just for writing Header part of the log text.
    
    }
    

    Here is the ReadyRead Signal's connected slot code:

    void MyObject::toReadThePort()
    {
    
        static uint8 testData[400];
        static int counter=0;
    
        NumberOfBytesToRead = serial->bytesAvailable();
        if(NumberOfBytesToRead > 0 && serial->isReadable())
        {
    
            ArrayBuffer.clear();
            ArrayBuffer = serial->readAll();
            remain = (NumberOfBytesToRead % ExpectedPacketLength);
    
            memcpy(testData,ArrayBuffer,(NumberOfBytesToRead-remain));
    
            for(counter=0; counter < (NumberOfBytesToRead-remain); counter++)
            {
            CircularBufferManager_ApiPush(&SerialCircularBufferManager_s,(void*)&testData[counter]);
            }
            procCounter += (NumberOfBytesToRead-remain);
            serial->clear(QSerialPort::AllDirections); // Clear Serial Write and Read Internal Buffers
    
            receiveData();
    
        }
    
    }
    

    for last concern receivedata() function is that just the concerned part :

             while(pulledData !='s')
             {
                 CircularBufferManager_ApiPull(&SerialCircularBufferManager_s,&pulledData);
                 qCnt++;
             }
    
    
            for(qCnt=0; qCnt<(NumberOfBytesToRead-remain); qCnt += ExpectedPacketLength)
    //        for(qCnt; qCnt<procCounter; qCnt+= ExpectedPacketLength)
            {
                dummy=0;
                if(!(((NumberOfBytesToRead-remain)-qCnt) < ExpectedPacketLength))
                {
                    for(dummyCounter=0;dummyCounter<ExpectedPacketLength;dummyCounter++)
                    {
    
                        dummyArray[dummyCounter] = pulledData;
                        shortArray[dummyCounter] = pulledData;
                        CircularBufferManager_ApiPull(&SerialCircularBufferManager_s,&pulledData);
    
                    }
                }
    

    Note: remain variable is required for circular buffer to don't getting the wrong package data.
    Note: ExpectedPacketLength is define variable which can vary but in this code its "5".


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    From a quick look at your code, why are you calling clear on your serial port instance ? You are likely there dropping data.

    As for your data, why not just use a QByteArray to which you append your serial data and then once big enough you start to parse ?

    Another thing, why for a queued connection ? If you want your serial communication to not influence your GUI, move that part to another thread.



  • @SGaist

    Hi. Application should be delayless. So getting data and appending it then parsing process is causing some delay. I tried that but it didnt work.
    QueuedConnection was just a trying code where i saw in qt forums. I didn't use it on purpose.

    It seems logical to me in serial instance part using

    serial->setFlowControl(QSerialPort::SoftwareControl);
    

    But when i run my program like this it works sometime and stopping without any error then when i tried second time to run my program USB serial port is not recognizible by the computer. I cant read,write,open,close my USB Serial Port i couldn't figure it out either.

    Thanks for the help. I'm really trying to fix this problem.


  • Lifetime Qt Champion

    You should check your hardware for what type of flow control it supports and use the correct one. Also if you need super fast communication you should check what your hardware can handle and make a protocol that takes that into account.


Log in to reply
 

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