GPS Module Randomly Ignores RMC and 10HZ commands

I have been fighting this seemingly random issue on my Fastrax GPS UP501 module not accepting my commands. I have tested this directly connected(via a breadboard circuit) to my Uno R3, on an AF gps shield, via my MicroView OLED and finally connected to my Uno via a Sparkfun uSD shield with a connector/circuit on the proto space. At first i thought it was a physical connection issue but for it to happen randomly in all the different configurations makes me think otherwise.

General overview: I am sending 2 commands, RMCONLY and UPDATE 10HZ as seen in the code below. I have the GPS module running at the default 9600bps(when i kicked it up i was getting garbage on the serial monitor and SD card). I would say about 75% of the time i get the RMC data at 10HZ just fine. If i reset the Arduino it always keeps the RMC/10HZ setting and spits data out how i would expect. The issue seems to happen when its first powered up with a 9v battery pack or reconnected via USB to program/debug. It doesn't matter how many times i reset the board it spits out all NMEA data. When i check my SD card i am getting 1HZ updates but double printing the data. In order to get the RMC/10HZ to work i have to unplug and power the board up a few times before it finally seems to take.

What i would like to know is: Am i doing something wrong in the sketch? Should I be passing other commands, adding a delay in there or something else? I don't currently have any "wait for good data" functions in place but i plan to add them. I would assume i could maybe ask for the current setting from the GPS module and if its not RMC and 10hz to resent the commands back to gpsSerial. I just can't seem to figure out why its random.

Thanks for any and all insight!!

#include <SPI.h>
#include <SdFat.h>
#include <TinyGPS.h>
//#include <SoftwareSerial.h>
#include <gSoftSerial.h>

long lat, lon;
unsigned long fix_age, date, time, speed, altitude, course;
float CorrectedSpeed, CorrectedLon, CorrectedLat;
const int chipSelect = 8;

//#define PMTK_SET_NMEA_BAUDRATE_38400 "$PMTK251,38400*1F" // Set Baud Rate to 38400
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"
#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"     // only RMC data

File logfile;

gSoftSerial gpsSerial (2,3); // create gps sensor connection
TinyGPS gps;                 // create gps object
SdFat SD;                    // create SD object

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  gpsSerial.begin(9600);
  gpsSerial.println(PMTK_SET_NMEA_OUTPUT_RMCONLY);            // turn on only RMC
  gpsSerial.println(PMTK_SET_NMEA_UPDATE_10HZ);               // turn on 10Hz
  
  while (!Serial) {
    ; // wait for serial port to connect. 
  }
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

  char filename[15];
 strcpy(filename, "data_00.txt");
 for (uint8_t i=0; i<100; i++) {
  filename[5] = '0' + i/10;
  filename[6] = '0' + i%10;
  if (!SD.exists(filename)) {
    break;
  }
 }
logfile = SD.open(filename, FILE_WRITE);
  if(!logfile) {
    Serial.print("Couldnt create "); 
    Serial.println(filename);
    while (1) {}
  }
  Serial.print("Writing to "); 
  Serial.println(filename);
  logfile.println("latitude, longitude, speed, time");
 

}

void loop() {
  
  while(gpsSerial.available()>0){                                // check for gps data
//    char c = gpsSerial.read();                                 // read gps data into char c
//    Serial.print(c);                                           // pring NMEA RMC strings to the Serial Monitor, this is here to figure if its passing all NMEA sentences or just RMC for debug
    if (gps.encode(gpsSerial.read())){
      gps.get_position(&lat, &lon, &fix_age);                    // get GPS lat, lon and fix age variables
      gps.get_datetime(&date, &time, &fix_age);                  // get GPS date, time and fix age, when i tried to omit the date variable i had bad results
      speed = gps.speed();                                       // get speed value in 100th of a knot from TinyGPS    
      CorrectedSpeed = speed * 0.0115;                           // convert speed to mph
      CorrectedLon = lon * 1E-6;                                 // Convert Longitude to a normal value for GPS Visualizer
      CorrectedLat = lat * 1E-6;                                 // Convert Latitude to a normal value for GPS Visualizer
      Serial.print(((float)CorrectedLat),8);Serial.print(",");Serial.print(((float)CorrectedLon), 8);Serial.print(",");Serial.println(time); // print data to serial monitor for debug
      logfile.print(((float)CorrectedLat),8);logfile.print(","); // print CorrectedLat to SD with 8 decimal places
      logfile.print(((float)CorrectedLon),8);logfile.print(","); // print CorrectedLon to SD with 8 decimal places
      logfile.print(CorrectedSpeed);logfile.print(",");          // print CorrectedSpeed to SD
      logfile.println(time);                                     // print time string from RMC, no conversion yet
      logfile.flush();                                           // flush to push the data to the SD without having to close it
    }
    }
    }

