diff --git a/examples/Example13_PVT/Example1_AutoPVT/Example1_AutoPVT.ino b/examples/Example13_PVT/Example1_AutoPVT/Example1_AutoPVT.ino index b5dd97e..0370e90 100644 --- a/examples/Example13_PVT/Example1_AutoPVT/Example1_AutoPVT.ino +++ b/examples/Example13_PVT/Example1_AutoPVT/Example1_AutoPVT.ino @@ -54,7 +54,8 @@ void setup() void loop() { // Calling getPVT returns true if there actually is a fresh navigation solution available. - if (myGPS.getPVT()) + // Start the reading only when valid LLH is available + if (myGPS.getPVT() && (myGPS.getInvalidLlh() == false)) { Serial.println(); long latitude = myGPS.getLatitude(); @@ -105,6 +106,33 @@ void loop() Serial.print(horizontalAccEst); Serial.print(F(" (mm)")); + int speedAccEst = myGPS.getSpeedAccEst(); + Serial.print(F(" SpeedAccEst: ")); + Serial.print(speedAccEst); + Serial.print(F(" (mm/s)")); + + int headAccEst = myGPS.getHeadingAccEst(); + Serial.print(F(" HeadAccEst: ")); + Serial.print(headAccEst); + Serial.print(F(" (degrees * 10^-5)")); + + if (myGPS.getHeadVehValid() == true) { + int headVeh = myGPS.getHeadVeh(); + Serial.print(F(" HeadVeh: ")); + Serial.print(headVeh); + Serial.print(F(" (degrees * 10^-5)")); + + int magDec = myGPS.getMagDec(); + Serial.print(F(" MagDec: ")); + Serial.print(magDec); + Serial.print(F(" (degrees * 10^-2)")); + + int magAcc = myGPS.getMagAcc(); + Serial.print(F(" MagAcc: ")); + Serial.print(magAcc); + Serial.print(F(" (degrees * 10^-2)")); + } + Serial.println(); } else { Serial.print("."); diff --git a/keywords.txt b/keywords.txt index 7c1dbe4..99345c1 100644 --- a/keywords.txt +++ b/keywords.txt @@ -58,6 +58,13 @@ getVerticalAccEst KEYWORD2 getNedNorthVel KEYWORD2 getNedEastVel KEYWORD2 getNedDownVel KEYWORD2 +getSpeedAccEst KEYWORD2 +getHeadingAccEst KEYWORD2 +getInvalidLlh KEYWORD2 +getHeadVeh KEYWORD2 +getMagDec KEYWORD2 +getMagAcc KEYWORD2 +getHeadVehValid KEYWORD2 setPortOutput KEYWORD2 setPortInput KEYWORD2 diff --git a/src/SparkFun_Ublox_Arduino_Library.cpp b/src/SparkFun_Ublox_Arduino_Library.cpp index 06653e9..224305d 100644 --- a/src/SparkFun_Ublox_Arduino_Library.cpp +++ b/src/SparkFun_Ublox_Arduino_Library.cpp @@ -1027,8 +1027,9 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg) fixType = extractByte(20 - startingSpot); gnssFixOk = extractByte(21 - startingSpot) & 0x1; //Get the 1st bit - diffSoln = extractByte(21 - startingSpot) >> 1 & 0x1; //Get the 2nd bit + diffSoln = (extractByte(21 - startingSpot) >> 1) & 0x1; //Get the 2nd bit carrierSolution = extractByte(21 - startingSpot) >> 6; //Get 6th&7th bits of this byte + headVehValid = (extractByte(21 - startingSpot) >> 5) & 0x1; // Get the 5th bit SIV = extractByte(23 - startingSpot); longitude = extractSignedLong(24 - startingSpot); latitude = extractSignedLong(28 - startingSpot); @@ -1039,10 +1040,15 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg) nedNorthVel = extractSignedLong(48 - startingSpot); nedEastVel = extractSignedLong(52 - startingSpot); nedDownVel = extractSignedLong(56 - startingSpot); - groundSpeed = extractSignedLong(60 - startingSpot); headingOfMotion = extractSignedLong(64 - startingSpot); + speedAccEst = extractLong(68 - startingSpot); + headingAccEst = extractLong(72 - startingSpot); pDOP = extractInt(76 - startingSpot); + invalidLlh = extractByte(78 - startingSpot) & 0x1; + headVeh = extractSignedLong(84 - startingSpot); + magDec = extractSignedInt(88 - startingSpot); + magAcc = extractInt(90 - startingSpot); //Mark all datums as fresh (not read before) moduleQueried.gpsiTOW = true; @@ -1059,23 +1065,28 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg) moduleQueried.all = true; moduleQueried.gnssFixOk = true; moduleQueried.diffSoln = true; + moduleQueried.headVehValid = true; moduleQueried.longitude = true; moduleQueried.latitude = true; moduleQueried.altitude = true; moduleQueried.altitudeMSL = true; - moduleQueried.horizontalAccEst = true; moduleQueried.verticalAccEst = true; moduleQueried.nedNorthVel = true; moduleQueried.nedEastVel = true; moduleQueried.nedDownVel = true; - moduleQueried.SIV = true; moduleQueried.fixType = true; moduleQueried.carrierSolution = true; moduleQueried.groundSpeed = true; moduleQueried.headingOfMotion = true; + moduleQueried.speedAccEst = true; + moduleQueried.headingAccEst = true; moduleQueried.pDOP = true; + moduleQueried.invalidLlh = true; + moduleQueried.headVeh = true; + moduleQueried.magDec = true; + moduleQueried.magAcc = true; } else if (msg->id == UBX_NAV_HPPOSLLH && msg->len == 36) { @@ -3111,6 +3122,19 @@ uint16_t SFE_UBLOX_GPS::extractInt(uint8_t spotToStart) return (val); } +//Just so there is no ambiguity about whether a uint16_t will cast to a int16_t correctly... +int16_t SFE_UBLOX_GPS::extractSignedInt(int8_t spotToStart) +{ + union // Use a union to convert from uint16_t to int16_t + { + uint16_t unsignedInt; + int16_t signedInt; + } stSignedInt; + + stSignedInt.unsignedInt = extractInt(spotToStart); + return (stSignedInt.signedInt); +} + //Given a spot, extract a byte from the payload uint8_t SFE_UBLOX_GPS::extractByte(uint8_t spotToStart) { @@ -3195,6 +3219,54 @@ bool SFE_UBLOX_GPS::getTimeValid(uint16_t maxWait) return (gpsTimeValid); } +uint32_t SFE_UBLOX_GPS::getSpeedAccEst(uint16_t maxWait) +{ + if (moduleQueried.speedAccEst == false) + getPVT(maxWait); + moduleQueried.speedAccEst = false; //Since we are about to give this to user, mark this data as stale + return (speedAccEst); +} + +uint32_t SFE_UBLOX_GPS::getHeadingAccEst(uint16_t maxWait) +{ + if (moduleQueried.headingAccEst == false) + getPVT(maxWait); + moduleQueried.headingAccEst = false; //Since we are about to give this to user, mark this data as stale + return (headingAccEst); +} + +bool SFE_UBLOX_GPS::getInvalidLlh(uint16_t maxWait) +{ + if (moduleQueried.invalidLlh == false) + getPVT(maxWait); + moduleQueried.invalidLlh = false; //Since we are about to give this to user, mark this data as stale + return (invalidLlh); +} + +int32_t SFE_UBLOX_GPS::getHeadVeh(uint16_t maxWait) +{ + if (moduleQueried.headVeh == false) + getPVT(maxWait); + moduleQueried.headVeh = false; //Since we are about to give this to user, mark this data as stale + return (headVeh); +} + +int16_t SFE_UBLOX_GPS::getMagDec(uint16_t maxWait) +{ + if (moduleQueried.magDec == false) + getPVT(maxWait); + moduleQueried.magDec = false; //Since we are about to give this to user, mark this data as stale + return (magDec); +} + +uint16_t SFE_UBLOX_GPS::getMagAcc(uint16_t maxWait) +{ + if (moduleQueried.magAcc == false) + getPVT(maxWait); + moduleQueried.magAcc = false; //Since we are about to give this to user, mark this data as stale + return (magAcc); +} + //Get the current millisecond uint16_t SFE_UBLOX_GPS::getMillisecond(uint16_t maxWait) { @@ -3780,6 +3852,18 @@ uint8_t SFE_UBLOX_GPS::getCarrierSolutionType(uint16_t maxWait) return (carrierSolution); } +//Get whether head vehicle valid or not +bool SFE_UBLOX_GPS::getHeadVehValid(uint16_t maxWait) +{ + if (moduleQueried.headVehValid == false) + getPVT(maxWait); + moduleQueried.headVehValid = false; //Since we are about to give this to user, mark this data as stale + moduleQueried.all = false; + + return (headVehValid); +} + + //Get the ground speed in mm/s int32_t SFE_UBLOX_GPS::getGroundSpeed(uint16_t maxWait) { @@ -3901,6 +3985,7 @@ void SFE_UBLOX_GPS::flushPVT() moduleQueried.all = false; moduleQueried.gnssFixOk = false; moduleQueried.diffSoln = false; + moduleQueried.headVehValid = false; moduleQueried.longitude = false; moduleQueried.latitude = false; moduleQueried.altitude = false; @@ -3910,7 +3995,13 @@ void SFE_UBLOX_GPS::flushPVT() moduleQueried.carrierSolution = false; moduleQueried.groundSpeed = false; moduleQueried.headingOfMotion = false; + moduleQueried.speedAccEst = false; + moduleQueried.headingAccEst = false; moduleQueried.pDOP = false; + moduleQueried.invalidLlh = false; + moduleQueried.headVeh = false; + moduleQueried.magDec = false; + moduleQueried.magAcc = false; } //Mark all the HPPOSLLH data as read/stale. This is handy to get data alignment after CRC failure diff --git a/src/SparkFun_Ublox_Arduino_Library.h b/src/SparkFun_Ublox_Arduino_Library.h index b437de4..9a3e250 100644 --- a/src/SparkFun_Ublox_Arduino_Library.h +++ b/src/SparkFun_Ublox_Arduino_Library.h @@ -507,17 +507,16 @@ class SFE_UBLOX_GPS bool getGnssFixOk(uint16_t maxWait = getPVTmaxWait); //Get whether we have a valid fix (i.e within DOP & accuracy masks) bool getDiffSoln(uint16_t maxWait = getPVTmaxWait); //Get whether differential corrections were applied + bool getHeadVehValid(uint16_t maxWait = getPVTmaxWait); int32_t getLatitude(uint16_t maxWait = getPVTmaxWait); //Returns the current latitude in degrees * 10^-7. Auto selects between HighPrecision and Regular depending on ability of module. int32_t getLongitude(uint16_t maxWait = getPVTmaxWait); //Returns the current longitude in degrees * 10-7. Auto selects between HighPrecision and Regular depending on ability of module. int32_t getAltitude(uint16_t maxWait = getPVTmaxWait); //Returns the current altitude in mm above ellipsoid int32_t getAltitudeMSL(uint16_t maxWait = getPVTmaxWait); //Returns the current altitude in mm above mean sea level - int32_t getHorizontalAccEst(uint16_t maxWait = getPVTmaxWait); int32_t getVerticalAccEst(uint16_t maxWait = getPVTmaxWait); int32_t getNedNorthVel(uint16_t maxWait = getPVTmaxWait); int32_t getNedEastVel(uint16_t maxWait = getPVTmaxWait); int32_t getNedDownVel(uint16_t maxWait = getPVTmaxWait); - uint8_t getSIV(uint16_t maxWait = getPVTmaxWait); //Returns number of sats used in fix uint8_t getFixType(uint16_t maxWait = getPVTmaxWait); //Returns the type of fix: 0=no, 3=3D, 4=GNSS+Deadreckoning uint8_t getCarrierSolutionType(uint16_t maxWait = getPVTmaxWait); //Returns RTK solution: 0=no, 1=float solution, 2=fixed solution @@ -535,6 +534,12 @@ class SFE_UBLOX_GPS uint32_t getTimeOfWeek(uint16_t maxWait = getPVTmaxWait); bool getDateValid(uint16_t maxWait = getPVTmaxWait); bool getTimeValid(uint16_t maxWait = getPVTmaxWait); + uint32_t getSpeedAccEst(uint16_t maxWait = getPVTmaxWait); + uint32_t getHeadingAccEst(uint16_t maxWait = getPVTmaxWait); + bool getInvalidLlh(uint16_t maxWait = getPVTmaxWait); + int32_t getHeadVeh(uint16_t maxWait = getPVTmaxWait); + int16_t getMagDec(uint16_t maxWait = getPVTmaxWait); + uint16_t getMagAcc(uint16_t maxWait = getPVTmaxWait); int32_t getHighResLatitude(uint16_t maxWait = getHPPOSLLHmaxWait); int8_t getHighResLatitudeHp(uint16_t maxWait = getHPPOSLLHmaxWait); @@ -730,9 +735,9 @@ class SFE_UBLOX_GPS bool gpsDateValid; bool gpsTimeValid; - bool gnssFixOk; //valid fix (i.e within DOP & accuracy masks) bool diffSoln; //Differential corrections were applied + bool headVehValid; int32_t latitude; //Degrees * 10^-7 (more accurate than floats) int32_t longitude; //Degrees * 10^-7 (more accurate than floats) int32_t altitude; //Number of mm above ellipsoid @@ -747,7 +752,13 @@ class SFE_UBLOX_GPS uint8_t carrierSolution; //Tells us when we have an RTK float/fixed solution int32_t groundSpeed; //mm/s int32_t headingOfMotion; //degrees * 10^-5 + uint32_t speedAccEst; + uint32_t headingAccEst; uint16_t pDOP; //Positional dilution of precision * 10^-2 (dimensionless) + bool invalidLlh; + int32_t headVeh; + int16_t magDec; + uint16_t magAcc; uint8_t versionLow; //Loaded from getProtocolVersion(). uint8_t versionHigh; @@ -943,6 +954,7 @@ class SFE_UBLOX_GPS uint32_t extractLong(uint8_t spotToStart); //Combine four bytes from payload into long int32_t extractSignedLong(uint8_t spotToStart); //Combine four bytes from payload into signed long (avoiding any ambiguity caused by casting) uint16_t extractInt(uint8_t spotToStart); //Combine two bytes from payload into int + int16_t extractSignedInt(int8_t spotToStart); uint8_t extractByte(uint8_t spotToStart); //Get byte from payload int8_t extractSignedChar(uint8_t spotToStart); //Get signed 8-bit value from payload void addToChecksum(uint8_t incoming); //Given an incoming byte, adjust rollingChecksumA/B @@ -1022,23 +1034,28 @@ class SFE_UBLOX_GPS uint32_t all : 1; uint32_t gnssFixOk : 1; uint32_t diffSoln : 1; + uint32_t headVehValid : 1; uint32_t longitude : 1; uint32_t latitude : 1; uint32_t altitude : 1; uint32_t altitudeMSL : 1; - uint32_t horizontalAccEst : 1; uint32_t verticalAccEst : 1; uint32_t nedNorthVel : 1; uint32_t nedEastVel : 1; uint32_t nedDownVel : 1; - uint32_t SIV : 1; uint32_t fixType : 1; uint32_t carrierSolution : 1; uint32_t groundSpeed : 1; uint32_t headingOfMotion : 1; + uint32_t speedAccEst : 1; + uint32_t headingAccEst : 1; uint32_t pDOP : 1; + uint32_t invalidLlh : 1; + uint32_t headVeh : 1; + uint32_t magDec : 1; + uint32_t magAcc : 1; uint32_t versionNumber : 1; } moduleQueried;