Parsing GPS Data - Partially Working

I’ve connected a GPS antenna to my laptop. With several attempts to troubleshoot the code,
It appears the issue is within serialEvent(), and/or my parsing structure.

If I print(inString); to the console, I can see the entire message block. When the string is
split into the array, I’m only seeing 8 elements, and primarily $GPGLL header 95% of the time. Why is this?

Thank you in advance for pointing me in the right direction!

My code is below and here is the data read into processing, and the latter is parsed into
the array:

read into inStringGPS variable:

$GPRMC,030557.00,A,4355.94375,N,07859.68041,W,0.360,060320,A67
$GPVTG,T,M,0.360,N,0.666,K,A
20
$GPGGA,030557.00,4355.94375,N,07859.68041,W,1,08,1.15,151.0,M,-35.9,M,63
$GPGSA,A,3,02,06,12,19,17,05,23,04,2.00,1.15,1.64
0F
$GPGSV,3,1,12,02,67,290,30,04,13,053,24,05,27,201,22,06,67,040,3375
$GPGSV,3,2,12,09,20,086,18,12,50,280,31,17,29,116,27,19,48,109,31
79
$GPGSV,3,3,12,23,15,057,19,25,24,313,07,46,19,240,51,32,218,70
$GPGLL,4355.94375,N,07859.68041,W,030557.00,A,A
7C

split into gpsData array:

[0] “$GPGLL”
[1] “4355.94696”
[2] “N”
[3] “07859.67775”
[4] “W”
[5] “024134.00”
[6] “A”
[7] "A*7F

import processing.serial.*;
Serial gpsPort, numsPort;

int gpsHeading, gpsAltitude;
String gpsData = new String[215]; //65
String numsData = new String[15];
String inStringNums, inStringGPS;

void setup() {

fullScreen(SPAN);
background(0);
// numsPort = new Serial(this, Serial.list()[1], 115200);
// numsPort.bufferUntil(‘\n’);

gpsPort = new Serial(this, Serial.list()[0], 9600);
gpsPort.bufferUntil(10); //‘\n’

delay(500);
}

void draw() {

background(0);
// inStringGPS = gpsPort.readString();

gpsData = split(inStringGPS, ‘,’);
String block = gpsData[0];
String str2 = “$GPVTG”, str3 = “$GPRMC”;

if (str2.equals(block) == true){ // $GPVTG
float gpsData2 = float(split(inStringGPS, ‘,’));
gpsHeading = int(gpsData2[1]); //TRUE
}

if (str3.equals(block) == true){ // $GPRMC
float gpsData2 = float(split(inStringGPS, ‘,’));
gpsHeading = int(gpsData2[8]); //TRUE
}

text(gpsHeading, 40, 40);
print(inStringGPS); // for troubleshooting
printArray(gpsData);
}

void serialEvent(Serial xCOM){
if(xCOM == gpsPort) inStringGPS = xCOM.readString(); //move to draw function?
// if(xCOM == numsPort) inString = xCOM.readString();
}

1 Like

Trying to work through this, but I’m too “green” to understand what I’m seeing. After messing around, this is better.

Notice how split() is parsing with ‘,’ and the data header $GPVTG is shifted.

[0] “$GPRMC”
[1] “140752.00”
[2] “A”
[3] “4355.94889”
[4] “N”
[5] “07859.68009”
[6] “W”
[7] “0.201”
[8] “”
[9] “060320”
[10] “”
[11] “”
[12] "A64 // << has line ending, not comma separated. How to parse this?
$GPVTG"
[13] “”
[14] “T”
[15] “”
[16] “M”
[17] “0.201”
[18] “N”
[19] “0.373”
[20] “K”
[21] "A
27

New Code:

void draw(){

background(0);

while(gpsPort.available() > 0){
// inStringGPS = gpsPort.readStringUntil(13); //‘D’, 10, 9
inStringGPS = gpsPort.readString();
}

gpsData = split(inStringGPS, ‘,’);
String blockRMC = gpsData[0];

if (str3.equals(blockRMC) == true){
float gpsData2 = float(split(inStringGPS, ‘,’));
gpsHeading = int(gpsData2[8]);
}
text(gpsHeading, 40, 40);

// print(inStringGPS); // for troubleshooting
printArray(gpsData);
}

