Problem parsing HDOP, satellites number and altitude
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?
Which (example) code do you use?
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:
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.
The HDOP class has a member hdop() that does the division for you, if that helps. Try
lcd.print(gps.hdop.hdop());
@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.
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???
You need to divide the HDOP by 100.0f I also use altitude.meters(), but this does return a
doubleSo you might want to tryaltitude.value()/100.0fso you get the value as a float.
Unfortunately, it doesn't help.
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
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
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 :)
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 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.
How did this go in the end? Baud rate/comms issue?
Same problem here with NEO6M module using the latest version 1.1.0.
UPDATE: Reflashed it and now seems to work correctly.