PDA

View Full Version : QExtSerialPort does weired things!



xtlc
7th August 2013, 13:48
I am reading a String from the Arduino, which comes like this:


string_outData = 'a' + string_1 + '&' + string_2 + '&' + string_3 + 'E';
char char_buf[40];
string_outData.toCharArray(char_buf, 50);
Serial.write(char_buf);

In QT, I want to receive the chars and build a string:

QString incoming_string = QString::fromLatin1(port->readLine());
ui->recv_text->moveCursor(QTextCursor::End);
ui->recv_text->append(incoming_string);
This works fine so far - but this is a QTextEdit and not a string. In the QTextEdit I do not get 1 Line with the whole string, but this:
XXX // 3 chars
XXXX // 4 chars. ... why?
XXXX
XXXX
XX

instead of:
XXXXXXXXXXXXXXXXXXXXXXXX

What I want to get is the whole content of what is char_buf at the Arduino in incoming_string in the QT5 GUI. But I am failing miserably so far. I want to seperate the incoming_string later so I am able to work with the three strings. Please, I am very much in need of input :) How can I get a perfectly fine string :(?

Lesiok
7th August 2013, 17:27
From QIODevice::readLine doc :
Data is read until either of the following conditions are met:

The first '\n' character is read.
maxSize - 1 bytes are read.
The end of the device data is detected.

and this is what You have. Remember that serial interface is very slow compared to the processor.
Use QIODevice::read instead of readLine.

xtlc
7th August 2013, 17:37
ok, sounds logical so far .... but i send 50 chars from the Arduino and I get the same result with read(50):

X
XXXX
XXXX
XXXX
XXXX
XXXX
X

XX
XXXX
XXXX
XXXX
XXXX
XXXX

XX
XXXX
XXXX
XXXX
XXXX
XXXX
X

Shouldnt the GUI wait for 50 chars with read(50)?

Lesiok
7th August 2013, 18:52
Not because readLine quits after reading all the data. Your 50 is not the number of characters that readLine must return but the maximum number that can be returned. The message of 50 characters at 9600 bps it takes about 47 ms. For a modern PC it is almost an eternity. After 10 ms from the beginning of sending You can read first 5-6 characters and readLine does it. After displaying this next readLine gets next 4-5 characters and so on. This is a basic problem in the data transmission : the difference in the speed of data processing by the transmitter and receiver
If your data are in the form of a solid frame construction (start character a, end character E) read data by the read() method and build ready-to-display lines by analyzing the received data. Remember that one sample can contain the end of one frame and the beginning of the next.

ChrisW67
7th August 2013, 23:46
Just another word of warning:


string_outData = 'a' + string_1 + '&' + string_2 + '&' + string_3 + 'E';
char char_buf[40];
string_outData.toCharArray(char_buf, 50);

Putting up to 50 characters in a 40 byte buffer is a health hazard.


Since the string you send does not end in '\n' any attempt to read using QIODevice::readLine() is unlikely to be fruitful.

xtlc
8th August 2013, 15:46
I found a working solution to this, I am only a little bit worried, somewhere in Australia a kitten may have died.


void MainWindow::onReadyRead()
{
boolean eos = false;

if (port->bytesAvailable()) {
QString recvData=(QString::fromLatin1(port->read(4)));

if(recvData.contains('A')) {
appended_str = recvData.mid(recvData.indexOf('A')+1);
}
else if(recvData.contains('E'=) {
int pos = recvData.length() - recvData.indexOf('E') - 1;
appended_str += recvData.mid(pos);
eos = true;
}
else {
appended_str += recvData;
}


if(eos) {
int appended_str_length = appended_str.length() - 1;
appended_str.truncate(appended_str_length);
QString incoming_string = appended_str;
ui->recv_text->append(appended_str);
eos = false;
appended_str = "";
}

is this a crime?

Lesiok
8th August 2013, 16:20
Better but not quite well. Firstly, what do you do when the receiver buffer is more than four characters? You're reading up to 4 (line 6). You should read all available data and then analyze them char by char. Remember what I said : read a portion of the data may contain several frames.

xtlc
9th August 2013, 10:04
What confuses me: Isn't there a function to do that? An implemented one? This must be a very common problem?!

Lesiok
9th August 2013, 10:33
Function for what ? Structure of the transmitted data is your private affair.
In our system, we use two devices: fiscal printer and contactless card programmer. Both devices use a serial interface (physical layer) but they use completely different protocols (logical layer). Physical layer is what QExtSerialPort do. You must create logical layer.