Skip to content

Commit fe02879

Browse files
committed
added UBX_CFG_SMGR configuration support
1 parent 9b27ef1 commit fe02879

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
Configure Time & Frequency Sync manager (UBX-CFG-SMGR)
3+
By: Danylo Ulianych
4+
SparkFun Electronics
5+
Date: March 6th, 2024
6+
License: MIT. See license file for more information but you can
7+
basically do whatever you want with this code.
8+
9+
This example reads / sets UBX-CFG-SMGR configuration and polls for UBX messages.
10+
Works only with Time & Frequency Sync products like LEA-M8F, etc.
11+
12+
Feel like supporting open source hardware?
13+
Buy a board from SparkFun!
14+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
15+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
16+
SAM-M8Q: https://www.sparkfun.com/products/15106
17+
18+
Hardware Connections:
19+
Plug a Qwiic cable into the GNSS and a BlackBoard
20+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
21+
Open the serial monitor at 115200 baud to see the output
22+
*/
23+
24+
#include <Wire.h> //Needed for I2C to GNSS
25+
26+
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
27+
SFE_UBLOX_GNSS myGNSS;
28+
29+
30+
void printUbxCfgSmgr(const UBX_CFG_SMGR_data_t& smgr) {
31+
Serial.printf("\nUBX-CFG-SMGR:");
32+
Serial.printf("\n version %u (0x%02x)", smgr.version, smgr.version);
33+
Serial.printf("\n minGNSSFix %u (0x%02x)", smgr.minGNSSFix, smgr.minGNSSFix);
34+
Serial.printf("\n maxFreqChangeRate %u (0x%02x)", smgr.maxFreqChangeRate, smgr.maxFreqChangeRate);
35+
Serial.printf("\n maxPhaseCorrRate %u (0x%02x)", smgr.maxPhaseCorrRate, smgr.maxPhaseCorrRate);
36+
Serial.printf("\n freqTolerance %u (0x%02x)", smgr.freqTolerance, smgr.freqTolerance);
37+
Serial.printf("\n timeTolerance %u (0x%02x)", smgr.timeTolerance, smgr.timeTolerance);
38+
Serial.printf("\n messageCfg:");
39+
Serial.printf("\n measInternal: %u", smgr.messageCfg.measInternal);
40+
Serial.printf("\n measGNSS: %u", smgr.messageCfg.measGNSS);
41+
Serial.printf("\n measEXTINT0: %u", smgr.messageCfg.measEXTINT0);
42+
Serial.printf("\n measEXTINT1: %u", smgr.messageCfg.measEXTINT1);
43+
Serial.printf("\n maxSlewRate %u (0x%02x)", smgr.maxSlewRate, smgr.maxSlewRate);
44+
Serial.printf("\n flags:");
45+
Serial.printf("\n disableInternal: %u", smgr.flags.disableInternal);
46+
Serial.printf("\n disableExternal: %u", smgr.flags.disableExternal);
47+
Serial.printf("\n preferenceMode: %u", smgr.flags.preferenceMode);
48+
Serial.printf("\n enableGNSS: %u", smgr.flags.enableGNSS);
49+
Serial.printf("\n enableEXTINT0: %u", smgr.flags.enableEXTINT0);
50+
Serial.printf("\n enableEXTINT1: %u", smgr.flags.enableEXTINT1);
51+
Serial.printf("\n enableHostMeasInt: %u", smgr.flags.enableHostMeasInt);
52+
Serial.printf("\n enableHostMeasExt: %u", smgr.flags.enableHostMeasExt);
53+
Serial.printf("\n useAnyFix: %u", smgr.flags.useAnyFix);
54+
Serial.printf("\n disableMaxSlewRate: %u", smgr.flags.disableMaxSlewRate);
55+
Serial.printf("\n issueFreqWarn: %u", smgr.flags.issueFreqWarn);
56+
Serial.printf("\n issueTimeWarn: %u", smgr.flags.issueTimeWarn);
57+
Serial.printf("\n TPCoherent: %u", smgr.flags.TPCoherent);
58+
Serial.printf("\n disableOffset: %u", smgr.flags.disableOffset);
59+
Serial.println("\n");
60+
}
61+
62+
63+
void setup()
64+
{
65+
Serial.begin(115200);
66+
while (!Serial); // wait for Serial ready
67+
Serial.println("SparkFun u-blox Example");
68+
69+
Wire.begin();
70+
71+
if (myGNSS.begin() == false)
72+
{
73+
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
74+
while (1);
75+
}
76+
77+
myGNSS.setI2COutput(COM_TYPE_UBX); // ignore NMEA messages
78+
79+
// setPacketCfgPayloadSize tells the library how many bytes our customPayload can hold.
80+
// It is more memory-efficient to call setPacketCfgPayloadSize before .begin (to avoid creating a new buffer, copying across
81+
// the contents of the old buffer and then deleting the old buffer). But let's call it here just to prove that we can.
82+
myGNSS.setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
83+
84+
UBX_CFG_SMGR_data_t cfgSmgrPayload;
85+
86+
// The next line creates and initialises the packet information which wraps around the payload
87+
ubxPacket customCfg = {0, 0, 0, 0, 0, (uint8_t*) &cfgSmgrPayload, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
88+
89+
// The structure of ubxPacket is:
90+
// uint8_t cls : The message Class
91+
// uint8_t id : The message ID
92+
// uint16_t len : Length of the payload. Does not include cls, id, or checksum bytes
93+
// uint16_t counter : Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
94+
// uint16_t startingSpot : The counter value needed to go past before we begin recording into payload array
95+
// uint8_t *payload : The payload
96+
// uint8_t checksumA : Given to us by the module. Checked against the rolling calculated A/B checksums.
97+
// uint8_t checksumB
98+
// sfe_ublox_packet_validity_e valid : Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
99+
// sfe_ublox_packet_validity_e classAndIDmatch : Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID
100+
101+
// sendCommand will return:
102+
// SFE_UBLOX_STATUS_DATA_RECEIVED if the data we requested was read / polled successfully
103+
// SFE_UBLOX_STATUS_DATA_SENT if the data we sent was writted successfully (ACK'd)
104+
// Other values indicate errors. Please see the sfe_ublox_status_e enum for further details.
105+
106+
// Referring to the u-blox M8 Receiver Description and Protocol Specification we see that
107+
// the navigation rate is configured using the UBX-CFG-RATE message. So let's load our
108+
// custom packet with the correct information so we can read (poll / get) the current settings.
109+
110+
customCfg.cls = UBX_CLASS_CFG; // This is the message Class
111+
customCfg.id = UBX_CFG_SMGR; // This is the message ID
112+
customCfg.len = 0; // Setting the len (length) to zero let's us poll the current settings
113+
customCfg.startingSpot = 0; // Always set the startingSpot to zero (unless you really know what you are doing)
114+
115+
// We also need to tell sendCommand how long it should wait for a reply
116+
uint16_t maxWait = 250; // Wait for up to 250ms (Serial may need a lot longer e.g. 1100)
117+
118+
// Now let's read the current UBX-CFG-SMGR settings. The results will be loaded into customCfg.
119+
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
120+
{
121+
Serial.println(F("sendCommand (poll / get) failed! Freezing..."));
122+
while (1)
123+
;
124+
}
125+
126+
printUbxCfgSmgr(cfgSmgrPayload);
127+
128+
cfgSmgrPayload.minGNSSFix = 5; // update the min no. of GNSS fixes to start freq/phase sync
129+
cfgSmgrPayload.flags.useAnyFix = 1; // use any fix
130+
131+
// Now let's set the updated settings.
132+
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) // We are expecting data and an ACK
133+
{
134+
Serial.println(F("sendCommand set failed! Freezing..."));
135+
while (1)
136+
;
137+
}
138+
139+
Serial.println("UBX-CFG-SMGR successfully updated");
140+
141+
myGNSS.setOutputPort(Serial);
142+
}
143+
144+
void loop()
145+
{
146+
myGNSS.checkUblox(); //See if new UBX data is available. Process bytes as they come in.
147+
148+
delay(250); //Don't pound too hard on the I2C bus
149+
}