Note: removed serialEvent() and used while(gpsPort.available() > 0) in the draw() function.

I know this is not correct, but I’m starting to understand the issue. I just don’t know how
to break up the comma separated and line ending in the buffer.

:confused:

1 Like
2 Likes

Thank you for the reply!

I’m not using the Arduino for the GPS module. It’s a USB type receiver. VFAN PN# UG-353

I’ll try splitTokens() inside of serialEvent() and read your link,

That info helped a little bit. Perhaps I’m still missing the obvious? Is it possible to link a YouTube video to explain in detail?

In any case, this is what happens after more experimenting. I cannot get the entire NMEA block
to read into Processing via serialEvent(). It works when moving the code within draw(). Here
are the outputs:

THIS code:


 void serialEvent(final Serial s){ 
    inStringGPS = splitTokens(s.readStringUntil(ENTER));
 }

and THIS code:


void serialEvent(final Serial s){ 
   while(gpsPort.available() > 0){
      inStringGPS = splitTokens(s.readString());   //Until(ENTER));
  }
}

Output the following:

[0] "$GPGLL,4355.94453,N,07859.68160,W,171628.00,A,A*72"
[0] "$GPGLL,4355.94453,N,07859.68160,W,171628.00,A,A*72"
[0] "$GPGLL,4355.94453,N,07859.68160,W,171628.00,A,A*72"
[0] "$GPGLL,4355.94453,N,07859.68160,W,171628.00,A,A*72"
[0] "$GPGSV,4,4,16,29,04,028,,31,25,092,29,46,19,240,,51,32,218,*7C"
[0] "$GPGLL,4355.94448,N,07859.68158,W,171629.00,A,A*72"

However, this code gives me:

 import processing.serial.*;
 Serial gpsPort;
 
 float  speedometer;
 int gpsHeading;
 String[] gpsData = new String[500]; //65
 String[] inStringGPS;
 
 void draw() {
 
   background(0);
  
   while(gpsPort.available() > 0){
    inStringGPS = splitTokens(gpsPort.readString());
   }
  
  gpsData = split(inStringGPS[0], ','); 
  
   String blockRMC = gpsData[0];
   String str3 = "$GPRMC";
  
   if (str3.equals(blockRMC) == true){  // $GPRMC  
     gpsHeading = int(gpsData[9]);
     speedometer = float(gpsData[7]); 
     text(gpsHeading, 40, 40);
     text(speedometer, 80, 40);
   }     
    printArray(gpsData);
 }

[0] "$GPRMC,172645.00,A,4355.94291,N,07859.68291,W,0.010,,060320,,,A*60"
[1] "$GPVTG,,T,,M,0.010,N,0.019,K,A*2A"
[2] "$GPGGA,172645.00,4355.94291,N,07859.68291,W,1,07,1.25,149.7,M,-35.9,M,,*62"
[3] "$GPGSA,A,3,31,03,23,04,09,26,27,,,,,,2.19,1.25,1.80*0B"
[4] "$GPGSV,4,1,15,03,12,224,19,04,70,258,35,07,08,287,,08,16,179,07*7B"
[5] "$GPGSV,4,2,15,09,42,304,29,16,80,047,08,21,04,070,,22,00,206,*78"
[6] "$GPGSV,4,3,15,23,64,269,38,26,50,054,31,27,38,153,29,29,01,026,*71"
[7] "$GPGSV,4,4,15,31,22,096,24,46,19,240,,51,32,218,*44"
[8] "$GPGLL,4355.94291,N,07859.68291,W,172645.00,A,A*7F"

Why is serialEvent missing most of the NMEA data block?

1 Like

Hello,

I am interested.

Please format your code:
https://discourse.processing.org/faq#format-your-code

I can’t look at the code as is and unable to cut and past working code (try and you will see why).

