10hz GNSS with NEOGPS library

Hello everyone,
I am using Quectel L86 GNSS module and want to get data with 10Hz, I am using NEOGPS Library.

I have a code which works with the Quectel L80 GPS module but not with L86 GNSS module.

Here is the code

#include <Arduino.h>
#include <NMEAGPS.h>

NMEAGPS  gps; // This parses the GPS characters

#define gps_port Serial2

//------------------------------------

void doSomeWork( const gps_fix & fix )
{
  if (fix.valid.date & fix.valid.time & fix.valid.location) {

    // Date
    Serial.print( fix.dateTime.date );
    Serial.print( ':' );
    Serial.print( fix.dateTime.month );
    Serial.print( ':' );
    Serial.print( fix.dateTime.full_year() );
    Serial.print( F("      ") );

    // Time
    if ( fix.dateTime.hours < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.hours );
    Serial.print( ':' );
    if ( fix.dateTime.minutes < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.minutes );
    Serial.print( ':' );
    if ( fix.dateTime.seconds < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.seconds );
    Serial.print( '.' );
    if ( fix.dateTime_cs < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime_cs );
    Serial.print( F("         ") );

    // Location
    Serial.print( fix.latitude(), 5 );
    Serial.print( F("      ") );
    Serial.print( fix.longitude(), 5 );

  } else {
    // No valid location data yet!
    Serial.print( '?' );
  }

  Serial.println();

} // doSomeWork

//------------------------------------

void GPSloop()
{
  while (gps.available( gps_port ))
    doSomeWork( gps.read() );

} // GPSloop
  
//------------------------------------

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
 Serial.flush();

  
  gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  gps_port.end();                                // empty the input buffer, too
  
  gps_port.begin( 115200 );                      // use the new baud rate
  gps.send_P( &gps_port, F("PMTK220,100") );     // set 10Hz update rate
}

//------------------------------------

void loop()
{
  GPSloop();
}

only i can see in Serial monitor is

Date Time Latitude Longitude

I want to use this code to run GNSS at 10Hz while GNSS is on Serial2
Please help
Thank you

This means that the LAST_SENTENCE is never received by the Arduino.

Run NMEAorder to see what sentences the L86 is emitting. Maybe it is not sending the same sentences, and you have to enable something with configuration commands, or change the NeoGPS configuration to parse the sentences it does send (and change LAST_SENTENCE).

You can also run NMEAdiagnostic to see what data it does send. Maybe it is sending messages in a binary protocol instead of NMEA text.

In either case, post the results for us to examine.

Cheers,
/dev

Hello /Dev,
Thank you for replying…

Run NMEAorder

How can i run this code while my GNSS module is connected to Serial2.?

I have changed   #define DEBUG_PORT Serial to   #define DEBUG_PORT Serial2 but nothing displays on the Serial Monitor…

I have tried using this older code which shows data at 1hz

#include <Arduino.h>
#include <NMEAGPS.h>

NMEAGPS  gps; // This parses the GPS characters

#define gps_port Serial2

//------------------------------------

void doSomeWork( const gps_fix & fix )
{
  if (fix.valid.date & fix.valid.time & fix.valid.location) {

    // Date
    Serial.print( fix.dateTime.date );
    Serial.print( ':' );
    Serial.print( fix.dateTime.month );
    Serial.print( ':' );
    Serial.print( fix.dateTime.full_year() );
    Serial.print( F("      ") );

    // Time
    if ( fix.dateTime.hours < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.hours );
    Serial.print( ':' );
    if ( fix.dateTime.minutes < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.minutes );
    Serial.print( ':' );
    if ( fix.dateTime.seconds < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.seconds );
    Serial.print( '.' );
    if ( fix.dateTime_cs < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime_cs );
    Serial.print( F("         ") );

    // Location
    Serial.print( fix.latitude(), 5 );
    Serial.print( F("      ") );
    Serial.print( fix.longitude(), 5 );

  } else {
    // No valid location data yet!
    Serial.print( '?' );
  }

  Serial.println();

} // doSomeWork

//------------------------------------

void GPSloop()
{
  while (gps.available( gps_port ))
    doSomeWork( gps.read() );

} // GPSloop
  
//------------------------------------

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();
  
  gps_port.begin( 9600 );
}

//------------------------------------

void loop()
{
  GPSloop();
}

This code works fine…
What could be the problem.?

Hello /Dev,
Please see my above comment also.

I am trying to log GPS and Analog Accelerometer data into SD card.

here is my code below

#include <Arduino.h>
#include <NMEAGPS.h>
#include <SPI.h>
#include <SdFat.h>


NMEAGPS  gps; // This parses the GPS characters
gps_fix  fix; // This contains all the GPS fields

#define gps_port Serial2

int chip = 35;
SdFat SD;
File  dataFile;
char filename[] = "98765.tcx";


const int xpin = A0;                  // x-axis of the accelerometer
const int ypin = A1;                  // y-axis
const int zpin = A2;                  // z-axis
int x, y, z, total;

void setup()  {
  Serial.begin(9600);
  Serial.flush();

  gps_port.begin( 9600 );
  //  gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
  //  gps_port.flush();                              // wait for the command to go out
  //  delay( 100 );                                  // wait for the GPS device to change speeds
  //  gps_port.end();                                // empty the input buffer, too
  //
  //  gps_port.begin( 115200 );                      // use the new baud rate
  //  gps.send_P( &gps_port, F("PMTK220,100") );     // set 10Hz update rate
  pinMode(chip, OUTPUT);
  digitalWrite(chip, LOW);
  pinMode(2, INPUT_PULLUP);

  if (!SD.begin(36)) {
    Serial.println( F("Card failed, or not present") );
    // don't do anything more:
    return;
  }
  Serial.println( F("card initialized.") );
  Serial.println( F("Code Running") );

} // setup

