10Hz GPS data with TinyGPSPlus library

Hello everybody,
I am working on a home made project which will log GPS data into a SD card, I am able to log data with 1Hz which is default by TinyGPSPlus and also with the Quectel L80 module, I sent Baudrate(115200) and update rate (10Hz) of Quectel L80 receiver! and logged data.

The data shows each second in the time second consists of 10 data like below :

Date Time Latitude Longitude

17:2:2017 9:05:01 17.355995 78.441528
17:2:2017 9:05:01 17.355995 78.441528
17:2:2017 9:05:01 17.355994 78.441535
17:2:2017 9:05:01 17.355999 78.441522
17:2:2017 9:05:01 17.355985 78.441562
17:2:2017 9:05:01 17.355994 78.441523
17:2:2017 9:05:01 17.355999 78.441511
17:2:2017 9:05:01 17.355990 78.441510
17:2:2017 9:05:01 17.355995 78.441528
17:2:2017 9:05:01 17.355996 78.441512

as can be seen, 9:05:01 only one second have 10 coordinates...

Is there any way so that i can get in this way!

Date Time Latitude Longitude

17:2:2017 9:05:01:000 17.355996 78.441512
17:2:2017 9:05:01:100 17.355995 78.441528
17:2:2017 9:05:01:200 17.355995 78.441528
17:2:2017 9:05:01:300 17.355994 78.441535
17:2:2017 9:05:01:400 17.355999 78.441522
17:2:2017 9:05:01:500 17.355985 78.441562
17:2:2017 9:05:01:600 17.355994 78.441523
17:2:2017 9:05:01:700 17.355999 78.441511
17:2:2017 9:05:01:800 17.355990 78.441510
17:2:2017 9:05:01:900 17.355995 78.441528

Thank you

mudassir9999:
Is there any way so that i can get in this way!

My NeoGPS library parses the fractional seconds. Here is a NeoGPS sketch that produces the output you are asking for:

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

NMEAGPS  gps; // This parses the GPS characters

#define gps_port Serial1

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

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();
}

If you'd like to try it, NeoGPS is available from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries. NeoGPS is also faster, smaller and more accurate than all other libraries. You'll have to add the baud rate and update rate commands, of course.

Depending on your SD card, you may be losing a record when the card takes longer than 100ms to perform a write. You may need to use the Interrupt processing style of NeoGPS.

And if you need more accurate locations, NeoGPS can be used to log up to 10 significant digits, not just the typical 7 digits you get from other libraries (via float). NeoGPS has been used to reliably log 20Hz GPS to an SD card (no data loss!).

Cheers,
/dev

Thank very muvh /Dev for replying.

I am now using NEOGps library as you have suggested, I have also tested the code you supplied (Thank you very much for that).

But i came across with another issue regarding obtaining 10Hz Gps data, I have to use PowerGPS to send two commands which is

"$PMTK251,115200*27"

and

"$PMTK220,100*1F"

, then i connect that to Arduino, whenever i power down the Quectel L80 (receiver) it's coming back to defualt 1Hz update rate mode.

I have learned from the quectel tech support person where he said : For getting 10Hz data, i need to update the default baudrate (9600) to more than that like 115200.

So i want to send that command to set the receiver on that baudrate

I want to send these two commands while the recevier is connected to Serial1, how will be the syntax for it.?

Here i am getting the output with the above supplied code

Date Time Latitude Longitude

