mikalhart / TinyGPSPlus

A new, customizable Arduino NMEA parsing library
http://arduiniana.org
1.05k stars 486 forks source link

custom line GPGST works but when it is GNGST it does not #48

Closed KommandorKeen closed 5 years ago

KommandorKeen commented 5 years ago

I updated my GPS firmware and now it spits out GNGST rather than GPGST. When it was outputting GPGST the following worked: TinyGPSCustom posrms(gps, "GPGST", 2); TinyGPSCustom latsig(gps, "GPGST", 6); TinyGPSCustom lonsig(gps, "GPGST", 7); TinyGPSCustom htsig(gps, "GPGST", 8);

but as it now outputs GNGST I updated my code to look look this.

TinyGPSCustom posrms(gps, "GNGST", 2); TinyGPSCustom latsig(gps, "GNGST", 6); TinyGPSCustom lonsig(gps, "GNGST", 7); TinyGPSCustom htsig(gps, "GNGST", 8);

TinyGPSplus is not now extracting any info.

The GNSS unit is outputting the following: $GNGST,093415.00,2.963,,,,0.466,0.421,0.819*60

Eheran1 commented 5 years ago

Same here: TinyGPSCustom errorlat(gps, "GNGST", 6); //=1 sigma error TinyGPSCustom errorlong(gps, "GNGST", 7); //=1 sigma error TinyGPSCustom errorheight(gps, "GNGST", 8); //=1 sigma error

With sentence: $GNGST,114341.00,2827,,,,1.8,1.2,1.7*48

Results in: errorlat.value() = 2.7 errorlong.value() = 2.1 errorheight.value() = 2.7 These numbers never change. Its always 2.7, 2.1 and 2.7 (after rebooting these 3 numbers are different, so maybe its a problem with updating?) instead of 1.8, 1.2 and 1.7.

mikalhart commented 5 years ago

Interesting. I'd like to do some experimenting with this. Could one of you possibly provide a stream of sample sentences--maybe 15 or 20--that I could run through my test engine? Thanks.

Eheran1 commented 5 years ago

Due to Checksum I didnt alter the position information. Please delete this after reading it or let me know so I can do that. Please note that GGA and GNS show different numbers of satellites (12 and 21) for some reason and a custom GNS to get the correct (here 21) is not working either. Its a uBlox NEO-M8Q.

<NMEA stream here>
mikalhart commented 5 years ago

Thanks. I removed the location data.

mikalhart commented 5 years ago

I'm starting to wonder whether the problems you guys are experiencing are due to dropping characters.

I made a test program that statically parses the GPS data and it seems to work fine.

Could you monitor the gps.failedChecksum() count? That number should be 0 or at least very small and non-increasing over time in a properly working sketch.

My test program, using the data @Eheran1 posted earlier:

#include <TinyGPS++.h>
TinyGPSPlus gps;

char data[] = 
"$GNRMC,094507.00,A,XXXX.XXXXX,N,XXXXX.XXXXX,E,0.030,,020119,,,D,V*1B\r\n"
"$GNVTG,,T,,M,0.030,N,0.055,K,D*3B\r\n"
<big snip>
"$GNGST,094535.00,23,,,,1.2,1.3,2.1*44\r\n"
"$GNZDA,094535.00,02,01,2019,00,00*7F\r\n";

TinyGPSCustom errorlat(gps, "GNGST", 6); //=1 sigma error
TinyGPSCustom errorlong(gps, "GNGST", 7); //=1 sigma error
TinyGPSCustom errorheight(gps, "GNGST", 8); //=1 sigma error

void setup() 
{
  delay(5000);
  Serial.begin(115200);
}

const char *p = data;

