TinyGPSPlus icon indicating copy to clipboard operation
TinyGPSPlus copied to clipboard

Problem parsing HDOP, satellites number and altitude

Open ghost opened this issue 1 year ago • 12 comments

Hi,

I've got a problem with the library. For some reason, I get back too high HDOP (Horizontal Dilution of Precision), satellites number and altitude.

The input is: $GPGGA,110641.00,5126.37428,N,00003.02175,E,1,07,1.02,58.8,M,45.4,M,,*63 where: 07 – number of satellites being tracked 1.02 - Horizontal dilution of position 58.8,M - Altitude, in meters above the sea level 45.4,M - Height of geoid (mean sea level) above WGS84 ellipsoid

Outputs on Arduino serial are: 11:06:42 UTC 22/07/2024 Latitude = 51.439590N Longitude = 0.050383E COG = 0.0 SOG = 1.86 MPH = 2.14 KMPH = 3.44 Altitude in meters = 0.00 Altitude in feet = 0.00 Number of satellites in use = 7 HDOP = 354

Any thoughts?

ghost avatar Jul 22 '24 14:07 ghost

Which (example) code do you use?

TD-er avatar Jul 22 '24 15:07 TD-er

This is a bare minimum code:

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup() {
  Serial.begin(9600);
  ss.begin(GPSBaud);
  lcd.init();
  lcd.backlight();
  lcd.clear();
}

void loop() {
  while (ss.available() > 0) {
    gps.encode(ss.read());
    if (gps.location.isUpdated()) {

      Serial.print("HDOP: ");
      Serial.println(gps.hdop.value());
      Serial.print("Satellites: ");
      Serial.println(gps.satellites.value());
      Serial.print("Altitude: ");
      Serial.println(gps.altitude.meters());

      lcd.setCursor(0, 0);
      lcd.print("HDOP: ");
      lcd.print(gps.hdop.value());
      lcd.setCursor(0, 1);
      lcd.print("Satellites: ");
      lcd.print(gps.satellites.value());
      lcd.setCursor(0, 2);
      lcd.print("Altitude: ");
      lcd.print(gps.altitude.meters());
    }
  }
}

And a few images with setup and output from the serial port: GP__5386 GP__5389 GP__5395

ghost avatar Jul 22 '24 18:07 ghost

You need to divide the HDOP by 100.0f I also use altitude.meters(), but this does return a double So you might want to try altitude.value()/100.0f so you get the value as a float.

TD-er avatar Jul 22 '24 21:07 TD-er

The HDOP class has a member hdop() that does the division for you, if that helps. Try

    lcd.print(gps.hdop.hdop());

mikalhart avatar Jul 22 '24 21:07 mikalhart

@TD-er Thanks. I will try altitude.value()/100.0f There are two altitude values as an output from the GPS module - 58.2m and 45.4m. Which one comes from gps.altitude.meters() Below there is an example for data parsing, also screenshot attached from my terminal. In my case it should be: satellites number - 6, HDOP - 1.90 and altitudes are 58.2m and 45.4m.

$GPGGA,110617.00,41XX.XXXXX,N,00831.54761,W,1,05,2.68,129.0,M,50.1,M,,*42

110617 – represents the time at which the fix location was taken, 11:06:17 UTC 41XX.XXXXX,N – latitude 41 deg XX.XXXXX’ N 00831.54761,W – Longitude 008 deg 31.54761′ W 1 – fix quality (0 = invalid; 1= GPS fix; 2 = DGPS fix; 3 = PPS fix; 4 = Real Time Kinematic; 5 = Float RTK; 6 = estimated (dead reckoning); 7 = Manual input mode; 8 = Simulation mode) 05 – number of satellites being tracked 2.68 – Horizontal dilution of position 129.0, M – Altitude, in meters above the sea level 50.1, M – Height of geoid (mean sea level) above WGS84 ellipsoid empty field – time in seconds since last DGPS update empty field – DGPS station ID number *42 – the checksum data, always begins with *

@mikalhart Thanks, I will try today and let you know if it works.

Screenshot 2024-07-23 085927

ghost avatar Jul 23 '24 08:07 ghost

50.1, M – Height of geoid (mean sea level) above WGS84 ellipsoid

Just the first hit on DuckDuckGo when searching for "GGA nmea message": https://receiverhelp.trimble.com/alloy-gnss/en-us/NMEA-0183messages_GGA.html

Fields 11 & 12:

11 | Geoid separation 12 | M: geoid separation measured in meters

Since I had no idea what this is, I searched for it and found this: https://gis.stackexchange.com/a/174116 And to be honest, I still don't think I fully understand what use it has. Maybe it can be used to improve altitude calculations by applying some other model of the curvature of the earth???

TD-er avatar Jul 23 '24 08:07 TD-er

You need to divide the HDOP by 100.0f I also use altitude.meters(), but this does return a double So you might want to try altitude.value()/100.0f so you get the value as a float.

