QByteArray to float
-
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; }
-
@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;
-
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. :)
-
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 }
-
Hi
the write expects a const char *
To get that from Q String you can doserial->write(text.toStdString().c_str());
http://doc.qt.io/qt-5/qiodevice.html#write
or use bytearray/ convert to. -
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); }
-
@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).