From 16043c644a2e86de3af8c3bf357ecb16c18a47b8 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 20 Mar 2023 11:17:17 +0000 Subject: [PATCH] Add enable / configure odometer methods and example - resolves #185 --- .../CallbackExample2_NAV_ODO.ino | 33 ++++++++-- keywords.txt | 14 ++++ library.properties | 2 +- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 64 +++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 21 +++++- 5 files changed, 126 insertions(+), 8 deletions(-) diff --git a/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino b/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino index 181824b..3c372e3 100644 --- a/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino +++ b/examples/Callbacks/CallbackExample2_NAV_ODO/CallbackExample2_NAV_ODO.ino @@ -2,9 +2,8 @@ Configuring the GNSS to automatically send odometer reports over I2C and display the data using a callback By: Paul Clark SparkFun Electronics - Date: December 30th, 2020 - License: MIT. See license file for more information but you can - basically do whatever you want with this code. + Date: March 20th, 2023 + License: MIT. See license file for more information. This example shows how to configure the u-blox GNSS to send odometer reports automatically and display the data via a callback. No more polling! @@ -55,6 +54,8 @@ void printODOdata(UBX_NAV_ODO_data_t *ubxDataStruct) void setup() { + delay(1000); + Serial.begin(115200); while (!Serial); //Wait for user to open terminal Serial.println("SparkFun u-blox Example"); @@ -63,10 +64,9 @@ void setup() //myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial - if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port + while (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.println(F("u-blox GNSS not detected at default I2C address. Please check wiring.")); } myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) @@ -74,6 +74,27 @@ void setup() myGNSS.setNavigationFrequency(1); //Produce one solution per second + //By default, the odometer is disabled. We need to enable it. + //We can enable it using the default settings: + myGNSS.enableOdometer(); + + //Or we can configure it using our own settings, by performing a read-modify-write: + uint8_t flags; // Odometer/Low-speed COG filter flags + uint8_t odoCfg; // Odometer filter settings + uint8_t cogMaxSpeed; // Speed below which course-over-ground (COG) is computed with the low-speed COG filter : m/s * 0.1 + uint8_t cogMaxPosAcc; // Maximum acceptable position accuracy for computing COG with the low-speed COG filter + uint8_t velLpGain; // Velocity low-pass filter level + uint8_t cogLpGain; // COG low-pass filter level + + if (myGNSS.getOdometerConfig(&flags, &odoCfg, &cogMaxSpeed, &cogMaxPosAcc, &velLpGain, &cogLpGain)) + { + flags = UBX_CFG_ODO_USE_ODO; // Enable the odometer + odoCfg = UBX_CFG_ODO_CAR; // Use the car profile (others are RUN, CYCLE, SWIM, CUSTOM) + myGNSS.setOdometerConfig(flags, odoCfg, cogMaxSpeed, cogMaxPosAcc, velLpGain, cogLpGain); // Set the configuration + } + else + Serial.println("Could not read odometer config!"); + //myGNSS.resetOdometer(); //Uncomment this line to reset the odometer myGNSS.setAutoNAVODOcallbackPtr(&printODOdata); // Enable automatic NAV ODO messages with callback to printODOdata diff --git a/keywords.txt b/keywords.txt index 52cfef2..6f1b29e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -193,6 +193,9 @@ setDynamicModel KEYWORD2 getDynamicModel KEYWORD2 resetOdometer KEYWORD2 +enableOdometer KEYWORD2 +getOdometerConfig KEYWORD2 +setOdometerConfig KEYWORD2 enableGNSS KEYWORD2 isGNSSenabled KEYWORD2 @@ -831,6 +834,17 @@ VAL_CFG_SUBSEC_ANTCONF LITERAL1 VAL_CFG_SUBSEC_LOGCONF LITERAL1 VAL_CFG_SUBSEC_FTSCONF LITERAL1 +UBX_CFG_ODO_USE_ODO LITERAL1 +UBX_CFG_ODO_USE_COG LITERAL1 +UBX_CFG_ODO_OUT_LP_VEL LITERAL1 +UBX_CFG_ODO_OUT_LP_COG LITERAL1 + +UBX_CFG_ODO_RUN LITERAL1 +UBX_CFG_ODO_CYCLE LITERAL1 +UBX_CFG_ODO_SWIM LITERAL1 +UBX_CFG_ODO_CAR LITERAL1 +UBX_CFG_ODO_CUSTOM LITERAL1 + DYN_MODEL_PORTABLE LITERAL1 DYN_MODEL_STATIONARY LITERAL1 DYN_MODEL_PEDESTRIAN LITERAL1 diff --git a/library.properties b/library.properties index 987ab33..86de605 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.2.21 +version=2.2.22 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_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 16ea35f..3d9e702 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -8207,6 +8207,70 @@ bool SFE_UBLOX_GNSS::resetOdometer(uint16_t maxWait) return (sendCommand(&packetCfg, maxWait, true) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK } +// Enable / disable the odometer +bool SFE_UBLOX_GNSS::enableOdometer(bool enable, uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_ODO; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + // Ask module for the current odometer configuration. Loads into payloadCfg. + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + if (enable) + payloadCfg[4] = payloadCfg[4] | UBX_CFG_ODO_USE_ODO; + else + payloadCfg[4] = payloadCfg[4] & ~UBX_CFG_ODO_USE_ODO; + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + +// Read the odometer configuration +bool SFE_UBLOX_GNSS::getOdometerConfig(uint8_t *flags, uint8_t *odoCfg, uint8_t *cogMaxSpeed, uint8_t *cogMaxPosAcc, uint8_t *velLpGain, uint8_t *cogLpGain, uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_ODO; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + // Ask module for the current odometer configuration. Loads into payloadCfg. + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + *flags = payloadCfg[4]; + *odoCfg = payloadCfg[5]; + *cogMaxSpeed = payloadCfg[12]; + *cogMaxPosAcc = payloadCfg[13]; + *velLpGain = payloadCfg[16]; + *cogLpGain = payloadCfg[17]; + + return true; +} + +// Configure the odometer +bool SFE_UBLOX_GNSS::setOdometerConfig(uint8_t flags, uint8_t odoCfg, uint8_t cogMaxSpeed, uint8_t cogMaxPosAcc, uint8_t velLpGain, uint8_t cogLpGain, uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_ODO; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + // Ask module for the current odometer configuration. Loads into payloadCfg. + if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK + return (false); + + payloadCfg[4] = flags; + payloadCfg[5] = odoCfg; + payloadCfg[12] = cogMaxSpeed; + payloadCfg[13] = cogMaxPosAcc; + payloadCfg[16] = velLpGain; + payloadCfg[17] = cogLpGain; + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + // Enable/Disable individual GNSS systems using UBX-CFG-GNSS bool SFE_UBLOX_GNSS::enableGNSS(bool enable, sfe_ublox_gnss_ids_e id, uint16_t maxWait) { diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 18f2562..c83f002 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -465,6 +465,22 @@ const uint8_t COM_TYPE_NMEA = (1 << 1); const uint8_t COM_TYPE_RTCM3 = (1 << 5); const uint8_t COM_TYPE_SPARTN = (1 << 6); +// Odometer configuration - flags +const uint8_t UBX_CFG_ODO_USE_ODO = (1 << 0); +const uint8_t UBX_CFG_ODO_USE_COG = (1 << 1); +const uint8_t UBX_CFG_ODO_OUT_LP_VEL = (1 << 2); +const uint8_t UBX_CFG_ODO_OUT_LP_COG = (1 << 3); + +// Odometer configuration - odoCfg +enum odoCfg_e +{ + UBX_CFG_ODO_RUN = 0, + UBX_CFG_ODO_CYCLE, + UBX_CFG_ODO_SWIM, + UBX_CFG_ODO_CAR, + UBX_CFG_ODO_CUSTOM, +}; + // Configuration Sub-Section mask definitions for saveConfigSelective (UBX-CFG-CFG) const uint32_t VAL_CFG_SUBSEC_IOPORT = 0x00000001; // ioPort - communications port settings (causes IO system reset!) const uint32_t VAL_CFG_SUBSEC_MSGCONF = 0x00000002; // msgConf - message configuration @@ -909,8 +925,11 @@ public: bool setDynamicModel(dynModel newDynamicModel = DYN_MODEL_PORTABLE, uint16_t maxWait = defaultMaxWait); uint8_t getDynamicModel(uint16_t maxWait = defaultMaxWait); // Get the dynamic model - returns 255 if the sendCommand fails - // Reset the odometer + // Reset / enable / configure the odometer bool resetOdometer(uint16_t maxWait = defaultMaxWait); // Reset the odometer + bool enableOdometer(bool enable = true, uint16_t maxWait = defaultMaxWait); // Enable / disable the odometer + bool getOdometerConfig(uint8_t *flags, uint8_t *odoCfg, uint8_t *cogMaxSpeed, uint8_t *cogMaxPosAcc, uint8_t *velLpGain, uint8_t *cogLpGain, uint16_t maxWait = defaultMaxWait); // Read the odometer configuration + bool setOdometerConfig(uint8_t flags, uint8_t odoCfg, uint8_t cogMaxSpeed, uint8_t cogMaxPosAcc, uint8_t velLpGain, uint8_t cogLpGain, uint16_t maxWait = defaultMaxWait); // Configure the odometer // Enable/Disable individual GNSS systems using UBX-CFG-GNSS // Note: you must leave at least one major GNSS enabled! If in doubt, enable GPS before disabling the others