diff --git a/examples/Basics/Example8_GetProtocolVersion/Example8_GetProtocolVersion.ino b/examples/Basics/Example8_GetModuleInfo/Example8_GetModuleInfo.ino similarity index 65% rename from examples/Basics/Example8_GetProtocolVersion/Example8_GetProtocolVersion.ino rename to examples/Basics/Example8_GetModuleInfo/Example8_GetModuleInfo.ino index 1fb504d..e3ac0d5 100644 --- a/examples/Basics/Example8_GetProtocolVersion/Example8_GetProtocolVersion.ino +++ b/examples/Basics/Example8_GetModuleInfo/Example8_GetModuleInfo.ino @@ -1,5 +1,5 @@ /* - Reading the protocol version of a u-blox module + Reading the protocol and firmware versions of a u-blox module By: Nathan Seidle SparkFun Electronics Date: January 3rd, 2019 @@ -32,27 +32,43 @@ #include //http://librarymanager/All#SparkFun_u-blox_GNSS_v3 SFE_UBLOX_GNSS myGNSS; -long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module. - void setup() { + delay(1000); + Serial.begin(115200); Serial.println("SparkFun u-blox Example"); Wire.begin(); + //myGNSS.enableDebugging(Serial); // Uncomment this line to enable debug messages on Serial + if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port { Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing.")); while (1); } - Serial.print(F("Version: ")); - byte versionHigh = myGNSS.getProtocolVersionHigh(); - Serial.print(versionHigh); - Serial.print("."); - byte versionLow = myGNSS.getProtocolVersionLow(); - Serial.print(versionLow); + if (myGNSS.getModuleInfo()) + { + Serial.print(F("FWVER: ")); + Serial.print(myGNSS.getFirmwareVersionHigh()); // Returns uint8_t + Serial.print(F(".")); + Serial.println(myGNSS.getFirmwareVersionLow()); // Returns uint8_t + + Serial.print(F("Firmware: ")); + Serial.println(myGNSS.getFirmwareType()); // Returns HPG, SPG etc. as (const char *) + + Serial.print(F("PROTVER: ")); + Serial.print(myGNSS.getProtocolVersionHigh()); // Returns uint8_t + Serial.print(F(".")); + Serial.println(myGNSS.getProtocolVersionLow()); // Returns uint8_t + + Serial.print(F("MOD: ")); + Serial.println(myGNSS.getModuleName()); // Returns ZED-F9P, MAX-M10S etc. as (const char *) + } + else + Serial.println(F("Error: could not read module info!")); } void loop() diff --git a/examples/Basics/Example8_GetProtocolVersion_Serial/Example8_GetProtocolVersion_Serial.ino b/examples/Basics/Example8_GetModuleInfo_Serial/Example8_GetModuleInfo_Serial.ino similarity index 72% rename from examples/Basics/Example8_GetProtocolVersion_Serial/Example8_GetProtocolVersion_Serial.ino rename to examples/Basics/Example8_GetModuleInfo_Serial/Example8_GetModuleInfo_Serial.ino index 5ad0ac1..09011ee 100644 --- a/examples/Basics/Example8_GetProtocolVersion_Serial/Example8_GetProtocolVersion_Serial.ino +++ b/examples/Basics/Example8_GetModuleInfo_Serial/Example8_GetModuleInfo_Serial.ino @@ -1,5 +1,5 @@ /* - Reading the protocol version of a u-blox module + Reading the protocol and firmware versions of a u-blox module By: Nathan Seidle SparkFun Electronics Date: January 3rd, 2019 @@ -32,21 +32,20 @@ #include -//#define mySerial Serial1 // Uncomment this line to connect via Serial1 +#define mySerial Serial1 // Uncomment this line to connect via Serial1 // - or - //SoftwareSerial mySerial(10, 11); // Uncomment this line to connect via SoftwareSerial(RX, TX). Connect pin 10 to GNSS TX pin. // - or - -#define mySerial Serial // Uncomment this line if you just want to keep using Serial +//#define mySerial Serial1 // Uncomment this line if you just want to keep using Serial #include //http://librarymanager/All#SparkFun_u-blox_GNSS_v3 SFE_UBLOX_GNSS_SERIAL myGNSS; -long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module. - void setup() { + delay(1000); + Serial.begin(115200); - while (!Serial); //Wait for user to open terminal Serial.println("SparkFun u-blox Example"); Serial.println("Trying 38400 baud"); @@ -70,12 +69,26 @@ void setup() } } - Serial.print(F("Version: ")); - byte versionHigh = myGNSS.getProtocolVersionHigh(); - Serial.print(versionHigh); - Serial.print("."); - byte versionLow = myGNSS.getProtocolVersionLow(); - Serial.print(versionLow); + if (myGNSS.getModuleInfo()) + { + Serial.print(F("FWVER: ")); + Serial.print(myGNSS.getFirmwareVersionHigh()); + Serial.print(F(".")); + Serial.println(myGNSS.getFirmwareVersionLow()); + + Serial.print(F("Firmware: ")); + Serial.println(myGNSS.getFirmwareType()); + + Serial.print(F("PROTVER: ")); + Serial.print(myGNSS.getProtocolVersionHigh()); + Serial.print(F(".")); + Serial.println(myGNSS.getProtocolVersionLow()); + + Serial.print(F("MOD: ")); + Serial.println(myGNSS.getModuleName()); + } + else + Serial.println(F("Error: could not read module info!")); } void loop() diff --git a/examples/Example9_SFE_UBLOX_GNSS_SUPER/Example9_SFE_UBLOX_GNSS_SUPER.ino b/examples/Example9_SFE_UBLOX_GNSS_SUPER/Example9_SFE_UBLOX_GNSS_SUPER.ino new file mode 100644 index 0000000..efbd9da --- /dev/null +++ b/examples/Example9_SFE_UBLOX_GNSS_SUPER/Example9_SFE_UBLOX_GNSS_SUPER.ino @@ -0,0 +1,195 @@ +/* + Using the SFE_UBLOX_GNSS_SUPER class + By: Paul Clark + SparkFun Electronics + Date: January 20th, 2023 + License: MIT. See license file for more information. + + This example shows how to use the SFE_UBLOX_GNSS_SUPER class. + It allows you to write multi-purpose code that can: + * Detect what hardware the code is running on + * Select the correct GNSS interface (I2C/SPI/Serial) for that hardware + + Feel like supporting open source hardware? + Buy a board from SparkFun! + SparkFun GPS-RTK2 - ZED-F9P (GPS-15136) https://www.sparkfun.com/products/15136 + SparkFun GPS-RTK-SMA - ZED-F9P (GPS-16481) https://www.sparkfun.com/products/16481 + SparkFun MAX-M10S Breakout (GPS-18037) https://www.sparkfun.com/products/18037 + SparkFun ZED-F9K Breakout (GPS-18719) https://www.sparkfun.com/products/18719 + SparkFun ZED-F9R Breakout (GPS-16344) https://www.sparkfun.com/products/16344 + + Hardware Connections: + Plug a Qwiic cable into the GNSS and a BlackBoard + If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425) + Open the serial monitor at 115200 baud to see the output +*/ + +#include // Needed for I2C to GNSS +#include // Needed for SPI to GNSS + +#include //http://librarymanager/All#SparkFun_u-blox_GNSS_v3 + +// Create an object of the GNSS super-class +SFE_UBLOX_GNSS_SUPER theGNSS; + +// The super class supports I2C, SPI and Serial. +// Create a global enum that defines which interface to use +typedef enum { + GNSS_IS_I2C, + GNSS_IS_SPI, + GNSS_IS_SERIAL +} GNSS_INTERFACE; +GNSS_INTERFACE theGNSSinterface; + +// Define which Serial port the GNSS is (or could be) connected to: +#define gnssSerial Serial1 // Use hardware Serial1 to connect to the GNSS +uint32_t gnssBaudRate = 38400; // Define what Baud Rate to use. Both F9 and M10 devices default to 38400. + +// If the GNSS is (or could be) connected via SPI, we need to define the port and the Chip Select pin: +#define gnssSPI SPI // Use SPI to connect to the GNSS +const int gnssSPICS = 4; // Define the Chip Select pin for the SPI interface - Pin 4 is the "free" pin on Thing Plus C + +// Define which Wire (I2C) port the GNSS is (or could be) connected to: +#define gnssWire Wire // Use Wire to connect to the GNSS +const uint8_t gnssI2CAddress = 0x42; // Define the GNSS I2C address. The default is usually 0x42. (NEO-D9S uses 0x43) + +void setup() +{ + delay(1000); + + Serial.begin(115200); + Serial.println("SFE_UBLOX_GNSS_SUPER example"); + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // Define which interface to test. + // The code could auto-detect what board it is running on, e.g. by measuring the + // voltage on an analog pin (defined by a pair of resistors) or reading the board + // type from EEPROM, and then set theGNSSinterface to match. + + theGNSSinterface = GNSS_IS_I2C; // Select I2C for this test + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // Now prepare the correct hardware interface for GNSS communication + + if (theGNSSinterface == GNSS_IS_SERIAL) + { + gnssSerial.begin(gnssBaudRate); // Begin the Serial port + } + else if (theGNSSinterface == GNSS_IS_SPI) + { + pinMode(gnssSPICS, OUTPUT); // Pull the chip select pin high + digitalWrite(gnssSPICS, HIGH); + SPI.begin(); + } + else // if (theGNSSinterface == GNSS_IS_I2C) // Catch-all. Default to I2C + { + Wire.begin(); // Begin the Wire port + //Wire.setClock(400000); + } + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // Enable debug messages if required + + //theGNSS.enableDebugging(Serial); // Uncomment this line to enable debug messages on Serial + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // Now begin the GNSS + + bool beginSuccess = false; + + if (theGNSSinterface == GNSS_IS_SERIAL) + { + beginSuccess = theGNSS.begin(gnssSerial); + } + + else if (theGNSSinterface == GNSS_IS_SPI) + { + beginSuccess = theGNSS.begin(gnssSPI, gnssSPICS); // SPI, default to 4MHz + + //beginSuccess = theGNSS.begin(gnssSPI, gnssSPICS, 4000000); // Custom + + //SPISettings customSPIsettings = SPISettings(4000000, MSBFIRST, SPI_MODE0); + //beginSuccess = theGNSS.begin(gnssSPI, gnssSPICS, customSPIsettings); // Custom + } + + else // if (theGNSSinterface == GNSS_IS_I2C) // Catch-all. Default to I2C + { + beginSuccess = theGNSS.begin(gnssWire, gnssI2CAddress); + } + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // Check begin was successful + + if (beginSuccess == false) + { + Serial.println(F("u-blox GNSS not detected. Please check wiring. Freezing...")); + while (1) + { + ; // Do nothing more + } + } + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // Disable the NMEA messages, just to show how to do it on the three interfaces: + + if (theGNSSinterface == GNSS_IS_SERIAL) + { + // Assume we're connected to UART1. Could be UART2 + theGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART1 port to output UBX only (turn off NMEA noise) + } + else if (theGNSSinterface == GNSS_IS_SPI) + { + theGNSS.setSPIOutput(COM_TYPE_UBX); //Set the SPI port to output UBX only (turn off NMEA noise) + } + else // if (theGNSSinterface == GNSS_IS_I2C) // Catch-all. Default to I2C + { + theGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) + } + + // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // Read the module info + + if (theGNSS.getModuleInfo()) // This line is optional. getModuleName() etc. will read the info if required + { + Serial.print(F("The GNSS module is: ")); + Serial.println(theGNSS.getModuleName()); + + Serial.print(F("The firmware type is: ")); + Serial.println(theGNSS.getFirmwareType()); + + Serial.print(F("The firmware version is: ")); + Serial.print(theGNSS.getFirmwareVersionHigh()); + Serial.print(F(".")); + Serial.println(theGNSS.getFirmwareVersionLow()); + + Serial.print(F("The protocol version is: ")); + Serial.print(theGNSS.getProtocolVersionHigh()); + Serial.print(F(".")); + Serial.println(theGNSS.getProtocolVersionLow()); + } +} + +void loop() +{ + // Request (poll) the position, velocity and time (PVT) information. + // The module only responds when a new position is available. Default is once per second. + // getPVT() returns true when new data is received. + if (theGNSS.getPVT() == true) + { + int32_t latitude = theGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + int32_t longitude = theGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + int32_t altitude = theGNSS.getAltitudeMSL(); // Altitude above Mean Sea Level + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.print(F(" (mm)")); + + Serial.println(); + } +} diff --git a/keywords.txt b/keywords.txt index cb6aca5..46410c8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -9,6 +9,7 @@ SFE_UBLOX_GNSS KEYWORD1 SFE_UBLOX_GNSS_SPI KEYWORD1 SFE_UBLOX_GNSS_SERIAL KEYWORD1 +SFE_UBLOX_GNSS_SUPER KEYWORD1 DevUBLOXGNSS KEYWORD1 ubxPacket KEYWORD1 @@ -185,7 +186,12 @@ setDGNSSConfiguration KEYWORD2 getProtocolVersionHigh KEYWORD2 getProtocolVersionLow KEYWORD2 +getFirmwareVersionHigh KEYWORD2 +getFirmwareVersionLow KEYWORD2 +getFirmwareType KEYWORD2 +getModuleName KEYWORD2 getProtocolVersion KEYWORD2 +getModuleInfo KEYWORD2 addGeofence KEYWORD2 clearGeofences KEYWORD2 diff --git a/library.properties b/library.properties index bcaa335..b0e0e26 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS v3 -version=3.0.0 +version=3.0.1 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules

diff --git a/src/SparkFun_u-blox_GNSS_v3.h b/src/SparkFun_u-blox_GNSS_v3.h index dee9184..6ee332d 100644 --- a/src/SparkFun_u-blox_GNSS_v3.h +++ b/src/SparkFun_u-blox_GNSS_v3.h @@ -160,7 +160,7 @@ class SFE_UBLOX_GNSS_SPI : public DevUBLOXGNSS } // Version 2: - // User passes in an SPI object and SPISettings (optional). + // User passes in an SPI object and SPISettings (optional). bool begin(SPIClass &spiPort, uint8_t cs, SPISettings ismSettings, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait, bool assumeSuccess = false) { // Setup a SPI object and pass into the superclass @@ -174,7 +174,7 @@ class SFE_UBLOX_GNSS_SPI : public DevUBLOXGNSS } // Version 3: - // User passes in an SPI object and SPI speed (optional). + // User passes in an SPI object and SPI speed (optional). bool begin(SPIClass &spiPort, uint8_t cs, uint32_t spiSpeed, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait, bool assumeSuccess = false) { // Setup a SPI object and pass into the superclass @@ -230,3 +230,84 @@ class SFE_UBLOX_GNSS_SERIAL : public DevUBLOXGNSS // I2C bus class SparkFun_UBLOX_GNSS::SfeSerial _serialBus; }; + +class SFE_UBLOX_GNSS_SUPER : public DevUBLOXGNSS // A Super Class - all three in one +{ +public: + SFE_UBLOX_GNSS_SUPER(){}; + + bool begin(uint8_t deviceAddress = kUBLOXGNSSDefaultAddress, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait, bool assumeSuccess = false) + { + _commType = COMM_TYPE_I2C; + + // Setup I2C object and pass into the superclass + setCommunicationBus(_i2cBus); + + // Initialize the I2C buss class i.e. setup default Wire port + _i2cBus.init(deviceAddress); + + // Initialize the system - return results + return this->DevUBLOXGNSS::init(maxWait, assumeSuccess); + } + + bool begin(TwoWire &wirePort, uint8_t deviceAddress = kUBLOXGNSSDefaultAddress, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait, bool assumeSuccess = false) + { + _commType = COMM_TYPE_I2C; + + // Setup I2C object and pass into the superclass + setCommunicationBus(_i2cBus); + + // Give the I2C port provided by the user to the I2C bus class. + _i2cBus.init(wirePort, deviceAddress); + + // Initialize the system - return results + return this->DevUBLOXGNSS::init(maxWait, assumeSuccess); + } + + bool begin(SPIClass &spiPort, uint8_t cs, SPISettings ismSettings, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait, bool assumeSuccess = false) + { + _commType = COMM_TYPE_SPI; + + // Setup a SPI object and pass into the superclass + setCommunicationBus(_spiBus); + + // Initialize the SPI bus class with provided SPI port, SPI setttings, and chip select pin. + _spiBus.init(spiPort, ismSettings, cs, true); + + // Initialize the system - return results + return this->DevUBLOXGNSS::init(maxWait, assumeSuccess); + } + + bool begin(SPIClass &spiPort, uint8_t cs, uint32_t spiSpeed = 4000000, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait, bool assumeSuccess = false) + { + _commType = COMM_TYPE_SPI; + + // Setup a SPI object and pass into the superclass + setCommunicationBus(_spiBus); + + // Initialize the SPI bus class with provided SPI port, SPI setttings, and chip select pin. + _spiBus.init(spiPort, spiSpeed, cs, true); + + // Initialize the system - return results + return this->DevUBLOXGNSS::init(maxWait, assumeSuccess); + } + + bool begin(Stream &serialPort, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait, bool assumeSuccess = false) + { + _commType = COMM_TYPE_SERIAL; + + // Setup Serial object and pass into the superclass + setCommunicationBus(_serialBus); + + // Initialize the Serial bus class + _serialBus.init(serialPort); + + // Initialize the system - return results + return this->DevUBLOXGNSS::init(maxWait, assumeSuccess); + } + +private: + SparkFun_UBLOX_GNSS::SfeI2C _i2cBus; + SparkFun_UBLOX_GNSS::SfeSPI _spiBus; + SparkFun_UBLOX_GNSS::SfeSerial _serialBus; +}; diff --git a/src/u-blox_GNSS.cpp b/src/u-blox_GNSS.cpp index 939237e..4214eff 100644 --- a/src/u-blox_GNSS.cpp +++ b/src/u-blox_GNSS.cpp @@ -6819,19 +6819,51 @@ bool DevUBLOXGNSS::setDGNSSConfiguration(sfe_ublox_dgnss_mode_e dgnssMode, uint8 // This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) uint8_t DevUBLOXGNSS::getProtocolVersionHigh(uint16_t maxWait) { - if (moduleSWVersion == nullptr) - initModuleSWVersion(); // Check that RAM has been allocated for the SW version - if (moduleSWVersion == nullptr) // Bail if the RAM allocation failed - return (false); + if (!prepareModuleInfo(maxWait)) + return 0; + return (moduleSWVersion->protocolVersionHigh); +} +uint8_t DevUBLOXGNSS::getProtocolVersionLow(uint16_t maxWait) +{ + if (!prepareModuleInfo(maxWait)) + return 0; + return (moduleSWVersion->protocolVersionLow); +} - if (moduleSWVersion->moduleQueried == false) - getProtocolVersion(maxWait); - return (moduleSWVersion->versionHigh); +// Get the firmware version of the u-blox module we're communicating with +uint8_t DevUBLOXGNSS::getFirmwareVersionHigh(uint16_t maxWait) +{ + if (!prepareModuleInfo(maxWait)) + return 0; + return (moduleSWVersion->firmwareVersionHigh); +} +uint8_t DevUBLOXGNSS::getFirmwareVersionLow(uint16_t maxWait) +{ + if (!prepareModuleInfo(maxWait)) + return 0; + return (moduleSWVersion->firmwareVersionLow); } -// Get the current protocol version of the u-blox module we're communicating with -// This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) -uint8_t DevUBLOXGNSS::getProtocolVersionLow(uint16_t maxWait) +// Get the firmware type +const char *DevUBLOXGNSS::getFirmwareType(uint16_t maxWait) +{ + static const char unknownFirmware[4] = { 'T', 'B', 'D', '\0' }; + if (!prepareModuleInfo(maxWait)) + return unknownFirmware; + return ((const char *)moduleSWVersion->firmwareType); +} + +// Get the module name +const char *DevUBLOXGNSS::getModuleName(uint16_t maxWait) +{ + static const char unknownModule[4] = { 'T', 'B', 'D', '\0' }; + if (!prepareModuleInfo(maxWait)) + return unknownModule; + return ((const char *)moduleSWVersion->moduleName); +} + +// PRIVATE: Common code to initialize moduleSWVersion +bool DevUBLOXGNSS::prepareModuleInfo(uint16_t maxWait) { if (moduleSWVersion == nullptr) initModuleSWVersion(); // Check that RAM has been allocated for the SW version @@ -6839,13 +6871,19 @@ uint8_t DevUBLOXGNSS::getProtocolVersionLow(uint16_t maxWait) return (false); if (moduleSWVersion->moduleQueried == false) - getProtocolVersion(maxWait); - return (moduleSWVersion->versionLow); + getModuleInfo(maxWait); + + return moduleSWVersion->moduleQueried; } // Get the current protocol version of the u-blox module we're communicating with // This is helpful when deciding if we should call the high-precision Lat/Long (HPPOSLLH) or the regular (POSLLH) -bool DevUBLOXGNSS::getProtocolVersion(uint16_t maxWait) +bool DevUBLOXGNSS::getProtocolVersion(uint16_t maxWait) // Old name - deprecated +{ + return getModuleInfo(maxWait); +} + +bool DevUBLOXGNSS::getModuleInfo(uint16_t maxWait) { if (moduleSWVersion == nullptr) initModuleSWVersion(); // Check that RAM has been allocated for the SW version @@ -6865,26 +6903,79 @@ bool DevUBLOXGNSS::getProtocolVersion(uint16_t maxWait) // Payload should now contain ~220 characters (depends on module type) // We will step through the payload looking at each extension field of 30 bytes - for (uint8_t extensionNumber = 0; extensionNumber < 10; extensionNumber++) + char *ptr; + uint8_t fwProtMod = 0; // Flags to show if we extracted the FWVER, PROTVER and MOD data + for (uint8_t extensionNumber = 0; extensionNumber < ((packetCfg.len - 40) / 30); extensionNumber++) { - // Now we need to find "PROTVER=18.00" in the incoming byte stream - if ((payloadCfg[(30 * extensionNumber) + 0] == 'P') && (payloadCfg[(30 * extensionNumber) + 6] == 'R')) + ptr = strstr((const char *)&payloadCfg[(30 * extensionNumber)], "FWVER="); // Check for FWVER (should be in extension 1) + if (ptr != nullptr) { - moduleSWVersion->versionHigh = (payloadCfg[(30 * extensionNumber) + 8] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 9] - '0'); // Convert '18' to 18 - moduleSWVersion->versionLow = (payloadCfg[(30 * extensionNumber) + 11] - '0') * 10 + (payloadCfg[(30 * extensionNumber) + 12] - '0'); // Convert '00' to 00 - moduleSWVersion->moduleQueried = true; // Mark this data as new + ptr += strlen("FWVER="); // Point to the firmware type (HPG etc.) + int i = 0; + while ((i < firmwareTypeLen) && (*ptr != '\0') && (*ptr != ' ')) // Extract the firmware type (3 chars) + moduleSWVersion->firmwareType[i++] = *ptr++; + moduleSWVersion->firmwareType[i] = '\0'; // NULL-terminate -#ifndef SFE_UBLOX_REDUCED_PROG_MEM - if (_printDebug == true) + if (*ptr == ' ') + ptr++; // Skip the space + + int firmwareHi = 0; + int firmwareLo = 0; + int scanned = sscanf(ptr, "%d.%d", &firmwareHi, &firmwareLo); + if (scanned == 2) // Check we extracted the firmware version successfully { - _debugSerial.print(F("Protocol version: ")); - _debugSerial.print(moduleSWVersion->versionHigh); - _debugSerial.print(F(".")); - _debugSerial.println(moduleSWVersion->versionLow); + moduleSWVersion->firmwareVersionHigh = firmwareHi; + moduleSWVersion->firmwareVersionLow = firmwareLo; + fwProtMod |= 0x01; // Record that we got the FWVER + } + } + ptr = strstr((const char *)&payloadCfg[(30 * extensionNumber)], "PROTVER="); // Check for PROTVER (should be in extension 2) + if (ptr != nullptr) + { + ptr += strlen("PROTVER="); // Point to the protocol version + int protHi = 0; + int protLo = 0; + int scanned = sscanf(ptr, "%d.%d", &protHi, &protLo); + if (scanned == 2) // Check we extracted the firmware version successfully + { + moduleSWVersion->protocolVersionHigh = protHi; + moduleSWVersion->protocolVersionLow = protLo; + fwProtMod |= 0x02; // Record that we got the PROTVER } -#endif - return (true); // Success! } + ptr = strstr((const char *)&payloadCfg[(30 * extensionNumber)], "MOD="); // Check for MOD (should be in extension 3) + if (ptr != nullptr) + { + ptr += strlen("MOD="); // Point to the module name + int i = 0; + while ((i < moduleNameMaxLen) && (*ptr != '\0') && (*ptr != ' ')) // Copy the module name + moduleSWVersion->moduleName[i++] = *ptr++; + moduleSWVersion->moduleName[i] = '\0'; // NULL-terminate + fwProtMod |= 0x04; // Record that we got the MOD + } + } + + if (fwProtMod == 0x07) // Did we extract all three? + { +#ifndef SFE_UBLOX_REDUCED_PROG_MEM + if (_printDebug == true) + { + _debugSerial.print(F("getModuleInfo: FWVER: ")); + _debugSerial.print(moduleSWVersion->firmwareVersionHigh); + _debugSerial.print(F(".")); + _debugSerial.println(moduleSWVersion->firmwareVersionLow); + _debugSerial.print(F("getModuleInfo: PROTVER: ")); + _debugSerial.print(moduleSWVersion->protocolVersionHigh); + _debugSerial.print(F(".")); + _debugSerial.println(moduleSWVersion->protocolVersionLow); + _debugSerial.print(F("getModuleInfo: MOD: ")); + _debugSerial.println(moduleSWVersion->moduleName); + } +#endif + + moduleSWVersion->moduleQueried = true; // Mark this data as new + + return (true); } return (false); // We failed @@ -6902,8 +6993,12 @@ bool DevUBLOXGNSS::initModuleSWVersion() #endif return (false); } - moduleSWVersion->versionHigh = 0; - moduleSWVersion->versionLow = 0; + moduleSWVersion->protocolVersionHigh = 0; // Clear the contents + moduleSWVersion->protocolVersionLow = 0; + moduleSWVersion->firmwareVersionHigh = 0; + moduleSWVersion->firmwareVersionLow = 0; + moduleSWVersion->firmwareType[0] = 0; + moduleSWVersion->moduleName[0] = 0; moduleSWVersion->moduleQueried = false; return (true); } diff --git a/src/u-blox_GNSS.h b/src/u-blox_GNSS.h index 00d0c66..849c298 100644 --- a/src/u-blox_GNSS.h +++ b/src/u-blox_GNSS.h @@ -353,8 +353,16 @@ class DevUBLOXGNSS // Read the module's protocol version uint8_t getProtocolVersionHigh(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Returns the PROTVER XX.00 from UBX-MON-VER register uint8_t getProtocolVersionLow(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Returns the PROTVER 00.XX from UBX-MON-VER register - bool getProtocolVersion(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Queries module, loads low/high bytes - moduleSWVersion_t *moduleSWVersion = nullptr; // Pointer to struct. RAM will be allocated for this if/when necessary + uint8_t getFirmwareVersionHigh(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Returns the FWVER XX.00 from UBX-MON-VER register + uint8_t getFirmwareVersionLow(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Returns the FWVER 00.XX from UBX-MON-VER register + const char *getFirmwareType(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Returns the firmware type (SPG, HPG, ADR, etc.) from UBX-MON-VER register + const char *getModuleName(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Returns the module name (ZED-F9P, ZED-F9R, etc.) from UBX-MON-VER register + bool getProtocolVersion(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Deprecated. Use getModuleInfo. + bool getModuleInfo(uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Queries module, extracts info +protected: + bool prepareModuleInfo(uint16_t maxWait); +public: + moduleSWVersion_t *moduleSWVersion = nullptr; // Pointer to struct. RAM will be allocated for this if/when necessary // Support for geofences bool addGeofence(int32_t latitude, int32_t longitude, uint32_t radius, uint8_t confidence = 0, bool pinPolarity = 0, uint8_t pin = 0, uint8_t layer = VAL_LAYER_RAM_BBR, uint16_t maxWait = kUBLOXGNSSDefaultMaxWait); // Add a new geofence diff --git a/src/u-blox_config_keys.h b/src/u-blox_config_keys.h index aa31f67..223c8ca 100644 --- a/src/u-blox_config_keys.h +++ b/src/u-blox_config_keys.h @@ -1022,7 +1022,7 @@ const uint32_t UBLOX_CFG_RINV_BINARY = UBX_CFG_L | 0x10c70002; // Data is bi const uint32_t UBLOX_CFG_RINV_DATA_SIZE = UBX_CFG_U1 | 0x20c70003; // Size of data const uint32_t UBLOX_CFG_RINV_CHUNK0 = UBX_CFG_X8 | 0x50c70004; // Data bytes 1-8 (LSB) const uint32_t UBLOX_CFG_RINV_CHUNK1 = UBX_CFG_X8 | 0x50c70005; // Data bytes 9-16 -const uint32_t UBLOX_CFG_RINV_CHUNK2 = UBX_CFG_X8 | 0x50c70006; // Data bytes 17-240x44434241. +const uint32_t UBLOX_CFG_RINV_CHUNK2 = UBX_CFG_X8 | 0x50c70006; // Data bytes 17-24 const uint32_t UBLOX_CFG_RINV_CHUNK3 = UBX_CFG_X8 | 0x50c70007; // Data bytes 25-30 (MSB) // CFG-RTCM: RTCM protocol configuration diff --git a/src/u-blox_external_typedefs.h b/src/u-blox_external_typedefs.h index d40b0ee..7854724 100644 --- a/src/u-blox_external_typedefs.h +++ b/src/u-blox_external_typedefs.h @@ -215,10 +215,16 @@ typedef struct } geofenceParams_t; // Struct to hold the module software version +#define firmwareTypeLen 3 // HPG, SPG, etc. +#define moduleNameMaxLen 13 // Allow for: 4-chars minus 4-chars minus 3-chars typedef struct { - uint8_t versionLow; // Loaded from getProtocolVersion(). - uint8_t versionHigh; + uint8_t protocolVersionLow; // Loaded from getModuleInfo() + uint8_t protocolVersionHigh; + uint8_t firmwareVersionLow; + uint8_t firmwareVersionHigh; + char firmwareType[firmwareTypeLen + 1]; // Include space for a NULL + char moduleName[moduleNameMaxLen + 1]; // Include space for a NULL bool moduleQueried; } moduleSWVersion_t;