18:2:2017 07:21:15.00 17.35709 78.44269
18:2:2017 07:21:16.00 17.35709 78.44269
18:2:2017 07:21:17.00 17.35709 78.44269
18:2:2017 07:21:18.00 17.35709 78.44269
18:2:2017 07:21:18.21 17.35709 78.44269
18:2:2017 07:21:20.00 17.35709 78.44269
18:2:2017 07:21:21.00 17.35709 78.44269
18:2:2017 07:21:22.00 17.35709 78.44269
18:2:2017 07:21:23.00 17.35709 78.44269
18:2:2017 07:21:24.00 17.35709 78.44269
18:2:2017 07:21:24.21 17.35709 78.44269
18:2:2017 07:21:26.00 17.35709 78.44269
18:2:2017 07:21:27.00 17.35709 78.44269
18:2:2017 07:21:28.00 17.35709 78.44269
18:2:2017 07:21:29.00 17.35709 78.44269
18:2:2017 07:21:30.00 17.35709 78.44269
18:2:2017 07:21:30.20 17.35709 78.44269
18:2:2017 07:21:32.00 17.35709 78.44269
18:2:2017 07:21:33.00 17.35709 78.44269
18:2:2017 07:21:34.00 17.35709 78.44269
18:2:2017 07:21:35.00 17.35709 78.44269
18:2:2017 07:21:36.00 17.35709 78.44269
18:2:2017 07:21:36.21 17.35709 78.44269
18:2:2017 07:21:38.00 17.35709 78.44269
18:2:2017 07:21:39.00 17.35709 78.44269
18:2:2017 07:21:40.00 17.35709 78.44269
18:2:2017 07:21:41.00 17.35709 78.44269
18:2:2017 07:21:42.00 17.35709 78.44269
18:2:2017 07:21:42.20 17.35709 78.44269
18:2:2017 07:21:44.00 17.35709 78.44269
18:2:2017 07:21:45.00 17.35709 78.44269
18:2:2017 07:21:46.00 17.35709 78.44269
18:2:2017 07:21:47.00 17.35709 78.44269
18:2:2017 07:21:48.00 17.35709 78.44269
18:2:2017 07:21:48.20 17.35709 78.44269
18:2:2017 07:21:50.00 17.35709 78.44269
18:2:2017 07:21:51.00 17.35709 78.44269
18:2:2017 07:21:52.00 17.35709 78.44269
18:2:2017 07:21:53.00 17.35709 78.44269
18:2:2017 07:21:54.00 17.35709 78.44269
18:2:2017 07:21:54.20 17.35709 78.44269
18:2:2017 07:21:56.00 17.35709 78.44269
18:2:2017 07:21:57.00 17.35709 78.44269
18:2:2017 07:21:58.00 17.35709 78.44269
18:2:2017 07:21:59.00 17.35709 78.44269
18:2:2017 07:22:00.00 17.35709 78.44269
18:2:2017 07:22:01.00 17.35709 78.44269
18:2:2017 07:22:02.00 17.35709 78.44269

Thank you

So i want to send that command

Ok, just send it in setup:

void setup()
{
  Serial.begin(9600);
  Serial.println( F("Date              Time             Latitude         Longitude\n") );
  Serial.flush();
  
  gps_port.begin( 9600 );
  gps_port.print( F("$PMTK251,115200*27\r\n") ); // set 115200 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_port.print( F("$PMTK220,100*1F\r\n") );    // set 10Hz update rate

}

Remember that at 9600, you can only print 100 characters to Serial for each GPS update. You are currently printing 60 characters per GPS update. If you want to print more, you'll have to increase the Serial baud rate. (This is not a limit when writing to the SD card.)

If you haven't run NMEAorder.ino, now would be a good time to try it. For each brand of GPS device, you need to confirm that NMEAGPS_cfg.h has the correct LAST_SENTENCE_IN_INTERVAL. NMEAorder expects a 1Hz update rate, so be sure to try it before you have run a sketch that sets 10Hz. You could also use PowerGPS to set the update rate back to 1Hz. You only have to do this once.

Cheers,
/dev

Hello /Dev,
Thank you again for replying, I haved tested the above code and plugged that into the void setup () as you have said (Full code below), When i open Serial monitor in 9600 mode - It only shows

Date Time Latitude Longitude

when switched to 115200 it doesn't show anything

below is the full code i have tried.

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


NMEAGPS  gps; // This parses the GPS characters

#define gps_port Serial1

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

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_port.print( F("$PMTK251,115200*27\r\n") ); // set 115200 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_port.print( F("$PMTK220,100*1F\r\n") );    // set 10Hz update rate

}

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

void loop()
{
  GPSloop();
}

also i have tested the GPS receiver wth the NEMAorder.ino from the NeoGPS Library, after trying the above full code. it shows me 1 second of interval.

Serial Monitor output for NMEAorder.ino

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

You could also use PowerGPS to set the update rate back to 1Hz. You only have to do this once.

do i have to set 10Hz with my receiver only for one time.? This doesn't happen with me :frowning: is it because i have plugged VBat pin to arduino 3.3V supply.? I have not connected RTC battery to GPS receiver.

Thanks

The PMTK commands you posted were not correct, and I just copied them into my sketch. They do not have the correct checksum, so the GPS device will ignore them. Change these 2 prints:

  gps_port.print( F("$PMTK251,115200*1F\r\n") ); // set 115200 baud rate
     ...
  gps_port.print( F("$PMTK220,100*2F\r\n") );    // set 10Hz update rate

The two hex digits after the '*' are different (calculator here). This is one reason I added a "send" function to NeoGPS that would calculate the checksum for you. You could do this instead:

  gps.send_P( &gps_port, F("PMTK251,115200") ); // set baud rate
     ...
  gps.send_P( &gps_port, F("PMTK220,100") );    // set 10Hz update rate

