TinyGPS++ 5Hz data has repeat timestamps

Hi all,

I'm using the Neo 6M in a GPS project. It's working well and I've got one lingering issue. Here's the code in question (copied almost exactly from an example -- which is why I'm a bit confused):

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (gpsSerial.available() > 0){
    if (gps.encode(gpsSerial.read())){
      displayInfo();
    }
  }
...
...
}

I have programmed the GPS to do updates at 5Hz, and I am getting data with 0.2s granularity. The issue is I get repeating data. For example, I'll get three lines for timestamp 1:00:00 and then finally a line for timestamp 1:00:08. Here is some lines from my Serial Log. The displayInfo() function prints all this.

21:04:52.620 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:46.40
21:04:52.780 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:46.40
21:04:52.977 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:46.40
21:04:53.263 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:47.00
21:04:53.415 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:47.00
21:04:53.628 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:47.40
21:04:53.779 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:47.40
21:04:54.013 -> Location: 40.618953,-111.864372 Date/Time: 2/28/2024 04:04:47.40
21:04:54.283 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:48.00
21:04:54.431 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:48.00
21:04:54.646 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:48.40
21:04:54.804 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:48.40
21:04:55.049 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:48.80
21:04:55.205 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:48.80
21:04:55.427 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:49.20
21:04:55.586 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:49.20
21:04:55.816 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:49.60
21:04:55.971 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:49.60
21:04:56.168 -> Location: 40.618957,-111.864372 Date/Time: 2/28/2024 04:04:49.60

When I use the uCenter app (manufacturer provided software), I can confirm that I am getting data every 200ms. But when I read out that data in the Arduino IDE, I get these jumps in time.

I'm wondering if it has to do with the gps.encode() function? Should I have a delay between encode attempts? Is there still some data sitting in the software serial that I need to flush?

If the GPS has mediocre signal and doesn't get new location data in 200ms, does it just send over the previous data?

Thanks everyone

Please post all of your code, using code tags. The errors are almost always in the part not posted.

Also state the type of Arduino, and how it is connected to the computer printing the timestamps.

Will do:

Using an arduino Uno. Connected to computer with the USB port. GPS is controlled via a softwareSerial port.

I knows the SD card writing code still needs work. That's my next bug to iron out.

Entire Code:

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

#include <SD.h>
#include <SPI.h>

// Choose two Arduino pins to use for software serial
int RXPin = 3;
int TXPin = 2;
const int chipSelect = 10;
File myFile;
int GPSBaud = 9600;

// Create a TinyGPS++ object
TinyGPSPlus gps;
String fileName;

// Create a software serial port called "gpsSerial"
SoftwareSerial gpsSerial(RXPin, TXPin);

bool debug = true; 

void setup()
{
    // Start the Arduino hardware serial port at 9600 baud
    Serial.begin(115200);
    fileName = "gpsData_" + String(millis()) + ".txt";
    // Start the software serial port at the GPS's default baud
    gpsSerial.begin(GPSBaud);

    if (SD.begin(chipSelect))
    {
      Serial.println("SD card is present & ready");
      Serial.println("Will be saving to file: " + fileName);
      delay(3000);

    } 
    else
    {
      Serial.println("SD card missing or failure");
      //while(1);  //wait here forever
    }
  

      const unsigned char UBLOX_INIT[] PROGMEM = {
    // Rate (pick one)
    //  0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz)
      0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz)
      //0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39 //(1Hz)
    };

    //for(unsigned int i = 0; i < sizeof(UBLOX_INIT); i++) {                        
    //  gpsSerial.write( pgm_read_byte(UBLOX_INIT+i) );
    //  delay(5);
   // }

  Serial.println("Programming the GPS to 5HZ");
  delay(500);
  gpsSerial.write(UBLOX_INIT, sizeof(UBLOX_INIT));
  delay(500);
  Serial.println("DONE Programming the GPS to 5HZ");

  myFile = SD.open(fileName, FILE_WRITE);
  if(myFile)
    Serial.println("File Created Successfully");
  else
    Serial.println("DIDNT MAKE THE FILE!!!!");
  delay(3000);

}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (gpsSerial.available() > 0){
  //Serial.println("gpsData: ");
  //Serial.println(gps.encode(gpsSerial.read()));
    if (gps.encode(gpsSerial.read())){
      displayInfo();
      Serial.println("Did encode");
      gpsSerial.flush();
      delay(100);
    }
  }

  // If 5000 milliseconds pass and there are no characters coming in
  // over the software serial port, show a "No GPS detected" error
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println("No GPS detected");
    while(true);
  }

}

