TinyGPS library reporting checksum errors, but no visible corruption

Hi! I am working on a GPS project and I turned to TinyGPS for parsing the NMEA data. I have been able to get the most basic example sketch to work fine ("simple_test"), and it was reporting no checksum errors up until I tried to add code to extract the time from the NMEA sentences. The "CSUM" error counter suddenly starting going up even when data wasn't being received. The counter will go up by one and sometimes two for ever 1-10ish chunks of data it parses. While this concerns me, the time data is shown accurately and without fault.

Even if these errors have no consequence, it will make it harder to detect when errors of consequence actually do happen. Here is the full code. Can somebody please help me? Thanks!

#include <SoftwareSerial.h>

#include <TinyGPS.h>
#include <string.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 2(rx) and 3(tx).
*/

TinyGPS gps;
SoftwareSerial ss(2, 3);

void setup()
{
  Serial.begin(115200);
  ss.begin(4800);
  
  Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
}

void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  // For one second we parse GPS data and report some key values
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

  if (newData)
  {
    float flat, flon;
    unsigned long age;
    int year;
    byte month, day, hour, minute, second, hundredths;
    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
    char datastring1[80];
    sprintf(datastring1,"%02d:%02d:%02d", hour, minute, second);
    gps.f_get_position(&flat, &flon, &age);
    Serial.print("LAT=");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(" LON=");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(" ALT=");
    Serial.print(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0.0 : gps.f_altitude(), 2);
    Serial.print(" SPD=");
    Serial.print(gps.f_speed_mps() == TinyGPS::GPS_INVALID_F_SPEED ? 0.0 : gps.f_speed_mps(), 2);
    Serial.print(" CRS=");
    Serial.print(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : gps.f_course(), 6);
    Serial.print(" TIM=");
    Serial.print(age == TinyGPS::GPS_INVALID_AGE ? 0 : datastring1);
    Serial.print(" SAT=");
    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
    Serial.print(" PREC=");
    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
  }
  
  gps.stats(&chars, &sentences, &failed);
  Serial.print(" CHARS=");
  Serial.print(chars);
  Serial.print(" SENTENCES=");
  Serial.print(sentences);
  Serial.print(" CSUM ERR=");
  Serial.println(failed);
}

I use the same library And I 'think' that the 'bad' or failed checksum sentences are discarded... Or I remember reading that somewhere Re: Mikal Harts TinyGPSV12

Bob

  for (unsigned long start = millis(); millis() - start < 1000;)

This is what a while statement is supposed to be used for, not a for loop.

How often does the GPS actually report a new sentence? It may not really be necessary to use that while/for loop at all.

    char datastring1[80];
    sprintf(datastring1,"%02d:%02d:%02d", hour, minute, second);

2 + 1 + 2 + 1 + 2 + 1 < 80.

@Docedison
The Arduiniana page says: "If the $GPRMC sentence reports a validity of “V” (void) instead of “A” (active), or if the $GPGGA sentence reports fix type “0? (no fix) then those sentences are discarded."

I'm not sure if this is what the error counter is keeping track of, but even if the invalid data is being discarded, I still think it is a problem if I cannot find other invalid data.

@PaulS
Hello from another Seattleite! The GPS updates every second, whether it has data or not. I'll try fiddling around with that loop later in the day, thanks!

The GPS updates every second, whether it has data or not.

One of the fields is whether the data is good, or not. I'd eliminate that while loop, and let the GPS tell you when it has (good) data.

By the "while loop" do you mean this part?

for (unsigned long start = millis(); millis() - start < 1000;)

How would this fix the checksum error?

I think I found a fix. I do not know much about what the checksum is counting in this particular code, but after experimenting around a bit I found that it was not the time data itself that was triggering the error, but rather how many things I attempted to parse and print to serial. When I commented out the "CRS" data only, the checksum error counter stayed at zero. When I commented out the time data only, the checksum error counter stayed at zero as well (sometimes it began at 1 and stayed at 1). When I tried printing both course and time to serial, the counter rose up.

I can work with not having the course data if need be, but does anyone know why the csum errors start counting when I add too much stuff to the if(newData) statement?

By the "while loop" do you mean this part?

Yes.

How would this fix the checksum error?

It's causing the Arduino to miss data that the GPS is sending. The GPS sends data once a second (you confirmed), so you don't need to screw around with reading data only for one second, and then printing a boat load of stuff to the serial monitor.

but rather how many things I attempted to parse and print to serial.

Hint: It's not the parsing that is causing the problems...

Removing the loop works fine, but I still get checksum errors depending on how many things I try to print.

It's not the parsing that is causing the problems...

I agree that the parsing works fine, but if the printing to serial is where the errors are coming from, what about the printing to serial is causing them?

Printing to serial takes time. If, during that time, the GPS dumps more data to the serial port than the buffer can hold, that data is lost. Oops. Checksum error.

You could try printing 1/4 of the data on each pass through loop, so that less time is taken printing the data before you check the incoming serial data again.

So that is why the example sketch used the maximum baud rate! I was wondering what the need was for that. This idea of a buffer time for the serial to print in also pertains to the post-testing phase of my project. Thanks for helping me, this clears up my confusion!