Here is the data sheet for the GPS module.

and the NMEA manual for the same.

The NMEA commands in the code below work and are good.

I put a 500ms delay between the commands. I use a Mega 2560, so I use a hardware serial port. Maybe that will work for you also.

void GPS_init() {
  Serial1.begin(9600);

  delay(500);

// change to 19200 baud  
  Serial1.println("$PMTK251,19200*22");
  delay(500);

// restart serial at new baud
  Serial1.end();
  delay(1000);
  Serial1.begin(19200);
  delay(500);
  
// update 500ms (twice per second)
  Serial1.println("$PMTK220,500*2B");
  delay(500);
    
// position only
  Serial1.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
}

9v battery pack

Is that an akaline battery with the snaps on top, or a rechargeable pack assembled from smaller cells like an RC battery, with wire leads? A 9v snap-top has marginal lifetime and sketchy current capability.

I would say about 75% of the time i get the RMC data at 10HZ just fine.

Hmmm... Remember this?

Shift314:
I do have it currently sending 10hz rmc data to the sd card but its really doing nothing else. I haven't noticed any dropped data and my timestamps in my .txt file follow 10 updates a second.

Did something change? This is a harder problem than most people realize. From the Troubleshooting section I referred you to in that other thread:

Many programmers want to write GPS data to an SD card. This is completely reasonable to do, but an SD.write can block long enough to cause the input buffer to overflow. SD libraries have their own buffers, and when they are filled, the library performs SPI operations to "flush" the buffer to the SD card. While that is happening, the GPS device is still sending data, and it will eventually overflow the serial input buffer.

This is a very common problem!

It just happened again! :smiley:

Am i doing something wrong in the sketch? Should I be passing other commands, adding a delay in there or something else?

As SurferTime said, a delay after changing the baud rate is a good idea, but you're not doing that. Delays anywhere else would not help. At least you're not using smartDelay!

I don't currently have any "wait for good data" functions in place but i plan to add them.

There's a library for that.

BTW, flushing 10 times per second isn't going to help. Even if you don't, one of the SD flushes or writes will eventually cause the same data loss, just at a lower frequency. If only there were a way to keep handling the GPS data while the SD write was busy... :wink:

It would also help to put the GPS on Serial and the debug prints on the software serial. That would decrease the CPU load for handling GPS data and allow you to increase the GPS baudrate. Unfortunately, you would still lose GPS data if the SD flush/write ever takes longer than 60ms to 80ms. Even 100ms is common, and that's an entire 10Hz interval.

I'm surprised you're still using floats, though. Are you sure you want our advice?

Cheers,
/dev

/dev:
Is that an akaline battery with the snaps on top, or a rechargeable pack assembled from smaller cells like an RC battery, with wire leads? A 9v snap-top has marginal lifetime and sketchy current capability.
Hmmm... Remember this?
Did something change? This is a harder problem than most people realize. From the Troubleshooting section I referred you to in that other thread:
It just happened again! :smiley:
As SurferTime said, a delay after changing the baud rate is a good idea, but you're not doing that. Delays anywhere else would not help. At least you're not using smartDelay!
There's a library for that.

BTW, flushing 10 times per second isn't going to help. Even if you don't, one of the SD flushes or writes will eventually cause the same data loss, just at a lower frequency. If only there were a way to keep handling the GPS data while the SD write was busy... :wink:

It would also help to put the GPS on Serial and the debug prints on the software serial. That would decrease the CPU load for handling GPS data and allow you to increase the GPS baudrate. Unfortunately, you would still lose GPS data if the SD flush/write ever takes longer than 60ms to 80ms. Even 100ms is common, and that's an entire 10Hz interval.

I'm surprised you're still using floats, though. Are you sure you want our advice?

Cheers,
/dev

Dev, im using a snap top 9v but its a lithium high mah unit I use in protos for other stuff.

So nothing changed code wise. When I moved everything to the new proto space on the uSD shield it worked for a while so I assumed it was a wiring issue. Not so lucky.