void firstStage()
{
  Serial.println( F("Co-ordinates Achieved") );
  dataFile = SD.open(filename , FILE_WRITE);
  Serial.println(filename);

  if (dataFile) {
    Serial.println( F("File created\n"
                      "LOGGING DATA!\n") );

    dataFile.println( F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                        "<TrainingCenterDatabase xmlns=\""
                        "http://www.garmin.com/"
                        "xmlschemas/TrainingCenterDatabase/v2\">\n"
                        "<Activities>\n"
                        "<Activity Sport=\"Other\">") );
    dataFile.println( F("<Id>") );
    if ( fix.dateTime.full_year() < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.full_year() );
    dataFile.print  ( '-' );
    if ( fix.dateTime.month < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.month );
    dataFile.print  ( '-' );
    if ( fix.dateTime.date  < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.date );
    dataFile.print  ( 'T' );
    if ( fix.dateTime.hours < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.hours );
    dataFile.print  ( ':' );
    if ( fix.dateTime.minutes < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.minutes );
    dataFile.print  ( ':' );
    if ( fix.dateTime.seconds < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.seconds );
    dataFile.print  ( '.' );
    dataFile.print  ( fix.dateTime_cs );
    dataFile.println( F("0Z"
                        "</Id>\n"
                        "<Lap StartTime=\"") );
    /////dataFile.println( F("<Id>") );
    if ( fix.dateTime.full_year() < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.full_year() );
    dataFile.print  ( '-' );
    if ( fix.dateTime.month < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.month );
    dataFile.print  ( '-' );
    if ( fix.dateTime.date  < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.date );
    dataFile.print  ( 'T' );
    if ( fix.dateTime.hours < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.hours );
    dataFile.print  ( ':' );
    if ( fix.dateTime.minutes < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.minutes );
    dataFile.print  ( ':' );
    if ( fix.dateTime.seconds < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.seconds );
    dataFile.print  ( '.' );
    dataFile.print  ( fix.dateTime_cs );
    dataFile.println( F("0Z\">"
                        "<Track>") );
  }
} // firstStage

void secondStage()
{
  if (dataFile.isOpen()) {
    dataFile.println( F("<Trackpoint>\n"
                        "<Time>") );
    if ( fix.dateTime.full_year() < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.full_year() );
    dataFile.print  ( '-' );
    if ( fix.dateTime.month < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.month );
    dataFile.print  ( '-' );
    if ( fix.dateTime.date  < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.date );
    dataFile.print  ( 'T' );
    if ( fix.dateTime.hours < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.hours );
    dataFile.print  ( ':' );
    if ( fix.dateTime.minutes < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.minutes );
    dataFile.print  ( ':' );
    if ( fix.dateTime.seconds < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.seconds );
    dataFile.print  ( '.' );
    dataFile.print  ( fix.dateTime_cs );
    dataFile.print  ( F("0Z"
                        "</Time>"
                        "<Position>\n"
                        "<LatitudeDegrees>") );
    dataFile.print  ( fix.latitude(), 5 );
    dataFile.print  ( F("</LatitudeDegrees>\n"
                        "<LongitudeDegrees>") );
    dataFile.print  ( fix.longitude(), 5 );
    dataFile.print  ( F("</LongitudeDegrees>\n"
                        "</Position>\n"
                        "<HeartRateBpm>\n"
                        "<Value>") );
    dataFile.print  ( '0' );
    dataFile.print  ( F("</Value>\n"
                        "</HeartRateBpm>\n"
                        "<SensorState>"
                        "Present"
                        "</SensorState>\n") );

    analogReference(EXTERNAL);
    x     = analogRead(xpin);
    y     = analogRead(ypin);
    z     = analogRead(zpin);
    total = sqrt( x * x + y * y + z * z );

    dataFile.print  ( F("<Impact>"
                        "<Gforce>") );
    dataFile.print  ( total );
    dataFile.print  ( F("</Gforce>\n"
                        "<Xaxis>") );
    dataFile.print  ( x );
    dataFile.print  ( F("</Xaxis>\n"
                        "<Yaxis>") );
    dataFile.print  ( y );
    dataFile.print  ( F("</Yaxis>\n"
                        "<Zaxis>") );
    dataFile.print  ( z );
    dataFile.println( F("</Zaxis>\n"
                        "</Impact>\n"
                        "</Trackpoint>") );
  }

} // secondStage

void doSomeWork() {

  if (fix.valid.date && fix.valid.time && fix.valid.location)
  {
    if (!dataFile.isOpen())
      firstStage();

    if (dataFile.isOpen())
      secondStage();
  }
  else {
    // No valid location data yet!
    Serial.print  ( '?' );
  }

  Serial.println();

} // doSomeWork

void GPSloop()
{
  while (gps.available( gps_port) ) {
    fix = gps.read();
    doSomeWork();
  }

} // GPSloop

