Missing data in qSerialPort



  • Hello,
    I have written a very simple class to check serial port communication over Qt.

    This is actually serial port communication via the USB port. I am talking to a PIC based microcontroller. I read all the serial ports, identify the one to which the microcontroller is attached; Then I send 0xE0 repeatedly and read all the data sent over the serial port with a readAll().

    When I send the 0xE0 over the serial port using "realterm serial port communication program", the microcontroller sends data for nearly a second, the status of all 15 I/O ports.

    When I use the qserialport I hardly get 10 bytes and that too, not every time, also it does not take 1 second to read unlike in the realterm application!
    @#include <QCoreApplication>
    #include <QDebug>
    #include <QSerialPort>
    #include <QSerialPortInfo>
    #include <QIODevice>

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);
    QString portID;

    qDebug() << "Number of serial ports:" << QSerialPortInfo::availablePorts().count();
    
    foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
    
        qDebug() << "\nPort:" << serialPortInfo.portName();
        if (serialPortInfo.description() == "Communications Port") portID = serialPortInfo.portName();
    
    }
    printf ("Opening Port %s\n",qPrintable(portID));
    if (portID.size() > 1)
    {
        //could do  reinterpret_cast and have const unsigned char
        unsigned char temp_char = 0xE0;
        QSerialPort embed;
        embed.setPortName(portID);
        embed.setBaudRate(QSerialPort::Baud115200);
        embed.setDataBits(QSerialPort::Data8);
        embed.setParity(QSerialPort::NoParity);
        embed.setStopBits(QSerialPort::OneStop);
        embed.open(QIODevice::ReadWrite);
        embed.write(reinterpret_cast<const char*>(&temp_char),1);
    
        int numRead = 0,numReadTotal = 0;
        QByteArray buffer;
    
        for (int i=1; i<=20;i++) {
            QCoreApplication::processEvents( QEventLoop::AllEvents );
            buffer = embed.readAll();
            numRead  = buffer.size();
            printf ("%d Reading Port Data count %d\n",i, numRead);
            for (int j = 0; j < numRead; j++)
                printf ("Data %x, count %d\n",buffer.at(j),j+1);
            // Do whatever with the array
    
            numReadTotal += numRead;
            if (numRead == 0 && (numReadTotal > 100))
                break;
            embed.write(reinterpret_cast<const char*>(&temp_char));
        }
        embed.close();
    }
    else printf("Port Not Found!\n");
    
    return 0;
    

    }@
    Any suggestions on where to look for a bug?



  • This is wrong init sequence:
    @
    embed.setPortName(portID);
    embed.setBaudRate(QSerialPort::Baud115200);
    embed.setDataBits(QSerialPort::Data8);
    embed.setParity(QSerialPort::NoParity);
    embed.setStopBits(QSerialPort::OneStop);
    embed.open(QIODevice::ReadWrite);
    @

    should be:
    @
    embed.setPortName(portID);
    embed.open(QIODevice::ReadWrite);
    embed.setBaudRate(QSerialPort::Baud115200);
    embed.setDataBits(QSerialPort::Data8);
    embed.setParity(QSerialPort::NoParity);
    embed.setStopBits(QSerialPort::OneStop);
    @

    Besides, it is strongly recommended to check returned values of the methods: open() and setXXX().

    Also please provide an log out of expected data and real received (your printf) data.



  • This what I get from the realterm:
    E0F960880090179D10A000877F880190129D0CA00088009016A000877F901E9C7D87
    7F88009024A000877F901D9C71877F88009C6BA00088009010A000877F88009C61A00088009020A0
    01877F90249C59877F88009C55A001880090149C51877F88009C4EA00188009018A001877F90229C
    48877F88009C45A001877F901C9C42877F88009C40A00188009012A002877F901A9C3CA002880090
    23A002877F90229C38877F88009C36A00288009.........................9C1B

    I get about 10 bytes through qt :(



  • bq. I get about 10 bytes through qt :(

    Because this is wrong:

    @
    for (int i=1; i<=20;i++) {
    ...
    }
    @

    Why do you think that for 20 iterations the device will accept more than 10 bytes?

    The serial port - very slow device in comparison with qt event-loop. Thus your 20 iterations will end before the device will receive all data.

    You need to use the forever loop with the method of waiting of data waitForReadyRead() and the method of getting number of available data bytesAvailable() instead of 20 iterations.

    Besides, the waitForReadyRead() method has an bugs. These bugs are fixed in the following release of Qt 5.2.1 (but you can download the "release" branch from Git and manually rebuild and reinstall the QtSerialPort).

    And last, very important council: use asynchronous approach with signals/slots. This decision is better because doesn't contain bugs (at least doesn't contain critical errors). See QtSerialPort's examples, read documentation.



  • I thought waitforreadyread() made the call synchronous? I thought my approach was asynchronous. I will have to rethink my approach.

    I put a loop of 20 because for every 0XE0 sent to the microprocessor, it returns upto about 3000 bytes, the status of 15 input/output ports.

    Thanks for the input, I will look into signal/slot for the communication.

    Thanks!


Log in to reply
 

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