Yes I know you reffered to neoGps in the other thread but I haven't been able to carve out time yet. I assumed(incorrectly im sure) tjat if im not passing codes to set the gps the codes to check settings wouldn't go through.

I wasn't sure how else to write to sd without flush. Several examples I found open and close the sd file every time to write!

The floats I added in the 6decimal point thread. Thst didn't seem to change this issue. The data in the SD file is ok as long as I get rmc only. When it spits out everything is when the SD is wrong.

Sorry again. I am trying to learn as fast as possible and isolate problems I am seeing. I keep trying to isolate but my knowledge of what is going on behind the scenes shows.

For what its worth I turned off SS and printing to the serial monitor for about 30 test files. Again once powered up if it was spitting out rmc all was good. If it gave all nmea it would never reset.

So on the whole is this an issue where the nmea sentences are passed tonthe gps module too soon? Would a void function checking the seting amd looping back until its set be acceptable?

Dev you have been extremely helpful in all of this! The next time I sit down to work on this ill start with NeoGPS to put me in your wheelhouse.

Thanks!

Try this. It works for me. You will need to change the Serial1 stuff to your softwareSerial code tho. I left some debugging Serial output if you need it. It is accurate to 1/10th second. I would appreciate somebody else testing it for me.

int charCount = 0;
char gpsBuf[255];
byte tIndex[16];
char latDegrees[4];
char latMinutes[8];
char latSeconds[6];
char longDegrees[5];
char longMinutes[8];
char longSeconds[6];
char gpsSpeed[8];
char gpsHeading[8];
boolean gpsLock = false;
boolean readLock = false;

void setup() {
  Serial.begin(115200);
  GPS_init();
}

void loop() {
  checkGPS();
}

void computeSeconds(char* minuteBuf,char* secondBuf)
{
  for(int i = 0; i < 8; i++)
  {
    if(minuteBuf[i] == '.')
    {
      minuteBuf[i] = 0;
      unsigned int secondInt = atoi(&minuteBuf[i+1]);
      secondInt = (secondInt * 6)/100;
      itoa(secondInt,secondBuf,10);      
      secondBuf[strlen(secondBuf) + 1] = 0;
      secondBuf[strlen(secondBuf)] = secondBuf[strlen(secondBuf) -1];
      secondBuf[strlen(secondBuf) -2] = '.';
    }
  }
}

void GPS_init() {
  Serial1.begin(9600);

// warm start if you need it
//  Serial1.println("$PMTK102*31");
  delay(500);

  Serial1.println("$PMTK251,19200*22");
  delay(500);

  Serial1.end();
  delay(1000);
  Serial1.begin(19200);
  delay(500);
  
// update 500ms
  Serial1.println("$PMTK220,500*2B");
  delay(100);
    
// position only
  Serial1.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
}