void loop()
{
  GPSloop();

  // Testing the button could go almost anywhere.
  //    Putting it here will close dataFile the fastest,
  //    because it won't have to wait for the next
  //    GPS update.
  if (digitalRead(37) == LOW) {
    endtask();

    // stop here!
    while (1)
      ;
  }

} // loop

void endtask()
{
  if (dataFile.isOpen()) {
    dataFile.println( F("</Track>\n"
                        "</Lap>\n"
                        "</Activity>\n"
                        "</Activities>\n"
                        "</TrainingCenterDatabase>") );
    dataFile.close();
    Serial.println( F("file closed") );
  } else {
    Serial.println( F("(file never opened)") );
  }

} // endtask

I only get this in serial Monitor

card initialized.
Code Running
(file never opened)

I am using Atmega2560V-8AU with MegaCore bootloaders.

i have tried datalogging example from SD library, it works fine.

How can i run [NMEAorder] while my GNSS module is connected to Serial2?

Edit GPSport.h:

  HardwareSerial & gps_port = Serial2;   <-- was Serial1
 #define USING_GPS_PORT "Serial2"

This will make all the NeoGPS examples use Serial for the Serial Monitor window and Serial2 for the GPS device. Both NMEAorder and NMEAdiagnostic will be affected.

Don’t change DEBUG_PORT. That’s the port connected to the Serial Monitor window (almost always Serial). NMEAorder.ino should have this for DEBUG_PORT:

//  'Serial' is for debug output to the Serial Monitor window.
//
//======================================================================

#if defined( UBRR1H ) | defined( ID_USART0 )
  // Default is to use Serial1 when available.  You could also
  // use NeoHWSerial, especially if you want to handle GPS characters
  // in an Interrupt Service Routine.
  //#include <NeoHWSerial.h>
#else  
  // Only one serial port is available, uncomment one of the following:
  //#include <NeoICSerial.h>
  //#include <AltSoftSerial.h>
  #include <NeoSWSerial.h>
  //#include <SoftwareSerial.h> /* NOT RECOMMENDED */
#endif
#include "GPSport.h"
  
#ifdef NeoHWSerial_h
  #define DEBUG_PORT NeoSerial
#else
  #define DEBUG_PORT Serial
#endif

I have tried using this older code which shows data at 1hz

The main differences between the new code (in your original post) and the older code are:

  • The new code sets the GPS baud rate to 115200 (the old code leaves it at 9600)

  • The new code sets the GPS update interval to 10Hz (the old code leaves it at 1Hz)

According to the protocol spec, the PMTK220 message can only go up to 5Hz (200ms). I don’t know how this is different from the PMTK300 message, which can go up to 10Hz (100ms).

And since you are only using date, time and lat/lon, you should disable all sentences except the RMC. The RMC has all three pieces. I would suggest sending this command first:

gps.send( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only

Then the GPS device will only send about 70 characters per update. Make sure the LAST_SENTENCE is RMC in NMEAGPS_cfg.h.

Then try NMEAorder and the old code, to make sure the GPS device is only sending the RMC, and the old code prints updates once per second.

Then try adding the baud rate configuration commands to the old code, to see if you can still get RMC at 1Hz, but at the higher baud rate.

Then add the PMTK220 message at 200ms to the old code, to see if you can get updates at 5Hz.

If that works, try the PMTK220 at 100ms (or the PMTK300 message at 100ms) to see if you can get updates at 10Hz

I only get this in serial Monitor

card initialized.

Code Running



(file never opened)
I am using Atmega2560V-8AU with MegaCore bootloaders.

i have tried datalogging example from SD library, it works fine.

If you are not seeing "?" printed over and over, then NeoGPS is not receiving the LAST_SENTENCE. If you make the changes I listed in the previous post, this would be an RMC.

If you ran a sketch that changed the baud rate to 115200, then run your data logging sketch that does "gps_port.begin(9600)", the logging sketch will not receive any data. It will be listening at the wrong baud rate. You may have to power off the GPS device to reset it to 9600 for the data logging sketch.

Hello -Dev,

Thank you for replying.

I have edited GPSport.h as you told and tried NMEAorder example, I have get the Serial output

NMEAorder.INO: started
fix object size = 31
NMEAGPS object size = 84
Looking for GPS device on Serial2
.....................
Sentence order in each 1-second interval:
RMC
VTG
GGA
GSA
GSA
GSV
GSV
GLL

and tried NMEADiagnostic example and get the serial output

Checking 9600 baud...
Received GSA
Received GSA
Received GSV
Received GSV
Received GLL
Received RMC
Received VTG
Received GGA
Received GSA
Received GSA
Received GSV
Received GSV
Received GLL
Received RMC
Received VTG
Received GGA
Received GSA
Received GSA
Received GSV
Received GSV
Received GLL

**** NMEA sentence(s) detected! ****
Received data:
82826262626262826282628E89A98A89A98A89498912350A2447504753412C41 ..bbbbb.b.b........I..5.$GPGSA,A
2C312C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2A31450D0A2447504753412C412C31 ,1,,,,,,,,,,,,,,,1E..$GPGSA,A,1
2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2A31450D0A2447504753562C312C312C30 ,,,,,,,,,,,,,,,1E..$GPGSV,1,1,0
302A37390D0A24474C4753562C312C312C30302A36350D0A244750474C4C2C2C 0
79..$GLGSV,1,1,00
65..$GPGLL,,
2C2C2C3233353934322E3830302C562C4E2A37390D0A2447505458542C30312C ,,,235942.800,V,N79..$GPTXT,01,
30312C30322C414E545354415455533D4F50454E2A32420D0A244750524D432C 01,02,ANTSTATUS=OPEN
2B..$GPRMC,
3233353934332E3830302C562C2C2C2C2C302E30302C302E30302C3035303138 235943.800,V,,,,,0.00,0.00,05018
302C2C2C4E2A34330D0A2447505654472C302E30302C542C2C4D2C302E30302C 0,,,N*43..$GPVTG,0.00,T,,M,0.00,

Device baud rate is 9600

GPS data fields received:

Status,UTC Date/Time,Lat,Lon,Hdg,Spd,Alt,Sats,Rx ok,Rx err,Rx chars,
0,2080-01-05 23:59:44.79,,,0,0,,0,21,0,720,

** NMEAdiagnostic completed **

GNSS is connected to Serial2 now....

According to the protocol spec, the PMTK220 message can only go up to 5Hz (200ms). I don't know how this is different from the PMTK300 message, which can go up to 10Hz (100ms)

I have used PMTK220 message at 10Hz(100ms) previously, we had a forum on this CLICK HERE I have used this with Quectel L80 Module and datasheet of L86 GNSS also shows this will work at 10Hz.

And since you are only using date, time and lat/lon, you should disable all sentences except the RMC. The RMC has all three pieces. I would suggest sending this command first:

I have tried this line of code in the Setup of NMEAorder example

DEBUG_PORT.begin(9600);

  while (!DEBUG_PORT)
    ;

  DEBUG_PORT.print( F("NMEAorder.INO: started\n") );
  DEBUG_PORT.print( F("fix object size = ") );
  DEBUG_PORT.println( sizeof(gps.fix()) );
  DEBUG_PORT.print( F("NMEAGPS object size = ") );
  DEBUG_PORT.println( sizeof(gps) );
  DEBUG_PORT.println( F("Looking for GPS device on " USING_GPS_PORT) );
  DEBUG_PORT.flush();

  // Start the UART for the GPS device
  gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
                             // wait for the command to go out

I have added _P after gps.send , If i didn't i was getting some error..

I can only get GPRMC and GPTXT, I have seen this by GPS Echo test...

$GPTXT,01,01,02,ANTSTATUS=OPEN2B
$GPRMC,071620.088,V,,,,,0.19,111.84,010817,,,N
45
$GPTXT,01,01,02,ANTSTATUS=OPEN2B
$GPRMC,071623.088,V,,,,,0.05,313.07,010817,,,N
40
$GPTXT,01,01,02,ANTSTATUS=OPEN2B
$GPRMC,071624.088,V,,,,,0.19,291.34,010817,,,N
41
$GPTXT,01,01,02,ANTSTATUS=OPEN2B
$GPRMC,071625.088,V,,,,,0.28,83.47,010817,,,N
77
$GPTXT,01,01,02,ANTSTATUS=OPEN2B
$GPRMC,071626.088,V,,,,,0.11,312.02,010817,,,N
44
$GPTXT,01,01,02,ANTSTATUS=OPEN2B
$GPRMC,071627.088,V,,,,,0.28,82.35,010817,,,N
71
$GPTXT,01,01,02,ANTSTATUS=OPEN2B
$GPRMC,071628.088,V,,,,,0.02,337.15,010817,,,N
49

I am wondering Why it's showing GPRMC while i am using GNSS module i was expecting GNRMC..?

Then try NMEAorder and the old code, to make sure the GPS device is only sending the RMC,

I have tested NMEAorder

NMEAorder.INO: started
fix object size = 31
NMEAGPS object size = 84
Looking for GPS device on Serial2
..
Sentence order in each 1-second interval:
RMC

Make sure the LAST_SENTENCE is RMC in NMEAGPS_cfg.h.

What do you mean by here.? do i have to search LAST_SENCTNCE in NMEAGPS_cfg.h and change to RMC.?

CONTINUATION ON ABOVE

Problem comes now…

my finished code upto here is

#include <Arduino.h>
#include <NMEAGPS.h>

NMEAGPS  gps; // This parses the GPS characters


#include "GPSport.h"


#define DEBUG_PORT Serial


void doSomeWork( const gps_fix & fix )
{
  if (fix.valid.date & fix.valid.time & fix.valid.location) {

    // Date
    Serial.print( fix.dateTime.date );
    Serial.print( ':' );
    Serial.print( fix.dateTime.month );
    Serial.print( ':' );
    Serial.print( fix.dateTime.full_year() );
    Serial.print( F("      ") );

    // Time
    if ( fix.dateTime.hours < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.hours );
    Serial.print( ':' );
    if ( fix.dateTime.minutes < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.minutes );
    Serial.print( ':' );
    if ( fix.dateTime.seconds < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.seconds );
    Serial.print( '.' );
    if ( fix.dateTime_cs < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime_cs );
    Serial.print( F("         ") );

    // Location
    Serial.print( fix.latitude(), 5 );
    Serial.print( F("      ") );
    Serial.print( fix.longitude(), 5 );

  } else {
    // No valid location data yet!
    Serial.print( '?' );
  }

  Serial.println();

} // doSomeWork

//------------------------------------

void GPSloop()
{
  while (gps.available( gps_port ))
    doSomeWork( gps.read() );

} // GPSloop

//------------------------------------

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();

  gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
//    gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
//    gps_port.flush();                              // wait for the command to go out
//    delay( 100 );                                  // wait for the GPS device to change speeds
//    gps_port.end();                                // empty the input buffer, too
//  
//    gps_port.begin( 115200 );                      // use the new baud rate
//    gps.send_P( &gps_port, F("PMTK220,100") );
}