void loop() 
{
  if (*p)
    gps.encode(*p++);

  // Every time anything is updated, print it.
  if (gps.altitude.isUpdated())
  {
    Serial.print(F("ALT=")); Serial.print(gps.altitude.meters()); 
  }

  if (gps.satellites.isUpdated())
  {
    Serial.print(F(" SATS=")); Serial.println(gps.satellites.value());
  }

  if (errorlat.isUpdated())
  {
     Serial.print(F(" ERRLT=")); Serial.println(errorlat.value());
  }

  if (errorlong.isUpdated())
  {
     Serial.print(F(" ERRLG=")); Serial.println(errorlong.value());
  }

  if (errorheight.isUpdated())
  {
     Serial.print(F(" ERRHT=")); Serial.println(errorheight.value());
  }
}

This generates the following output:

ALT=94.30 SATS=12 ERRLT=1.3 ERRLG=1.5 ERRHT=2.5 ALT=94.10 SATS=12 ERRLT=1.3 ERRLG=1.5 ERRHT=2.5 ALT=93.80 SATS=12 ERRLT=1.3 ERRLG=1.4 ERRHT=2.4 ALT=93.70 SATS=12 ERRLT=1.3 ERRLG=1.4 ERRHT=2.4 ALT=93.50 SATS=12 ERRLT=1.3 ERRLG=1.4 ERRHT=2.4 ALT=93.30 SATS=12 ERRLT=1.3 ERRLG=1.4 ERRHT=2.4 ALT=93.40 SATS=12 ERRLT=1.3 ERRLG=1.4 ERRHT=2.3 ALT=93.40 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.3 ALT=93.20 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.3 ALT=93.10 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.3 ALT=92.80 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.3 ALT=92.40 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.3 ALT=92.20 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.3 ALT=91.90 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.3 ALT=91.70 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=91.30 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=90.90 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=90.60 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=90.30 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=89.70 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=89.30 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=89.00 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=88.70 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=88.20 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.2 ALT=87.70 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.1 ALT=86.80 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.1 ALT=86.30 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.1 ALT=85.60 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.1 ALT=85.40 SATS=12 ERRLT=1.2 ERRLG=1.3 ERRHT=2.1

Eheran1 commented 5 years ago

gps.failedChecksum() stays at 0 with my normal application.

Ur example doesnt produce output for me. I gues im doing something wrong? A simple "Serial.println(gps.altitude.meters());" without any if-condition always returns 0. gps.failedChecksum() stays 0 for the first 101 loops, then goes "slowly" up to 297 and stays there forever. There are 300 lines of NMEA data. I have no idea what is going on... Is my library bugged?

This is how my first Block (1 second) of NMEA-data looks like, the only thing I had to change in the example:

  "GNRMC,094507.00,A,xxxx.23052,N,xxxxx.45724,E,0.030,,020119,,,D,V*XX\r\n"
  "GNVTG,,T,,M,0.030,N,0.055,K,D*3B\r\n"
<snip>
  "GNGST,094507.00,34,,,,1.3,1.5,2.5*40\r\n"
  "GNZDA,094507.00,02,01,2019,00,00*7E\r\n"
mikalhart commented 5 years ago

I count 584 lines. Here's mine:

"$GNRMC,094507.00,A,xxxx.23052,N,xxxxx.45724,E,0.030,,020119,,,D,V*1B\r\n"
<snip>
"$GNGST,094535.00,23,,,,1.2,1.3,2.1*44\r\n"
"$GNZDA,094535.00,02,01,2019,00,00*7F\r\n";

Interesting that your failedChecksum counter increases during the run with the STATIC data above. That is definitely weird. What microcontroller are you using? (I.e. you need more than just Uno to store all this data, which overflows the RAM.)

Eheran1 commented 5 years ago

I deleted all the (here useless) *GSV data to save RAM. Im using a adafruit feather m0. I c&p the data now, had to crop a little to make it fit in RAM and it did work! I gathered some new NMEA data and put it in there, worked too!

Then I changed something: I added "TinyGPSCustom satnr(gps, "GNGNS", 7);" and corresponding "if (satnr.isUpdated()) { Serial.print(F(" realsat=")); Serial.print(satnr.value()); }" Still works.

THEN I put all the prints into one "if", and that was "if (gps.speed.isUpdated())". This is how my main application works, one new value triggers all the action. This broke it. This, however, workes, I only changed "speed" to "altitude". It doesnt fix it for my application tho, only in this example:

if (gps.altitude.isUpdated())
  {    
    Serial.print(F("ALT="));        Serial.print(gps.altitude.meters());
    Serial.print(F("  SATS="));     Serial.print(gps.satellites.value());
    Serial.print(F("  realsat="));  Serial.print(satnr.value());
    Serial.print(F("  ERRLT="));    Serial.print(errorlat.value());
    Serial.print(F("  ERRLG="));    Serial.print(errorlong.value());
    Serial.print(F("  ERRHT="));    Serial.println(errorheight.value());  }

Its also broken with "gps.location.isUpdated()" and "gps.time.isUpdated()" and gps.course.isUpdated() and gps.hdop.isUpdated(). It works with said "gps.altitude.isUpdated()" and "gps.satellites.isUpdated()".

Since I need to do everything with every updated GPS-point and the main object is speed... this is a issue for me now. Altitude might stay the same while speed and position changes. Only time, position and speed are values that have to define a "new position" to display/log etc. - idealy its time, since that always iterates up with a new GPS-solution/position.

This is how it looks like when its working (first values missing since they come after the altitude-value, the others are the previous ones):

5s
Start
ALT=110.10  SATS=12  realsat=14  ERRLT=  ERRLG=  ERRHT=
ALT=110.00  SATS=12  realsat=15  ERRLT=3.5  ERRLG=2.8  ERRHT=4.9
ALT=109.60  SATS=12  realsat=15  ERRLT=2.9  ERRLG=2.4  ERRHT=4.2
ALT=109.20  SATS=12  realsat=15  ERRLT=2.6  ERRLG=2.2  ERRHT=3.9
ALT=108.50  SATS=12  realsat=14  ERRLT=2.6  ERRLG=2.2  ERRHT=3.8
ALT=108.10  SATS=12  realsat=14  ERRLT=2.4  ERRLG=2.1  ERRHT=3.5
ALT=108.10  SATS=12  realsat=14  ERRLT=2.2  ERRLG=2.0  ERRHT=3.3
ALT=107.90  SATS=11  realsat=11  ERRLT=2.2  ERRLG=2.0  ERRHT=3.3
ALT=107.80  SATS=10  realsat=10  ERRLT=2.1  ERRLG=2.0  ERRHT=3.3
ALT=106.70  SATS=12  realsat=15  ERRLT=2.1  ERRLG=1.9  ERRHT=3.3
ALT=106.70  SATS=12  realsat=15  ERRLT=1.9  ERRLG=1.9  ERRHT=3.1
ALT=106.60  SATS=12  realsat=16  ERRLT=1.9  ERRLG=1.8  ERRHT=3.1
ALT=101.80  SATS=12  realsat=19  ERRLT=1.9  ERRLG=1.8  ERRHT=3.1
ALT=101.60  SATS=12  realsat=19  ERRLT=1.6  ERRLG=1.4  ERRHT=2.6
ALT=101.40  SATS=12  realsat=19  ERRLT=1.5  ERRLG=1.4  ERRHT=2.5
ALT=100.80  SATS=12  realsat=19  ERRLT=2.3  ERRLG=2.2  ERRHT=2.6
ALT=100.40  SATS=12  realsat=19  ERRLT=2.1  ERRLG=1.9  ERRHT=2.5
ALT=100.00  SATS=12  realsat=19  ERRLT=1.9  ERRLG=1.9  ERRHT=2.4
ALT=99.90  SATS=12  realsat=19  ERRLT=1.8  ERRLG=1.8  ERRHT=2.4
ALT=99.50  SATS=12  realsat=18  ERRLT=1.7  ERRLG=1.7  ERRHT=2.3
ALT=99.40  SATS=12  realsat=18  ERRLT=1.5  ERRLG=1.6  ERRHT=2.2
ALT=99.40  SATS=12  realsat=18  ERRLT=1.5  ERRLG=1.6  ERRHT=2.2
ALT=99.80  SATS=12  realsat=18  ERRLT=1.5  ERRLG=1.5  ERRHT=2.1
ALT=104.90  SATS=12  realsat=20  ERRLT=1.4  ERRLG=1.5  ERRHT=2.1

