Go Down

Topic: help with strtok() (Read 1 time) previous topic - next topic

fbriggs4

I am working with a GPS and working to parse the NMEA data myself. I am aware of libraries such as TinyGPS but I prefer to learn and do it myself. I am 95% done in being able to grab all the information I need and what I have works great. I need pieces of data from 3 separate lines in order to store the data I want and here is an example of what I get.

Code: [Select]

$GPRMC,044159.000,A,3903.1262,N,07729.0495,W,0.00,40.30,061212,,,A*4D
$GPGGA,044200.000,3903.1262,N,07729.0497,W,1,08,1.0,83.7,M,-33.4,M,,0000*5F                     
$GPGSA,A,3,30,31,32,16,20,23,29,14,,,,,2.1,1.0,1.8*33


In the $GPRMC and $GPGGA data I can easily grab any piece of data that I want such as latitude and longitude using strtok() using the comma as a delimiter. This part is working perfectly.

Where I struggle is grabbing the data from the $GPGSA line since many of the comma delimited fields have no data and the data I want is at the end. In the example data I need to be able to grab the 2.1, 1.0 and 1.8 at the end. fixType (in the code below) works reliably since it is in a fixed position within the data, but PDOP is the 2.1 and it has a variable number of blank spaces before it. I cant seem to keep a fixed number here because the number of blank data can be different from one second to the next. For example $GPGSA could have 8 blank fields instead of 4 and could easily look like this instead $GPGSA,A,3,30,31,32,16,,,,,,,,,2.1,1.0,1.8*33. How should I handle data like this?

Here is a sample of how I break the data apart and store it as separate variables.

Code: [Select]

void GPGSA(){
  valPosition = strtok(GPGSAC, delimiters);
  i = 0;
  while(valPosition != NULL && i < 18){
    i++;
    valPosition = strtok(NULL, delimiters);
    if (i ==2){
      fixType = atoi(valPosition);
      Serial.print(F("fixType = "));
      Serial.println(fixType);
    }
    if (i ==15){
      PDOP = atof(valPosition);
      Serial.print(F("PDOP = "));
      Serial.println(PDOP);
    }
  }
}


johnwasser

Looks like strtok() is known to not work with empty fields.

Options:
    strsep(); // http://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html
    strchr();  //  find the next comma
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

guix

#2
Dec 06, 2012, 07:18 pm Last Edit: Dec 06, 2012, 07:20 pm by guix Reason: 1
Hello,

I suggest you make your own function, similar to strtok but that it skips blocks of ",,"..Something like that:

http://codepad.org/5rWaj2iA

fbriggs4

I have been working your suggestions and I don't think strsep() will work. Reading the documentation suggests that if multiple delimiters are in a row it it will count 2 of them as one. Since the instance of multiple delimiters can change I don't think this will work. I need the data that is between the 15th and 16th delimiter. So I tried using strchr() to find where the 15th delimiters starts and use the 16th delimiter as a end marker. I used some code from an example I found and I it works to get the start/end points. Now I am not clear on how I grab the data from between those points?

Code: [Select]

void GPGSA(){
  pch=strchr(GPGSAC,',');
  i = 0;
  while (pch!=NULL)
  {
    i++;
    Serial.print("found at comma at ");
    Serial.println(pch-GPGSAC+1);
    pch=strchr(pch+1,',');
  }

johnwasser

Since atoi() and atof() will stop when they hit a comma or * I don't think you need to isolate the end of each value:
Code: [Select]

void GPGSA(){
  pch=strchr(GPGSAC,',');
  i = 0;
  while (pch!=NULL)
  {
    i++;
    if (i ==2){
      fixType = atoi(pch+1);
      Serial.print(F("fixType = "));
      Serial.println(fixType);
    }
    if (i==15) {
        PDOP = atof(pch+1);
        Serial.print(F("PDOP = "));
        Serial.println(PDOP);
    }
    pch=strchr(pch+1,',');
  }
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

fbriggs4

I knew there had to be an easy way. It works perfectly now, thanks so much for the help!

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy