Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit 97467fd

Browse files
authored
Merge pull request #19 from RollieRowland/master
Added functionality for reading from the High Precision Geodetic Posi…
2 parents 3aeb6b5 + 63fb62e commit 97467fd

File tree

4 files changed

+336
-10
lines changed

4 files changed

+336
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
Get the high precision geodetic solution for latituude and longitude
3+
By: Nathan Seidle
4+
Modified by: Steven Rowland
5+
SparkFun Electronics
6+
Date: January 3rd, 2019
7+
License: MIT. See license file for more information but you can
8+
basically do whatever you want with this code.
9+
10+
This example shows how to inspect the accuracy of the high-precision
11+
positional solution.
12+
13+
Feel like supporting open source hardware?
14+
Buy a board from SparkFun!
15+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
16+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
17+
SAM-M8Q: https://www.sparkfun.com/products/15106
18+
19+
Hardware Connections:
20+
Plug a Qwiic cable into the GPS and a BlackBoard
21+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
22+
Open the serial monitor at 115200 baud to see the output
23+
*/
24+
25+
#include <Wire.h> //Needed for I2C to GPS
26+
27+
#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
28+
SFE_UBLOX_GPS myGPS;
29+
30+
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to Ublox module.
31+
32+
void setup()
33+
{
34+
Serial.begin(115200);
35+
while (!Serial); //Wait for user to open terminal
36+
37+
Wire.begin();
38+
39+
if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
40+
{
41+
Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
42+
while (1);
43+
}
44+
45+
//myGPS.enableDebugging(Serial);
46+
47+
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
48+
myGPS.setNavigationFrequency(20); //Set output to 20 times a second
49+
50+
byte rate = myGPS.getNavigationFrequency(); //Get the update rate of this module
51+
Serial.print("Current update rate:");
52+
Serial.println(rate);
53+
54+
myGPS.saveConfiguration(); //Save the current settings to flash and BBR
55+
}
56+
57+
void loop()
58+
{
59+
//Query module only every second. Doing it more often will just cause I2C traffic.
60+
//The module only responds when a new position is available
61+
if (millis() - lastTime > 1000)
62+
{
63+
lastTime = millis(); //Update the timer
64+
Serial.print("HP Lat: ");
65+
int32_t latitude = myGPS.getHighResLatitude();
66+
Serial.print(latitude);
67+
Serial.print(", HP Lon: ");
68+
69+
int32_t longitude = myGPS.getHighResLongitude();
70+
Serial.print(longitude);
71+
Serial.print(", Accuracy: ");
72+
73+
uint32_t accuracy = myGPS.getHorizontalAccuracy();
74+
Serial.println(accuracy);
75+
}
76+
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
Get the high precision geodetic solution
3+
By: Nathan Seidle
4+
Modified by: Steven Rowland
5+
SparkFun Electronics
6+
Date: January 3rd, 2019
7+
License: MIT. See license file for more information but you can
8+
basically do whatever you want with this code.
9+
10+
This example shows how to inspect the accuracy of the high-precision
11+
positional solution.
12+
13+
Feel like supporting open source hardware?
14+
Buy a board from SparkFun!
15+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
16+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
17+
SAM-M8Q: https://www.sparkfun.com/products/15106
18+
19+
Hardware Connections:
20+
Plug a Qwiic cable into the GPS and a BlackBoard
21+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
22+
Open the serial monitor at 115200 baud to see the output
23+
*/
24+
25+
#include <Wire.h> //Needed for I2C to GPS
26+
27+
#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
28+
SFE_UBLOX_GPS myGPS;
29+
30+
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to Ublox module.
31+
32+
void setup()
33+
{
34+
Serial.begin(115200);
35+
while (!Serial); //Wait for user to open terminal
36+
37+
Wire.begin();
38+
39+
if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
40+
{
41+
Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
42+
while (1);
43+
}
44+
45+
//myGPS.enableDebugging(Serial);
46+
47+
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
48+
myGPS.setNavigationFrequency(20); //Set output to 20 times a second
49+
50+
byte rate = myGPS.getNavigationFrequency(); //Get the update rate of this module
51+
Serial.print("Current update rate:");
52+
Serial.println(rate);
53+
54+
myGPS.saveConfiguration(); //Save the current settings to flash and BBR
55+
}
56+
57+
void loop()
58+
{
59+
//Query module only every second. Doing it more often will just cause I2C traffic.
60+
//The module only responds when a new position is available
61+
if (millis() - lastTime > 1000)
62+
{
63+
lastTime = millis(); //Update the timer
64+
Serial.print("HP Lat: ");
65+
int32_t latitude = myGPS.getHighResLatitude();
66+
Serial.print(latitude);
67+
Serial.print(", HP Lon: ");
68+
69+
int32_t longitude = myGPS.getHighResLongitude();
70+
Serial.print(longitude);
71+
Serial.print(", 2D Accuracy(MM): ");
72+
73+
uint32_t accuracy = myGPS.getHorizontalAccuracy();
74+
Serial.println(accuracy);
75+
Serial.print(", Vertical Accuracy(MM): ");
76+
77+
uint32_t verticalAccuracy = myGPS.getVerticalAccuracy();
78+
Serial.println(verticalAccuracy);
79+
Serial.print(", Elipsoid(MM): ");
80+
81+
int32_t elipsoid = myGPS.getElipsoid();
82+
Serial.println(elipsoid);
83+
Serial.print(", Mean Sea Level(MM): ");
84+
85+
int32_t meanSeaLevel = myGPS.getMeanSeaLevel();
86+
Serial.println(meanSeaLevel);
87+
Serial.print(", Geoid Separation(MM): ");
88+
89+
int32_t geoidSeparation = myGPS.getGeoidSeparation();
90+
Serial.println(geoidSeparation);
91+
Serial.print(", Time of Week(Millis): ");
92+
93+
uint32_t timeOfWeek = myGPS.getTimeOfWeek();
94+
Serial.println(timeOfWeek);
95+
Serial.print(",");
96+
97+
}
98+
99+
}

src/SparkFun_Ublox_Arduino_Library.cpp

+120-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@
1717
Development environment specifics:
1818
Arduino IDE 1.8.5
1919
20+
Modified by David Mann @ Loggerhead Instruments, 16 April 2019
21+
- Added support for parsing date and time
22+
- Added functions getYear(), getMonth(), getDay(), getHour(), getMinute(), getSecond()
23+
24+
Modified by Steven Rowland, June 11th, 2019
25+
- Added functionality for reading HPPOSLLH (High Precision Geodetic Position)
26+
- Added getTimeOfWeek(), getHighResLatitude(). getHighResLongitude(), getElipsoid(),
27+
getMeanSeaLevel(), getHorizontalAccuracy(), getVerticalAccuracy(), getHPPOSLLH()
28+
- Modified ProcessUBXPacket to parse HPPOSLLH packet
29+
- Added query staleness verification for HPPOSLLH data
30+
2031
This program is distributed in the hope that it will be useful,
2132
but WITHOUT ANY WARRANTY; without even the implied warranty of
2233
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -541,6 +552,38 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg)
541552
moduleQueried.headingOfMotion = true;
542553
moduleQueried.pDOP = true;
543554
}
555+
else if (msg->id == UBX_NAV_HPPOSLLH && msg->len == 36){
556+
timeOfWeek = extractLong(4);
557+
highResLatitude = extractLong(8);
558+
highResLongitude = extractLong(12);
559+
elipsoid = extractLong(16);
560+
meanSeaLevel = extractLong(20);
561+
geoidSeparation = extractLong(24);
562+
horizontalAccuracy = extractLong(28);
563+
verticalAccuracy = extractLong(32);
564+
565+
highResModuleQueried.all = true;
566+
highResModuleQueried.timeOfWeek = true;
567+
highResModuleQueried.highResLatitude = true;
568+
highResModuleQueried.highResLongitude = true;
569+
highResModuleQueried.elipsoid = true;
570+
highResModuleQueried.meanSeaLevel = true;
571+
highResModuleQueried.geoidSeparation = true;
572+
highResModuleQueried.horizontalAccuracy = true;
573+
highResModuleQueried.verticalAccuracy = true;
574+
575+
if (_printDebug == true)
576+
{
577+
Serial.print("Sec: "); Serial.print(((float)extractLong(4)) / 1000.0f); Serial.print(" ");
578+
Serial.print("LON: "); Serial.print(((float)(int32_t)extractLong(8)) / 10000000.0f); Serial.print(" ");
579+
Serial.print("LAT: "); Serial.print(((float)(int32_t)extractLong(12)) / 10000000.0f); Serial.print(" ");
580+
Serial.print("ELI M: "); Serial.print(((float)(int32_t)extractLong(16)) / 1000.0f); Serial.print(" ");
581+
Serial.print("MSL M: "); Serial.print(((float)(int32_t)extractLong(20)) / 1000.0f); Serial.print(" ");
582+
Serial.print("GEO: "); Serial.print(((float)(int32_t)extractLong(24))/ 1000.0f); Serial.print(" ");
583+
Serial.print("HA 2D M: "); Serial.print(((float)extractLong(28)) / 1000.0f); Serial.print(" ");
584+
Serial.print("VERT M: "); Serial.print(((float)extractLong(32)) / 1000.0f); Serial.print(" ");
585+
}
586+
}
544587
break;
545588
}
546589
}
@@ -721,8 +764,8 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet)
721764
_debugSerial->print(" ID:");
722765
_debugSerial->print(packet->id, HEX);
723766

724-
//_debugSerial->print(" Len: 0x");
725-
//_debugSerial->print(packet->len, HEX);
767+
_debugSerial->print(" Len: 0x");
768+
_debugSerial->print(packet->len, HEX);
726769

727770
_debugSerial->print(" Payload:");
728771

@@ -1197,19 +1240,19 @@ boolean SFE_UBLOX_GPS::setAutoPVT(boolean enable, uint16_t maxWait)
11971240
uint32_t SFE_UBLOX_GPS::extractLong(uint8_t spotToStart)
11981241
{
11991242
uint32_t val = 0;
1200-
val |= (int32_t)payloadCfg[spotToStart + 0] << 8 * 0;
1201-
val |= (int32_t)payloadCfg[spotToStart + 1] << 8 * 1;
1202-
val |= (int32_t)payloadCfg[spotToStart + 2] << 8 * 2;
1203-
val |= (int32_t)payloadCfg[spotToStart + 3] << 8 * 3;
1243+
val |= (uint32_t)payloadCfg[spotToStart + 0] << 8 * 0;
1244+
val |= (uint32_t)payloadCfg[spotToStart + 1] << 8 * 1;
1245+
val |= (uint32_t)payloadCfg[spotToStart + 2] << 8 * 2;
1246+
val |= (uint32_t)payloadCfg[spotToStart + 3] << 8 * 3;
12041247
return (val);
12051248
}
12061249

12071250
//Given a spot in the payload array, extract two bytes and build an int
12081251
uint16_t SFE_UBLOX_GPS::extractInt(uint8_t spotToStart)
12091252
{
12101253
uint16_t val = 0;
1211-
val |= (int16_t)payloadCfg[spotToStart + 0] << 8 * 0;
1212-
val |= (int16_t)payloadCfg[spotToStart + 1] << 8 * 1;
1254+
val |= (uint16_t)payloadCfg[spotToStart + 0] << 8 * 0;
1255+
val |= (uint16_t)payloadCfg[spotToStart + 1] << 8 * 1;
12131256
return (val);
12141257
}
12151258

@@ -1296,6 +1339,74 @@ boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait)
12961339
}
12971340
}
12981341

1342+
uint32_t SFE_UBLOX_GPS::getTimeOfWeek(uint16_t maxWait/* = 250*/){
1343+
if (highResModuleQueried.timeOfWeek == false)
1344+
getHPPOSLLH();
1345+
highResModuleQueried.timeOfWeek = false; //Since we are about to give this to user, mark this data as stale
1346+
return (timeOfWeek);
1347+
}
1348+
1349+
int32_t SFE_UBLOX_GPS::getHighResLatitude(uint16_t maxWait/* = 250*/){
1350+
if (highResModuleQueried.highResLatitude == false)
1351+
getHPPOSLLH();
1352+
highResModuleQueried.highResLatitude = false; //Since we are about to give this to user, mark this data as stale
1353+
return (highResLatitude);
1354+
}
1355+
1356+
int32_t SFE_UBLOX_GPS::getHighResLongitude(uint16_t maxWait/* = 250*/){
1357+
if (highResModuleQueried.highResLongitude == false)
1358+
getHPPOSLLH();
1359+
highResModuleQueried.highResLongitude = false; //Since we are about to give this to user, mark this data as stale
1360+
return (highResLongitude);
1361+
}
1362+
1363+
int32_t SFE_UBLOX_GPS::getElipsoid(uint16_t maxWait/* = 250*/){
1364+
if (highResModuleQueried.elipsoid == false)
1365+
getHPPOSLLH();
1366+
highResModuleQueried.elipsoid = false; //Since we are about to give this to user, mark this data as stale
1367+
return (elipsoid);
1368+
}
1369+
1370+
int32_t SFE_UBLOX_GPS::getMeanSeaLevel(uint16_t maxWait/* = 250*/){
1371+
if (highResModuleQueried.meanSeaLevel == false)
1372+
getHPPOSLLH();
1373+
highResModuleQueried.meanSeaLevel = false; //Since we are about to give this to user, mark this data as stale
1374+
return (meanSeaLevel);
1375+
}
1376+
1377+
int32_t SFE_UBLOX_GPS::getGeoidSeparation(uint16_t maxWait/* = 250*/){
1378+
if (highResModuleQueried.geoidSeparation == false)
1379+
getHPPOSLLH();
1380+
highResModuleQueried.geoidSeparation = false; //Since we are about to give this to user, mark this data as stale
1381+
return (geoidSeparation);
1382+
}
1383+
1384+
uint32_t SFE_UBLOX_GPS::getHorizontalAccuracy(uint16_t maxWait/* = 250*/){
1385+
if (highResModuleQueried.horizontalAccuracy == false)
1386+
getHPPOSLLH();
1387+
highResModuleQueried.horizontalAccuracy = false; //Since we are about to give this to user, mark this data as stale
1388+
return (horizontalAccuracy);
1389+
}
1390+
1391+
uint32_t SFE_UBLOX_GPS::getVerticalAccuracy(uint16_t maxWait/* = 250*/){
1392+
if (highResModuleQueried.verticalAccuracy == false)
1393+
getHPPOSLLH();
1394+
highResModuleQueried.verticalAccuracy = false; //Since we are about to give this to user, mark this data as stale
1395+
return (verticalAccuracy);
1396+
}
1397+
1398+
boolean SFE_UBLOX_GPS::getHPPOSLLH(uint16_t maxWait)
1399+
{
1400+
//The GPS is not automatically reporting navigation position so we have to poll explicitly
1401+
packetCfg.cls = UBX_CLASS_NAV;
1402+
packetCfg.id = UBX_NAV_HPPOSLLH;
1403+
packetCfg.len = 0;
1404+
1405+
return sendCommand(packetCfg, maxWait);
1406+
return (false); //If command send fails then bail
1407+
}
1408+
1409+
12991410
//Get the current 3D high precision positional accuracy - a fun thing to watch
13001411
//Returns a long representing the 3D accuracy in millimeters
13011412
uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait)
@@ -1557,4 +1668,4 @@ boolean SFE_UBLOX_GPS::getRELPOSNED(uint16_t maxWait)
15571668
relPosInfo.refObsMiss = flags & (1 << 7);
15581669

15591670
return (true);
1560-
}
1671+
}

0 commit comments

Comments
 (0)