PDA

View Full Version : Reading GPS data from virtual serial port on a Windows system



vittorio
7th October 2015, 16:44
Dear forum,

I have the following problem: I try to read GPS data (a so called nmea-string)from a GPS-mouse via a virtual serial port into my application and to show this data in a QPlainTextEdit-widget. I do this using the following very simple function (connection to the serial port is allready opened):


void DialogPreferences::readData()
{
QByteArray rawData = serial->readAll(); // read data from serial port
ui->plainTextEdit->insertPlainText(rawData) // show data in QPlainTextEdit
qDebug() << rawData; // show same data in the console
}

The serial port is connected to the QPlainTextEdit widget via


connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));

Output in the QPlainTextEdit-Widget:

$GPGGA,141559.000,5858.4209,N,00956.6503,E,2,8,1.7 5,29.4,M,41.2,M,0000,0000*64
$GPGLL,5858.4209,N,00956.6503,E,141559.000,A,D*54
$GPGSA,A,3,14,08,32,03,11,04,19,01,,,,,1.97,1.75,0 .91*04
$GPRMC,141559.000,A,5858.4209,N,00956.6503,E,0.36, 235.13,071015,,,D*62

This works as it should. But if I try to display the same data with qDebug() in the console, I get the following result:

"GPGGA,141559.000"
",5858.4209,N,0095"
"6.6503,E,2,8,1"
".75,29.4,M,41.2"
",M,0000,0000*64"
"\r\n$GPGLL,5858.42"
"09,N,00956.6503,"
"E,141559.000,"
"A,D*54\r\n$GPGSA,"
"A,3,14,08,32,03,"
"11,04,19,01,,,"
",,1.97,1.75,0.9"
"1*04\r\n$GPRMC,14"
"1559.000,A,5858"
".4209,N,00956."
"6503,E,0.36,235"
".13,071015,,,D*"
"62\r\n$GPVTG,235."

In the raw data the lines are seperated by a combination of \r\n. But obvisouly the array is splitted on, for me, arbitrary places, and I have no idea why! I need the line exact as shown in the QPlainText widget for further analysis, any suggenstions, how I can reach that?

Thanks in advance for your help!

vittorio

Cruz
7th October 2015, 17:12
Oh it's really just that qDebug() starts a new line every time you call it, and the data does't arrive exactly in lines from the serial port. Collect everything in one string and split on \r\n and you should be fine.

d_stranz
7th October 2015, 19:01
To further explain - QPlainTextWidget::insertPlainText() updates the cursor position each time it is called. If you don't change the cursor position between calls, this has the effect of appending each new piece of text onto the end of whatever is already there. So your plain text widget has the appearance of showing a single string, when in fact it is the accumulation of each of the strings you see in the qDebug() output. The qDebug() output is showing you the sequence of what is actually being received by the serial port in each of the calls to the readData() slot.

As Cruz said, create a QString or QByteArray member variable and append onto it each time readData() is called. When you are done reading, split the string on the CRLF delimiters.

vittorio
7th October 2015, 20:39
To further explain - QPlainTextWidget::insertPlainText()When you are done reading, split the string on the CRLF delimiters.

Hi, thanks for your explanation! I think, I understand what happens, but another thing: the data I'm dealing with is a permanent stream coming in via the serial port. Simple said, each line represents a geographic coordinate, and for a moving system, this coordinates must be updated as soon as new data comes in. The strings are build following the nmea rules. The data I need are on a defined postition within this string. THis all is no problem, but I don't know how to create the correct strings in runtime, do you have any idea?

ChrisW67
7th October 2015, 21:54
I don't know how to create the correct strings

What strings do you need to create?

Cruz
7th October 2015, 21:56
In that case you need to collect multiple segments of a line in a QByteArray and check every byte. When you receive a "\r\n", you have a complete line. Pass it on to your program for example by emiting a signal, and make sure to keep the rest of the bytes as you may have read the beginning of the next line after the \r\n.

Roughly like so:



QByteArray line;

void DialogPreferences::readData()
{
QByteArray rawData = serial->readAll(); // read data from serial port

for (int i=0; i < rawData.size(); i++)
{
line << rawData[i];
if (line.size() >= 2 && line[line.size()-2] == '\r' && line[line.size()-1] == '\n')
{
emit(line);
line.clear();
}
}

}


But this is only quickly hacked pseudo code. Please debug it and complete it yourself.