//------------------------------------

void loop()
{
  GPSloop();
}

When i uncomment

//    gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
//    gps_port.flush();                              // wait for the command to go out
//    delay( 100 );                                  // wait for the GPS device to change speeds
//    gps_port.end();                                // empty the input buffer, too

i am not getting anything except

Date Time Latitude Longitude

I have tested with the GPS ECHO test below code

void setup()
{
  Serial.begin(9600);
  Serial2.begin(9600);
}

void loop()
{

  while (Serial2.available())
    Serial.write( Serial2.read() );
}

I am getting GARBAGE in Serial Monitor…

Then i uncommented these lines

//    gps_port.begin( 115200 );                      // use the new baud rate
//    gps.send_P( &gps_port, F("PMTK220,100") );

Again i cannot see anything except

Date Time Latitude Longitude

I again tested with GPS ECHO, then i can see GARBAGE but with faster speed…

Hello -Dev,

I have just tested by ONLY changing the frequency of samples to 10Hz by

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();

  gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );
 
  gps.send_P( &gps_port, F("PMTK220,100") );
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  
//  gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
//  gps_port.flush();                              // wait for the command to go out
//  delay( 100 );
//  gps_port.begin( 115200 );
//  gps_port.end();
}

it's working i can see LAT LONG ,DATE and TIME in serial monitor

But when i uncomment lines for changing baud rate, i am not seeing anything again :frowning:

I have used PMTK220 message at 10Hz(100ms) previously

Ok, the spec has an error.

I have just tested by ONLY changing the frequency of samples to 10Hz by
...
it's working i can see LAT LONG ,DATE and TIME in serial monitor

But when i uncomment lines for changing baud rate, i am not seeing anything again :frowning:

It seems like it is ignoring the baud rate command.

Try sending the command, but don't call gps_port.end and begin. If it keeps getting data at 9600, the GPS device ignored the baud rate command.

Try sending other baud rate commands for 19200, 38400 and 57600.

Try disabling all sentences (put all 0's in the PMTK314 command), then send the baud rate command (and call gps_port.begin and end), then enable only the RMC.

Make sure the LAST_SENTENCE is RMC in NMEAGPS_cfg.h.
What do you mean by here.? do i have to search LAST_SENCTNCE in NMEAGPS_cfg.h and change to RMC?

Yes, see line 31 of NMEAGPS_cfg.h:

    #define LAST_SENTENCE_IN_INTERVAL NMEAGPS::NMEA_RMC

Hello -Dev,
Thank you for replying,

Now i am able to read output from the GNSS but there’s a data lost in between.

here is my full code.

#include <Arduino.h>
#include <NMEAGPS.h>

NMEAGPS  gps; // This parses the GPS characters

#if defined( UBRR1H ) | defined( ID_USART0 )
// Default is to use Serial1 when available.  You could also
// use NeoHWSerial, especially if you want to handle GPS characters
// in an Interrupt Service Routine.
//#include <NeoHWSerial.h>
#else
// Only one serial port is available, uncomment one of the following:
//#include <NeoICSerial.h>
//#include <AltSoftSerial.h>
#include <NeoSWSerial.h>
//#include <SoftwareSerial.h> /* NOT RECOMMENDED */
#endif
#include "GPSport.h"

#ifdef NeoHWSerial_h
#define DEBUG_PORT NeoSerial
#else
#define DEBUG_PORT Serial
#endif

//------------------------------------------------------------

//------------------------------------


void doSomeWork( const gps_fix & fix )
{
  if (fix.valid.date & fix.valid.time & fix.valid.location) {

    // Date
    Serial.print( fix.dateTime.date );
    Serial.print( ':' );
    Serial.print( fix.dateTime.month );
    Serial.print( ':' );
    Serial.print( fix.dateTime.full_year() );
    Serial.print( F("      ") );

    // Time
    if ( fix.dateTime.hours < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.hours );
    Serial.print( ':' );
    if ( fix.dateTime.minutes < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.minutes );
    Serial.print( ':' );
    if ( fix.dateTime.seconds < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.seconds );
    Serial.print( '.' );
    if ( fix.dateTime_cs < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime_cs );
    Serial.print( F("         ") );

    // Location
    Serial.print( fix.latitude(), 5 );
    Serial.print( F("      ") );
    Serial.print( fix.longitude(), 5 );

  } else {
    // No valid location data yet!
    Serial.print( '?' );
  }

  Serial.println();

} // doSomeWork

//------------------------------------

void GPSloop()
{
  while (gps.available( gps_port ))
    doSomeWork( gps.read() );

} // GPSloop

//------------------------------------

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();

  gps_port.begin( 9600 );

  
  Serial.flush();
  
  gps_port.begin( 9600 );
 gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  gps_port.end();                                // empty the input buffer, too
//  
  gps_port.begin( 115200 );                      // use the new baud rate
  gps.send_P( &gps_port, F("PMTK220,100") );
}

//------------------------------------

void loop()
{
  GPSloop();
}

Here is the output