void checkGPS() {
  while(Serial1.available()) {
    char ch = Serial1.read();
    
    if(charCount < 254 && ch != '\r' && ch != '\n') {
      gpsBuf[charCount] = ch;
      charCount++;      
      gpsBuf[charCount] = 0;
    }

    if(ch == '\n') {

      if(strncmp(gpsBuf,"$GPRMC",6) == 0) {
//        Serial.println(gpsBuf);
        int commaCount = 0;
                
        for(int i = 0; i < 254; i++) {
          if(gpsBuf[i] == ',') {
            tIndex[commaCount] = i + 1;
            gpsBuf[i] = 0;
            commaCount++;              
          }
          else if(gpsBuf[i] == '*') {
            gpsBuf[i] = 0;
            break;            
          }
        }

        Serial.print("Time: ");
        Serial.print(&gpsBuf[tIndex[0]]);

//        Serial.print(" Status: ");
        Serial.println(&gpsBuf[tIndex[1]]);

        if(gpsBuf[tIndex[1]] == 'A')
        {
          readLock = true;
          gpsLock = true;
          delay(10);
          
//          Serial.print(" ");
//          Serial.print(&gpsBuf[tIndex[3]]);
//          Serial.print(&gpsBuf[tIndex[2]]);

          strcpy(latDegrees,&gpsBuf[tIndex[3]]);
          strncat(latDegrees,&gpsBuf[tIndex[2]],2);
          strcpy(latMinutes,&gpsBuf[tIndex[2] + 2]);
          computeSeconds(latMinutes,latSeconds);

          Serial.print(latDegrees);
          Serial.print(" ");
          Serial.print(latMinutes);
          Serial.print("' ");
          Serial.print(latSeconds);
          Serial.print("\" ");
//          Serial.print(&gpsBuf[tIndex[5]]);
//          Serial.print(&gpsBuf[tIndex[4]]);

          strcpy(longDegrees,&gpsBuf[tIndex[5]]);
          strncat(longDegrees,&gpsBuf[tIndex[4]],3);
          strcpy(longMinutes,&gpsBuf[tIndex[4] + 3]);
          computeSeconds(longMinutes,longSeconds);
          
          Serial.print(longDegrees);
          Serial.print(" ");
          Serial.print(longMinutes);
          Serial.print("' ");
          Serial.print(longSeconds);
          Serial.println("\" ");

/*
          Serial.print(" Speed: ");
          Serial.print(&gpsBuf[tIndex[6]]);
*/

          int thisSpeed = atoi(&gpsBuf[tIndex[6]]);
          itoa(thisSpeed,gpsSpeed,10);
          strcpy(gpsSpeed,&gpsBuf[tIndex[6]]);
                 
//          Serial.print(" Hdg: ");
//          Serial.println(&gpsBuf[tIndex[7]]);

          int thisHdg = atoi(&gpsBuf[tIndex[7]]);
          itoa(thisHdg,gpsHeading,10);

          strcpy(gpsHeading,&gpsBuf[tIndex[7]]);
          readLock = false;
        }
        else {
          Serial.println(" No lock");
          gpsLock = false;
        }
      }
      else Serial.println("No position");
            
      charCount = 0;
      gpsBuf[0] = 0;
    }
  }
}

edit: I'm using an Adafruit Ultimate GPS unit. It uses the same commands as yours.

