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

Commit 9803472

Browse files
committed
Now parsing PVT with global lat/lat/siv/alt/etc.
1 parent e050707 commit 9803472

File tree

3 files changed

+186
-126
lines changed

3 files changed

+186
-126
lines changed

examples/Example3_GetPosition/Example3_GetPosition.ino

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,51 @@ void setup()
4343
while (1);
4444
}
4545

46-
//Wire.setClock(400000); //Increase I2C clock speed to 400kHz
46+
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
4747

48-
//long pos = myGPS.getPositionAccuracy(2000);
49-
//Serial.print("pos: ");
50-
//Serial.println(pos);
48+
/*long pos = myGPS.getPositionAccuracy();
49+
Serial.print("pos: ");
50+
Serial.println(pos);
51+
52+
byte version = myGPS.getProtocolVersionHigh();
53+
Serial.print("version: ");
54+
Serial.println(version);*/
55+
56+
long latitude = myGPS.getLatitude(1000);
57+
Serial.print("Lat: ");
58+
Serial.print(latitude);
59+
60+
61+
long longitude = myGPS.getLongitude(2000);
62+
Serial.print(" Long: ");
63+
Serial.print(longitude);
64+
Serial.print(" (degrees * 10^-7)");
65+
66+
long altitude = myGPS.getAltitude();
67+
Serial.print(" Alt (above mean sea level): ");
68+
Serial.print(altitude);
69+
Serial.print(" (mm)");
70+
71+
byte SIV = myGPS.getSIV();
72+
Serial.print(" SIV: ");
73+
Serial.print(SIV);
74+
75+
byte fixType = myGPS.getFixType();
76+
Serial.print(" Fix: ");
77+
Serial.print(fixType);
78+
79+
byte RTK = myGPS.getCarrierSolutionType();
80+
Serial.print(" RTK: ");
81+
Serial.print(RTK);
82+
if(RTK == 1) Serial.println("High precision float fix!");
83+
if(RTK == 2) Serial.println("High precision fix!");
5184

52-
byte version = myGPS.getProtocolVersionHigh(2000);
53-
5485
while (1);
5586
}
5687

5788
void loop()
5889
{
59-
myGPS.checkUblox(); //See if new data is available. Process bytes as they come in.
90+
/* myGPS.checkUblox(); //See if new data is available. Process bytes as they come in.
6091
6192
delay(250); //Don't pound too hard on the I2C bus
6293
@@ -83,6 +114,6 @@ void loop()
83114
Serial.print(" AltMSL (above Ellipsoid model surface of earth): ");
84115
Serial.print(altitudeEllipsoid);
85116
Serial.println(" (mm)");
86-
}
117+
}*/
87118

88119
}

src/SparkFun_Ublox_Arduino_Library.cpp

Lines changed: 112 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -676,128 +676,134 @@ boolean SFE_UBLOX_GPS::getPortSettings(uint8_t portID, uint16_t maxWait)
676676
return ( sendCommand(packetCfg, maxWait) );
677677
}
678678

679-
//Get the current 3D high precision positional accuracy - a fun thing to watch
680-
//Returns a float representing the 3D accuracy in millimeters
681-
uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait)
679+
//Given a spot, extract four bytes and build a long from the payload
680+
uint32_t SFE_UBLOX_GPS::extractLong(uint8_t spotToStart)
682681
{
683-
packetCfg.cls = UBX_CLASS_NAV;
684-
packetCfg.id = UBX_NAV_HPPOSECEF;
685-
packetCfg.len = 0;
686-
packetCfg.startingSpot = 0;
687-
688-
if(sendCommand(packetCfg, maxWait) == false)
689-
return(0); //If command send fails then bail
690-
691-
//We got a response, now parse the byte fields into our variable
692-
uint32_t tempAccuracy = 0;
693-
tempAccuracy |= payloadCfg[24] << 8*0;
694-
tempAccuracy |= payloadCfg[25] << 8*1;
695-
tempAccuracy |= payloadCfg[26] << 8*2;
696-
tempAccuracy |= payloadCfg[27] << 8*3;
697-
698-
Serial.print("temp: ");
699-
Serial.println(tempAccuracy, HEX);
700-
701-
if( (tempAccuracy % 10) >= 5) tempAccuracy += 5; //Round fraction of mm up to next mm if .5 or above
702-
tempAccuracy /= 10; //Convert 0.1mm units to mm
703-
704-
Serial.print("temp: ");
705-
Serial.println(tempAccuracy, HEX);
682+
uint32_t pos = 0;
683+
pos |= (int32_t)payloadCfg[spotToStart + 0] << 8*0;
684+
pos |= (int32_t)payloadCfg[spotToStart + 1] << 8*1;
685+
pos |= (int32_t)payloadCfg[spotToStart + 2] << 8*2;
686+
pos |= (int32_t)payloadCfg[spotToStart + 3] << 8*3;
687+
return(pos);
688+
}
706689