2:8:2017 10:21:14.20 17.35594 78.44156
2:8:2017 10:21:14.30 17.35594 78.44156
2:8:2017 10:21:14.40 17.35594 78.44156
2:8:2017 10:21:14.50 17.35594 78.44156
2:8:2017 10:21:14.60 17.35594 78.44156
2:8:2017 10:21:14.70 17.35594 78.44156
2:8:2017 10:21:14.80 17.35594 78.44156
2:8:2017 10:21:14.90 17.35594 78.44156
2:8:2017 10:21:15.00 17.35594 78.44156
2:8:2017 10:21:15.10 17.35594 78.44156
2:8:2017 10:21:15.20 17.35594 78.44156
2:8:2017 10:21:15.30 17.35594 78.44156
2:8:2017 10:21:15.50 17.35594 78.44156
2:8:2017 10:21:15.60 17.35594 78.44156
2:8:2017 10:21:15.70 17.35594 78.44156
2:8:2017 10:21:15.80 17.35594 78.44156
2:8:2017 10:21:15.90 17.35594 78.44156

See this lines

2:8:2017 10:21:15.30 17.35594 78.44156
2:8:2017 10:21:15.50 17.35594 78.44156

what could be the problem?

I have also tried with

  gps.send_P( &gps_port, F("PMTK220,500") );

but still there's a loss of data, see below.

2:8:2017 10:37:19.00 17.35593 78.44154
2:8:2017 10:37:19.50 17.35593 78.44154
2:8:2017 10:37:20.00 17.35593 78.44154
2:8:2017 10:37:20.50 17.35593 78.44154
2:8:2017 10:37:21.50 17.35593 78.44154
2:8:2017 10:37:22.00 17.35593 78.44154
2:8:2017 10:37:23.50 17.35593 78.44154
2:8:2017 10:37:24.00 17.35593 78.44154
2:8:2017 10:37:24.50 17.35593 78.44154
2:8:2017 10:37:25.00 17.35593 78.44154

Hello -Dev,
I Think i have solved the problem, I was using ATmega2560V at 3.3V ,8Mhz on 38400 BaudRate. I have changed baudrate in my code to 38400 and it solved :slight_smile:

Thank you

Try increasing the Serial speed. Maybe that is what is slowing things up.

// change this
  Serial.begin(9600);

// to this
  Serial.begin(115200);

I have one question..
When testing in open field, i can see there's no problem in data, no data loss and everything works fine, But when i come in to my room where there's no chance of GPS signals, then i can see it started printing....

?
?
?
?
?
?
?
?

rather than the last received data...
is this can be curable.?

but still there’s a loss of data, see below.

Yes, like SurferTim said, the Serial baud rate must be fast enough to print each line faster than the GPS update rate. It’s always the first thing I suspect. The NeoGPS Troubleshooting page mentions this common problem: Printing too much.

For example, if you print this many characters for each GPS update:

    2:8:2017      10:37:20.50         17.35593      78.44154

That’s 59 characters. If Serial is running at 9600 baud, that takes 59 * 10 / 9600 = 0.061458s, or ~62ms. The GPS update rate you selected is 100ms, so there should be enough time to print this information between each GPS update.

BTW, I do not see this command in your sketch:

    gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only

You should put that command in setup so that the GPS device sends the minimum number of characters to the Arduino:

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();

  gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
  gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  gps_port.end();                                // empty the input buffer, too
  gps_port.begin( 115200 );                      // use the new baud rate

  gps.send_P( &gps_port, F("PMTK220,100") );     // set the GPS update interval
}

I have changed baudrate in my code to 38400 and it solved :slight_smile:

Which port? Serial or gps_port?

If it was gps_port, one possibility is that the RX/TX wires have too much noise to run at 115200. Running at 38400 would be more reliable. Another possibility is that the 8MHz crystal is slightly inaccurate, so that the 115200 “clock” is too different from the GPS baud rate.

When testing in open field, i can see there’s no problem in data, no data loss and everything works fine, But when i come in to my room where there’s no chance of GPS signals, then i can see it started printing…

?

?
?
?
?
?



rather than the last received data... is this can be curable?

Yes. Add an extra global variable to hold on to the last good received data. If the new data is good, copy it into that global variable. Then always print the global variable:

#include <Arduino.h>
#include <NMEAGPS.h>

NMEAGPS  gps; // This parses the GPS characters
gps_fix  fix;

#define gps_port Serial2

//------------------------------------

void doSomeWork( const gps_fix & newFix )
{
  if (newFix.valid.date & newFix.valid.time & newFix.valid.location) {
    // If the new fix has good information, save it for use when 
    //    the information is no longer available.
    fix = newFix;
  }

  // Print the last good information, if we ever received it.
  if (fix.valid.date & fix.valid.time & fix.valid.location) {

    // Date
    Serial.print( fix.dateTime.date );
    Serial.print( ':' );
    Serial.print( fix.dateTime.month );
    Serial.print( ':' );
    Serial.print( fix.dateTime.full_year() );
    Serial.print( F("      ") );

    // Time
    if ( fix.dateTime.hours < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.hours );
    Serial.print( ':' );
    if ( fix.dateTime.minutes < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.minutes );
    Serial.print( ':' );
    if ( fix.dateTime.seconds < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime.seconds );
    Serial.print( '.' );
    if ( fix.dateTime_cs < 10 )
      Serial.print( '0' );
    Serial.print( fix.dateTime_cs );
    Serial.print( F("         ") );

    // Location
    Serial.print( fix.latitude(), 5 );
    Serial.print( F("      ") );
    Serial.print( fix.longitude(), 5 );

  } else {
    // No valid location data!
    Serial.print( '?' );
  }

  Serial.println();

} // doSomeWork