src/SparkFun_u-blox_GNSS_Arduino_Library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ const uint8_t UBX_CFG_RINV = 0x34; // Contents of Remote Inventory
231231
const uint8_t UBX_CFG_RST = 0x04; // Reset Receiver / Clear Backup Data Structures. Used to reset device.
232232
const uint8_t UBX_CFG_RXM = 0x11; // RXM configuration
233233
const uint8_t UBX_CFG_SBAS = 0x16; // SBAS configuration
234+
const uint8_t UBX_CFG_SMGR = 0x62; // Synchronization manager configuration
234235
const uint8_t UBX_CFG_TMODE3 = 0x71; // Time Mode Settings 3. Used to enable Survey In Mode
235236
const uint8_t UBX_CFG_TP5 = 0x31; // Time Pulse Parameters
236237
const uint8_t UBX_CFG_USB = 0x1B; // USB Configuration

src/u-blox_structs.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,6 +1877,51 @@ typedef struct
18771877
uint8_t reserved3[8];
18781878
} UBX_CFG_TMODE3_data_t;
18791879

1880+
1881+
// UBX-CFG-SMGR (0x06 0x62): Synchronization manager configuration
1882+
const uint16_t UBX_CFG_SMGR_LEN = 20;
1883+
1884+
typedef struct
1885+
{
1886+
uint8_t version; /* Message version (0x00 for this version) */
1887+
uint8_t minGNSSFix; /* Minimum number of GNSS fixes before we commit to use it as a source */
1888+
uint16_t maxFreqChangeRate; /* Maximum frequency change rate during disciplining. Must not exceed 30ppb/s*/
1889+
uint16_t maxPhaseCorrRate; /* Maximum phase correction rate in coherent time pulse mode. */
1890+
uint16_t reserved1; /* Reserved. Do not use */
1891+
uint16_t freqTolerance; /* Freq limit of possible deviation from nominal */
1892+
uint16_t timeTolerance; /* Time pulse limit of possible deviation from nominal */
1893+
union {
1894+
uint16_t messageCfgX;
1895+
struct {
1896+
uint8_t measInternal : 1; /* 1 = report the estimated offset of the internal oscillator based on the oscillator model */
1897+
uint8_t measGNSS : 1; /* 1 = report the internal oscillator's offset relative to GNSS */
1898+
uint8_t measEXTINT0 : 1; /* 1 = report the internal oscillator's offset relative to the source on EXTINT0 */
1899+
uint8_t measEXTINT1 : 1; /* 1 = report the internal oscillator's offset relative to the source on EXTINT1 */
1900+
} messageCfg;
1901+
};
1902+
uint16_t maxSlewRate;
1903+
union {
1904+
uint32_t flagsX;
1905+
struct {
1906+
uint8_t disableInternal : 1; /* 1 = disable disciplining of the internal oscillator */
1907+
uint8_t disableExternal : 1; /* 1 = disable disciplining of the external oscillator */
1908+
uint8_t preferenceMode : 1; /* Reference selection preference: 0 - best frequency accuracy; 1 - best phase accuracy */
1909+
uint8_t enableGNSS : 1; /* 1 = enable use of GNSS as synchronization source */
1910+
uint8_t enableEXTINT0 : 1; /* 1 = enable use of EXTINT0 as synchronization source */
1911+
uint8_t enableEXTINT1 : 1; /* 1 = enable use of EXTINT1 as synchronization source */
1912+
uint8_t enableHostMeasInt : 1; /* 1 = enable use of host measurements on the internal oscillator as synchronization source */
1913+
uint8_t enableHostMeasExt : 1; /* 1 = enable use of host measurements on the external oscillator as synchronization source */
1914+
uint8_t reserved : 2; /* Reserved. Do not use */
1915+
uint8_t useAnyFix : 1; /* 0 - use over-determined navigation solutions only; 1 - use any fix */
1916+
uint8_t disableMaxSlewRate : 1; /* 1 - don't use the value in the field maxSlewRate */
1917+
uint8_t issueFreqWarn : 1; /* 1 - issue a warning (via UBX-TIM-TOS flag) when frequency uncertainty exceeds freqTolerance */
1918+
uint8_t issueTimeWarn : 1; /* 1 = issue a warning (via UBX-TIM-TOS flag) when time uncertainty exceeds timeTolerance */
1919+
uint8_t TPCoherent : 2; /* Control time pulse coherency: 0 - Coherent pulses; 1 - Non-coherent pulses; 2 - Post-initialization coherent pulses*/
1920+
uint8_t disableOffset : 1; /* 1 = disable automatic storage of oscillator offset */
1921+
} flags;
1922+
};
1923+
} UBX_CFG_SMGR_data_t;
1924+
18801925
// MON-specific structs
18811926

18821927
// UBX-MON-HW (0x0A 0x09): Hardware status

0 commit comments

Comments
 (0)