707-
return(tempAccuracy);
690+
//Given a spot, extract byte the payload
691+
uint8_t SFE_UBLOX_GPS::extractByte(uint8_t spotToStart)
692+
{
693+
return(payloadCfg[spotToStart]);
708694
}
709-
//Get the current latitude in degrees
710-
//Returns a long representing the number of degrees *10^-7
711-
int32_t SFE_UBLOX_GPS::getLatitude(uint16_t maxWait)
695+
696+
//Get the latest Position/Velocity/Time solution and fill all global variables
697+
boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait)
712698
{
713699
//Query the module for the latest lat/long
714700
packetCfg.cls = UBX_CLASS_NAV;
715-
packetCfg.id = UBX_NAV_POSLLH;
701+
packetCfg.id = UBX_NAV_PVT;
716702
packetCfg.len = 0;
717-
packetCfg.startingSpot = 0;
703+
packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+MAX_PAYLOAD_SIZE = 84 bytes
718704

719705
if(sendCommand(packetCfg, maxWait) == false)
720-
return(0); //If command send fails then bail
721-
722-
//We got a response, now parse the byte fields
723-
uint32_t pos = 0;
724-
pos |= payloadCfg[8] << 8*0;
725-
pos |= payloadCfg[9] << 8*1;
726-
pos |= payloadCfg[10] << 8*2;
727-
pos |= payloadCfg[11] << 8*3;
728-
729-
return(pos);
706+
return(false); //If command send fails then bail
707+
708+
//Parse various byte fields into global vars
709+
fixType = extractByte(20 - packetCfg.startingSpot);
710+
carrierSolution = extractByte(21 - packetCfg.startingSpot) >> 6; //Get 6th&7th bits of this byte
711+
SIV = extractByte(23 - packetCfg.startingSpot);
712+
longitude = extractLong(24 - packetCfg.startingSpot);
713+
latitude = extractLong(28 - packetCfg.startingSpot);
714+
altitude = extractLong(36 - packetCfg.startingSpot);
715+
716+
//Mark all datums as fresh (not read before)
717+
//moduleQueried ThisStruct;
718+
//memset(&ThisStruct, 0, sizeof(moduleQueried));
719+
moduleQueried.longitude = true;
720+
moduleQueried.latitude = true;
721+
moduleQueried.altitude = true;
722+
moduleQueried.SIV = true;
723+
moduleQueried.fixType = true;
724+
moduleQueried.carrierSolution = true;
725+
726+
return(true);
730727
}
731728

