Loosing GPS.fix with LCD.print

If I put the LCD.print statements in with the Serial.print statements it works fine. If I put the LCD.print statements outside of the GPS logic, at end of void loop, I loose GPS.fix. I have the same problem when I try to add any other functions, like the servo control, to this sketch.

Yes, if the sketch spends all its time updating the LCD (every time through loop), it will lose some GPS characters. The GPSserial input buffer overflows because the LCD prints have not finished.

Remember that loop will run thousands and thousands of times per second. Instead of trying to update the LCD as fast as you can (every time through loop), only update the LCD when the displayed information has changed. For those prints, you should only update the LCD when the GPS data is updated: once per second (at the most). Once every two seconds is also OK.

A secondary problem is synchronizing the GPS updates (once per second) with the LCD updates (approx once every two seconds. Because the Arduino clock is not that accurate, the millis times will "drift" against the true GPS clock. Sometimes the Arduino will update the LCD between two GPS updates (the GPS quiet time), and sometimes the Arduino will update the LCD during a GPS update. If it takes too long to update the LCD, the GPSserial input buffer will overflow.

Instead, update the LCD only when the GPS information changes. Your GPS device is sending two sentences per second: RMC & GGA, according to the the configuration command you send. So you would have to wait for both of those sentences to arrive, and then start updating the LCD. Unfortunately, this is a little awkward with the Adafruit_GPS library.

My NeoGPS library groups all those sentences received into one "fix" per second. This is a structure that contains all the fields that were reported by all of those sentences. The fix structure contains both the lat & lon from RMC and the altitude from GGA (all fields described here). It will make one fix available per second, not two sentences (or more) per second.

Here is a NeoGPS version of your sketch that updates the display exactly once every two seconds:

// GPS Parsing sketch using NeoGPS with Wifi added
// and commented lines removed

// Add Libraries

#include <NMEAGPS.h>
#include <LiquidCrystal.h>

// what's the name of the hardware serial port?
#define GPSserial Serial3 // changed from Serial1

NMEAGPS GPS;
gps_fix fix;
uint8_t fixCount;

// initialize the lcd library with the numbers of the interface pins
LiquidCrystal lcd(33, 34, 35, 36, 37, 38);

// arrays for parsing data from controller
const size_t MAX_CHARS = 64;
      char   receivedChars[ MAX_CHARS ];
      char   tempChars    [ MAX_CHARS ];
      size_t count = 0;

// variables to hold the parsed data from controller
int           Throttle_Ref     = 0;
int           Steering_Ref     = 0;
int           ThrottleOutValue = 0;
int           SteeringOutValue = 0;
unsigned long Comm_Time        = 0;
unsigned long Comm_Time_2      = 0;
int           Comm_Delay_Time  = 1000;
int           index            = 0;

#define XbeeSerial Serial1



void setup()
{
  Serial.begin(115200);
  Serial.println( F("Xbee + LCD + NeoGPS test!") );


  XbeeSerial.begin(9600);


  lcd.begin(20, 4); // columns and rows

  GPSserial.begin(9600); // default baud rate for MTK GPS's- some use 4800

  // turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.send_P( &GPSserial, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") );

  // Set the update rate
  GPS.send_P( &GPSserial, F("PMTK220,1000") ); // 1Hz = 1000ms between updates

}


void loop()
{
  // Read and parse characters from the GPS device
  if (GPS.available( GPSserial )) {

    // A complete fix is ready, get the latest structure of GPS fields
    fix = GPS.read();
    fixCount++;

    // Every 2 seconds (exactly), print out the current stats
    if (fixCount >= 2) {
      fixCount = 0; // reset

      Serial.print("Status: ");
      if (fix.valid.status)
        Serial.print( fix.status);

      Serial.print("\nTime: ");      // first newline is for previous print
      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' ); // leading zero for .05, for example
      Serial.print(fix.dateTime_cs);

      Serial.print( F("\nDate: ") );
      if (fix.valid.date)
        Serial << fix.dateTime;

      Serial.print( F("\nLocation: ") );
      if (fix.valid.location) {
        Serial.print( fix.latitude(), 6 );
        Serial.print( ',' );
        Serial.print( fix.longitude(), 6 );
      }

      Serial.print("\nSpeed (knots): ");
      if (fix.valid.speed)
        Serial.println( fix.speed() );

      Serial.print("\nHeading: ");
      if (fix.valid.heading)
        Serial.println( fix.heading() );

      Serial.print( F("\nAltitude: ") );
      if (fix.valid.altitude)
        Serial.print( fix.altitude() );

      Serial.print("Satellites: ");
      if (fix.valid.satellites)
        Serial.print( fix.satellites );

      // ******* Print to LCD display  *******
      // GPS.fix good when LCD.prints are here
      lcd.setCursor(0, 0);
      lcd.print("Lat = ");
      if (fix.valid.location)
        lcd.print( fix.latitude(), 6 );
      else
        lcd.print( F("    ?      ") ); // erases old values, too

      lcd.setCursor(0, 1);
      lcd.print("Lon = ");
      if (fix.valid.location)
        lcd.print( fix.longitude(), 6 );
      else
        lcd.print( F("    ?      ") );

    }
  }

  // Check for commands?
  if (lineReady()) {
    Serial.print( F("Command = '") );
    Serial.print( receivedChars );
    Serial.println( '\'' );
  }

} // loop


bool lineReady()
{
  bool          ready     = false;
  const char    endMarker = '\n';

  while (Serial.available()) {

    char c = Serial.read();

    if (c != endMarker) {
      // Only save the printable characters, if there's room
      if ((' ' <= c) and (count < MAX_CHARS-1)) {
        receivedChars[ count++ ] = c;
      }
    } else {
      //  It's the end marker, line is completely received
      receivedChars[count] = '\0'; // terminate the string
      count       = 0;    // reset for next time
      ready       = true;
      break;
    }
  }

  return ready;

} // lineReady

This will keep the display in perfect sync with the GPS atomic clock. Well, within a few milliseconds, anyway. :wink: It also eliminates any flicker you may have been seeing.

NeoGPS is smaller, faster, more reliable and more accurate than all other libraries. In this case,

The original sketch uses 12132 bytes of program space and 1200 bytes of RAM.
The NeoGPS version uses 9016 bytes of program space and 659 bytes of RAM, a significant savings.

It's available from the Arduino Library Manager, under the menu Sketch-> Include Library-> Manage Libraries.

Cheers,
/dev