PDA

View Full Version : QextSerialPort reading error: wrong values



Lawand
19th April 2009, 15:21
Hello,
I have a serial hardware device that is sending a certain (hardware-controlled) numeric value in the range [0 .. 255] over and over again.
I am sure the device is sending the correct value, but when I am trying to read it through an instance of QextSerialPort, I am getting wrong values.
And even when changing that (hardware-controlled) value, I am reading the same old wrong value :confused:

Here is the code used (a modified version of the example shipped with QextSerialPort):


/* qesptest.h
**************************************/

#ifndef _QESPTEST_H_
#define _QESPTEST_H_

#include <QWidget>


class QTextEdit;
class QextSerialPort;

class QespTest : public QWidget
{
Q_OBJECT
public:
QespTest(QWidget *parent=0);

virtual ~QespTest();

private:
QTextEdit *received_msg;
QextSerialPort *port;

private slots:
void receiveByte();
};

#endif

charToBinaryStdString() is created so that I can display the read char as 1s and 0s...

/* qesptest.cpp
**************************************/
#include "qesptest.h"
#include <qextserialport.h>
#include <QLayout>
#include <QTextEdit>
#include <QPushButton>
#include <string>

QespTest::QespTest(QWidget* parent)
: QWidget(parent)

{
//port settings
port = new QextSerialPort("COM1");
port->setBaudRate(BAUD9600);
port->setFlowControl(FLOW_XONXOFF);
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setStopBits(STOP_1);
port->open(QIODevice::ReadOnly);

QPushButton *receiveButton = new QPushButton("Receive");
connect(receiveButton, SIGNAL(clicked()), SLOT(receiveByte()));

received_msg = new QTextEdit();

QVBoxLayout *myVBox = new QVBoxLayout;
myVBox->addWidget(receiveButton);
myVBox->addWidget(received_msg);
setLayout(myVBox);
}

QespTest::~QespTest()
{
port->close();
delete port;
port = NULL;
}

std::string charToBinaryStdString(char ch)
{
std::string result;
int i = 8;

while (i >0)
{
--i;
result += (ch&(1 << i) ? '1' : '0');
}

return result;
}

void QespTest::receiveByte()
{
port->open(QIODevice::ReadOnly);

char ch;
if(port->bytesAvailable() > 0)
{
port->read(&ch,1);
received_msg->append(QString::fromStdString(charToBinaryStdStrin g(ch)));
}
}



main() just includes an instance of QespTest and QApplication...

--------

What's wrong?

Lawand
28th April 2009, 19:29
since I found no solution, I am going to use a USB device.

wysota
29th April 2009, 01:07
Shouldn't you be using unsigned char instead of char?

By the way, reading the first character in the buffer is not a good idea. You'll be getting stale data if you read slower than the device writes data to the port. Also check the endianess differences between the machines.

Lawand
29th April 2009, 19:59
Shouldn't you be using unsigned char instead of char?

Thanks a million, this seems to have solved the problem, the only thing left is:


By the way, reading the first character in the buffer is not a good idea.

That is one of life's mysteries to me :D
I am really looking for a way not to do that, and I would really appreciate it if you told me how to...

wysota
29th April 2009, 22:40
That is one of life's mysteries to me :D
I am really looking for a way not to do that, and I would really appreciate it if you told me how to...

I'd read everything there is to be read using QIODevice::readAll() and I'd take the last character, not the first one.

Lawand
30th April 2009, 09:32
I'd read everything there is to be read using QIODevice::readAll() and I'd take the last character, not the first one.
This works, thanks :)
However, is there any more efficient (in terms of complexity) way to do it?, perhaps just clearing the buffer or something like that, because readAll() is taking about 5 seconds to get done (because of low data transfer rate)

BTW, I tried closing and opening the port each time receiveByte() is invoked but I get a wrong value...

wysota
30th April 2009, 09:43
The data gets transfered TO the port in a low rate but once it reaches the port (bytesAvailable()>0) it's read from a buffer. So if you experience a delay it might be that there is no data to be read and your read() call blocks until some data is returned. So before reading check if there is anything to be read.

Lawand
30th April 2009, 15:45
The data gets transfered TO the port in a low rate but once it reaches the port (bytesAvailable()>0) it's read from a buffer. So if you experience a delay it might be that there is no data to be read and your read() call blocks until some data is returned. So before reading check if there is anything to be read.

I don't thinks so, because once I start the program, bytesAvailable() are 0 then it increases into ~4000 in like 5 or 6 seconds, and it stops there, then when I read a byte it increases again until it reaches ~20000 and stabilizes, henceforth it doesn't increase again until it's less than the first number (~4000).

Note that it takes a fraction of a second to read a byte when the number is around 20000 but it takes about 5 only in the time the number gets below the certain limit (~4000) and the QextSerialPort refills about 16000 bytes...

So, my guess is, it takes a long time for these values to get filled then read.

wysota
4th May 2009, 07:47
As far as I remember QExtSerialPort is a stupid class that does not do any buffering on its own and it's only a thin layer over native API. So if you are experiencing such behaviours, they are probably happening in your operating system. In general I'd suggest reading faster so that the system buffers don't get full.

Lawand
6th May 2009, 19:29
Thanks for all the info.