void displayInfo()
{
  
  myFile = SD.open(fileName, FILE_WRITE);
  if (gps.date.isValid())
  {
    if(debug){
      Serial.print("Date: ");
      Serial.print(gps.date.month());
      Serial.print("/");
      Serial.print(gps.date.day());
      Serial.print("/");
      Serial.println(gps.date.year());
    }

    
    
    myFile.print(gps.date.year());
    myFile.print(",");
    myFile.print(gps.date.month());
    myFile.print(",");
    myFile.print(gps.date.day());
    myFile.print(",");

  }
  else
  {
    Serial.println("Not Available");
  }

  if (gps.time.isValid())
  {
    if(debug){
      Serial.print("Time: ");
      if (gps.time.hour() < 10) Serial.print(F("0"));
      Serial.print(gps.time.hour());
      Serial.print(":");
      if (gps.time.minute() < 10) Serial.print(F("0"));
      Serial.print(gps.time.minute());
      Serial.print(":");
      if (gps.time.second() < 10) Serial.print(F("0"));
      Serial.print(gps.time.second());
      Serial.print(".");
      if (gps.time.centisecond() < 10) Serial.print(F("0"));
      Serial.println(gps.time.centisecond());
    }

  
    myFile.print(gps.time.hour());
    myFile.print(",");
    myFile.print(gps.time.minute());
    myFile.print(",");
    myFile.print(gps.time.second());
    myFile.print(",");
    myFile.print(gps.time.centisecond());
    myFile.print(",");

  }
  else
  {
    Serial.println("Not Available");
  }

  if (gps.location.isValid())
  {
    if(debug){
      Serial.print("Latitude: ");
      Serial.println(gps.location.lat(), 6);
      Serial.print("Longitude: ");
      Serial.println(gps.location.lng(), 6);
      Serial.print("Altitude: ");
      Serial.println(gps.altitude.meters());
    }


   //Lat
    myFile.print(gps.location.lat(), 6);
    myFile.print(",");
    //long
    myFile.print(gps.location.lng(), 6);
    myFile.println("");
    

  }
  else
  {
    Serial.println("Location: Not Available");
  }
  Serial.print("wrote to file");
  myFile.close();
  Serial.println();
  Serial.println();
 
}

There are lots of problems with that code. I recommend to get started with the TinyGPS examples, and learn how to read the GPS, displaying only the relevant information properly. You need to learn how to check whether the data has been updated since you last read it, and ignore stale data. Save the SD card stuff for later.

Some hints:

  1. Avoid using Strings on the Uno and other AVR-based Arduinos. They are never necessary and cause program malfunctions or outright crashes.

  2. Avoid using delay(). It is not necessary in your application.

  3. Do not simply throw in statements like this unless you know exactly what it does and why. In this case, it does nothing useful.

      gpsSerial.flush();

Sort of, but encode() is likley doing what you tell it.

TinyGPS++ only reads the GPGGA and GPRMC sentences. While in the average GPS are about 2 of eight sentences the GPS outputs.

Using SoftwareSerial and then printing out a big heap of stuff to the Serial monitor (the location time etc) after each of the 8 sentences is probably going to cause software serial to miss characters and thus sentences, which could well give you 'gaps' in the decode process.

Most likely you didn't set the GPS to 5Hz

Install u-blox Center (it's free) and check if it actually reads at 5Hz.
You can use Arduino as a Serial bridge:

Follow these steps to set Baudrate correctly:

Looks like you are getting every other update, with the times approximately 0.40 seconds apart. That is what I would expect with all the SD and Serial activity. Anything over about 63mS between reading the software serial port will overflow the buffer, and additionally you are dumpling the entire buffer with flush(), which then requires you to wait for the next full valid sentence from the GPS. Just needlessly opening and closing the SD file repeatedly wastes time.

I strongly recommend that you use SlashDevin's NeoGPS library.
It is not as simple to understand as TinyGPS but it is far superior.
TinyGPS can mistakenly mix fields from different data frames, something NeoGPS does not do.
TinyGPS is prone to generating these types of errors.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.