:)

1 Like

Okay, one more update. I’m trying, I’m really trying, but literally 14 hours on this already and
I’m spent. :frowning:

New Code to line out each array:

//declarations
  String[] gpsData = new String[50]; //65
  String[] gpsData1 = new String[50]; //65

//draw()
  gpsData = split(inStringGPS[0], ','); 
  gpsData1 = split(inStringGPS[1], ',');


Outputs:

[0] "$GPGGA,182533.00,4355.94412,N,07859.68771,W,1,08,1.20,138.8,M,-35.9,M,,*6A"
[1] "$GPGSA,A,3,16,04,23,09,27,26,08,07,,,,,3.01,1.20,2.76*05"
[2] "$GPGSV,4,1,13,04,53,204,29,07,29,300,29,08,44,175,31,09,55,268,33*79"
[3] "$GPGSV,4,2,13,11,07,169,,16,52,051,19,21,10,048,20,23,53,216,35*70"
[4] "$GPGSV,4,3,13,26,26,063,28,27,61,123,31,31,03,112,,46,19,240,*7C"
[5] "$GPGSV,4,4,13,51,32,218,*45"
[6] "$GPGLL,4355.94412,N,07859.68771,W,182533.00,A,A*74"
[0] "$GPRMC"
[1] "182922.00"
[2] "A"
[3] "4355.94180"
[4] "N"
[5] "07859.69043"
[6] "W"
[7] "0.342"
[8] ""
[9] "060320"
[10] ""
[11] ""
[12] "A*6A"
[0] "$GPVTG"
[1] ""
[2] "T"
[3] ""
[4] "M"
[5] "0.342"
[6] "N"
[7] "0.634"
[8] "K"
[9] "A*27"

BUT… I get an “ArrayOutofBoundsException:1” error after about 15 seconds even though
data is present on the console?

Anyway, I’m willing to live without gpsData1 , and revert back to previous code IF serialEvent
can produce the proper output.

Thanks again for helping…and stressing me out by overthinking! :smiley:

With the help of a friend (mostly him), we were able to figure out code that works.
I’ll need to move the data into an array, but other than that it works well.

I’m going to start another thread about serialEvent(). This is pretty much done.
Thanks to those that responded and helped!

void mySplit (String str) {
  int N = str.length(); 
  int i; 
  String str2 = "";  
  char c; 
  for (i = 0; i < N; i++){
    c = str.charAt(i);
    if (c == ',') {
      println(str2);
      str2 = "";
    }
    else {
     str2 += c;
    }
  }
 println(str2);
}
2 Likes

Hello,

Pleased to see that you found a solution for your project.

I added a ‘\n’ to a string and tested your function and split().

trim() removes the ‘\n’.

Your function works the same as split() with this example:

Summary
void setup() 
 {
  size(640, 360);
  String inString = "$GPGGA,182533.00,4355.94412,N,07859.68771,W,1,08,1.20,138.8,M,-35.9,M,,*6A\n";
  println(split(inString.trim(), ','));    //Gives a warning put still prints to console
  mySplit(inString.trim(), true);

  printArray(split(inString.trim(), ','));
  mySplit(inString.trim(), false);

  printArray(split(inString, ','));
  mySplit(inString, false);
  
  print("");	
  }

void draw() 
  {
  background(0);
  }


void mySplit (String str, boolean row) {
  int N = str.length(); 
  int i; 
  String str2 = "";  
  char c; 
  for (i = 0; i < N; i++){
    c = str.charAt(i);
    if (c == ',') {
      if (row)
        print(str2 + " ");
      else
        println(str2);
      str2 = "";
    }
    else {
     str2 += c;
    }
  }
 println(str2);
}

Source code for split()

I always like to see code examples to replace existing functions; all too often the workings of a function are hidden away from us and I like to write my own and\or see the source to help me better understand the underlying code and sometimes improve on it.

I did find some Android apps on Google Play to generate GPS data and send serial
data over Bluetooth and I wrote code to receive with Processing.
I was able to plot my movement in my room!

:)

1 Like