732-
//Get the current longitude in degrees
733-
//Returns a long representing the number of degrees *10^-7
734-
int32_t SFE_UBLOX_GPS::getLongitude(uint16_t maxWait)
729+
//Get the current 3D high precision positional accuracy - a fun thing to watch
730+
//Returns a float representing the 3D accuracy in millimeters
731+
uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait)
735732
{
736-
//Query the module for the latest lat/long
737733
packetCfg.cls = UBX_CLASS_NAV;
738-
packetCfg.id = UBX_NAV_POSLLH;
734+
packetCfg.id = UBX_NAV_HPPOSECEF;
739735
packetCfg.len = 0;
740736
packetCfg.startingSpot = 0;
741737

742738
if(sendCommand(packetCfg, maxWait) == false)
743739
return(0); //If command send fails then bail
744740

745-
//We got a response, now parse the byte fields
746-
uint32_t pos = 0;
747-
pos |= payloadCfg[4] << 8*0;
748-
pos |= payloadCfg[5] << 8*1;
749-
pos |= payloadCfg[6] << 8*2;
750-
pos |= payloadCfg[7] << 8*3;
741+
uint32_t tempAccuracy = extractLong(24); //We got a response, now extract a long beginning at a given position
751742

752-
return(pos);
753-
}
743+
if( (tempAccuracy % 10) >= 5) tempAccuracy += 5; //Round fraction of mm up to next mm if .5 or above
744+
tempAccuracy /= 10; //Convert 0.1mm units to mm
754745

755-
//Get the current altitude in mm according to the Ellipsoid model.
756-
//Ellipsoid model: https://www.esri.com/news/arcuser/0703/geoid1of3.html
757-
//Difference between Ellipsoid Model and Mean Sea Level: https://eos-gnss.com/elevation-for-beginners/
758-
int32_t SFE_UBLOX_GPS::getAltitudeEllipsoid(uint16_t maxWait)
746+
return(tempAccuracy);
747+
}
748+
//Get the current latitude in degrees
749+
//Returns a long representing the number of degrees *10^-7
750+
int32_t SFE_UBLOX_GPS::getLatitude(uint16_t maxWait)
759751
{
760-
//Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID.
761-
packetCfg.cls = UBX_CLASS_NAV;
762-
packetCfg.id = UBX_NAV_POSLLH;
763-
packetCfg.len = 0;
764-
packetCfg.startingSpot = 0;
765-
766-
if(sendCommand(packetCfg, maxWait) == false)
767-
return(0); //If command send fails then bail
768-
769-
//We got a response, now parse the byte fields
770-
uint32_t alt = 0;
771-
alt |= payloadCfg[12] << 8*0;
772-
alt |= payloadCfg[13] << 8*1;
773-
alt |= payloadCfg[14] << 8*2;
774-
alt |= payloadCfg[15] << 8*3;
752+
if(moduleQueried.latitude == false) getPVT();
753+
moduleQueried.latitude = false; //Since we are about to give this to user, mark this data as stale
754+
755+
return(latitude);
756+
}
775757

776-
return(alt);
758+
//Get the current longitude in degrees
759+
//Returns a long representing the number of degrees *10^-7
760+
int32_t SFE_UBLOX_GPS::getLongitude(uint16_t maxWait)
761+
{
762+
if(moduleQueried.longitude == false) getPVT();
763+
moduleQueried.longitude = false; //Since we are about to give this to user, mark this data as stale
764+
765+
return(longitude);
777766
}
778767

779768
//Get the current altitude in mm according to mean sea level
780769
//Ellipsoid model: https://www.esri.com/news/arcuser/0703/geoid1of3.html
781770
//Difference between Ellipsoid Model and Mean Sea Level: https://eos-gnss.com/elevation-for-beginners/
782771
int32_t SFE_UBLOX_GPS::getAltitude(uint16_t maxWait)
783772
{
784-
//Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID.
785-
packetCfg.cls = UBX_CLASS_NAV;
786-
packetCfg.id = UBX_NAV_POSLLH;
787-
packetCfg.len = 0;
788-
packetCfg.startingSpot = 0;
773+
if(moduleQueried.altitude == false) getPVT();
774+
moduleQueried.altitude = false; //Since we are about to give this to user, mark this data as stale
775+
776+
return(altitude);
777+
}
789778

790-
if(sendCommand(packetCfg, maxWait) == false)
791-
return(0); //If command send fails then bail
779+
//Get the number of satellites used in fix
780+
uint8_t SFE_UBLOX_GPS::getSIV(uint16_t maxWait)
781+
{
782+
if(moduleQueried.SIV == false) getPVT();
783+
moduleQueried.SIV = false; //Since we are about to give this to user, mark this data as stale
784+
785+
return(SIV);
786+
}
787+
788+
//Get the current fix type
792789