//------------------------------------

void GPSloop()
{
  while (gps.available( gps_port ))
    doSomeWork( gps.read() );

} // GPSloop

//------------------------------------

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();

  gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
  gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  gps_port.end();                                // empty the input buffer, too
  gps_port.begin( 115200 );                      // use the new baud rate

  gps.send_P( &gps_port, F("PMTK220,100") );     // set the GPS update interval
}

//------------------------------------

void loop()
{
  GPSloop();
}

Notice that you don’t really need the gps_port.h file. The gps_port.h include file is for all the NeoGPS example sketches. You can declare your own variables in your own sketch.

I am wondering Why it’s showing GPRMC while i am using GNSS module i was expecting GNRMC.

Usually, if the GPS device is only receiving from GPS satellites, it will report GPRMC. If it receives from a mix of GLONASS and GPS satellites, it should report GNRMC. According to the L86 spec:

Section 2.1, --RMC:
Notes:

  1. If the receiver is fixed by GPS only, it will print GPRMC, GPVTG, GPGGA, GPGSA, GPGSV, GPGLL and GPTXT.

  2. If the receiver is fixed by GPS only, and can also search QZSS satellite, it will print GPRMC, GPVTG, GPGGA, GPGSA, QZQSA, GPGSV, QZGSV, GPGLL and GPTXT.

  3. If the receiver is fixed by GLONASS only, it will print GNRMC, GPVTG, GPGGA, GNGSA, GPGSV, GLGSV, GNGLL and GPTXT.

  4. If the receiver is fixed by multi-GNSS, it will print GNRMC, GPVTG, GPGGA, GNGSA, GPGSV, GLGSV, GNGLL and GPTXT.

  5. In the state of no satellite positioning, it will print initial state of NMEA, such as GPRMC, GPVTG, GPGGA, GPGSA, GPGSV, GPGLL and GPTXT. The time before satellite positioning after cold start, warm start or hot start is belong to this situation

Hello -Dev,

Thank you for explaining me,

Which port? Serial or gps_port?

gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
  gps.send_P( &gps_port, F("PMTK251,38400") );  // set baud rate
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  gps_port.end();                                // empty the input buffer, too

  gps_port.begin( 38400 );                      // use the new baud rate
  gps.send_P( &gps_port, F("PMTK220,100") );     // set 10Hz update rate
  delay(50);
  gps.send_P( &gps_port, F("PMTK886,1") );       // Setting FR to Fitness mode
  delay(50);

Yes. Add an extra global variable to hold on to the last good received data

I have tested the code, it's working great :slight_smile: but i having problem with my SD LOGGING code, I want to add that extra global variable in this code as well..Do i need to add that in secondStage or doSomeWork.?

Code below

Here is the code :

#include <Arduino.h>
#include <NMEAGPS.h>
#include <SPI.h>
#include <SdFat.h>



gps_fix  fix; // This contains all the GPS fields
NMEAGPS  gps; // This parses the GPS characters

//#define gps_port Serial



//------------------------------------
#if defined( UBRR1H ) | defined( ID_USART0 )
// Default is to use Serial1 when available.  You could also
// use NeoHWSerial, especially if you want to handle GPS characters
// in an Interrupt Service Routine.
//#include <NeoHWSerial.h>
#else
// Only one serial port is available, uncomment one of the following:
//#include <NeoICSerial.h>
//#include <AltSoftSerial.h>
#include <NeoSWSerial.h>
//#include <SoftwareSerial.h> /* NOT RECOMMENDED */
#endif
#include "GPSport.h"

#ifdef NeoHWSerial_h
#define DEBUG_PORT NeoSerial
#else
#define DEBUG_PORT Serial
#endif

//------------------------------------



SdFat SD;
File  dataFile;
char filename[]="3.xml";


const int xpin = A0;                  // x-axis of the accelerometer
const int ypin = A1;                  // y-axis
const int zpin = A2;                  // z-axis
int x, y, z, total;
int button = 2;



void setup()  {
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();
  gps_port.begin( 9600 );
  gps.send_P( &gps_port, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );  
  gps.send_P( &gps_port, F("PMTK251,115200") );  // set baud rate
  gps_port.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  gps_port.end(); 
  gps_port.begin( 115200 );
  gps.send_P( &gps_port, F("PMTK220,100") );     // set 10Hz update rate

  
  pinMode(button, INPUT_PULLUP);

  if (!SD.begin(36)) {
    Serial.println( F("Card failed, or not present") );
    // don't do anything more:
    return;
  }
  Serial.println( F("card initialized.") );
  Serial.println( F("Code Running") );

} // setup