Unfortunately, it doesn't help.

ghost avatar Jul 24 '24 05:07 ghost

The HDOP class has a member hdop() that does the division for you, if that helps. Try

    lcd.print(gps.hdop.hdop());

Also, this doesn't work as well

ghost avatar Jul 24 '24 05:07 ghost

An updated code is:

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>

static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup() {
  Serial.begin(9600);
  ss.begin(GPSBaud);
  lcd.init();
  lcd.backlight();
  lcd.clear();
}

void loop() {
  while (ss.available() > 0) {
    gps.encode(ss.read());
    if (gps.location.isUpdated()) {
      Serial.print("HDOP: ");
      // Serial.println(gps.hdop.value());
      Serial.println(gps.hdop.hdop());      //HDOP has a member hdop() - updated 23/07/2024
      Serial.print("Satellites: ");
      Serial.println(gps.satellites.value());
      Serial.print("Altitude: ");
      // Serial.println(gps.altitude.meters());
      Serial.println(gps.altitude.value() / 100.0f);      //updated 23/07/2024

      lcd.setCursor(0, 0);
      lcd.print("HDOP: ");
      // lcd.print(gps.hdop.value());
      lcd.print(gps.hdop.hdop());         //HDOP has a member hdop() - updated 23/07/2024
      lcd.setCursor(0, 1);
      lcd.print("Satellites: ");
      lcd.print(gps.satellites.value());
      lcd.setCursor(0, 2);
      lcd.print("Altitude: ");
      // lcd.print(gps.altitude.meters());
      lcd.print(gps.altitude.value() / 100.0f);     //updated 23/07/2024
    }
  }
}

Input from GPS module: $GPRMC,054347.00,A,5126.37255,N,00003.01659,E,0.230,,240724,,,A79 $GPVTG,,T,,M,0.230,N,0.426,K,A22 $GPGGA,054347.00,5126.37255,N,00003.01659,E,1,06,1.96,68.3,M,45.4,M,,63 $GPGSA,A,3,31,23,05,18,26,16,,,,,,,3.02,1.96,2.2908 $GPGSV,3,1,12,01,50,155,,05,05,023,15,07,11,329,,08,17,274,78 $GPGSV,3,2,12,10,13,154,18,16,75,262,20,18,52,062,31,23,32,124,207D $GPGSV,3,3,12,26,54,169,31,27,50,277,23,29,04,085,,31,11,202,1273 $GPGLL,5126.37255,N,00003.01659,E,054347.00,A,A66

Output from Arduino: HDOP: 0.00 Satellites: 0 Altitude: 0.00

ghost avatar Jul 24 '24 05:07 ghost

Can you wrap your code in 3 backticks (each on a separate line) so it is better readable? And if you really want to do it fancy, add c++ right after the first 3 backticks :)

TD-er avatar Jul 24 '24 06:07 TD-er

I have been using this library on my test instruments for years. I may have missed why you are having issues. Try lcd.print(" HDOP " + String(gps.hdop.value())); This will print out the GPS side (I know this works) Do the division later, once you know the initial value is working

number of sats lcd.print("Sat # " + String(gps.satellites.value()));

Like NASA and startrek, altitude is in metres.

What is the GPS model what settings do you have for the GPS. IE, sea, Air, pedestrian, mobile.... GPS unit have configuration setting that affects the NMEA output. IE, I use the Sea setting, pedestrian or air, depending what testing i am performing.

Great idea for the terminal. I will have to try that

svdrummer avatar Jul 24 '24 06:07 svdrummer

I have been using this library on my test instruments for years. I may have missed why you are having issues. Try lcd.print(" HDOP " + String(gps.hdop.value())); This will print out the GPS side (I know this works) Do the division later, once you know the initial value is working

number of sats lcd.print("Sat # " + String(gps.satellites.value()));

Like NASA and startrek, altitude is in metres.

What is the GPS model what settings do you have for the GPS. IE, sea, Air, pedestrian, mobile.... GPS unit have configuration setting that affects the NMEA output. IE, I use the Sea setting, pedestrian or air, depending what testing i am performing.

Great idea for the terminal. I will have to try that

I tried using the setup yesterday, but it doesn't seem to be working as expected. It appears that the data from the Arduino doesn't match the raw data from the GPS module for HDOP, the number of satellites, and altitude. It looks like there is a bug in the TinyGPS++ library. The GPS module I'm using is the GY-NEO6MV2. 1721905123201 1721905123223

ghost avatar Jul 25 '24 11:07 ghost

How did this go in the end? Baud rate/comms issue?

svdrummer avatar Apr 06 '25 01:04 svdrummer

Same problem here with NEO6M module using the latest version 1.1.0.

UPDATE: Reflashed it and now seems to work correctly.

sakisdog avatar May 03 '25 15:05 sakisdog