793-
//We got a response, now parse the byte fields
794-
uint32_t alt = 0;
795-
alt |= payloadCfg[16] << 8*0;
796-
alt |= payloadCfg[17] << 8*1;
797-
alt |= payloadCfg[18] << 8*2;
798-
alt |= payloadCfg[19] << 8*3;
790+
uint8_t SFE_UBLOX_GPS::getFixType(uint16_t maxWait)
791+
{
792+
if(moduleQueried.fixType == false) getPVT();
793+
moduleQueried.fixType = false; //Since we are about to give this to user, mark this data as stale
794+
795+
return(fixType);
796+
}
799797

800-
return(alt);
798+
//Get the carrier phase range solution status
799+
//Useful when querying module to see if it has high-precision RTK fix
800+
//0=No solution, 1=Float solution, 2=Fixed solution
801+
uint8_t SFE_UBLOX_GPS::getCarrierSolutionType(uint16_t maxWait)
802+
{
803+
if(moduleQueried.carrierSolution == false) getPVT();
804+
moduleQueried.carrierSolution = false; //Since we are about to give this to user, mark this data as stale
805+
806+
return(carrierSolution);
801807
}
802808

803809
//Get the current protocol version of the Ublox module we're communicating with
@@ -807,40 +813,35 @@ uint8_t SFE_UBLOX_GPS::getProtocolVersionHigh(uint16_t maxWait)
807813
//Send packet with only CLS and ID, length of zero. This will cause the module to respond with the contents of that CLS/ID.
808814
packetCfg.cls = UBX_CLASS_MON;
809815
packetCfg.id = UBX_MON_VER;
810-
packetCfg.len = 0;
811-
812-
packetCfg.startingSpot = 0; //Get software version
813-
814-
if(sendCommand(packetCfg, maxWait) == false)
815-
return(0); //If command send fails then bail
816816

817-
Serial.print("Software version: ");
818-
for(int location = 0 ; location < 64 ; location++)
819-
{
820-
Serial.write(payloadCfg[location]);
821-
if(payloadCfg[location] == '\0') break;
822-
}
823-
Serial.println();
824-
825-
//while(1);
826-
827817
//We will send the command repeatedly, increasing the startingSpot as we go
828818
//Then we look at each extension field of 30 bytes
829-
for(uint8_t extensionNumber = 0 ; extensionNumber < 4 ; extensionNumber++)
819+
for(uint8_t extensionNumber = 0 ; extensionNumber < 10 ; extensionNumber++)
830820
{
821+
packetCfg.len = 0;
831822
packetCfg.startingSpot = 40 + (30*extensionNumber);
832823

833824
if(sendCommand(packetCfg, maxWait) == false)
834825
return(0); //If command send fails then bail
835-
836-
//Now we need to start looking for "PROTVER" in the incoming byte stream
837-
Serial.print("Extension: ");
838-
for(int location = 0 ; location < 64 ; location++)
826+
827+
#ifdef DEBUG
828+
Serial.print("Extension ");
829+
Serial.print(extensionNumber);
830+
Serial.print(": ");
831+
for(int location = 0 ; location < MAX_PAYLOAD_SIZE ; location++)
839832
{
840-
Serial.write(payloadCfg[location]);
841833
if(payloadCfg[location] == '\0') break;
834+
Serial.write(payloadCfg[location]);
842835
}
843836
Serial.println();
837+
#endif
838+
839+
//Now we need to find "PROTVER=18.00" in the incoming byte stream
840+
if(payloadCfg[0] == 'P' && payloadCfg[6] == 'R')
841+
{
842+
byte versionHigh = (payloadCfg[8] - '0') * 10 + (payloadCfg[9] - '0'); //Convert '18' to 18
843+
return(versionHigh);
844+
}
844845
}
845846

846847
return(0);

0 commit comments

Comments
 (0)