Thanks Tim! I will look over your code when i get a chance. What libraries/declarations are above this part of the code? or is that it? I was going to use pins 0-1 for my gps but in my searches i kept finding a lot of (don't do this unless you know what you are doing) and i don't :slight_smile: so i opted for pins 2 and 3. I know that using the rx/tx pins means i cant have the gps module hooked up while programming, but is there something else i should be concerned or aware of?

SurferTim:
Try this. It works for me. You will need to change the Serial1 stuff to your softwareSerial code tho. I left some debugging Serial output if you need it. It is accurate to 1/10th second. I would appreciate somebody else testing it for me.

int charCount = 0;

char gpsBuf[255];
byte tIndex[16];
char latDegrees[4];
char latMinutes[8];
char latSeconds[6];
char longDegrees[5];
char longMinutes[8];
char longSeconds[6];
char gpsSpeed[8];
char gpsHeading[8];
boolean gpsLock = false;
boolean readLock = false;

void setup() {
  Serial.begin(115200);
  GPS_init();
}

void loop() {
  checkGPS();
}

void computeSeconds(char* minuteBuf,char* secondBuf)
{
  for(int i = 0; i < 8; i++)
  {
    if(minuteBuf[i] == '.')
    {
      minuteBuf[i] = 0;
      unsigned int secondInt = atoi(&minuteBuf[i+1]);
      secondInt = (secondInt * 6)/100;
      itoa(secondInt,secondBuf,10);     
      secondBuf[strlen(secondBuf) + 1] = 0;
      secondBuf[strlen(secondBuf)] = secondBuf[strlen(secondBuf) -1];
      secondBuf[strlen(secondBuf) -2] = '.';
    }
  }
}

void GPS_init() {
  Serial1.begin(9600);

// warm start if you need it
//  Serial1.println("$PMTK102*31");
  delay(500);

Serial1.println("$PMTK251,19200*22");
  delay(500);

Serial1.end();
  delay(1000);
  Serial1.begin(19200);
  delay(500);
 
// update 500ms
  Serial1.println("$PMTK220,5002B");
  delay(100);
   
// position only
  Serial1.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
29");
}

void checkGPS() {
  while(Serial1.available()) {
    char ch = Serial1.read();
   
    if(charCount < 254 && ch != '\r' && ch != '\n') {
      gpsBuf[charCount] = ch;
      charCount++;     
      gpsBuf[charCount] = 0;
    }

if(ch == '\n') {

if(strncmp(gpsBuf,"$GPRMC",6) == 0) {
//        Serial.println(gpsBuf);
        int commaCount = 0;
               
        for(int i = 0; i < 254; i++) {
          if(gpsBuf[i] == ',') {
            tIndex[commaCount] = i + 1;
            gpsBuf[i] = 0;
            commaCount++;             
          }
          else if(gpsBuf[i] == '*') {
            gpsBuf[i] = 0;
            break;           
          }
        }

Serial.print("Time: ");
        Serial.print(&gpsBuf[tIndex[0]]);

//        Serial.print(" Status: ");
        Serial.println(&gpsBuf[tIndex[1]]);

if(gpsBuf[tIndex[1]] == 'A')
        {
          readLock = true;
          gpsLock = true;
          delay(10);
         
//          Serial.print(" ");
//          Serial.print(&gpsBuf[tIndex[3]]);
//          Serial.print(&gpsBuf[tIndex[2]]);

strcpy(latDegrees,&gpsBuf[tIndex[3]]);
          strncat(latDegrees,&gpsBuf[tIndex[2]],2);
          strcpy(latMinutes,&gpsBuf[tIndex[2] + 2]);
          computeSeconds(latMinutes,latSeconds);

Serial.print(latDegrees);
          Serial.print(" ");
          Serial.print(latMinutes);
          Serial.print("' ");
          Serial.print(latSeconds);
          Serial.print("" ");
//          Serial.print(&gpsBuf[tIndex[5]]);
//          Serial.print(&gpsBuf[tIndex[4]]);

strcpy(longDegrees,&gpsBuf[tIndex[5]]);
          strncat(longDegrees,&gpsBuf[tIndex[4]],3);
          strcpy(longMinutes,&gpsBuf[tIndex[4] + 3]);
          computeSeconds(longMinutes,longSeconds);
         
          Serial.print(longDegrees);
          Serial.print(" ");
          Serial.print(longMinutes);
          Serial.print("' ");
          Serial.print(longSeconds);
          Serial.println("" ");

/*
          Serial.print(" Speed: ");
          Serial.print(&gpsBuf[tIndex[6]]);
*/

int thisSpeed = atoi(&gpsBuf[tIndex[6]]);
          itoa(thisSpeed,gpsSpeed,10);
          strcpy(gpsSpeed,&gpsBuf[tIndex[6]]);
               
//          Serial.print(" Hdg: ");
//          Serial.println(&gpsBuf[tIndex[7]]);

int thisHdg = atoi(&gpsBuf[tIndex[7]]);
          itoa(thisHdg,gpsHeading,10);

strcpy(gpsHeading,&gpsBuf[tIndex[7]]);
          readLock = false;
        }
        else {
          Serial.println(" No lock");
          gpsLock = false;
        }
      }
      else Serial.println("No position");
           
      charCount = 0;
      gpsBuf[0] = 0;
    }
  }
}



edit: I'm using an Adafruit Ultimate GPS unit. It uses the same commands as yours.

No includes. You may need to include softwareSerial. Don't use D0 or D1. Those are the Serial RX and TX lines. You want those for debugging. D2 and D3 should be ok on an Uno. See the section on "Limitations" here:

edit: You maybe able to get away with this on your Uno without modifying my sketch. Add this at the top of the sketch. I don't have an Uno to test this with.

#include <SoftwareSerial.h>

const byte rxPin = 2;
const byte txPin = 3;

// set up a new serial object
SoftwareSerial Serial1 (rxPin, txPin);

SurferTim:
I would appreciate somebody else testing it for me.

I notice you don't watch for the leading '$' to set the charCount to zero. This means your buffer may have a partial sentence at the beginning. Then when you go looking for fields separated by commas, you may be indexing a field from the previous partial sentence. Once you get a newline char, it's "in sync", and the buffer will have complete sentences. I would suggest either testing for the '$' in loop or waiting in setup until you get a newline.

But parsing isn't really the OP's problem. The real problem is that the SD write takes so long that the input buffer overflows. (Have you read this?) As soon as one character is dropped, the checksum will fail, and TinyGPS ignores it.

I also noticed that your program doesn't verify the checksum, so it never rejects a sentence. It's easy to add, though. Just XOR the characters after the '$' up to the '*'. Then compare with the 2 hex digits that follow. I doubt that you are dropping characters with this program, but the CS would confirm that. And you may want to add it, depending on what you are doing with the parsed GPS info. Losing a character from a "degrees" field will produce a goofy value. BTDT. :smiley:

And what's this doing in there?

          delay(10);

That's 10% of the 100ms interval. Don't make me come over there! :slight_smile:

SurferTim:
You may need to include softwareSerial.

Eeeew. SoftwareSerial is a real CPU-killer; it's SUPER inefficient. The OP has already switched to a better alternative, the "gSoftSerial" from jboyton... which I polished up into NeoSWSerial. Paul has a great description on his website of why SoftwareSerial is sooo bad. If you ever use your sketch on an UNO, you'll get better results with almost any other software serial library.

Cheers,
/dev

Shift314:
So on the whole is this an issue where the nmea sentences are passed to the gps module too soon?

It doesn't hurt to delay a little in setup before sending the configuration commands to the GPS module. That's all you should have to do.

If you were using NeoGPS, you could watch for other sentences and send the RMC_ONLY command again if you do get something else (e.g., a GGA). That's not really necessary, though. NeoGPS is very fast at skipping things you have configured out of the library. The NMEAloc.ino example only uses RMC locations. You can turn everything else off.

Cheers,
/dev

I notice you don't watch for the leading '$' to set the charCount to zero.

No, I don't. I wait for the '\n' and check the string for "$GPRMC". Note the '$'.

I have all those software serial libraries outdone. I have a Mega and use a hardware serial port. Try getting better than that! :wink:

SurferTim:
I have all those software serial libraries outdone. I have a Mega and use a hardware serial port. Try getting better than that! :wink:

Okay, a Pro Micro... hardware serial port and it's a lot smaller. :slight_smile:

aarg:
Okay, a Pro Micro... hardware serial port and it's a lot smaller. :slight_smile:

...and it has how many I/O pins?

SurferTim:
...and it has how many I/O pins?

All I usually need. If I need more, I use a Mega.

The hardware serial is the best for the GPS, and the rest is dependent on your application.

Now to find if the GPS works with the software serial library of your choice. The OP already has a device with only one hardware serial port.

Dev, ive spent some time today reading through the documents on NeoGPS. I don't understand a lot of whats happenimg, and I was reading it on my phone when I could, but I think it makes sense how to implement. I hate no understanding the code but ill get there.

While I haven't had time to dig into this I was able to do a few quick tests.

  1. Powered up via usb. The sketch on there ran and I got 10hz RMC data on the Serial Monitor and SD.

  2. Added delays after the serial connection and the nmea sentences. Still got rmc at 10hz on the monitor and sd.

  3. Arduino reset button. Still rmc at 10hz.

  4. Powered up with 9v probably a min later(1200mah I think) and walked around. Obviously no serial monitor but it was spitting out the data to sd but only 2 sentences a second. Because I added a few decimal places to the speed value I noticed that lines with the same timestamp had different speed values.

I currently have it running on the 9v and ill check it again in awhile to see what the data shows.

Now yesterday it was sending rmc and full nmea strings to serial monitor at various times so its not isolated to just the 9v, but are there variations on how these boards power up? What about neoGPS would change this? I'm not seeing or concerned with dripping data at the moment, just why sometimes it takes the default gps module settings and others it sends everything.

I will report back nore findings when I have them and as soon as I can carve out an hour or two ill run through a NeoGPS example. Probaly the ISR one.

Thanks!

SurferTim:
The hardware serial is the best for the GPS, and the rest is dependent on your application.

Now to find if the GPS works with the software serial library of your choice. The OP already has a device with only one hardware serial port.

Yes. I have been faced with adding GPS to a variety of boards lately. The latest experiment used NeoSWSerial for the extra serial port on an UNO. I like it. Before that, I used SoftwareSerial and it always worked in spite of its reported limitations. I see no good reason not to use NeoSWSerial from now on, if I have to use a software port.

It makes perfect sense to use a hardware port for such an intensive serial application. So I've begun to insist on hardware ports. The first way I solved that, was to abandon the USB serial port to free up the primary hardware serial port that is on every board. I bought a USBASP to program from the ICSP. It sounds complicated, but it isn't really. For stand alone applications, you seldom need the USB except for power anyway. The code is debugged on a different system with two ports, so I don't have to worry about missing a debug port.

I have to admit, the Pro Micro is tricky to use. You can brick it if you program it incorrectly. It can be unbricked, but it's a pain. As far as I know, no IDE past 1.6.4 has working support for the board. So I'm stuck at that version just for the sake of that board. I'm stubborn that way. It has another advantage besides the GPS port for my time applications, the crystal oscillator vs. resonator for a CPU clock.

I do use Mega's, I have 4 of them. Usually it is because of the extra memory that I need them, not because of the extra pins.

I was testing NeoGPS last week. I like it. I want to integrate it with my clock apps, but first I need to make it play properly with a PPS. The experiment is ongoing.

Here are some results.

Sketch as seen in the first post. Plugged into USB and viewed on the Serial monitor and SD.

From the SD text file.

latitude, longitude, speed, time
37.263656,-80.402023,0.06,22152750
37.263641,-80.402023,0.05,22152760
37.263633,-80.402015,0.07,22152770
37.263626,-80.402015,0.06,22152780
37.263618,-80.402023,0.10,22152790
37.263626,-80.402015,0.06,22152800
37.263614,-80.402023,0.16,22152810
37.263591,-80.402030,0.08,22152820
37.263591,-80.402038,0.12,22152830
37.263576,-80.402046,0.14,22152840
37.263565,-80.402053,0.14,22152850
37.263557,-80.402061,0.12,22152860
37.263553,-80.402061,0.10,22152870
37.263561,-80.402061,0.09,22152880
37.263572,-80.402053,0.10,22152890
37.263584,-80.402038,0.09,22152900
37.263595,-80.402030,0.09,22152910
37.263599,-80.402023,0.08,22152920
37.263595,-80.402023,0.08,22152930
37.263595,-80.402015,0.08,22152940
37.263599,-80.402015,0.07,22152950
37.263599,-80.402008,0.07,22152960
37.263599,-80.402008,0.07,22152970
37.263595,-80.402008,0.07,22152980
37.263587,-80.402008,0.08,22152990
37.263576,-80.402008,0.08,22153000
37.263568,-80.402015,0.10,22153010
37.263553,-80.402015,0.12,22153020
37.263553,-80.402015,0.10,22153030
37.263549,-80.402015,0.10,22153040
37.263542,-80.402015,0.14,22153050
37.263542,-80.402015,0.13,22153060
37.263542,-80.402015,0.13,22153070
37.263538,-80.402015,0.15,22153080
37.263534,-80.402015,0.16,22153090
37.263534,-80.402015,0.15,22153100
37.263534,-80.402023,0.17,22153110
37.263534,-80.402015,0.18,22153120
37.263538,-80.402015,0.17,22153130
37.263542,-80.402015,0.17,22153140
37.263538,-80.402015,0.17,22153150
37.263542,-80.402015,0.18,22153160
37.263549,-80.402015,0.20,22153170

Added delays(and i forgot i took the float to print out to 8 decimals).

latitude, longitude, speed, time
37.26464462,-80.40141296,0.12,22174270
37.26464462,-80.40141296,0.10,22174280
37.26464462,-80.40141296,0.09,22174290
37.26464462,-80.40141296,0.12,22174300
37.26464462,-80.40141296,0.12,22174310
37.26464462,-80.40141296,0.13,22174320
37.26464462,-80.40141296,0.14,22174330
37.26464462,-80.40141296,0.16,22174340
37.26464462,-80.40141296,0.17,22174350
37.26464080,-80.40141296,0.22,22174360
37.26464080,-80.40141296,0.28,22174370
37.26464080,-80.40141296,0.31,22174380
37.26464080,-80.40141296,0.35,22174390
37.26464080,-80.40141296,0.37,22174400
37.26464080,-80.40141296,0.37,22174410
37.26464080,-80.40141296,0.37,22174420
37.26464080,-80.40141296,0.37,22174430
37.26464080,-80.40141296,0.35,22174440
37.26464080,-80.40141296,0.33,22174450
37.26464080,-80.40141296,0.33,22174460
37.26464080,-80.40141296,0.32,22174470
37.26464080,-80.40141296,0.30,22174480
37.26464080,-80.40141296,0.29,22174490
37.26464080,-80.40141296,0.28,22174500
37.26464080,-80.40141296,0.26,22174510
37.26464080,-80.40141296,0.28,22174520
37.26464080,-80.40141296,0.28,22174530
37.26464080,-80.40141296,0.29,22174540
37.26464080,-80.40141296,0.29,22174550
37.26464080,-80.40141296,0.29,22174560
37.26464080,-80.40141296,0.29,22174570
37.26464080,-80.40141296,0.30,22174580
37.26464080,-80.40141296,0.31,22174590
37.26464080,-80.40141296,0.32,22174600
37.26464080,-80.40141296,0.32,22174610
37.26464080,-80.40141296,0.32,22174620

and here is the data from the serial monitor for the same test. I don't print speed to Serial, just lat/lon and time

Initializing SD card...card initialized.
Writing to data_02.txt
37.26464462,-80.40141296,22174270
37.26464462,-80.40141296,22174280
37.26464462,-80.40141296,22174290
37.26464462,-80.40141296,22174300
37.26464462,-80.40141296,22174310
37.26464462,-80.40141296,22174320
37.26464462,-80.40141296,22174330
37.26464462,-80.40141296,22174340
37.26464462,-80.40141296,22174350
37.26464080,-80.40141296,22174360
37.26464080,-80.40141296,22174370
37.26464080,-80.40141296,22174380
37.26464080,-80.40141296,22174390
37.26464080,-80.40141296,22174400
37.26464080,-80.40141296,22174410
37.26464080,-80.40141296,22174420
37.26464080,-80.40141296,22174430

This was when i powered it up the first time with the 9v battery(wired up to an on/off switch). Same exact code as the case above. Notice there are two time stamps per second and see the speed is the same from one second to the next but splits. I am not up on exactly how the TinyGPS library parses the NMEA data but maybe there is another sentence that has speed/time?

latitude, longitude, speed, time
37.26463317,-80.40134429,11500000.00,22230400
37.26463317,-80.40134429,1.15,22230400
37.26459884,-80.40135955,1.15,22230500
37.26459884,-80.40135955,0.74,22230500
37.26459884,-80.40135192,0.74,22230600
37.26459884,-80.40135192,0.45,22230600
37.26459121,-80.40135192,0.45,22230700
37.26459121,-80.40135192,0.01,22230700
37.26458740,-80.40135192,0.01,22230800
37.26458740,-80.40135192,0.06,22230800
37.26459121,-80.40135955,0.06,22230900
37.26459121,-80.40135955,0.01,22230900
37.26459503,-80.40135955,0.01,22231000
37.26459503,-80.40135955,0.07,22231000
37.26459884,-80.40136718,0.07,22231100
37.26459884,-80.40136718,0.01,22231100
37.26459884,-80.40136718,0.01,22231200
37.26459884,-80.40136718,0.07,22231200
37.26460647,-80.40136718,0.07,22231300
37.26460647,-80.40136718,0.02,22231300
37.26460647,-80.40135955,0.02,22231400
37.26460647,-80.40135955,0.02,22231400
37.26460266,-80.40135955,0.02,22231500
37.26460266,-80.40135955,0.03,22231500
37.26459884,-80.40135192,0.03,22231600
37.26459884,-80.40135192,0.03,22231600
37.26459884,-80.40135192,0.03,22231700
37.26459884,-80.40135192,0.03,22231700
37.26460266,-80.40135192,0.03,22231800

and finally the same code with the board hooked back up to the USB cable so i could debug.

Serial Monitor output

Initializing SD card...card initialized.
Writing to data_07.txt
37.26459121,-80.40121459,374300
37.26459121,-80.40121459,374300
37.26461029,-80.40122985,374400
37.26461029,-80.40122985,374400
37.26461410,-80.40124511,374500
37.26461410,-80.40124511,374500
37.26462173,-80.40126037,374600
37.26462173,-80.40126037,374600
37.26463317,-80.40125274,374700
37.26463317,-80.40125274,374700
37.26464080,-80.40126037,374800
37.26464080,-80.40126037,374800
37.26464080,-80.40126800,374900
37.26464080,-80.40126800,374900
37.26464080,-80.40128326,375000
37.26464080,-80.40128326,375000
37.26463317,-80.40129089,375100
37.26463317,-80.40129089,375100
37.26462554,-80.40129089,375200
37.26462554,-80.40129089,375200

Anyways i know that doesn't really answer anything but maybe seeing what data I am getting and when might help. The fact is i got good RMC 10hz updates at first, went to the 9v and got slower/bad updates. Back to usb and was still getting bad data.

You are testing too many things at once, to troubleshoot this properly. You have to break it into more separate pieces. You have a possible power issue, GPS config issue, possible overall logging or data conversion issue. You need to develop separate test sketches to isolate the problem to a specific area. Then you can narrow it down further.