This is the broken example. Just replace "if (gps.time.isUpdated())" with "if (gps.altitude.isUpdated())" and it works:

#include <TinyGPS++.h>
TinyGPSPlus gps;

char data[] =
  "$GNRMC,003242.00,A,xxxx.22586,N,xxxxx.45868,E,0.029,,030119,,,A,V*XX\r\n"
  "$GNVTG,,T,,M,0.029,N,0.053,K,A*30\r\n"
<snip>
  "$GNGST,004010.00,36,,,,1.2,1.4,2.1*4C\r\n"
  "$GNZDA,004010.00,03,01,2019,00,00*75\r\n";

TinyGPSCustom errorlat(gps, "GNGST", 6); //=1 sigma error
TinyGPSCustom errorlong(gps, "GNGST", 7); //=1 sigma error
TinyGPSCustom errorheight(gps, "GNGST", 8); //=1 sigma error
TinyGPSCustom satnr(gps, "GNGNS", 7);

void setup()
{
  delay(3000);
  Serial.begin(115200);
  Serial.println(F("5s"));
  delay(3000);
  Serial.println(F("Start"));

}

const char *p = data;

void loop()
{
  if (*p)
    gps.encode(*p++);

  if (gps.time.isUpdated())
  {

    Serial.print(F("ALT="));        Serial.print(gps.altitude.meters());
    Serial.print(F("  SATS="));     Serial.print(gps.satellites.value());
    Serial.print(F("  realsat="));  Serial.print(satnr.value());
    Serial.print(F("  ERRLT="));    Serial.print(errorlat.value());
    Serial.print(F("  ERRLG="));    Serial.print(errorlong.value());
    Serial.print(F("  ERRHT="));    Serial.println(errorheight.value());
  }
}
mikalhart commented 5 years ago

Ah, at least I understand why this variant doesn't work. Since you never query the value of gps.time, gpt.time.isUpdated() will return "true" always. For every character read, you're printing out all the data, and that takes forever. Add this like to the very last block:

    Serial.print(F("  TIME="));     Serial.println(gps.time.value());
Eheran1 commented 5 years ago

I think I know why it doesnt work after playing around a lot more: The NMEA-informations come asynchronus and I have to trigger all my action after the LAST "gps.?????.isUpdated()" and not time or speed, since they are both befor the other values. Using the wrong "trigger" causes all sorts of absurd problems, even checksumm-errors. Which is the last item to be updated? In my case the last item is the height error at the end of GST. With that all 3 errors work.

The only thing that still doesnt work is TinyGPSCustom satnr(gps, "GNGNS", 7); And that is far befor GST almost at the beginning of the NMEA-stream, right befor the (in my case incorrect) GGA-satellite value which ur library fetches.

This should return 18 and it does so in the simple Testsketch with fixed NMEA-Data. $GNGNS,003451.00,XXXX.22645,N,XXXXX.46189,E,DAAN,18,0.82,99.4,45.0,,0000,V*XX

Can I stream the raw NMEA out somehow while its processed? The NMEA-Data I posted here was gathered over USB of the GPS unit, not via Serial of the µC.

EDIT: Never mind, it works. I Checked with my 'scope and it turns out GNGNS is not active on UART but only on the USB of the GPS. Changed it and its fine.

EDIT2: The custom values seems to be stored as const char? Thus I cant print them with (n) decimal places. ```error: call of overloaded 'print(const char, int)' is ambiguous```

mikalhart commented 5 years ago

Re: EDIT2: Yeah, TinyGPSCustom objects don't make any assumptions about the underlying type. You need to convert the string yourself, i.e.

Serial.print(atof(satnr.value()), 2);

Anything still unclear in this thread?

Eheran1 commented 5 years ago

Not for me. Thanks for the great help and ur superb library.