@@ -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/
782771int32_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