QByteArray to float



  • Hello,

    I have an application going with a micro-controller sending voltage values as a string to be read by the Qt App (QtSerialPort). The string gets to Qt correctly, but now I have to convert this to a floating point so that I can do math operations. for example, when readADC(); is called I get a string with 24.21. How can I convert this to a floating int?

    void MainWindow::readADC()
    {
    
        QByteArray data;
            data = serial->readAll();
            qDebug() << data;
    
    }
    

  • Moderators

    Hi!

    const QByteArray data = ...
    bool ok = false;
    const float = data.toFloat(&ok);
    if (!ok) qDebug() << "Conversion failed";
    

    See also: QByteArray



  • This is how I got it going, not sure if it's the best way of doing it, any input will be appreciated.

    int MainWindow::readADC(int range)
    {
        QByteArray data;
        float x, i, z, k, r;
        if (range == 24)
        {
            data = serial->readAll();
            qDebug() << data;
            x = static_cast<quint8>((data[0] -48) * 10);
            i = static_cast<quint8>((data[1] -48) * 1);
            z = static_cast<quint8>((data[3] -48) *.1);
            k = static_cast<quint8>((data[4] -48) * .01);
            r = x+i+z+k;
            //qDebug() << r;
            if ((r >= 23.3) && (r <= 24.7))
            return 1;
        }
        return 0;
    }
    

  • Qt Champions 2016

    @valerio.j said:

    This is how I got it going, not sure if it's the best way of doing it, any input will be appreciated.

    It's not. See what @Wieland wrote.



  • QDataStream in(serial, QIODevice::ReadOnly);
    float value;
    in >> value;
    

  • Qt Champions 2016

    @kuzulis
    Is this blocking (I'm curious for myself)?

    PS.
    Btw, he's sending it as a string. :)



  • It is just a simple example.. But real example it is something:

    void Foo::onReadyRead()
    {
        while (serial->bytesAvailable() >= 4) { // or, maybe QSataStream::atEnd()
            QDataStream in(serial);
            float value;
            in >> value;
        }
    }
    

    But, anyway, need to use serial->bytesAvailable() to control a number of received bytes, before reading.

    Is this blocking (I'm curious for myself)?

    No, why should it be blocking?

    PS: It is just an additional way to @Wieland 's example.

    Btw, he's sending it as a string. :)

    Ahh, ok. :)


  • Qt Champions 2016

    @kuzulis

    No, why should it be blocking?

    I'm not saying it should be; I was simply asking if it waits for the 4 bytes, or it tries to read them directly from the buffer. Non-blocking is just fine with me. :)



  • Btw, he's sending it as a string. :)

    Then he need to add a '\n' after each string value, to allow to parse it correctly. Then need to use @Wieland 's solution. Or, maybe QTextStream.



  • Wielands solution worked for me.

    Now I have another question.

    Sending data from the Qt App. This results in an error, it only works if chkTstr24VDC was a QBytearray which I can deal with, but I'm trying to understand why it won't work with QString. Below is the error. Maybe I need to convert QString to QBytearray??

    error: no matching function for call to 'QSerialPort::write(QString&)'
    serial->write(chkTstr24VDC);
    ^

    void MainWindow::on_powerON_clicked()
    {
         int res;
    
        QString chkTstr24VDC ("$AR!ARP022#");
    
         serial->write(chkTstr24VDC);
         res = readADC(24);                                  //Read and test 24VDC range
    }
    
    

  • Qt Champions 2016

    Hi
    the write expects a const char *
    To get that from Q String you can do

    serial->write(text.toStdString().c_str());

    http://doc.qt.io/qt-5/qiodevice.html#write
    or use bytearray/ convert to.


  • Qt Champions 2016

    @valerio-j

    Maybe I need to convert QString to QBytearray??

    Yes, indeed you need to do that. Also you need to be sure the port is ready after writing/before reading.

    QByteArray chkTstr24VDC = QByteArrayLiteral("$AR!ARP022#");
    
    serial->write(chkTstr24VDC);
    serial->waitForBytesWritten(1000); //< Wait up to a second so the data is written to the port
    
    serial->waitForReadyRead(1000);  //< Wait up to a second so the port is ready for reading
    res = readADC(24);                                  // Read and test 24VDC range
    

    @mrjj said:

    To get that from Q String you can do
    serial->write(text.toStdString().c_str());

    But you shouldn't, you should rather enforce the encoding with toLatin1, toUtf8 or alike, and get a byte array from there. Then this byte array can be sent through the serial port. For example:

    QString myStringData("some string data");
    QByteArray byteArrayData = myStringData.toLatin1();
    
    serial->write(byteArrayData);
    


  • @kshegunov said:

    serial->waitForReadyRead(1000);

    Thanks, this really improved my program, but it doesn't work 100% yet. Sometimes it combines both reads into a single string when using back to back write/reads. Below is what my code looks like now. I've tried with longer delays, but it doesn't help.

    void MainWindow::on_powerON_clicked()
    {
        int res24, res3v3;
        QPixmap stat_GO (":/res/images/stat_GO.png");
        QPixmap stat_noGO (":/res/images/stat_noGO.png");
    
        QByteArray chkTstr24VDC ("$AR!ARP022#");
        QByteArray chkBUT3_3VDC ("$AR^ARP032#");
    
        QByteArray powerON ("$DW!SHP079#");
        QByteArray kill ("$DW!SHP004#");
        QByteArray pwr_switch ("$DW!SLP058#");
    
        sndTesterData(powerON);                     //Enable 24VDC
        sndTesterData(chkTstr24VDC);                //Request 24VDC status to Tester
    
        serial->waitForReadyRead(1000);
        res24 = readADC(24);
    
        if(res24 == 1)
        {
        sndTesterData(kill);                        //E-OFF
        sndTesterData(pwr_switch);                  //On/Off Switch
        ui->_tstr24Vok->setPixmap(stat_GO);
    
            sndTesterData(chkBUT3_3VDC);
            serial->waitForReadyRead(1000);
            res3v3 = readADC(3);
    
            if(res3v3 == 1)
                ui->_but3v3Vok->setPixmap(stat_GO);
                    else
                    ui->_but3v3Vok->setPixmap(stat_noGO);
        }
        else
        ui->_tstr24Vok->setPixmap(stat_noGO);
    
    }
    

  • Qt Champions 2016

    @valerio.j said:

    Thanks, this really improved my program, but it doesn't work 100% yet. Sometimes it combines both reads into a single string when using back to back write/reads.

    This is not unexpected. There's buffering involved and there's no guarantee (as with TCP) that anything you write will be read as a separate packet. You need to ensure that the way you're sending the data is taking this into account (usually by using a protocol).


Log in to reply
 

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