Faster update rate with GPS and TinyGPS++ library (With “distance to” function)

Hello Arduino friends,

First of all: Happy New Year

I want to make a puzzle with RFID-Tags and a GPS Module, the goal: if you scan a tag, you’ll get directed to a location that belongs to that certain tag. So I started making a sketch, but I ran into one big problem: the update rate refreshes random (sometimes 2 seconds; sometimes even up to 30 seconds), that is way to slow. Does someone know how to get a faster update rate (with the ‘‘distance to’’ function)? To test the GPS-Module itself I ran another sketch, which worked perfectly. So the GPS-Module itself isn’t the problem. To eliminate that the issue is related with a problem of updating the display itself, I checked it with printing to the serial monitor in parallel: same random update rate is seen in here, so it has nothing to do with the display itself. So I think it has something to do with the TinyGPS++ library itself.
Someone who can help me out ???

Arduino: Arduino Nano
GPS: Ublox NEO M6N
RFID- Scanner: MFRC-522

PS: My sketch is not the cleanest: I’m a beginner.

#include <U8glib.h>
#include "TinyGPS++.h"
#include "SoftwareSerial.h"
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
SoftwareSerial serial_connection(3, 4); //RX=pin 3, TX=pin 4
TinyGPSPlus gps;//This is the GPS object that will pretty much do all the grunt work with the NMEA data
double lattogo;
double lngtogo;
double distanceMtowaypoint;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);//This opens up communications to the Serial monitor in the Arduino IDE
  serial_connection.begin(9600);//This opens up communications to the GPS
  SPI.begin();          // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
}

void loop() {
Serial.println(distanceMtowaypoint);

 
while(serial_connection.available())//While there are characters to come from the GPS
  {
    gps.encode(serial_connection.read());//This feeds the serial NMEA data into the library one char at a time
   
  }
 distanceMtowaypoint = gps.distanceBetween(gps.location.lat(), gps.location.lng(), lattogo, lngtogo);
 
  u8g.firstPage();
  do {
    u8g.setPrintPos(0,25);
    u8g.setFont(u8g_font_helvR24r);
    u8g.print(distanceMtowaypoint,0);
    u8g.drawLine(0,28,128,28);
    u8g.setPrintPos(85,25);
    u8g.setFont(u8g_font_unifont);
    u8g.print("Meter");
  }
  while ( u8g.nextPage() );

  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
 

  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }

  content.toUpperCase();
  
  Serial.println(content.substring(1));
  //Waypoint 1
  if (content.substring(1) == "6A FF 4F 19"){ // if this tag is scanned set waypoint 1 as destination
     lattogo = 51.432535;
    lngtogo = 4.358682;
  }
//Waypoint 2
  if (content.substring(1) == "87 BD 6E 60"){// if this tag is scanned set waypoint 2 as destination
    lattogo = 51.435717;
    lngtogo = 4.359201;
  }
//Waypoint 3
  if (content.substring(1) == "F7 88 80 52"){// if this tag is scanned set waypoint 3 as destination
    lattogo = 51.436540;
    lngtogo =  4.360675;
  }
  //Waypoint 4
  if (content.substring(1) == "1A 92 C3 25"){// if this tag is scanned set waypoint 4 as destination
    lattogo = 51.437216;
    lngtogo = 4.361009;
  }
  //Waypoint 5
  if (content.substring(1) == "9A 74 C8 25"){// if this tag is scanned set waypoint 5 as destination
    lattogo = 51.438385;
    lngtogo = 4.359228;
  }
  //Waypoint 6
  if (content.substring(1) == "09 02 3B A3"){// if this tag is scanned set waypoint 6 as destination
    lattogo = 51.439223;
    lngtogo = 4.359963;
  }
  //Waypoint 7
  if (content.substring(1) == "27 E3 6D 60"){// if this tag is scanned set waypoint 7 as destination
    lattogo = 51.440121; 
    lngtogo = 4.361162;
  }
  //Waypoint 8
  if (content.substring(1) == "87 F5 6D 60"){// if this tag is scanned set waypoint 8 as destination
    lattogo = 51.437077;
    lngtogo = 4.361624;
  }
  //Waypoint 9
  if (content.substring(1) == "3A 9A C3 25"){ // if this tag is scanned set waypoint 9 as destination
    lattogo = 51.435418;
    lngtogo = 4.360607;
  }
  //Waypoint 10
  if (content.substring(1) == "49 1D B4 A3"){ // if this tag is scanned set waypoint 10 as destination
    lattogo = 51.432001;
    lngtogo = 4.356934;
  }
 

  
}

Well first you want to check the pins your reading the GPS on;