void firstStage()
{
  Serial.println( F("Co-ordinates Achieved") );
 // sprintf(filename, "%02d-%02d-%02d-T-%02d-%02d-%02d.tcx", fix.dateTime.hours , fix.dateTime.minutes, fix.dateTime.hours, fix.dateTime.date , fix.dateTime.month , fix.dateTime.full_year());
  dataFile = SD.open(filename , FILE_WRITE);
  Serial.println(filename);

  if (dataFile) {
    Serial.println( F("File created\n"
                      "LOGGING DATA!\n") );

    dataFile.println( F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                        "<TrainingCenterDatabase xmlns=\""
                            "http://www.garmin.com/"
                                "xmlschemas/TrainingCenterDatabase/v2\">\n"
                        "<Activities>\n"
                        "<Activity Sport=\"Other\">") );
    dataFile.println( F("<Id>") );
       if ( fix.dateTime.full_year() < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.full_year() );
    dataFile.print  ( '-' );
       if ( fix.dateTime.month < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.month );
    dataFile.print  ( '-' );
       if ( fix.dateTime.date  < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.date );
    dataFile.print  ( 'T' );
       if ( fix.dateTime.hours < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.hours );
    dataFile.print  ( ':' );
       if ( fix.dateTime.minutes < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.minutes );
    dataFile.print  ( ':' );
       if ( fix.dateTime.seconds < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.seconds );
    dataFile.print  ( '.' );
    dataFile.print  ( fix.dateTime_cs );
    dataFile.println( F("0Z"
                        "</Id>\n"
                        "<Lap StartTime=\"") );
    /////dataFile.println( F("<Id>") );
    if ( fix.dateTime.full_year() < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.full_year() );
    dataFile.print  ( '-' );
       if ( fix.dateTime.month < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.month );
    dataFile.print  ( '-' );
       if ( fix.dateTime.date  < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.date );
    dataFile.print  ( 'T' );
       if ( fix.dateTime.hours < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.hours );
    dataFile.print  ( ':' );
       if ( fix.dateTime.minutes < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.minutes );
    dataFile.print  ( ':' );
       if ( fix.dateTime.seconds < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.seconds );
    dataFile.print  ( '.' );
    dataFile.print  ( fix.dateTime_cs );
    dataFile.println( F("0Z\">"
                        "<Track>") );
  }
} // firstStage

void secondStage()
{
  if (dataFile.isOpen()) {
    dataFile.println( F("<Trackpoint>\n"
                        "<Time>") );
    if ( fix.dateTime.full_year() < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.full_year() );
    dataFile.print  ( '-' );
       if ( fix.dateTime.month < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.month );
    dataFile.print  ( '-' );
       if ( fix.dateTime.date  < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.date );
    dataFile.print  ( 'T' );
       if ( fix.dateTime.hours < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.hours );
    dataFile.print  ( ':' );
       if ( fix.dateTime.minutes < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.minutes );
    dataFile.print  ( ':' );
       if ( fix.dateTime.seconds < 10 )
      dataFile.print( '0' );
    dataFile.print  ( fix.dateTime.seconds );
    dataFile.print  ( '.' );
    dataFile.print  ( fix.dateTime_cs );
    dataFile.print  ( F("0Z"
                        "</Time>"
                        "<Position>\n"
                        "<LatitudeDegrees>") );
    dataFile.print  ( fix.latitude(), 5 );
    dataFile.print  ( F("</LatitudeDegrees>\n"
                        "<LongitudeDegrees>") );
    dataFile.print  ( fix.longitude(), 5 );
    dataFile.print  ( F("</LongitudeDegrees>\n"
                        "</Position>\n"
                        "<HeartRateBpm>\n"
                        "<Value>") );
    dataFile.print  ( '0' );
    dataFile.print  ( F("</Value>\n"
                        "</HeartRateBpm>\n"
                        "<SensorState>"
                        "Present"
                        "</SensorState>\n") );

    analogReference(EXTERNAL);
    x     = analogRead(xpin);
    y     = analogRead(ypin);
    z     = analogRead(zpin);
    total = sqrt( x * x + y * y + z * z );

    dataFile.print  ( F("<Impact>"
                        "<Gforce>") );
    dataFile.print  ( total );
    dataFile.print  ( F("</Gforce>\n"
                        "<Xaxis>") );
    dataFile.print  ( x );
    dataFile.print  ( F("</Xaxis>\n"
                        "<Yaxis>") );
    dataFile.print  ( y );
    dataFile.print  ( F("</Yaxis>\n"
                        "<Zaxis>") );
    dataFile.print  ( z );
    dataFile.println( F("</Zaxis>\n"
                        "</Impact>\n"
                        "</Trackpoint>") );
  }

} // secondStage

void doSomeWork() {

  if (fix.valid.date && fix.valid.time && fix.valid.location)
  {
    if (!dataFile.isOpen())
      firstStage();

    if (dataFile.isOpen())
      secondStage();
  }
  else {
    // No valid location data yet!
    Serial.print  ( '?' );
  }

  Serial.println();

} // doSomeWork

void GPSloop()
{
  while (gps.available( gps_port) ) {
    fix = gps.read();
    doSomeWork();
  }

} // GPSloop

void loop()
{
  GPSloop();

  // Testing the button could go almost anywhere.
  //    Putting it here will close dataFile the fastest,
  //    because it won't have to wait for the next
  //    GPS update.
  if (digitalRead(button) == LOW) {
    endtask();

    // stop here!
    while (1)
      ;
  }

} // loop

void endtask()
{
  if (dataFile.isOpen()) {
    dataFile.println( F("</Track>\n"
                        "</Lap>\n"
                        "</Activity>\n"
                        "</Activities>\n"
                        "</TrainingCenterDatabase>") );
    dataFile.close();
    Serial.println( F("file closed") );
  } else {
    Serial.println( F("(file never opened)") );
  }

} // endtask

If the GPS has a valid date/time, but not a valid location, do you want to use the new date/time with the last valid location?

I have been lurking in the background hoping someone else would ask why is it necessary to update a GPS position 10 times per second? Or even once every 10 seconds? How fast are you moving?

...R