The problem is using delay
and printing too much. So many libraries’ examples have led users down this dead-end path.
Here is a sketch that shows how many times loop
gets called while waiting for each GPS update (1 second):
#include "SoftwareSerial.h"
#include <NMEAGPS.h>
SoftwareSerial gpsPort(2, 0);
//SoftwareSerial gpsPort(3, 1);
//SoftwareSerial gpsPort(9, 10);
NMEAGPS gps;
void setup() {
pinMode(2, INPUT);
pinMode(0, OUTPUT);
Serial.begin(115200);
Serial.println("Testing");
gpsPort.begin(115200);
}
unsigned long loopCount = 0;
unsigned long lastCharCount = 0;
void loop()
{
// This isn't really necessary, but it shows
// how *few* times a character is ready to be read.
loopCount++;
// Check for available GPS chars and parse them.
if (gps.available( gpsPort )) {
// Exactly once per second, a complete fix structure is ready to read.
// This structure contains all parsed GPS fields.
gps_fix fix = gps.read();
Serial.print( "READ characters: " );
Serial.println( gps.statistics.chars - lastCharCount );
lastCharCount = gps.statistics.chars;
Serial.print("CALLS to loop: ");
Serial.println( loopCount );
loopCount = 0;
Serial.print("LAT=");
if (fix.valid.location) {
Serial.print( fix.latitude(), 6 );
}
Serial.print(" LNG=");
if (fix.valid.location) {
Serial.print( fix.longitude(), 6 );
}
Serial.println();
}
}
On a 20MHz Mega, loop
gets called ~150000 times per second, to read about 450 characters. When you delay for 100ms, the GPS device has time to send 1152 characters (at 115200 baud). Because the input buffer only has room for 64 character, most of the GPS characters will get ignored.
The secondary issue is that you are printing on every call to loop
. The output buffer has room for only 64 characters. After a few iterations through loop, the output buffer is full, and those prints cause your sketch to wait for the previous characters to be transmitted (~86us per character). While waiting for the prints to go out, the GPS device continues to send characters. This will also cause the input buffer to overflow, losing more GPS characters.
The above sketch uses my NeoGPS library, which is smaller, faster, more accurate and more reliable than all other GPS libraries. There are many examples to show the correct program structure, and it supports many data fields. Even if you don’t use it, be sure the read the tips on the Installation and Troubleshooting pages.
Also notice that it does not try to use an invalid location. The GPS device may not know the location, so your sketch should not try to print an invalid location when you don’t have good satellite reception.
NeoGPS is available from the Arduino Library Manager, under the IDE menu Sketch → Include Library → Manage Libraries.
Cheers!