From a1814e32abfbeb458c6d3739a653efa42d6df56f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Jan 2022 10:38:20 +0000 Subject: [PATCH] Add setMainTalkerID and setHighPrecisionMode --- .../Example1_getLatestNMEAGPGGA.ino | 32 ++++++------ keywords.txt | 26 ++++++++-- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 50 +++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 35 +++++++++---- src/u-blox_structs.h | 6 +-- 5 files changed, 115 insertions(+), 34 deletions(-) diff --git a/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino index bf525a9..bb6b68a 100644 --- a/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino +++ b/examples/Automatic_NMEA/Example1_getLatestNMEAGPGGA/Example1_getLatestNMEAGPGGA.ino @@ -14,6 +14,10 @@ 1 if the data is valid but is stale (you have read it before) 2 if the data is valid and fresh + If the module is using multiple GNSS constellations, the GGA message will be prefixed with Talker ID "GN" instead of "GP". + The library includes a getLatestNMEAGNGGA function too. + This example shows how to use both functions - and how to change the Talker ID so the GNGGA messages become GPGGA. + This example turns off all sentences except for GPGGA. Feel like supporting open source hardware? @@ -59,7 +63,13 @@ void setup() myGNSS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C); myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); // Leave only GGA enabled at current navigation rate - //myGNSS.saveConfiguration(); //Optional: Save these settings to NVM + // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA + myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); + //myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_DEFAULT); // Uncomment this line to restore the default main talker ID + + myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages + + //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM Serial.println(F("Messages configured")); @@ -81,20 +91,14 @@ void loop() { Serial.println(F("GPGGA data is available but is stale")); } - else if (result == 2) + else // if (result == 2) { // Data contains .length and .nmea - Serial.print(F("NMEA: Length: ")); + Serial.print(F("Latest GPGGA: Length: ")); Serial.print(data.length); Serial.print(F("\tData: ")); Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated) } - else - { - Serial.print(F("result == ")); - Serial.print(result); - Serial.println(F(". This should be impossible!")); - } result = myGNSS.getLatestNMEAGNGGA(&data); // Get the latest GNGGA data (if any) @@ -106,20 +110,14 @@ void loop() { Serial.println(F("GNGGA data is available but is stale")); } - else if (result == 2) + else // if (result == 2) { // Data contains .length and .nmea - Serial.print(F("NMEA: Length: ")); + Serial.print(F("Latest GNGGA: Length: ")); Serial.print(data.length); Serial.print(F("\tData: ")); Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated) } - else - { - Serial.print(F("result == ")); - Serial.print(result); - Serial.println(F(". This should be impossible!")); - } delay(250); } diff --git a/keywords.txt b/keywords.txt index 2b01773..f884576 100644 --- a/keywords.txt +++ b/keywords.txt @@ -446,11 +446,6 @@ initPacketUBXHNRPVT KEYWORD2 flushHNRPVT KEYWORD2 logHNRPVT KEYWORD2 -setNMEALoggingMask KEYWORD2 -getNMEALoggingMask KEYWORD2 -setProcessNMEAMask KEYWORD2 -getProcessNMEAMask KEYWORD2 - setNavigationFrequency KEYWORD2 getNavigationFrequency KEYWORD2 setMeasurementRate KEYWORD2 @@ -559,6 +554,19 @@ getHNRroll KEYWORD2 getHNRpitch KEYWORD2 getHNRheading KEYWORD2 +setNMEALoggingMask KEYWORD2 +getNMEALoggingMask KEYWORD2 +setProcessNMEAMask KEYWORD2 +getProcessNMEAMask KEYWORD2 + +setMainTalkerID KEYWORD2 +setHighPrecisionMode KEYWORD2 + +getLatestNMEAGPGGA KEYWORD2 +setNMEAGPGGAcallback KEYWORD2 +getLatestNMEAGNGGA KEYWORD2 +setNMEAGNGGAcallback KEYWORD2 + extractLong KEYWORD2 extractSignedLong KEYWORD2 extractInt KEYWORD2 @@ -745,3 +753,11 @@ SFE_UBLOX_MGA_ACK_INFOCODE_SIZE_MISMATCH LITERAL1 SFE_UBLOX_MGA_ACK_INFOCODE_NOT_STORED LITERAL1 SFE_UBLOX_MGA_ACK_INFOCODE_NOT_READY LITERAL1 SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN LITERAL1 + +SFE_UBLOX_MAIN_TALKER_ID_DEFAULT LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GP LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GL LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GN LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GA LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GB LITERAL1 +SFE_UBLOX_MAIN_TALKER_ID_GQ LITERAL1 diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index fe36d01..650a15e 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -1707,7 +1707,9 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r { uint8_t *lengthPtr = getNMEAWorkingLengthPtr(); // Get a pointer to the working copy length uint8_t *nmeaPtr = getNMEAWorkingNMEAPtr(); // Get a pointer to the working copy NMEA data + uint8_t nmeaMaxLength = getNMEAMaxLength(); *lengthPtr = 6; // Set the working copy length + memset(nmeaPtr, 0, nmeaMaxLength); // Clear the working copy memcpy(nmeaPtr, &nmeaAddressField[0], 6); // Copy the start character and address field into the working copy } @@ -12020,6 +12022,54 @@ void SFE_UBLOX_GNSS::logHNRPVT(bool enabled) // ***** Helper Functions for NMEA Logging / Processing +// Set the mainTalkerId used by NMEA messages - allows all NMEA messages except GSV to be prefixed with GP instead of GN +bool SFE_UBLOX_GNSS::setMainTalkerID(sfe_ublox_talker_ids_e id, uint16_t maxWait) +{ + //Get the current extended NMEA protocol configuration (V1) + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NMEA; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + //Ask module for the current settings. Loads into payloadCfg. + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + payloadCfg[9] = (uint8_t)id; + + packetCfg.len = 20; + packetCfg.startingSpot = 0; + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + +// Enable/Disable NMEA High Precision Mode - include extra decimal places in the Lat and Lon +bool SFE_UBLOX_GNSS::setHighPrecisionMode(bool enable, uint16_t maxWait) +{ + //Get the current extended NMEA protocol configuration (V1) + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_NMEA; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + //Ask module for the current settings. Loads into payloadCfg. + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + if (enable) + { + payloadCfg[3] |= (1 << 3); // Set the highPrec flag + payloadCfg[3] &= ~((1 << 0) | (1 << 2)); // Clear the compat and limit82 flags + } + else + payloadCfg[3] &= ~(1 << 3); // Clear the highPrec flag + + packetCfg.len = 20; + packetCfg.startingSpot = 0; + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + // Log selected NMEA messages to file buffer - if the messages are enabled and if the file buffer exists // User needs to call setFileBufferSize before .begin void SFE_UBLOX_GNSS::setNMEALoggingMask(uint32_t messages) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 3d51197..5e0252c 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -522,6 +522,18 @@ enum sfe_ublox_mga_ack_infocode_e SFE_UBLOX_MGA_ACK_INFOCODE_TYPE_UNKNOWN }; +// The mainTalkerId, set by UBX-CFG-NMEA setMainTalkerID +enum sfe_ublox_talker_ids_e +{ + SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, + SFE_UBLOX_MAIN_TALKER_ID_GP, + SFE_UBLOX_MAIN_TALKER_ID_GL, + SFE_UBLOX_MAIN_TALKER_ID_GN, + SFE_UBLOX_MAIN_TALKER_ID_GA, + SFE_UBLOX_MAIN_TALKER_ID_GB, + SFE_UBLOX_MAIN_TALKER_ID_GQ +}; + //-=-=-=-=- #ifndef MAX_PAYLOAD_SIZE @@ -1167,14 +1179,6 @@ public: void flushHNRPVT(); //Mark all the data as read/stale void logHNRPVT(bool enabled = true); // Log data to file buffer - // Helper functions for NMEA logging - void setNMEALoggingMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Add selected NMEA messages to file buffer - if enabled. Default to adding ALL messages to the file buffer - uint32_t getNMEALoggingMask(); // Return which NMEA messages are selected for logging to the file buffer - if enabled - - // Helper functions to control which NMEA messages are passed to processNMEA - void setProcessNMEAMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Control which NMEA messages are passed to processNMEA. Default to passing ALL messages - uint32_t getProcessNMEAMask(); // Return which NMEA messages are passed to processNMEA - // Helper functions for CFG RATE bool setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = defaultMaxWait); //Set the number of nav solutions sent per second @@ -1323,8 +1327,21 @@ public: float getHNRpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees float getHNRheading(uint16_t maxWait = defaultMaxWait); // Returned as degrees + // Set the mainTalkerId used by NMEA messages - allows all NMEA messages except GSV to be prefixed with GP instead of GN + bool setMainTalkerID(sfe_ublox_talker_ids_e id = SFE_UBLOX_MAIN_TALKER_ID_DEFAULT, uint16_t maxWait = defaultMaxWait); + + // Enable/Disable NMEA High Precision Mode - include extra decimal places in the Lat and Lon + bool setHighPrecisionMode(bool enable = true, uint16_t maxWait = defaultMaxWait); + + // Helper functions for NMEA logging + void setNMEALoggingMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Add selected NMEA messages to file buffer - if enabled. Default to adding ALL messages to the file buffer + uint32_t getNMEALoggingMask(); // Return which NMEA messages are selected for logging to the file buffer - if enabled + + // Helper functions to control which NMEA messages are passed to processNMEA + void setProcessNMEAMask(uint32_t messages = SFE_UBLOX_FILTER_NMEA_ALL); // Control which NMEA messages are passed to processNMEA. Default to passing ALL messages + uint32_t getProcessNMEAMask(); // Return which NMEA messages are passed to processNMEA + // Support for "auto" storage of NMEA messages - uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 89d88f5..31fba28 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -2250,11 +2250,11 @@ struct nmeaAutomaticFlags }; // The max length for NMEA messages should be 82 bytes, but GGA messages can exceed that if they include the -// extra decimal places for "High Precision". +// extra decimal places for "High Precision Mode". // -// To be safe, let's allocate 90 bytes to store the GGA message +// To be safe, let's allocate 100 bytes to store the GGA message -const uint8_t NMEA_GGA_MAX_LENGTH = 90; +const uint8_t NMEA_GGA_MAX_LENGTH = 100; typedef struct {