From 5420c616dc33f71522a3c8ba92530a8b293899d4 Mon Sep 17 00:00:00 2001 From: Thomas Nabelek Date: Wed, 20 Oct 2021 23:41:43 -0600 Subject: [PATCH 1/5] Saving progress on UBX-CFG-PM2 implementation --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 56 ++++++++++++ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 3 +- src/u-blox_structs.h | 93 ++++++++++++-------- 3 files changed, 116 insertions(+), 36 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 736bf51..e390264 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4823,6 +4823,62 @@ uint8_t SFE_UBLOX_GNSS::getPowerSaveMode(uint16_t maxWait) return (payloadCfg[1]); // Return the low power mode } +// Extended power management configuration +// Sends the UBX-CFG-PM2 message to configure extended power management +// Note: Section 32.10.23 of the u-blox 8 / u-blox M8 Receiver description document gives three different versions +// of this message. Version 0x00 is implemented here since it is the most widely supported +boolean SFE_UBLOX_GNSS::configurePowerManagement(UBX_CFG_PM2_data_t* data, uint16_t maxWait) +{ + if (data == NULL) // If the user forgot to include the data pointer, bail + return (false); + + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_PM2; + packetCfg.len = UBX_CFG_PM2_LEN; + packetCfg.startingSpot = 0; + + // Insert the data, converting multi-byte values to little endian + payloadCfg[ 0] = 0x00; // Message version + + payloadCfg[ 1] = data->version; + payloadCfg[ 4] = data->antCableDelay & 0xFF; // Little Endian + payloadCfg[ 5] = data->antCableDelay >> 8; + payloadCfg[ 6] = data->rfGroupDelay & 0xFF; // Little Endian + payloadCfg[ 7] = data->rfGroupDelay >> 8; + payloadCfg[ 8] = data->freqPeriod & 0xFF; // Little Endian + payloadCfg[ 9] = (data->freqPeriod >> 8) & 0xFF; + payloadCfg[10] = (data->freqPeriod >> 16) & 0xFF; + payloadCfg[11] = (data->freqPeriod >> 24) & 0xFF; + payloadCfg[12] = data->freqPeriodLock & 0xFF; // Little Endian + payloadCfg[13] = (data->freqPeriodLock >> 8) & 0xFF; + payloadCfg[14] = (data->freqPeriodLock >> 16) & 0xFF; + payloadCfg[15] = (data->freqPeriodLock >> 24) & 0xFF; + payloadCfg[16] = data->pulseLenRatio & 0xFF; // Little Endian + payloadCfg[17] = (data->pulseLenRatio >> 8) & 0xFF; + payloadCfg[18] = (data->pulseLenRatio >> 16) & 0xFF; + payloadCfg[19] = (data->pulseLenRatio >> 24) & 0xFF; + payloadCfg[20] = data->pulseLenRatioLock & 0xFF; // Little Endian + payloadCfg[21] = (data->pulseLenRatioLock >> 8) & 0xFF; + payloadCfg[22] = (data->pulseLenRatioLock >> 16) & 0xFF; + payloadCfg[23] = (data->pulseLenRatioLock >> 24) & 0xFF; + payloadCfg[24] = data->userConfigDelay & 0xFF; // Little Endian + payloadCfg[25] = (data->userConfigDelay >> 8) & 0xFF; + payloadCfg[26] = (data->userConfigDelay >> 16) & 0xFF; + payloadCfg[27] = (data->userConfigDelay >> 24) & 0xFF; + payloadCfg[28] = data->flags.all & 0xFF; // Little Endian + payloadCfg[29] = (data->flags.all >> 8) & 0xFF; + payloadCfg[30] = (data->flags.all >> 16) & 0xFF; + payloadCfg[31] = (data->flags.all >> 24) & 0xFF; + + + payloadCfg[4] = (durationInMs >> (8 * 0)) & 0xff; + payloadCfg[5] = (durationInMs >> (8 * 1)) & 0xff; + payloadCfg[6] = (durationInMs >> (8 * 2)) & 0xff; + payloadCfg[7] = (durationInMs >> (8 * 3)) & 0xff; + + return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK +} + // Powers off the GPS device for a given duration to reduce power consumption. // NOTE: Querying the device before the duration is complete, for example by "getLatitude()" will wake it up! // Returns true if command has not been not acknowledged. diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index a7fb2d7..2ea791d 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -744,9 +744,10 @@ class SFE_UBLOX_GNSS // Storage for the geofence parameters. RAM is allocated for this if/when required. geofenceParams_t *currentGeofenceParams = NULL; // Pointer to struct. RAM will be allocated for this if/when necessary - //Power save / off + //Power save / power management configuration / power off boolean powerSaveMode(bool power_save = true, uint16_t maxWait = defaultMaxWait); uint8_t getPowerSaveMode(uint16_t maxWait = defaultMaxWait); // Returns 255 if the sendCommand fails + boolean configurePowerManagement(UBX_CFG_PM2_data_t* data = NULL, uint16_t maxWait = defaultMaxWait); boolean powerOff(uint32_t durationInMs, uint16_t maxWait = defaultMaxWait); boolean powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, boolean forceWhileUsb = true, uint16_t maxWait = 1100); diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 8f39453..3e66ff0 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1171,6 +1171,28 @@ typedef struct // CFG-specific structs +// UBX-CFG-PM2 (0x06 0x3B): Extended power management configuration +const uint16_t UBX_CFG_RATE_LEN = 43; + +typedef struct +{ + uint8_t maxStartupStateDur; + uint8_t flagExtintSel; + uint8_t flagExtintWake; + uint8_t flagExtintBackup; + uint8_t flagLimitPeakCurr; + uint8_t flagWaitTimeFix; + uint8_t flagUpdateRTC; + uint8_t flagUpdateEPH; + uint8_t flagDoNotEnterOff; + uint8_t flagMode; + uint32_t updatePeriod; + uint32_t searchPeriod; + uint32_t gridOffset; + uint16_t onTime; + uint16_t minAcqTime; +} UBX_CFG_PM2_data_t; + // UBX-CFG-RATE (0x06 0x08): Navigation/measurement rate settings const uint16_t UBX_CFG_RATE_LEN = 6; @@ -1206,6 +1228,42 @@ typedef struct UBX_CFG_RATE_data_t *callbackData; } UBX_CFG_RATE_t; + +// UBX-CFG-TP5 (0x06 0x31): Time pulse parameters +const uint16_t UBX_CFG_TP5_LEN = 32; + +typedef struct +{ + uint8_t tpIdx; // Time pulse selection (0 = TIMEPULSE, 1 = TIMEPULSE2) + uint8_t version; // Message version (0x01 for this version) + uint8_t reserved1[2]; + int16_t antCableDelay; // Antenna cable delay: ns + int16_t rfGroupDelay; // RF group delay: ns + uint32_t freqPeriod; // Frequency or period time, depending on setting of bit 'isFreq': Hz_or_us + uint32_t freqPeriodLock; // Frequency or period time when locked to GNSS time, only used if 'lockedOtherSet' is set: Hz_or_us + uint32_t pulseLenRatio; // Pulse length or duty cycle, depending on 'isLength': us_or_2^-32 + uint32_t pulseLenRatioLock; // Pulse length or duty cycle when locked to GNSS time, only used if 'lockedOtherSet' is set: us_or_2^-32 + int32_t userConfigDelay; // User-configurable time pulse delay: ns + union + { + uint32_t all; + struct + { + uint32_t active : 1; // If set enable time pulse; if pin assigned to another function, other function takes precedence. + uint32_t lockGnssFreq : 1; // If set, synchronize time pulse to GNSS as soon as GNSS time is valid. If not set, or before GNSS time is valid, use local clock. + uint32_t lockedOtherSet : 1; // If set the receiver switches between the timepulse settings given by 'freqPeriodLocked' & 'pulseLenLocked' and those given by 'freqPeriod' & 'pulseLen'. + uint32_t isFreq : 1; // If set 'freqPeriodLock' and 'freqPeriod' are interpreted as frequency, otherwise interpreted as period. + uint32_t isLength : 1; // If set 'pulseLenRatioLock' and 'pulseLenRatio' interpreted as pulse length, otherwise interpreted as duty cycle. + uint32_t alignToTow : 1; // Align pulse to top of second (period time must be integer fraction of 1s). Also set 'lockGnssFreq' to use this feature. + uint32_t polarity : 1; // Pulse polarity: 0: falling edge at top of second; 1: rising edge at top of second + uint32_t gridUtcGnss : 4; // Timegrid to use: 0: UTC; 1: GPS; 2: GLONASS; 3: BeiDou; 4: Galileo + uint32_t syncMode : 3; // Sync Manager lock mode to use: + // 0: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, never switch back to 'freqPeriod' and 'pulseLenRatio' + // 1: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, and switch back to 'freqPeriod' and 'pulseLenRatio' as soon as time gets inaccurate + } bits; + } flags; +} UBX_CFG_TP5_data_t; + // TIM-specific structs // UBX-TIM-TM2 (0x0D 0x03): Time mark data @@ -1849,39 +1907,4 @@ typedef struct UBX_HNR_INS_data_t *callbackData; } UBX_HNR_INS_t; -// UBX-CFG-TP5 (0x06 0x31): Time pulse parameters -const uint16_t UBX_CFG_TP5_LEN = 32; - -typedef struct -{ - uint8_t tpIdx; // Time pulse selection (0 = TIMEPULSE, 1 = TIMEPULSE2) - uint8_t version; // Message version (0x01 for this version) - uint8_t reserved1[2]; - int16_t antCableDelay; // Antenna cable delay: ns - int16_t rfGroupDelay; // RF group delay: ns - uint32_t freqPeriod; // Frequency or period time, depending on setting of bit 'isFreq': Hz_or_us - uint32_t freqPeriodLock; // Frequency or period time when locked to GNSS time, only used if 'lockedOtherSet' is set: Hz_or_us - uint32_t pulseLenRatio; // Pulse length or duty cycle, depending on 'isLength': us_or_2^-32 - uint32_t pulseLenRatioLock; // Pulse length or duty cycle when locked to GNSS time, only used if 'lockedOtherSet' is set: us_or_2^-32 - int32_t userConfigDelay; // User-configurable time pulse delay: ns - union - { - uint32_t all; - struct - { - uint32_t active : 1; // If set enable time pulse; if pin assigned to another function, other function takes precedence. - uint32_t lockGnssFreq : 1; // If set, synchronize time pulse to GNSS as soon as GNSS time is valid. If not set, or before GNSS time is valid, use local clock. - uint32_t lockedOtherSet : 1; // If set the receiver switches between the timepulse settings given by 'freqPeriodLocked' & 'pulseLenLocked' and those given by 'freqPeriod' & 'pulseLen'. - uint32_t isFreq : 1; // If set 'freqPeriodLock' and 'freqPeriod' are interpreted as frequency, otherwise interpreted as period. - uint32_t isLength : 1; // If set 'pulseLenRatioLock' and 'pulseLenRatio' interpreted as pulse length, otherwise interpreted as duty cycle. - uint32_t alignToTow : 1; // Align pulse to top of second (period time must be integer fraction of 1s). Also set 'lockGnssFreq' to use this feature. - uint32_t polarity : 1; // Pulse polarity: 0: falling edge at top of second; 1: rising edge at top of second - uint32_t gridUtcGnss : 4; // Timegrid to use: 0: UTC; 1: GPS; 2: GLONASS; 3: BeiDou; 4: Galileo - uint32_t syncMode : 3; // Sync Manager lock mode to use: - // 0: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, never switch back to 'freqPeriod' and 'pulseLenRatio' - // 1: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, and switch back to 'freqPeriod' and 'pulseLenRatio' as soon as time gets inaccurate - } bits; - } flags; -} UBX_CFG_TP5_data_t; - #endif From 79ea9b1e6151ffa2b8d322b635dfa756f09fc8a3 Mon Sep 17 00:00:00 2001 From: Thomas Nabelek Date: Tue, 26 Oct 2021 20:16:41 -0600 Subject: [PATCH 2/5] Saving progress --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 120 ++++++++++++------- src/SparkFun_u-blox_GNSS_Arduino_Library.h | 67 ++++++----- src/u-blox_structs.h | 2 +- 3 files changed, 113 insertions(+), 76 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index e390264..ced1499 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2933,9 +2933,12 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 len = i2cTransactionSize; _i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); - - for (uint16_t x = 0; x < len; x++) + char printBuffer[200] = {0}; + for (uint16_t x = 0; x < len; x++) { + sprintf(printBuffer, "Sending: 0x%02X", outgoingUBX->payload[startSpot + x]); + Serial.println(printBuffer); _i2cPort->write(outgoingUBX->payload[startSpot + x]); //Write a portion of the payload to the bus + } if (_i2cPort->endTransmission(false) != 0) //Don't release bus return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); //Sensor did not ACK @@ -4826,57 +4829,90 @@ uint8_t SFE_UBLOX_GNSS::getPowerSaveMode(uint16_t maxWait) // Extended power management configuration // Sends the UBX-CFG-PM2 message to configure extended power management // Note: Section 32.10.23 of the u-blox 8 / u-blox M8 Receiver description document gives three different versions -// of this message. Version 0x00 is implemented here since it is the most widely supported +// of this message. Version 0x01 is implemented here since it is the most widely supported version boolean SFE_UBLOX_GNSS::configurePowerManagement(UBX_CFG_PM2_data_t* data, uint16_t maxWait) { if (data == NULL) // If the user forgot to include the data pointer, bail return (false); - packetCfg.cls = UBX_CLASS_CFG; - packetCfg.id = UBX_CFG_PM2; - packetCfg.len = UBX_CFG_PM2_LEN; + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_PM2; + packetCfg.len = UBX_CFG_PM2_LEN; packetCfg.startingSpot = 0; // Insert the data, converting multi-byte values to little endian - payloadCfg[ 0] = 0x00; // Message version - - payloadCfg[ 1] = data->version; - payloadCfg[ 4] = data->antCableDelay & 0xFF; // Little Endian - payloadCfg[ 5] = data->antCableDelay >> 8; - payloadCfg[ 6] = data->rfGroupDelay & 0xFF; // Little Endian - payloadCfg[ 7] = data->rfGroupDelay >> 8; - payloadCfg[ 8] = data->freqPeriod & 0xFF; // Little Endian - payloadCfg[ 9] = (data->freqPeriod >> 8) & 0xFF; - payloadCfg[10] = (data->freqPeriod >> 16) & 0xFF; - payloadCfg[11] = (data->freqPeriod >> 24) & 0xFF; - payloadCfg[12] = data->freqPeriodLock & 0xFF; // Little Endian - payloadCfg[13] = (data->freqPeriodLock >> 8) & 0xFF; - payloadCfg[14] = (data->freqPeriodLock >> 16) & 0xFF; - payloadCfg[15] = (data->freqPeriodLock >> 24) & 0xFF; - payloadCfg[16] = data->pulseLenRatio & 0xFF; // Little Endian - payloadCfg[17] = (data->pulseLenRatio >> 8) & 0xFF; - payloadCfg[18] = (data->pulseLenRatio >> 16) & 0xFF; - payloadCfg[19] = (data->pulseLenRatio >> 24) & 0xFF; - payloadCfg[20] = data->pulseLenRatioLock & 0xFF; // Little Endian - payloadCfg[21] = (data->pulseLenRatioLock >> 8) & 0xFF; - payloadCfg[22] = (data->pulseLenRatioLock >> 16) & 0xFF; - payloadCfg[23] = (data->pulseLenRatioLock >> 24) & 0xFF; - payloadCfg[24] = data->userConfigDelay & 0xFF; // Little Endian - payloadCfg[25] = (data->userConfigDelay >> 8) & 0xFF; - payloadCfg[26] = (data->userConfigDelay >> 16) & 0xFF; - payloadCfg[27] = (data->userConfigDelay >> 24) & 0xFF; - payloadCfg[28] = data->flags.all & 0xFF; // Little Endian - payloadCfg[29] = (data->flags.all >> 8) & 0xFF; - payloadCfg[30] = (data->flags.all >> 16) & 0xFF; - payloadCfg[31] = (data->flags.all >> 24) & 0xFF; + memset(payloadCfg, 0, UBX_CFG_PM2_LEN); - payloadCfg[4] = (durationInMs >> (8 * 0)) & 0xff; - payloadCfg[5] = (durationInMs >> (8 * 1)) & 0xff; - payloadCfg[6] = (durationInMs >> (8 * 2)) & 0xff; - payloadCfg[7] = (durationInMs >> (8 * 3)) & 0xff; + payloadCfg[ 0] = 0x01; // Message version + payloadCfg[ 1] = 0; // Reserved + payloadCfg[ 2] = data->maxStartupStateDur; + payloadCfg[ 3] = 0; // Reserved - return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK + uint32_t flags = 0; + flags = flags | (data->flagExtintSel << 4); + flags = flags | (data->flagExtintWake << 5); + flags = flags | (data->flagExtintBackup << 6); + flags = flags | (data->flagLimitPeakCurr << 8); // Uses bits 8 and 9 + flags = flags | (data->flagWaitTimeFix << 10); + flags = flags | (data->flagUpdateRTC << 11); + flags = flags | (data->flagUpdateEPH << 12); + flags = flags | (data->flagDoNotEnterOff << 16); + flags = flags | (data->flagMode << 17); // Uses bits 17 and 18 + payloadCfg[ 4] = (flags >> (8 * 0)) & 0xFF; + payloadCfg[ 5] = (flags >> (8 * 1)) & 0xFF; + payloadCfg[ 6] = (flags >> (8 * 2)) & 0xFF; + payloadCfg[ 7] = (flags >> (8 * 3)) & 0xFF; + + payloadCfg[ 8] = (data->updatePeriod >> (8 * 0)) & 0xFF; + payloadCfg[ 9] = (data->updatePeriod >> (8 * 1)) & 0xFF; + payloadCfg[10] = (data->updatePeriod >> (8 * 2)) & 0xFF; + payloadCfg[11] = (data->updatePeriod >> (8 * 3)) & 0xFF; + + payloadCfg[12] = (data->searchPeriod >> (8 * 0)) & 0xFF; + payloadCfg[13] = (data->searchPeriod >> (8 * 1)) & 0xFF; + payloadCfg[14] = (data->searchPeriod >> (8 * 2)) & 0xFF; + payloadCfg[15] = (data->searchPeriod >> (8 * 3)) & 0xFF; + + payloadCfg[16] = (data->gridOffset >> (8 * 0)) & 0xFF; + payloadCfg[17] = (data->gridOffset >> (8 * 1)) & 0xFF; + payloadCfg[18] = (data->gridOffset >> (8 * 2)) & 0xFF; + payloadCfg[19] = (data->gridOffset >> (8 * 3)) & 0xFF; + + payloadCfg[20] = (data->onTime >> (8 * 0)) & 0xFF; + payloadCfg[21] = (data->onTime >> (8 * 1)) & 0xFF; + + payloadCfg[22] = (data->minAcqTime >> (8 * 0)) & 0xFF; + payloadCfg[23] = (data->minAcqTime >> (8 * 1)) & 0xFF; + + // Bytes 24 through (UBX_CFG_PM2_LEN-1) are reserved + + boolean cfg_result = sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT; + + return (cfg_result); // We are only expecting an ACK +} + +boolean SFE_UBLOX_GNSS::getPowerManagementConfiguration(uint16_t maxWait) +{ + packetCfg.cls = UBX_CLASS_CFG; + packetCfg.id = UBX_CFG_PM2; + packetCfg.len = 0; + packetCfg.startingSpot = 0; + + // Don't setup any payload items; we're just reading the current configuration + // Instead clear the structure since it will be read into + memset(payloadCfg, 0, UBX_CFG_PM2_LEN); + + boolean cfg_result = sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT; + + Serial.println("Data:"); + Serial.println(payloadCfg[0]); + Serial.println(payloadCfg[1]); + Serial.println(payloadCfg[2]); + Serial.println(payloadCfg[3]); + Serial.println(payloadCfg[4]); + + return (cfg_result); // We are only expecting an ACK } // Powers off the GPS device for a given duration to reduce power consumption. diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 2ea791d..e901449 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -190,40 +190,40 @@ const uint8_t UBX_CLASS_NMEA = 0xF0; //NMEA Strings: standard NMEA strings //Class: CFG //The following are used for configuration. Descriptions are from the ZED-F9P Interface Description pg 33-34 and NEO-M9N Interface Description pg 47-48 -const uint8_t UBX_CFG_ANT = 0x13; //Antenna Control Settings. Used to configure the antenna control settings -const uint8_t UBX_CFG_BATCH = 0x93; //Get/set data batching configuration. -const uint8_t UBX_CFG_CFG = 0x09; //Clear, Save, and Load Configurations. Used to save current configuration -const uint8_t UBX_CFG_DAT = 0x06; //Set User-defined Datum or The currently defined Datum -const uint8_t UBX_CFG_DGNSS = 0x70; //DGNSS configuration -const uint8_t UBX_CFG_ESFALG = 0x56; //ESF alignment -const uint8_t UBX_CFG_ESFA = 0x4C; //ESF accelerometer -const uint8_t UBX_CFG_ESFG = 0x4D; //ESF gyro -const uint8_t UBX_CFG_GEOFENCE = 0x69; //Geofencing configuration. Used to configure a geofence -const uint8_t UBX_CFG_GNSS = 0x3E; //GNSS system configuration -const uint8_t UBX_CFG_HNR = 0x5C; //High Navigation Rate -const uint8_t UBX_CFG_INF = 0x02; //Depending on packet length, either: poll configuration for one protocol, or information message configuration -const uint8_t UBX_CFG_ITFM = 0x39; //Jamming/Interference Monitor configuration +const uint8_t UBX_CFG_ANT = 0x13; //Antenna Control Settings. Used to configure the antenna control settings +const uint8_t UBX_CFG_BATCH = 0x93; //Get/set data batching configuration. +const uint8_t UBX_CFG_CFG = 0x09; //Clear, Save, and Load Configurations. Used to save current configuration +const uint8_t UBX_CFG_DAT = 0x06; //Set User-defined Datum or The currently defined Datum +const uint8_t UBX_CFG_DGNSS = 0x70; //DGNSS configuration +const uint8_t UBX_CFG_ESFALG = 0x56; //ESF alignment +const uint8_t UBX_CFG_ESFA = 0x4C; //ESF accelerometer +const uint8_t UBX_CFG_ESFG = 0x4D; //ESF gyro +const uint8_t UBX_CFG_GEOFENCE = 0x69; //Geofencing configuration. Used to configure a geofence +const uint8_t UBX_CFG_GNSS = 0x3E; //GNSS system configuration +const uint8_t UBX_CFG_HNR = 0x5C; //High Navigation Rate +const uint8_t UBX_CFG_INF = 0x02; //Depending on packet length, either: poll configuration for one protocol, or information message configuration +const uint8_t UBX_CFG_ITFM = 0x39; //Jamming/Interference Monitor configuration const uint8_t UBX_CFG_LOGFILTER = 0x47; //Data Logger Configuration -const uint8_t UBX_CFG_MSG = 0x01; //Poll a message configuration, or Set Message Rate(s), or Set Message Rate -const uint8_t UBX_CFG_NAV5 = 0x24; //Navigation Engine Settings. Used to configure the navigation engine including the dynamic model. -const uint8_t UBX_CFG_NAVX5 = 0x23; //Navigation Engine Expert Settings -const uint8_t UBX_CFG_NMEA = 0x17; //Extended NMEA protocol configuration V1 -const uint8_t UBX_CFG_ODO = 0x1E; //Odometer, Low-speed COG Engine Settings -const uint8_t UBX_CFG_PM2 = 0x3B; //Extended power management configuration -const uint8_t UBX_CFG_PMS = 0x86; //Power mode setup -const uint8_t UBX_CFG_PRT = 0x00; //Used to configure port specifics. Polls the configuration for one I/O Port, or Port configuration for UART ports, or Port configuration for USB port, or Port configuration for SPI port, or Port configuration for DDC port -const uint8_t UBX_CFG_PWR = 0x57; //Put receiver in a defined power state -const uint8_t UBX_CFG_RATE = 0x08; //Navigation/Measurement Rate Settings. Used to set port baud rates. -const uint8_t UBX_CFG_RINV = 0x34; //Contents of Remote Inventory -const uint8_t UBX_CFG_RST = 0x04; //Reset Receiver / Clear Backup Data Structures. Used to reset device. -const uint8_t UBX_CFG_RXM = 0x11; //RXM configuration -const uint8_t UBX_CFG_SBAS = 0x16; //SBAS configuration -const uint8_t UBX_CFG_TMODE3 = 0x71; //Time Mode Settings 3. Used to enable Survey In Mode -const uint8_t UBX_CFG_TP5 = 0x31; //Time Pulse Parameters -const uint8_t UBX_CFG_USB = 0x1B; //USB Configuration -const uint8_t UBX_CFG_VALDEL = 0x8C; //Used for config of higher version u-blox modules (ie protocol v27 and above). Deletes values corresponding to provided keys/ provided keys with a transaction -const uint8_t UBX_CFG_VALGET = 0x8B; //Used for config of higher version u-blox modules (ie protocol v27 and above). Configuration Items -const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version u-blox modules (ie protocol v27 and above). Sets values corresponding to provided key-value pairs/ provided key-value pairs within a transaction. +const uint8_t UBX_CFG_MSG = 0x01; //Poll a message configuration, or Set Message Rate(s), or Set Message Rate +const uint8_t UBX_CFG_NAV5 = 0x24; //Navigation Engine Settings. Used to configure the navigation engine including the dynamic model. +const uint8_t UBX_CFG_NAVX5 = 0x23; //Navigation Engine Expert Settings +const uint8_t UBX_CFG_NMEA = 0x17; //Extended NMEA protocol configuration V1 +const uint8_t UBX_CFG_ODO = 0x1E; //Odometer, Low-speed COG Engine Settings +const uint8_t UBX_CFG_PM2 = 0x3B; //Extended power management configuration +const uint8_t UBX_CFG_PMS = 0x86; //Power mode setup +const uint8_t UBX_CFG_PRT = 0x00; //Used to configure port specifics. Polls the configuration for one I/O Port, or Port configuration for UART ports, or Port configuration for USB port, or Port configuration for SPI port, or Port configuration for DDC port +const uint8_t UBX_CFG_PWR = 0x57; //Put receiver in a defined power state +const uint8_t UBX_CFG_RATE = 0x08; //Navigation/Measurement Rate Settings. Used to set port baud rates. +const uint8_t UBX_CFG_RINV = 0x34; //Contents of Remote Inventory +const uint8_t UBX_CFG_RST = 0x04; //Reset Receiver / Clear Backup Data Structures. Used to reset device. +const uint8_t UBX_CFG_RXM = 0x11; //RXM configuration +const uint8_t UBX_CFG_SBAS = 0x16; //SBAS configuration +const uint8_t UBX_CFG_TMODE3 = 0x71; //Time Mode Settings 3. Used to enable Survey In Mode +const uint8_t UBX_CFG_TP5 = 0x31; //Time Pulse Parameters +const uint8_t UBX_CFG_USB = 0x1B; //USB Configuration +const uint8_t UBX_CFG_VALDEL = 0x8C; //Used for config of higher version u-blox modules (ie protocol v27 and above). Deletes values corresponding to provided keys/ provided keys with a transaction +const uint8_t UBX_CFG_VALGET = 0x8B; //Used for config of higher version u-blox modules (ie protocol v27 and above). Configuration Items +const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version u-blox modules (ie protocol v27 and above). Sets values corresponding to provided key-value pairs/ provided key-value pairs within a transaction. //Class: NMEA //The following are used to enable NMEA messages. Descriptions come from the NMEA messages overview in the ZED-F9P Interface Description @@ -748,6 +748,7 @@ class SFE_UBLOX_GNSS boolean powerSaveMode(bool power_save = true, uint16_t maxWait = defaultMaxWait); uint8_t getPowerSaveMode(uint16_t maxWait = defaultMaxWait); // Returns 255 if the sendCommand fails boolean configurePowerManagement(UBX_CFG_PM2_data_t* data = NULL, uint16_t maxWait = defaultMaxWait); + boolean getPowerManagementConfiguration(uint16_t maxWait = defaultMaxWait); boolean powerOff(uint32_t durationInMs, uint16_t maxWait = defaultMaxWait); boolean powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, boolean forceWhileUsb = true, uint16_t maxWait = 1100); diff --git a/src/u-blox_structs.h b/src/u-blox_structs.h index 3e66ff0..33e1018 100644 --- a/src/u-blox_structs.h +++ b/src/u-blox_structs.h @@ -1172,7 +1172,7 @@ typedef struct // CFG-specific structs // UBX-CFG-PM2 (0x06 0x3B): Extended power management configuration -const uint16_t UBX_CFG_RATE_LEN = 43; +const uint16_t UBX_CFG_PM2_LEN = 44; typedef struct { From a0e83c8b5c376509aa17843aa8c017581dd7eb11 Mon Sep 17 00:00:00 2001 From: Thomas Nabelek Date: Mon, 15 Nov 2021 18:53:56 -0700 Subject: [PATCH 3/5] Fixing flag bitmap; resolved unrelated compiler warning; removed debug prints --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 39 +++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index ced1499..decf933 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2599,7 +2599,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg) { packetUBXESFMEAS->data.data[i].data.all = extractLong(msg, 8 + (i * 4)); } - if (msg->len > (8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4))) // IGNORE COMPILER WARNING comparison between signed and unsigned integer expressions + if ((uint32_t) msg->len > (uint32_t) (8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4))) // Casting to uint32_t to prevent compiler warning about comparison between signed and unsigned integer expressions packetUBXESFMEAS->data.calibTtag = extractLong(msg, 8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4)); //Mark all datums as fresh (not read before) @@ -2933,10 +2933,8 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 len = i2cTransactionSize; _i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); - char printBuffer[200] = {0}; + for (uint16_t x = 0; x < len; x++) { - sprintf(printBuffer, "Sending: 0x%02X", outgoingUBX->payload[startSpot + x]); - Serial.println(printBuffer); _i2cPort->write(outgoingUBX->payload[startSpot + x]); //Write a portion of the payload to the bus } @@ -4849,20 +4847,25 @@ boolean SFE_UBLOX_GNSS::configurePowerManagement(UBX_CFG_PM2_data_t* data, uint1 payloadCfg[ 2] = data->maxStartupStateDur; payloadCfg[ 3] = 0; // Reserved - uint32_t flags = 0; - flags = flags | (data->flagExtintSel << 4); - flags = flags | (data->flagExtintWake << 5); - flags = flags | (data->flagExtintBackup << 6); - flags = flags | (data->flagLimitPeakCurr << 8); // Uses bits 8 and 9 - flags = flags | (data->flagWaitTimeFix << 10); - flags = flags | (data->flagUpdateRTC << 11); - flags = flags | (data->flagUpdateEPH << 12); - flags = flags | (data->flagDoNotEnterOff << 16); - flags = flags | (data->flagMode << 17); // Uses bits 17 and 18 - payloadCfg[ 4] = (flags >> (8 * 0)) & 0xFF; - payloadCfg[ 5] = (flags >> (8 * 1)) & 0xFF; - payloadCfg[ 6] = (flags >> (8 * 2)) & 0xFF; - payloadCfg[ 7] = (flags >> (8 * 3)) & 0xFF; + // Some MCUs don't support larger uints, so break flags into separate uint8s + uint8_t flags_0 = 0; + uint8_t flags_1 = 0; + uint8_t flags_2 = 0; + uint8_t flags_3 = 0; + flags_0 = flags_0 | (data->flagExtintSel << 4); + flags_0 = flags_0 | (data->flagExtintWake << 5); + flags_0 = flags_0 | (data->flagExtintBackup << 6); + flags_1 = flags_1 | (data->flagLimitPeakCurr << 0); // Uses bits 8 and 9 + flags_1 = flags_1 | (data->flagWaitTimeFix << 2); + flags_1 = flags_1 | (data->flagUpdateRTC << 3); + flags_1 = flags_1 | (data->flagUpdateEPH << 4); + flags_2 = flags_2 | (data->flagDoNotEnterOff << 0); + flags_2 = flags_2 | (data->flagMode << 1); // Uses bits 17 and 18 + + payloadCfg[ 4] = flags_0; + payloadCfg[ 5] = flags_1; + payloadCfg[ 6] = flags_2; + payloadCfg[ 7] = flags_3; payloadCfg[ 8] = (data->updatePeriod >> (8 * 0)) & 0xFF; payloadCfg[ 9] = (data->updatePeriod >> (8 * 1)) & 0xFF; From 704a217ec40f07e761e46bc9af33f3a20ebf2fdd Mon Sep 17 00:00:00 2001 From: Thomas Nabelek Date: Mon, 15 Nov 2021 18:57:35 -0700 Subject: [PATCH 4/5] Reverting unnecessary diff --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index decf933..ae4f7d8 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -2934,9 +2934,8 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendI2cCommand(ubxPacket *outgoingUBX, uint16 _i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); - for (uint16_t x = 0; x < len; x++) { + for (uint16_t x = 0; x < len; x++) _i2cPort->write(outgoingUBX->payload[startSpot + x]); //Write a portion of the payload to the bus - } if (_i2cPort->endTransmission(false) != 0) //Don't release bus return (SFE_UBLOX_STATUS_I2C_COMM_FAILURE); //Sensor did not ACK From cb792f2058613e51222295b08a0c8b64a35cb1d6 Mon Sep 17 00:00:00 2001 From: Thomas Nabelek Date: Fri, 19 Nov 2021 21:28:51 -0700 Subject: [PATCH 5/5] Reworking getPowerManagementConfiguration() to return a UBX_CFG_PM2_data_t struct with the current cfg info --- src/SparkFun_u-blox_GNSS_Arduino_Library.cpp | 39 ++++++++++++++------ src/SparkFun_u-blox_GNSS_Arduino_Library.h | 2 +- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index 62db85e..bca451d 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -4994,7 +4994,7 @@ uint8_t SFE_UBLOX_GNSS::getPowerSaveMode(uint16_t maxWait) // Sends the UBX-CFG-PM2 message to configure extended power management // Note: Section 32.10.23 of the u-blox 8 / u-blox M8 Receiver description document gives three different versions // of this message. Version 0x01 is implemented here since it is the most widely supported version -boolean SFE_UBLOX_GNSS::configurePowerManagement(UBX_CFG_PM2_data_t* data, uint16_t maxWait) +bool SFE_UBLOX_GNSS::configurePowerManagement(UBX_CFG_PM2_data_t* data, uint16_t maxWait) { if (data == NULL) // If the user forgot to include the data pointer, bail return (false); @@ -5056,12 +5056,12 @@ boolean SFE_UBLOX_GNSS::configurePowerManagement(UBX_CFG_PM2_data_t* data, uint1 // Bytes 24 through (UBX_CFG_PM2_LEN-1) are reserved - boolean cfg_result = sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT; + bool cfg_result = sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT; return (cfg_result); // We are only expecting an ACK } -boolean SFE_UBLOX_GNSS::getPowerManagementConfiguration(uint16_t maxWait) +UBX_CFG_PM2_data_t SFE_UBLOX_GNSS::getPowerManagementConfiguration(uint16_t maxWait) { packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_PM2; @@ -5069,19 +5069,34 @@ boolean SFE_UBLOX_GNSS::getPowerManagementConfiguration(uint16_t maxWait) packetCfg.startingSpot = 0; // Don't setup any payload items; we're just reading the current configuration - // Instead clear the structure since it will be read into + // Instead, clear the structure since it will be read into memset(payloadCfg, 0, UBX_CFG_PM2_LEN); - boolean cfg_result = sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT; + // Not sure where it happens, but after sending the PM2 command to read the configuration data, the data is read into packetCfg + sendCommand(&packetCfg, maxWait); - Serial.println("Data:"); - Serial.println(payloadCfg[0]); - Serial.println(payloadCfg[1]); - Serial.println(payloadCfg[2]); - Serial.println(payloadCfg[3]); - Serial.println(payloadCfg[4]); + // Interpret the config data read back + UBX_CFG_PM2_data_t data_read; - return (cfg_result); // We are only expecting an ACK + memcpy(&data_read.maxStartupStateDur, &payloadCfg[ 2], sizeof(data_read.maxStartupStateDur)); + + data_read.flagExtintSel = (payloadCfg[4] >> 4) & 0b01; + data_read.flagExtintWake = (payloadCfg[4] >> 5) & 0b01; + data_read.flagExtintBackup = (payloadCfg[4] >> 6) & 0b01; + data_read.flagLimitPeakCurr = (payloadCfg[5] >> 0) & 0b11; + data_read.flagWaitTimeFix = (payloadCfg[5] >> 2) & 0b01; + data_read.flagUpdateRTC = (payloadCfg[5] >> 3) & 0b01; + data_read.flagUpdateEPH = (payloadCfg[5] >> 4) & 0b01; + data_read.flagDoNotEnterOff = (payloadCfg[6] >> 0) & 0b01; + data_read.flagMode = (payloadCfg[6] >> 1) & 0b11; + + memcpy(&data_read.updatePeriod, &payloadCfg[ 8], sizeof(data_read.updatePeriod)); + memcpy(&data_read.searchPeriod, &payloadCfg[12], sizeof(data_read.searchPeriod)); + memcpy(&data_read.gridOffset, &payloadCfg[16], sizeof(data_read.gridOffset)); + memcpy(&data_read.onTime, &payloadCfg[20], sizeof(data_read.onTime)); + memcpy(&data_read.minAcqTime, &payloadCfg[22], sizeof(data_read.minAcqTime)); + + return (data_read); } // Powers off the GPS device for a given duration to reduce power consumption. diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 4078b62..11cb311 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -759,7 +759,7 @@ class SFE_UBLOX_GNSS bool powerSaveMode(bool power_save = true, uint16_t maxWait = defaultMaxWait); uint8_t getPowerSaveMode(uint16_t maxWait = defaultMaxWait); // Returns 255 if the sendCommand fails bool configurePowerManagement(UBX_CFG_PM2_data_t* data = NULL, uint16_t maxWait = defaultMaxWait); - bool getPowerManagementConfiguration(uint16_t maxWait = defaultMaxWait); + UBX_CFG_PM2_data_t getPowerManagementConfiguration(uint16_t maxWait = defaultMaxWait); bool powerOff(uint32_t durationInMs, uint16_t maxWait = defaultMaxWait); bool powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, boolean forceWhileUsb = true, uint16_t maxWait = 1100);