SoftwareSerial serial_connection(0, 1); //RX=pin 10, TX=pin 11

I’ve changed it, and tried it again. But still the slow update rate

Your code does not reflect how a GPS works, every time the serial buffer from the GPS is empty, which might be often, you calculate the distance and direction, update the display etc. Which is rather a waste of time if there is no updated fix information to display. You could also miss characters coming from the GPS, so there will be no updated fix.

Try this program, it displays whats coming from the GPS on the serial monitor, waits till there is a fix and prints the results to serial monitor. You should get an updated fix around once a second. Adjust the GPS pins to suit your setup.

/*******************************************************************************************************
  LoRaTracker Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19

  http://www.LoRaTracker.uk

  This program is supplied as is, it is up to the user of the program to decide if the program is
  suitable for the intended purpose and free from errors.
*******************************************************************************************************/

/*******************************************************************************************************
  Program Operation -  This program is a GPS checker. At startup the program starts checking the data
  coming from the GPS for a valid fix. The GPS data is printed to the Serial monitor. When the program
  detects that the GPS has a fix, it prints the GPS fix time, Latitude, Longitude, Altitude, Number of
  satellites in use and the HDOP value to the Serial monitor.

  Serial monitor baud rate is set at 115200, GPS baud rate to 9600.
*******************************************************************************************************/

#include <Arduino.h>

#include <TinyGPS++.h>                            //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps;                                  //create the TinyGPS++ object

#define RXpin A3                                  //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin A2                                  //pin number for GPS TX output from Arduino- RX into GPS

#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, TXpin);

float GPSLat;                                     //Latitude from GPS
float GPSLon;                                     //Longitude from GPS
float GPSAlt;                                     //Altitude from GPS
uint8_t GPSSats;                                  //number of GPS satellites in use
uint32_t GPSHdop;                                 //HDOP from GPS
uint32_t GPSstarttimemS;                          //time in mS when GPS is scanned fo fix
uint32_t GPSendtimemS;                            //time in mS when GPS got a fix


void loop()
{
  gpsWaitFix();
  displayGPSfix();
}


void gpsWaitFix()
{
  //waits till the GPS gets an updated fix

  uint8_t GPSchar;

  Serial.println(F("Wait for updated GPS Fix"));
  GPSstarttimemS = millis();

  while (1)
  {
    if (GPSserial.available() > 0)
    {
      GPSchar = GPSserial.read();
      gps.encode(GPSchar);
      Serial.write(GPSchar);
    }

    if (gps.location.isUpdated() && gps.altitude.isUpdated())
    {
      GPSendtimemS = millis();
      break;
    }
  }
}


void displayGPSfix()
{
  float tempfloat;

  Serial.println();
  Serial.println();
  Serial.print(F("New GPS Fix "));
  Serial.print(GPSendtimemS - GPSstarttimemS);
  Serial.print(F("mS  "));

  GPSLat = gps.location.lat();
  GPSLon = gps.location.lng();
  GPSAlt = gps.altitude.meters();
  GPSSats = gps.satellites.value();
  GPSHdop = gps.hdop.value();
  tempfloat = ( (float) GPSHdop / 100);

  Serial.print(F("Lat,"));
  Serial.print(GPSLat, 6);
  Serial.print(F(",Lon,"));
  Serial.print(GPSLon, 6);
  Serial.print(F(",Alt,"));
  Serial.print(GPSAlt, 1);
  Serial.print(F("m,Sats,"));
  Serial.print(GPSSats);
  Serial.print(F(",HDOP,"));
  Serial.print(tempfloat, 2);

  Serial.println();
  Serial.println();
}


void setup()
{
  GPSserial.begin(9600);

  Serial.begin(115200);

  Serial.println(F("GPS_Checker Starting"));
  Serial.println();
}

Many thanks :slight_smile: .
It works, so thank you so much for taking your time to help me.

Greetings from the Netherlands
Arjan

arjanpals:
Many thanks :slight_smile: .
It works, so thank you so much for taking your time to help me.

Greetings from the Netherlands
Arjan

Glad to hear it.

Each character from the GPS @ 9600 baud, is around 100us long. The softserial buffer is 64 bytes long by default.

So if your program does not read from the GPS for around 6.4mS, you can miss a character. Miss a character and the sentence in progress is garbage, maybe no updated fix.

So most often its best to put the program in a tight loop, feeding characters into the GPS encode function until a updated fix arrives, then you can go off and do stuff.

Of course when you have finished 'doing stuff' and go back to reading the GPS again you might have missed a sentence or two, but the program should pick up the next set, and provide and updated fix, within a second or so.

For a fully updated fix (location and altitude) TinyGPS needs to read new versions of the GPGGA and GPRMC sentences.