GPS speedometer with NEO 6M - latency issue

I have built a speedometer, based on this youtube video: Arduino GPS Speedometer with Analog Gauge - YouTube

The speedometer is for a car, so it needs to be in real-time and accurate, with the actual speed that the car reads. The speedometer is built with a NEO-6m GPS module with an antenna. It is hooked up to an Arduino Nano and an OLED 0.96".

This is the code and wiring diagram. The code is the same as the video and uses TinyGps library. But simplified to just show me the current speed(kmh). I have removed every other line of code, to reduce latency.

#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

#include <SoftwareSerial.h>
#define rxPin 2
#define txPin 3 //unused
SoftwareSerial neogps(rxPin,txPin);



#include <TinyGPS++.h> //1.0.3
TinyGPSPlus gps;
//---------------------------------------------------------------------------
int x_max    = 128;       //OLED display width, in pixels
int y_max    = 62;        //OLED display width, in pixels
int x_center = x_max/2;
int y_center = y_max/2+10;
int speed;
int adjspeed;// Adjusted speed for oversetimation by car
int num_sat;

//satellite logo
#define sat_logo_width 20
#define sat_logo_height 20

const unsigned char sat_logo[] = {
  0x00, 0x01, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x60, 0x30, 0x00,
  0x60, 0x78, 0x00, 0xc0, 0xfc, 0x00, 0x00, 0xfe, 0x01, 0x00, 0xff, 0x01,
  0x80, 0xff, 0x00, 0xc0, 0x7f, 0x06, 0xc0, 0x3f, 0x06, 0x80, 0x1f, 0x0c,
  0x80, 0x4f, 0x06, 0x19, 0xc6, 0x03, 0x1b, 0x80, 0x01, 0x73, 0x00, 0x00,
  0x66, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x70, 0x00, 0x00
};
//---------------------------------------------------------------------------

//Program variables
double lat;
double lng;



void gauge() {


  //TOP LEFT: draw satellite logo and number of satellites
  u8g.drawXBM(0, 0, sat_logo_width, sat_logo_height, sat_logo);
  u8g.setPrintPos(18, 5);
  u8g.print(num_sat, 5);
 
  
  //---------------------------------------------------------------------------
  // Show Speed and align its position
  u8g.setFont(u8g_font_profont22);
  u8g.setPrintPos(54,60);
  
  if (adjspeed>99) {                                  
    u8g.setPrintPos(47,60);
  }
  
  u8g.print(adjspeed);
  //---------------------------------------------------------------------------
}



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

  neogps.begin(9600);
  
  u8g.setFont(u8g_font_chikita);
  u8g.setColorIndex(1);
}


void loop(void){
 
  Read_GPS();
  
  //Display Data on Oled
  {
    u8g.firstPage(); 
    do {             
      gauge();
    }
    while( u8g.nextPage() );
  }
  
}




void Read_GPS(){

  boolean newData = false;
 
for (unsigned long start = millis(); millis() - start < 100;)
  {
    while (neogps.available())
    {
      if (gps.encode(neogps.read()))
      {
        newData = true;
        break;
      }
    }
  }


  //If newData is true
  if(newData == true){
    newData = false;
    Get_GPS();
  }
  else { 
    //no data
  }
}


void Get_GPS(){
  num_sat = gps.satellites.value();

  if (gps.location.isValid() == 1) {
    speed = gps.speed.kmph();
    adjspeed = 1.03*speed; // the speed is adjusted(increaed) to match the speed that the actuall car outputs. (Because there is a law stating that cars need to overestimate the actual speed by a little bit
    Serial.print("Speed: ");
    Serial.println(adjspeed);
    
  
   
  }
}

The speedometer is accurate and shows the right speed, but there is a latency of around 1-2 seconds. For example, if the car starts accelerating from 0, the OLED shows the speed 1-2 seconds later, the same with when the car breaks. I need the latency, to be at least less than a second.

I'm a bit of a beginner and not sure how to reduce this latency. I was hoping for someone here to explain to me how I can reduce this latency

You could reduce the amount you draw, and increase the Serial line speed.
What is the update rate from the GPS?

may be something like this without second guessing when data is available from the GPS and updating the display only when needed (ie when you got a new fix - ideally you could also check if the information has changed)

#include "U8glib.h"
#include <SoftwareSerial.h>
#include <TinyGPS++.h> //1.0.3

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);

#define rxPin 2
#define txPin 3 //unused
SoftwareSerial neogps(rxPin, txPin);
TinyGPSPlus gps;

//---------------------------------------------------------------------------
//satellite logo
#define sat_logo_width 20
#define sat_logo_height 20

const unsigned char sat_logo[] = {
  0x00, 0x01, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x60, 0x30, 0x00,
  0x60, 0x78, 0x00, 0xc0, 0xfc, 0x00, 0x00, 0xfe, 0x01, 0x00, 0xff, 0x01,
  0x80, 0xff, 0x00, 0xc0, 0x7f, 0x06, 0xc0, 0x3f, 0x06, 0x80, 0x1f, 0x0c,
  0x80, 0x4f, 0x06, 0x19, 0xc6, 0x03, 0x1b, 0x80, 0x01, 0x73, 0x00, 0x00,
  0x66, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x70, 0x00, 0x00
};
//---------------------------------------------------------------------------

//Program variables
double lat, lng;
int adjspeed;// Adjusted speed for oversetimation by car
int num_sat;

void gauge() {
  //TOP LEFT: draw satellite logo and number of satellites
  u8g.drawXBM(0, 0, sat_logo_width, sat_logo_height, sat_logo);
  u8g.setFont(u8g_font_chikita);
  u8g.setPrintPos(18, 5);
  u8g.print(num_sat, 5);

  // Show Speed and align its position
  u8g.setFont(u8g_font_profont22);
  if (adjspeed > 99) u8g.setPrintPos(47, 60);
  else u8g.setPrintPos(54, 60);
  u8g.print(adjspeed);
}

void setup(void) {
  Serial.begin(115200);
  neogps.begin(9600);
  u8g.setColorIndex(1);
}

void loop(void) {
  if (neogps.available()) {
    if (gps.encode(neogps.read())) {
      if (gps.location.isValid()) {
        num_sat = gps.satellites.value();
        adjspeed = 1.03 * gps.speed.kmph(); // the speed is adjusted(increaed) to match the speed that the actuall car outputs. (Because there is a law stating that cars need to overestimate the actual speed by a little bit
        u8g.firstPage();
        do {gauge();} while ( u8g.nextPage() );
      }
    }
  }
}

typed here based on your code, so fully untested

1 Like

I'm pretty sure the update rate of the NEO-6M GPS is 1Hz per second. But after some research online, it has the potential to do 5hz per second, but not sure how to do this. According to the internet it may sometimes miss a second worth of data, due to not fully gathering enough data, so it skips that cycle and waits for the next complete data cycle

it would require sending a configuration code to your gps

for the time being, just listen to the data when it's available and when a fix is ready to be used, use it

if you find how to change the update rate then the code will continue working

To reduce latency of a standard setup you would need to;

Increase the GPS baud rate.

Change the update rate to the maximum, 5Hz.

Turn off all the NMEA sentences that the GPS library does not need to read the speed.

Details on how to do this will be in the GPS datasheet.

There is a video:
https://www.youtube.com/watch?v=Ao5XRtd-RAA showing you how to change the update rate from the default value of 1Hz to the maximum of 5Hz.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.