Pages: [1]   Go Down
Author Topic: help with strtok()  (Read 1165 times)
0 Members and 1 Guest are viewing this topic.
Virginia, USA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 93
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
$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:
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);
    }
  }
}

Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8821
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

France
Offline Offline
Edison Member
*
Karma: 37
Posts: 1005
Scientia potentia est.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

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

http://codepad.org/5rWaj2iA
« Last Edit: December 06, 2012, 01:20:34 pm by guix » Logged

Virginia, USA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 93
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 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:
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,',');
  }
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8821
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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,',');
  }
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Virginia, USA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 93
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Pages: [1]   Go Up
Jump to: