QtSerialPort: QByteArray



  • Hello,

    I have a small QtSerialPort app talking to an Arduino. I'm working on the Arduino sending data over to the Qt app for now. The Arduino simply sends "Hello Qt From Arduino".

    @Serial.write("Hello Qt From Arduino");@

    Now on the Qt side the below function is reading the data. It's reading it fine, so I think, but it's reading byte by byte. And the entire string is not displayed on the text box widget textEdit. Some input will be appreciated. Maybe once I'm done with this small app we can add it to the QtSerialPort examples, it will most defiantly help other. Thanks.

    @void MainWindow::readsData()
    {
    QByteArray inByteArray = serial->readAll();

    qDebug() << inByteArray;
    ui->textEdit->setText(inByteArray);
    

    }@

    Application output from Qt:
    @"H"
    "e"
    "l"
    "l"
    "o"
    " "
    "Q"
    "t"
    " "
    "f"
    "r"
    "o"
    "m"
    " "
    "A"
    "r"
    "d"
    "u"
    "i"
    "n"
    "o"
    "H"
    "e"
    "l"
    "l"
    "o"
    " "
    "Q"
    "t"
    " "
    "f"
    "r"
    "o"
    "m"
    " "
    "A"
    "r"
    "d"
    "u"
    "i"
    "n"
    "o"@

    QtSerialPort Settings:
    @void MainWindow::initSerialPort()
    {
    serial->setPort("COM5");
    if (serial->open(QIODevice::ReadWrite))
    {
    serial->setRate(SerialPort::Rate19200);
    serial->setDataBits(SerialPort::Data8);
    serial->setParity(SerialPort::NoParity);
    serial->setStopBits(SerialPort::OneStop);
    serial->setFlowControl(SerialPort::NoFlowControl);
    }

    else {
            serial->close();
            QMessageBox::critical(this, tr("Error"),
            tr("Can't configure the serial port: %1,\n"
            "error code: %2")
            .arg("COM5").arg(serial->error()));
            ui->statusBar->showMessage(tr("Open error"));
        }
    

    }@



  • There might be a list of problems:

    1. Maybe the problem is the Arduino's Serial.Write() function.
      serial->readAll() function reads all the data until it reaches the character '\0'.
      The device might be sending it byte by byte and appending '\0' for every byte.

      I am not using Arduino myself, instead I only focus on PIC microcontrollers. I was able to do a similar project using qextserialport. I also used this library with a GSM module/mobile broadband.

    1. Maybe a problem on the settings of QtSerialPort. Both [Arduino and QtSerialPort] must be synchronized, e.g. same baud rate, etc.


  • 2 DominicanTech,

    This is normal behavior.

    QtSerialPort reads data asynchronously, that is, read function returns immediately in the process of admission (without timeouts).

    Signal readyRead() just tells you that in the ring buffer class has data to read.
    In your case serial driver has time to take only 1 byte each readyRead(). It depends on the type of driver, percent of load the OS, setup baud rate and etc.

    The number of bytes you can get out by calling bytesAvailable().

    For example can be implement:

    @

    int expectedNumberOfBytes = 22; // length of "Hello Qt from Arduino" with '\0' char

    void MainWindow::readsData()
    {
    if (expectedNumberOfBytes == serial->bytesAvailable()) {
    QByteArray inByteArray = serial->readAll();

        qDebug() << inByteArray;
        ui->textEdit->setText(inByteArray);
    }
    

    }
    @

    Another way for the "text data" (if there is a symbols of carriage return and new line \n\r).

    @
    void MainWindow::readsData()
    {
    if (serial->canReadLine()) {
    QByteArray inByteArray = serial->readLine();

        qDebug() << inByteArray;
        ui->textEdit->setText(inByteArray);
    }
    

    }
    @

    Also can be use QTimer for detect receive timeout.

    Which way to choose - you decide.



  • I'm trying to now calculate temperature from a thermistor. The value sents sent from the Arduino have a range from 0 - 1024 (10 bit ADC).

    On the Arduino side I have the below function. Now my plan is to write another function in Qt to receive the data and display the values, but I'm having difficulties with QtSerialPort.

    Below is the Arduino function:

    @void readtemp (void)
    {
    //Reads the analog in value and store it in tempADCVal variable
    tempADCVal = analogRead(anPInA0);

        //Break down the data received into two bytes (LSB and MSB).
    

    unsigned int tempADCValLSB = lowByte(tempADCVal);
    unsigned int tempADCValMSB = highByte(tempADCVal);

        //Serial.write send the data over the comport as a byte, no formating.
        //Ref "Arduino Serial.write":http://www.arduino.cc/en/Serial/Write
    

    Serial.write(tempADCValLSB); //Send LSB
    Serial.write(tempADCValMSB); //Send MSB
    }@

    The data is transmitting and I can see it in the serial monitor, I'm just having difficulties on the Qt receiver side. What would be the best approach to receive the two separate bytes in the Qt and get the value into an int which will be in the range of 0-1024.

    I've tried doing the below function in Qt, but can't get it going.
    @void MainWindow::readsData()
    {
    int mytmpVal1;
    int mytmpVal2;
    int inBytesExpected = 2;
    char buf[2];
    qint64 inBytes;

    if (inBytesExpected  == serial->bytesAvailable())
          {
        inBytes = serial->getChar(buf);
        mytmpVal1 = static_cast<int>(buf[0]);
        mytmpVal2 = static_cast<int>(buf[1]);
        qDebug() << mytmpVal1;
        qDebug() << mytmpVal2;
        //qDebug() << buf;
                                 }
    

    }@



  • For good, have to implement a protocol between Arduino and PC.

    But in simplest possible way:

    @int expectedLength = sizeof(quint16);
    if (expectedLength == serial->bytesAvailable()) {
    quint16 temperature = 0;
    if (serial.read(&temperature, expectedLength)
    == expectedLength) {
    // ok
    } else {
    // error
    }
    }@



  • Ok thanks.
    This is the function that did it for me in Qt. It's pretty basic the simplest I could get it. Just in case someone is trying to do the same thing. Hope it helps out there.

    @void MainWindow::readsData()
    {
    quint8 ADCValMSB;
    quint8 ADCValLSB;
    int ADCVal;

    int inBytesExpected = 2;
    char buf[16];
    qint16 inBytes;
    
    if (inBytesExpected  == serial->bytesAvailable())
          {
        inBytes = serial->read(buf, inBytesExpected);
        ADCValMSB = buf[0];
        ADCValLSB = buf[1];
        ADCVal = ((ADCValMSB << 8 ) + ADCValLSB);
    
        qDebug() << ADCValMSB;
        qDebug() << ADCValLSB;
    
        qDebug() << (ADCVal);
        ui->textEdit->setText(QString::number(ADCVal));
    
    }@


  • Excellent Work! In our lab, I have been using Arduino with LabVIEW to control Arduino from desktop or laptop. Now I am ready to write some app to control Arduino directly on PC side. Your post is a good start for me. I noticed another SerialPort library for Qt, named "qestserialport":http://code.google.com/p/qextserialport/wiki/Welcome?tm=6 . So this is different from what you use in the post, right?
    Thanks for sharing!



  • If you want you can try this for manage serial interfaces:
    http://kde-apps.org/content/show.php?content=142378
    Look at qcserialcomport.cpp, qcserialcomport.h



  • [quote author="RockyWashU" date="1353146297"]So this is different from what you use in the post, right?
    Thanks for sharing![/quote]

    Yes, QtSerialPort is completely different library.

    [quote author="mrdebug" date="1354486301"]If you want you can try this for manage serial interfaces:
    http://kde-apps.org/content/show.php?content=142378
    Look at qcserialcomport.cpp, qcserialcomport.h[/quote]
    I briefly looked at the implementation of the decision. And I advise you not to use this decision, because the implementation is incorrect, unwise, made ​​"in haste", which will cause a lot of problems in the future, IMHO.



  • hi kuzulis

    I'm trying now to write a function to send data from the Qt App. I'm trying to create something similar to the readsData() method but I want to instead writeData(). I've tried using

    @qint64 SerialPort::writeData ( const char * data, qint64 maxSize )@

    But Can't send data over serial. Don't know if I'm missing anything.
    I tried using the example, but can't get it going using.

    @void MainWindow::writeData(const QByteArray &data)
    {
    serial->write(data);
    }@

    Any ideas or other examples??



  • @DominicanTech,

    I do not know what you do not understand?

    All examples are needed in /examples. Also, read the documentation.

    PS: Also, you can now update library, because added new examples and etc.



  • Hi,
    this post is somewhat oldish, so I dont know if anyone is still following.
    I am having bit of a head scratch I have RS232 data between my two devices and I would like to monitor the data (visual way some dials etc) data is continuose data stream which starts with four 0x0f and then there is 77 bytes of data.
    Since I am not really up to speed with C++ and PC programming (forced to do it by need :-) ) BTW it is done in QT5 under Ubuntu12.04 if that makes any difference.
    The question is how do I (not sure how to explain myself) synchronise data so I endup with array[77] and all data are in their correct slots.
    I have done it in Pic18 just by waiting for four 0f's and then push the data in to the array. Is there any better way in this world of higher level programming?

    thanks
    Josef



  • Hi. You should implement a some StateMachine object which will do parse of received data. You can read about state machines here: http://en.wikipedia.org/wiki/Automata-based_programming or try to search in google.


Log in to reply
 

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