From de5e73947be92f137f644df54039b043bf95dcda Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 1 Apr 2021 13:52:30 +0100 Subject: [PATCH] Starting to add support for multiple message rates --- .../Example27_MultipleRates.ino | 90 +++++++++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 26 ++++-- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 2 + 3 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 examples/Example27_MultipleRates/Example27_MultipleRates.ino diff --git a/examples/Example27_MultipleRates/Example27_MultipleRates.ino b/examples/Example27_MultipleRates/Example27_MultipleRates.ino new file mode 100644 index 0000000..2fa97bf --- /dev/null +++ b/examples/Example27_MultipleRates/Example27_MultipleRates.ino @@ -0,0 +1,90 @@ +/* + Configuring the GNSS to produce multiple messages at different rates + By: Paul Clark + SparkFun Electronics + Date: April 1st, 2021 + License: MIT. See license file for more information but you can + basically do whatever you want with this code. + + This example shows how to configure the U-Blox GNSS to output multiple messages at different rates: + PVT is output once per measurement; + POS_ECEF is output every second measurement; + VEL_NED is output every third measurement. + + Feel like supporting open source hardware? + Buy a board from SparkFun! + ZED-F9P RTK2: https://www.sparkfun.com/products/15136 + NEO-M8P RTK: https://www.sparkfun.com/products/15005 + SAM-M8Q: https://www.sparkfun.com/products/15106 + + 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 //http://librarymanager/All#SparkFun_u-blox_GNSS +SFE_UBLOX_GNSS myGNSS; + +void setup() +{ + Serial.begin(115200); + while (!Serial); //Wait for user to open terminal + Serial.println("SparkFun u-blox Example"); + + Wire.begin(); + + 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); + } + + myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) + myGNSS.setMeasurementRate(1000); //Produce a measurement every 1000ms + myGNSS.setNavigationRate(1); //Produce a navigation solution every measurement + + myGNSS.setAutoPVTrate(1); //Tell the GNSS to "send" each PVT solution every measurement + //myGNSS.setAutoPOSECEFrate(2); //Tell the GNSS to "send" each POS_ECEF solution every second measurement + myGNSS.setAutoNAVVELNEDrate(3); //Tell the GNSS to "send" each VEL_NED solution every third measurement + //myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR +} + +void loop() +{ + // Calling getPVT returns true if there actually is a fresh navigation solution available. + if (myGNSS.getPVT()) + { + long latitude = myGNSS.getLatitude(); + Serial.print(F("Lat: ")); + Serial.print(latitude); + + long longitude = myGNSS.getLongitude(); + Serial.print(F(" Long: ")); + Serial.print(longitude); + Serial.print(F(" (degrees * 10^-7)")); + + long altitude = myGNSS.getAltitude(); + Serial.print(F(" Alt: ")); + Serial.print(altitude); + Serial.println(F(" (mm)")); + } + + // Calling getVELNED returns true if there actually is fresh velocity data available. + if (myGNSS.getNAVVELNED()) + { + Serial.print(F("velN: ")); + Serial.print((float)myGNSS.packetUBXNAVVELNED->data.velN / 100.0, 2); // convert velN to m/s + + Serial.print(F(" velE: ")); + Serial.print((float)myGNSS.packetUBXNAVVELNED->data.velE / 100.0, 2); // convert velE to m/s + + Serial.print(F(" velD: ")); + Serial.print((float)myGNSS.packetUBXNAVVELNED->data.velD / 100.0, 2); // convert velD to m/s + Serial.println(F(" (m/s)")); + + myGNSS.flushNAVVELNED(); //Mark all the data as read/stale so we get fresh data next time + } +} diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 3fde61c..75e0cca 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -5755,12 +5755,19 @@ boolean SFE_UBLOX_GNSS::getPVT(uint16_t maxWait) //works. boolean SFE_UBLOX_GNSS::setAutoPVT(boolean enable, uint16_t maxWait) { - return setAutoPVT(enable, true, maxWait); + return setAutoPVTrate(enable ? 1 : 0, true, maxWait); } //Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT //works. boolean SFE_UBLOX_GNSS::setAutoPVT(boolean enable, boolean implicitUpdate, uint16_t maxWait) +{ + return setAutoPVTrate(enable ? 1 : 0, implicitUpdate, maxWait); +} + +//Enable or disable automatic navigation message generation by the GNSS. This changes the way getPVT +//works. +boolean SFE_UBLOX_GNSS::setAutoPVTrate(uint8_t rate, boolean implicitUpdate, uint16_t maxWait) { if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data if (packetUBXNAVPVT == NULL) //Only attempt this if RAM allocation was successful @@ -5772,12 +5779,12 @@ boolean SFE_UBLOX_GNSS::setAutoPVT(boolean enable, boolean implicitUpdate, uint1 packetCfg.startingSpot = 0; payloadCfg[0] = UBX_CLASS_NAV; payloadCfg[1] = UBX_NAV_PVT; - payloadCfg[2] = enable ? 1 : 0; // rate relative to navigation freq. + payloadCfg[2] = rate; // rate relative to navigation freq. boolean ok = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK if (ok) { - packetUBXNAVPVT->automaticFlags.flags.bits.automatic = enable; + packetUBXNAVPVT->automaticFlags.flags.bits.automatic = (rate > 0); packetUBXNAVPVT->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; } packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false; @@ -6199,12 +6206,19 @@ boolean SFE_UBLOX_GNSS::getNAVVELNED(uint16_t maxWait) //works. boolean SFE_UBLOX_GNSS::setAutoNAVVELNED(boolean enable, uint16_t maxWait) { - return setAutoNAVVELNED(enable, true, maxWait); + return setAutoNAVVELNEDrate(enable ? 1 : 0, true, maxWait); } //Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED //works. boolean SFE_UBLOX_GNSS::setAutoNAVVELNED(boolean enable, boolean implicitUpdate, uint16_t maxWait) +{ + return setAutoNAVVELNEDrate(enable ? 1 : 0, implicitUpdate, maxWait); +} + +//Enable or disable automatic navigation message generation by the GNSS. This changes the way getVELNED +//works. +boolean SFE_UBLOX_GNSS::setAutoNAVVELNEDrate(uint8_t rate, boolean implicitUpdate, uint16_t maxWait) { if (packetUBXNAVVELNED == NULL) initPacketUBXNAVVELNED(); //Check that RAM has been allocated for the data if (packetUBXNAVVELNED == NULL) //Only attempt this if RAM allocation was successful @@ -6216,12 +6230,12 @@ boolean SFE_UBLOX_GNSS::setAutoNAVVELNED(boolean enable, boolean implicitUpdate, packetCfg.startingSpot = 0; payloadCfg[0] = UBX_CLASS_NAV; payloadCfg[1] = UBX_NAV_VELNED; - payloadCfg[2] = enable ? 1 : 0; // rate relative to navigation freq. + payloadCfg[2] = rate; // rate relative to navigation freq. boolean ok = ((sendCommand(&packetCfg, maxWait)) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK if (ok) { - packetUBXNAVVELNED->automaticFlags.flags.bits.automatic = enable; + packetUBXNAVVELNED->automaticFlags.flags.bits.automatic = (rate > 0); packetUBXNAVVELNED->automaticFlags.flags.bits.implicitUpdate = implicitUpdate; } packetUBXNAVVELNED->moduleQueried.moduleQueried.bits.all = false; diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 515a87d..aee8552 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -733,6 +733,7 @@ public: boolean getPVT(uint16_t maxWait = defaultMaxWait); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Returns true if new PVT is available. boolean setAutoPVT(boolean enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVT reports at the navigation frequency boolean setAutoPVT(boolean enabled, boolean implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVT reports at the navigation frequency, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update + boolean setAutoPVTrate(uint8_t rate, boolean implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic PVT reports at the navigation frequency, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update boolean setAutoPVTcallback(void (*callbackPointer)(UBX_NAV_PVT_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic PVT reports at the navigation frequency. Data is accessed from the callback. boolean assumeAutoPVT(boolean enabled, boolean implicitUpdate = true); //In case no config access to the GPS is possible and PVT is send cyclically already void flushPVT(); //Mark all the PVT data as read/stale @@ -757,6 +758,7 @@ public: boolean getNAVVELNED(uint16_t maxWait = defaultMaxWait); // NAV VELNED boolean setAutoNAVVELNED(boolean enabled, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELNED reports at the navigation frequency boolean setAutoNAVVELNED(boolean enabled, boolean implicitUpdate, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELNED reports at the navigation frequency, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update + boolean setAutoNAVVELNEDrate(uint8_t rate, boolean implicitUpdate = true, uint16_t maxWait = defaultMaxWait); //Enable/disable automatic VELNED reports at the navigation frequency, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update boolean setAutoNAVVELNEDcallback(void (*callbackPointer)(UBX_NAV_VELNED_data_t), uint16_t maxWait = defaultMaxWait); //Enable automatic VELNED reports at the navigation frequency. Data is accessed from the callback. boolean assumeAutoNAVVELNED(boolean enabled, boolean implicitUpdate = true); //In case no config access to the GPS is possible and VELNED is send cyclically already void flushNAVVELNED(); //Mark all the data as read/stale