Notice how you don't need the '$', the '*', the checksum nor the CR/LF. send_P takes care of all that for you. Here's the complete sketch with the send_P:

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

NMEAGPS  gps; // This parses the GPS characters

#define gps_port Serial1

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

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();
  
  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();
}

Also, you should not change the Serial Monitor window baud rate from 9600. It should always match what you have in setup:

    Serial.begin( 9600 ); // Serial Monitor must match!

The PMTK command changes the baud rate of the GPS device, and then your sketch must change Serial1 (i.e., gps_port) to match it. It has nothing to do with the Serial Monitor.

Serial Monitor output for NMEAorder.ino:

NMEAorder.INO: started

...
Sentence order in each 1-second interval:
  RMC
  VTG
  GGA
  GSA
  GSV
  GSV
  GSV
  GLL

Make sure that NMEAGPS_cfg.h specifies the last sentence that you have enabled. The default NeoGPS configuration has RMC and GGA enabled, so you would choose GGA, according to the above output:

#define LAST_SENTENCE_IN_INTERVAL NMEAGPS::NMEA_GGA

Cheers,
/dev

do i have to set 10Hz with my receiver only for one time.?

No, I would set it every time, in setup.

is it because i have plugged VBat pin to arduino 3.3V supply.? I have not connected RTC battery to GPS receiver.

No, you weren't getting any output because the "change baud rate" command was rejected, and your sketch changed baud rate anyway. The GPS device was still running at 9600 and the Arduino gps_port changed to 115200. No GPS characters will be received by the Arduino when the baud rates don't match.

Cheers,
/dev

Thank you very much for the reply again /Dev, I have applied the code you provided and it's working flawlessly.

 gps.send_P( &gps_port, F("PMTK251,115200") ); // set baud rate
     ...
  gps.send_P( &gps_port, F("PMTK220,100") );    // set 10Hz update rate

this is the better way! as I don't want to mess with the things again.

I have been logging the data into a class 4 micro SD card using the catalex module, and I am using the SDFAT.h library for data logging.

below is my full code

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

NMEAGPS  gps; // This parses the GPS characters

#define gps_port Serial1
File dataFile;


char filename[] = "12345.tcx";


SdFat SD;

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(37, INPUT_PULLUP);
  if (!SD.begin(4)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("Code Running");

}

void doSomeWork( const gps_fix & fix ) {

  if (fix.valid.date )
  {
    Serial.println("Co-ordinates Achived");
    dataFile = SD.open(filename , FILE_WRITE);
    Serial.println(filename);
    if (dataFile) {
      Serial.println("File created");
      Serial.println("LOGGING DATA!");
      dataFile.println(F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
      dataFile.println(F("<TrainingCenterDatabase xmlns=\"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2\">"));
      dataFile.println(F("<Activities>"));
      dataFile.println(F("<Activity Sport=\"Other\">"));
      dataFile.println("<Id>");
      dataFile.print(fix.dateTime.full_year());
      dataFile.print("-");
      dataFile.print(fix.dateTime.month);
      dataFile.print("-");
      dataFile.print(fix.dateTime.date);
      dataFile.print("T");
      dataFile.print(fix.dateTime.hours);
      dataFile.print(":");
      dataFile.print(fix.dateTime.minutes);
      dataFile.print(":");
      dataFile.print(fix.dateTime.seconds);
      dataFile.print(":");
      dataFile.print(fix.dateTime_cs);
      dataFile.print(".000Z");
      dataFile.println("</Id>");
      dataFile.println("<Lap StartTime=\"");
      // dataFile.print(String(ddate));
      dataFile.print("T");
      //dataFile.print(String(ttime));
      dataFile.print(".000Z\">");
      dataFile.println("<Track>");
    }
    while (1)
    {
      if (digitalRead(37) == LOW) {
        endtask();
      }
      dataFile.println("<Trackpoint>");
      dataFile.println("<Time>");
      dataFile.print(fix.dateTime.full_year());
      dataFile.print("-");
      dataFile.print(fix.dateTime.month);
      dataFile.print("-");
      dataFile.print(fix.dateTime.date);
      dataFile.print("T");
      dataFile.print(fix.dateTime.hours);
      dataFile.print(":");
      dataFile.print(fix.dateTime.minutes);
      dataFile.print(":");
      dataFile.print(fix.dateTime.seconds);
      dataFile.print(":");
      dataFile.print(fix.dateTime_cs);
      dataFile.print(".000Z");
      dataFile.print("</Time>");
      dataFile.println("<Position>");
      dataFile.print("<LatitudeDegrees>");
      dataFile.print(fix.latitude(), 5 );
      dataFile.println("</LatitudeDegrees>");
      dataFile.print("<LongitudeDegrees>");
      dataFile.print(fix.longitude(), 5);
      dataFile.println("</LongitudeDegrees>");
      dataFile.println("</Position>");
      dataFile.println("<HeartRateBpm>");
      dataFile.print("<Value>");
      dataFile.print(String("0"));
      dataFile.println("</Value>");
      dataFile.println("</HeartRateBpm>");
      dataFile.print("<SensorState>");
      dataFile.print("Present");
      dataFile.println("</SensorState>");
      analogReference(EXTERNAL);
      x = analogRead(xpin);
      y = analogRead(ypin);
      z = analogRead(zpin);
      total = sqrt(x * x + y * y + z * z);
      dataFile.print("<impact>");
      dataFile.print("<gforce>");
      dataFile.print(total);
      dataFile.println("</gforce>");
      dataFile.print("<xaxis>");
      dataFile.print(x);
      dataFile.println("</xaxis>");
      dataFile.print("<yaxis>");
      dataFile.print(y);
      dataFile.println("</yaxis>");
      dataFile.print("<zaxis>");
      dataFile.print(z);
      dataFile.println("</zaxis>");
      dataFile.println("</impact>");
      dataFile.println("</Trackpoint>");
      //Serial.println();
    }
  }
  else {
    // No valid location data yet!
    Serial.print( '?' );
  }

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

} // GPSloop
void loop()
{
  GPSloop();
}

void endtask()
{
  dataFile.println("</Track>");
  dataFile.println("</Lap>");
  dataFile.println("</Activity>");
  dataFile.println("</Activities>");
  dataFile.println("</TrainingCenterDatabase>");
  dataFile.close();
  Serial.print("file close");
}

there is an error with in the logged data, The timings are same in every field below is the logged SD data (I have attached the logged 000.txt file with this message

Please look for
2017-2-19T9:31:19:60.000Z

I was expecting time change something like this:

2017-2-19T9:31:19:00.000Z 2017-2-19T9:31:19:01.000Z 2017-2-19T9:31:19:02.000Z 2017-2-19T9:31:19:03.000Z 2017-2-19T9:31:19:04.000Z 2017-2-19T9:31:19:05.000Z 2017-2-19T9:31:19:06.000Z 2017-2-19T9:31:19:07.000Z 2017-2-19T9:31:19:08.000Z 2017-2-19T9:31:19:09.000Z 2017-2-19T9:31:20:00.000Z

can you spot my mistake please
Thank you

000.txt (325 KB)

mudassir9999:
The timings are same in every field... can you spot my mistake

Yes, you are stuck in the "while (1)" loop (line 82) when you get a fix with a valid date. You never let it get a new fix. Your program call structure is basically

setup{}

loop() {
  GPSloop() {
    while (gps.available) {
      fix = gps.read();
      doSomeWork( fix ) {
        if (fix.valid.date) {
          if (datafile) {
            while (1) {
              ...print the same fix over and over...
            }
          }
        }
      }
    }
  }
}

(That's not the C++ code, it just shows how the calls are nested when it runs.)

You need to print the "current" fix and return from doSomeWork. When another fix comes in, you can print it next. Your program call structure should be something like this:

setup() { ... }

loop() {
  GPSloop() {
    while (gps.available) {
      fix = gps.read();
      doSomeWork( fix ) {
        if (fix.valid.date) {
          if (datafile) {
            ...print the fix (and return all the way to loop)...
          }
        }
      }
    }
  }
}

After returning, loop gets called thousands of times, but no GPS fixes will be ready. 100ms later, a new fix will be available, and doSomeWork gets called again to write the new fix.

Cheers,
/dev

Hello /Dev,
thank you replying, I completely understand your explanation, but I am trying to achieve while (1) content in a loop and to be saved in the SD card until I press the button on pin 37.

My Aim is to log below content at 10Hz until I pressed the button.

{
      if (digitalRead(37) == LOW) {
        endtask();
      }
      dataFile.println("<Trackpoint>");
      dataFile.println("<Time>");
      dataFile.print(fix.dateTime.full_year());
      dataFile.print("-");
      dataFile.print(fix.dateTime.month);
      dataFile.print("-");
      dataFile.print(fix.dateTime.date);
      dataFile.print("T");
      dataFile.print(fix.dateTime.hours);
      dataFile.print(":");
      dataFile.print(fix.dateTime.minutes);
      dataFile.print(":");
      dataFile.print(fix.dateTime.seconds);
      dataFile.print(":");
      dataFile.print(fix.dateTime_cs);
      dataFile.print(".000Z");
      dataFile.print("</Time>");
      dataFile.println("<Position>");
      dataFile.print("<LatitudeDegrees>");
      dataFile.print(fix.latitude(), 5 );
      dataFile.println("</LatitudeDegrees>");
      dataFile.print("<LongitudeDegrees>");
      dataFile.print(fix.longitude(), 5);
      dataFile.println("</LongitudeDegrees>");
      dataFile.println("</Position>");
      dataFile.println("<HeartRateBpm>");
      dataFile.print("<Value>");
      dataFile.print(String("0"));
      dataFile.println("</Value>");
      dataFile.println("</HeartRateBpm>");
      dataFile.print("<SensorState>");
      dataFile.print("Present");
      dataFile.println("</SensorState>");
      analogReference(EXTERNAL);
      x = analogRead(xpin);
      y = analogRead(ypin);
      z = analogRead(zpin);
      total = sqrt(x * x + y * y + z * z);
      dataFile.print("<impact>");
      dataFile.print("<gforce>");
      dataFile.print(total);
      dataFile.println("</gforce>");
      dataFile.print("<xaxis>");
      dataFile.print(x);
      dataFile.println("</xaxis>");
      dataFile.print("<yaxis>");
      dataFile.print(y);
      dataFile.println("</yaxis>");
      dataFile.print("<zaxis>");
      dataFile.print(z);
      dataFile.println("</zaxis>");
      dataFile.println("</impact>");
      dataFile.println("</Trackpoint>");
      //Serial.println();
    }
  }
  else {
    // No valid location data yet!
    Serial.print( '?' );
  }

  Serial.println();
}

The first part will be only for one time - initialization and will not be logged over and over again..

This will be logged only for one time INITIALIZATION

if (fix.valid.date )
  {
    Serial.println("Co-ordinates Achived");
    dataFile = SD.open(filename , FILE_WRITE);
    Serial.println(filename);
    if (dataFile) {
      Serial.println("File created");
      Serial.println("LOGGING DATA!");
      dataFile.println(F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
      dataFile.println(F("<TrainingCenterDatabase xmlns=\"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2\">"));
      dataFile.println(F("<Activities>"));
      dataFile.println(F("<Activity Sport=\"Other\">"));
      dataFile.println("<Id>");
      dataFile.print(fix.dateTime.full_year());
      dataFile.print("-");
      dataFile.print(fix.dateTime.month);
      dataFile.print("-");
      dataFile.print(fix.dateTime.date);
      dataFile.print("T");
      dataFile.print(fix.dateTime.hours);
      dataFile.print(":");
      dataFile.print(fix.dateTime.minutes);
      dataFile.print(":");
      dataFile.print(fix.dateTime.seconds);
      dataFile.print(":");
      dataFile.print(fix.dateTime_cs);
      dataFile.print(".000Z");
      dataFile.println("</Id>");
      dataFile.println("<Lap StartTime=\"");
      // dataFile.print(String(ddate));
      dataFile.print("T");
      //dataFile.print(String(ttime));
      dataFile.print(".000Z\">");
      dataFile.println("<Track>");
    }

that's the reason I have used while(1) loop.

Is there any way to get that while(1) content only in loop.

Thank you

hello /Dev,
I made a below code where it should do as I am expecting but it's not at all creating a file in SD card.

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

NMEAGPS  gps; // This parses the GPS characters

#define gps_port Serial1
File dataFile;


char filename[] = "12345.tcx";


SdFat SD;

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(37, INPUT_PULLUP);
  if (!SD.begin(4)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("Code Running");

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

} // GPSloop
void loop()
{
  GPSloop();

}

void doSomeWork( const gps_fix & fix ) {

  if (fix.valid.date )
  {
    Serial.println("Co-ordinates Achived");
    dataFile = SD.open(filename , FILE_WRITE);
    Serial.println(filename);
    if (dataFile) {
      Serial.println("File created");
      Serial.println("LOGGING DATA!");
      dataFile.println(F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
      dataFile.println(F("<TrainingCenterDatabase xmlns=\"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2\">"));
      dataFile.println(F("<Activities>"));
      dataFile.println(F("<Activity Sport=\"Other\">"));
      dataFile.println("<Id>");
      dataFile.print(fix.dateTime.full_year());
      dataFile.print("-");
      dataFile.print(fix.dateTime.month);
      dataFile.print("-");
      dataFile.print(fix.dateTime.date);
      dataFile.print("T");
      dataFile.print(fix.dateTime.hours);
      dataFile.print(":");
      dataFile.print(fix.dateTime.minutes);
      dataFile.print(":");
      dataFile.print(fix.dateTime.seconds);
      dataFile.print(":");
      dataFile.print(fix.dateTime_cs);
      dataFile.print(".000Z");
      dataFile.println("</Id>");
      dataFile.println("<Lap StartTime=\"");
      // dataFile.print(String(ddate));
      dataFile.print("T");
      //dataFile.print(String(ttime));
      dataFile.print(".000Z\">");
      dataFile.println("<Track>");
    }
  }
  else {
    // No valid location data yet!
    Serial.print( '?' );
  }

  Serial.println();
}
void logging  (const gps_fix & fix) {
  while (1)
  {
    if (digitalRead(37) == LOW) {
      endtask();
    }
    dataFile.println("<Trackpoint>");
    dataFile.println("<Time>");
    dataFile.print(fix.dateTime.full_year());
    dataFile.print("-");
    dataFile.print(fix.dateTime.month);
    dataFile.print("-");
    dataFile.print(fix.dateTime.date);
    dataFile.print("T");
    dataFile.print(fix.dateTime.hours);
    dataFile.print(":");
    dataFile.print(fix.dateTime.minutes);
    dataFile.print(":");
    dataFile.print(fix.dateTime.seconds);
    dataFile.print(":");
    dataFile.print(fix.dateTime_cs);
    dataFile.print(".000Z");
    dataFile.print("</Time>");
    dataFile.println("<Position>");
    dataFile.print("<LatitudeDegrees>");
    dataFile.print(fix.latitude(), 5 );
    dataFile.println("</LatitudeDegrees>");
    dataFile.print("<LongitudeDegrees>");
    dataFile.print(fix.longitude(), 5);
    dataFile.println("</LongitudeDegrees>");
    dataFile.println("</Position>");
    dataFile.println("<HeartRateBpm>");
    dataFile.print("<Value>");
    dataFile.print(String("0"));
    dataFile.println("</Value>");
    dataFile.println("</HeartRateBpm>");
    dataFile.print("<SensorState>");
    dataFile.print("Present");
    dataFile.println("</SensorState>");
    analogReference(EXTERNAL);
    x = analogRead(xpin);
    y = analogRead(ypin);
    z = analogRead(zpin);
    total = sqrt(x * x + y * y + z * z);
    dataFile.print("<impact>");
    dataFile.print("<gforce>");
    dataFile.print(total);
    dataFile.println("</gforce>");
    dataFile.print("<xaxis>");
    dataFile.print(x);
    dataFile.println("</xaxis>");
    dataFile.print("<yaxis>");
    dataFile.print(y);
    dataFile.println("</yaxis>");
    dataFile.print("<zaxis>");
    dataFile.print(z);
    dataFile.println("</zaxis>");
    dataFile.println("</impact>");
    dataFile.println("</Trackpoint>");
    //Serial.println();
  }
}


void endtask()
{
  dataFile.println("</Track>");
  dataFile.println("</Lap>");
  dataFile.println("</Activity>");
  dataFile.println("</Activities>");
  dataFile.println("</TrainingCenterDatabase>");
  dataFile.close();
  Serial.print("file close");
  while (1);
}

Look for

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

} // GPSloop

thank you

Yes, that's closer. In doSomeWork, when you have a valid date/time/location, open the file if it's not open yet:

void doSomeWork( const gps_fix & fix ) {

  if (fix.valid.location && fix.valid.date && fix.valid.time) {

    if (!datafile.isOpen()) {
      ...open the datafile and write the first few lines...
    }

    if (datafile.isOpen()) {
      ...write a fix date/time/location to the SD file...
    }

Test the switch in loop and close datafile when it's LOW:

void loop()
{
  GPSloop();

  if (digitalRead(37) == LOW) {
    endtask();
  }
}

GPSloop still gets called all the time, and it calls doSomework when there's a new fix. But if it never gets a valid date, time AND location, the datafile won't get opened, and it doesn't write anything. If that's what you want to do...

Cheers,
/dev

thank you very much for your rapid replies /Dev

If that's what you want to do...

No! what I am trying to do here is writing GPS data in SD card into two stages : First stage is the Initialisation ,which will be logged only for one time.

The data inside doSomeWork(); will be logged only for one time, in the beginning logging/writing.

Then the second stage is in the loop (over and over again until I press the button)

The data inside logging(); will be logged for many times right after the initialisation - until I press the button to stop and close the file.

It's true that, I wanted to write data into a file when ever it gets a valid date, time and location but also want the above first stage and second stage things.

Thank you

what I am trying to do here is writing GPS data in SD card into two stages : First stage is the Initialisation ,which will be logged only for one time. Then the second stage is in the loop... The data inside
logging() will be logged for many times right after the initialisation - until I press the button to stop and close the file.

Well, doSomeWork is where the logging (second stage) must take place. If you do it in loop, you're trying to log the same fix thousands of times. That's because doSomeWork is only called when a new fix is available. The rest of the time, loop and GPSloop are just checking to see is a new fix is available. Most of the time, there is no new fix.

The same is true for the first stage: you should only test for a valid date/time/location when a new fix is available. You would not test this in loop, for the same reason: fix.valid.date won't change until there is a new fix.

Here is your sketch, modified to do the first stage and second stage in doSomeWork.

#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 Serial1


SdFat SD;
File  dataFile;
char filename[] = "12345.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(37, INPUT_PULLUP);

  if (!SD.begin(4)) {
    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>") );
    dataFile.print  ( fix.dateTime.full_year() );
    dataFile.print  ( '-' );
    dataFile.print  ( fix.dateTime.month );
    dataFile.print  ( '-' );
    dataFile.print  ( fix.dateTime.date );
    dataFile.print  ( 'T' );
    dataFile.print  ( fix.dateTime.hours );
    dataFile.print  ( ':' );
    dataFile.print  ( fix.dateTime.minutes );
    dataFile.print  ( ':' );
    dataFile.print  ( fix.dateTime.seconds );
    dataFile.print  ( ':' );
    dataFile.print  ( fix.dateTime_cs );
    dataFile.println( F(".000Z"
                        "</Id>\n"
                        "<Lap StartTime=\"") );
    dataFile.print  ( 'T' );
    dataFile.println( F(".000Z\">"
                        "<Track>") );
  }
} // firstStage

void secondStage()
{
  if (dataFile.isOpen()) {
    dataFile.println( F("<Trackpoint>\n"
                        "<Time>") );
    dataFile.print  (fix.dateTime.full_year());
    dataFile.print  ( '-' );
    dataFile.print  (fix.dateTime.month);
    dataFile.print  ( '-' );
    dataFile.print  (fix.dateTime.date);
    dataFile.print  ( 'T' );
    dataFile.print  (fix.dateTime.hours);
    dataFile.print  ( ':' );
    dataFile.print  (fix.dateTime.minutes);
    dataFile.print  ( ':' );
    dataFile.print  (fix.dateTime.seconds);
    dataFile.print  ( '.' );
    if (fix.dateTime_cs < 10)
      dataFile.print  ( '0' );
    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 think this does what you described: when it gets a valid date/time/location, it opens the file and writes a few things. Then it writes each fix until the button is pressed, and it stops there. It never does anything else after pressing the button, right?

If you reset the Arduino, it will do it again, to the same file.

I also used the F macro on all "double-quoted strings", changed "A" single-character strings to 'A' single character, and merged sequential string prints into one print of a concatenated string. That is, this:

    dataFile.println("</zaxis>");
    dataFile.println("</impact>");
    dataFile.println("</Trackpoint>");

...can change to this:

    dataFile.println( F("</zaxis>\n"
                        "</impact>\n"
                        "</Trackpoint>") );

I added newline characters, '\n', when you did a println.

The original took 22712 bytes of program space and 1694 bytes of RAM.
This version takes 21198 bytes of program space and 1163 bytes of RAM. The string changes saved more than 500 bytes of RAM, and the print changes saved 1600 bytes of program space.

Cheers,
/dev

Thank you very much for replying /Dev

Well, doSomeWork is where the logging (second stage) must take place. If you do it in loop, you're trying to log the same fix thousands of times. That's because doSomeWork is only called when a new fix is available. The rest of the time, loop and GPSloop are just checking to see is a new fix is available. Most of the time, there is no new fix.

The same is true for the first stage: you should only test for a valid date/time/location when a new fix is available. You would not test this in loop, for the same reason: fix.valid.date won't change until there is a new fix.

Thank you for this excellent explanation :slight_smile:

Here is your sketch, modified to do the first stage and second stage in doSomeWork.

thank you very much for the code, which is working as I wanted :slight_smile: :slight_smile: :slight_smile:

I also used the F macro on all "double-quoted strings", changed "A" single-character strings to 'A' single character, and merged sequential string prints into one print of a concatenated string. That is, this:

WOW! That saved lots of space, thank you again /Dev

I have few more questions..

If you reset the Arduino, it will do it again, to the same file.

1: I don't want to write data, My idea here is : Everytime when Arduino resets, it should create a new file considering time and date as a file name, This will allow me to create a new file every resets and writes data into it.

I have made a line

  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());

and plugged it before   dataFile = SD.open(filename , FILE_WRITE); and tested, It is not at all creating a file, How do I do it.?

2: What if replaced my Quectel L80 GPS module with Quectel L86 which is GNSS module.? I think GPRMC in NeoGPS library has to replaced with GNRMC.??

3: How do I get the 10 digit more precise latitude and longitude with the NeoGPS library.? I have referred to the Readme notes of NeoGPS GitHub page where it was mentioned this :

a location structure (i.e., latitude and longitude), accessed with
fix.latitudeL() and fix.longitudeL() for the higher-precision integer degrees, scaled by 10,000,000 (10 significant digits)
fix.latitude() and fix.longitude() for the lower-precision floating-point degrees (~7 significant digits)

is that means I just have to replace fix.latitude() and fix.longitude() TO fix.latitudeL() and fix.longitudeL() .??

Thank you

mudassir9999:
1: Everytime when Arduino resets, it should create a new file considering time and date as a file name, This will allow me to create a new file every resets and writes data into it.

The example NMEASDlog.ino shows one way to create numbered filenames.

2: What if replaced my Quectel L80 GPS module with Quectel L86 which is GNSS module.? I think GPRMC in NeoGPS library has to replaced with GNRMC.??

NeoGPS will work correctly with other "talker IDs", like the "GN" of a "GNRMC" sentence.

3: How do I get the 10 digit more precise latitude and longitude with the NeoGPS library.? I have referred to the Readme notes of NeoGPS GitHub page where it was mentioned this :

is that means I just have to replace fix.latitude() and fix.longitude() TO fix.latitudeL() and fix.longitudeL() .??

Yes. Just remember that those uint32_t values (i.e. 32-bit integers) are the degrees * 107. NMEAloc.ino shows how to print those integers as if they were floating-point degrees. It basically drops a decimal point in at the right place.

For calculating distance or bearing, just use the Location.h methods. It knows how to use the scaled values correctly in the calculations. See NMEAdistance.ino for examples.

Cheers,
/dev

Hello /Dev,
Thank you for replying....

The example NMEASDlog.ino shows one way to create numbered filenames.

I complied the NEMASDlog.ino from the example, but it shows me this error.

Arduino: 1.6.13 (Mac OS X), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

/var/folders/_q/tnn1mv5109v3ymf1w_snxhlc0000gn/T/arduino_modified_sketch_104103/NMEASDlog.ino:26:27: fatal error: NeoHWSerial.h: No such file or directory
#include <NeoHWSerial.h>
^
compilation terminated.
exit status 1
Error compiling for board Arduino/Genuino Mega or Mega 2560.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I saw a NOTE comment in the code

// NOTE: There is an issue with IDEs before 1.6.6. The above include
// must be commented out for non-Mega boards, even though it is
// conditionally included. If you are using an earlier IDE,
// comment the above include.

and commented down   #include <NeoHWSerial.h>

then it shows me this error

Arduino: 1.6.13 (Mac OS X), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

NMEASDlog:61: error: #error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!
#error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!
^
exit status 1
#error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

I am using Arduino Mega with Quectel L80 module on Serial1.

And I have one question about the Ublox-Neo-6 receiver, I have downloaded it's datasheet ,Where on page number 6 of 25 it says about

Horizontal position accuracy6
GPS 2.5 m
SBAS 2.0 m
SBAS+PPP7 < 1 m (2D, R50)8)
SBAS+PPP7 < 2 m (3D, R50)8)

Is that mean using only GPS will provide 2.5CEP and Using SBAS will give 2.0CEP Vice versa.?

If 'Yes' : how do I achieve SBAS+PPP7 <1m(2d,R50)8) in my Quectel L86 Receiver.?
Thank you

I complied the NEMASDlog.ino from the example, but it shows me this error.

You need to install the NeoHWSerial library.

I'll have to look at the other questions later.

Cheers,
/dev

Thank you very much /Dev for helping :slight_smile:

You need to install the NeoHWSerial library.

I will test this Library

I'll have to look at the other questions later.

I will wait for your answers

Thank you again

Hello /Dev ,

I downloaded the NeoHWSerial library and tested the NMEASDlog.ino example, hit RUN and it gives me this error

Arduino: 1.6.13 (Mac OS X), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

NMEASDlog:61: error: #error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!
#error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!
^
exit status 1
#error You must define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h!

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.