Skip to content

Commit edbe2ed

Browse files
authored
Merge pull request #239 from sparkfun/release_candidate
v2.2.28
2 parents 4e542ba + 9096d80 commit edbe2ed

9 files changed

+1399
-22
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
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 prints UBX-TIM-SMEAS 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+
// Callback: printTIMSMEASdata will be called when new TIM SMEA data arrives
31+
// See u-blox_structs.h for the full definition of UBX_TIM_SMEAS_data_t
32+
// _____ You can use any name you like for the callback. Use the same name when you call setAutoTIMTM2callback
33+
// / _____ This _must_ be UBX_TIM_SMEAS_data_t
34+
// | / _____ You can use any name you like for the struct
35+
// | | /
36+
// | | |
37+
void printTIMSMEASdata(UBX_TIM_SMEAS_data_t smea)
38+
{
39+
Serial.print("UBX-TIM-SMEAS:");
40+
Serial.printf("\n version: %u", smea.version);
41+
Serial.printf("\n numMeas: %u", smea.numMeas);
42+
Serial.printf("\n iTOW: %lu", smea.iTOW);
43+
for (int i = 0; i < smea.numMeas; i++) {
44+
Serial.printf("\n sourceId %u:", smea.data[i].sourceId);
45+
Serial.printf("\n flags:");
46+
Serial.printf("\n freqValid %u", smea.data[i].flags.bits.freqValid);
47+
Serial.printf("\n phaseValid %u", smea.data[i].flags.bits.phaseValid);
48+
Serial.printf("\n phaseOffsetFrac %d", smea.data[i].phaseOffsetFrac);
49+
Serial.printf("\n phaseUncFrac %u", smea.data[i].phaseUncFrac);
50+
Serial.printf("\n phaseOffset %ld", smea.data[i].phaseOffset);
51+
Serial.printf("\n phaseUnc %lu", smea.data[i].phaseUnc);
52+
Serial.printf("\n freqOffset %ld", smea.data[i].freqOffset);
53+
Serial.printf("\n freqUnc %lu", smea.data[i].freqUnc);
54+
}
55+
}
56+
57+
58+
UBX_CFG_SMGR_data_t convertRawBufToCfgSmgr(const ubxPacket* msg) {
59+
UBX_CFG_SMGR_data_t smgr;
60+
if (msg->len < sizeof(UBX_CFG_SMGR_data_t)) {
61+
Serial.printf("Payload message size (%zu) is too small to be converted to UBX_CFG_SMGR_data_t\n", msg->len);
62+
return smgr;
63+
}
64+
65+
smgr.version = SFE_UBLOX_GNSS::extractByte(msg, 0);
66+
smgr.minGNSSFix = SFE_UBLOX_GNSS::extractByte(msg, 1);
67+
smgr.maxFreqChangeRate = SFE_UBLOX_GNSS::extractInt(msg, 2);
68+
smgr.maxPhaseCorrRate = SFE_UBLOX_GNSS::extractInt(msg, 4);
69+
smgr.freqTolerance = SFE_UBLOX_GNSS::extractInt(msg, 8);
70+
smgr.timeTolerance = SFE_UBLOX_GNSS::extractInt(msg, 10);
71+
smgr.messageCfg.all = SFE_UBLOX_GNSS::extractInt(msg, 12);
72+
smgr.maxSlewRate = SFE_UBLOX_GNSS::extractInt(msg, 14);
73+
smgr.flags.all = SFE_UBLOX_GNSS::extractLong(msg, 16);
74+
75+
return smgr;
76+
}
77+
78+
79+
void printUbxCfgSmgr(const UBX_CFG_SMGR_data_t& smgr) {
80+
Serial.printf("\nUBX-CFG-SMGR:");
81+
Serial.printf("\n version %u (0x%02x)", smgr.version, smgr.version);
82+
Serial.printf("\n minGNSSFix %u (0x%02x)", smgr.minGNSSFix, smgr.minGNSSFix);
83+
Serial.printf("\n maxFreqChangeRate %u (0x%02x)", smgr.maxFreqChangeRate, smgr.maxFreqChangeRate);
84+
Serial.printf("\n maxPhaseCorrRate %u (0x%02x)", smgr.maxPhaseCorrRate, smgr.maxPhaseCorrRate);
85+
Serial.printf("\n freqTolerance %u (0x%02x)", smgr.freqTolerance, smgr.freqTolerance);
86+
Serial.printf("\n timeTolerance %u (0x%02x)", smgr.timeTolerance, smgr.timeTolerance);
87+
Serial.printf("\n messageCfg:");
88+
Serial.printf("\n measInternal: %u", smgr.messageCfg.bits.measInternal);
89+
Serial.printf("\n measGNSS: %u", smgr.messageCfg.bits.measGNSS);
90+
Serial.printf("\n measEXTINT0: %u", smgr.messageCfg.bits.measEXTINT0);
91+
Serial.printf("\n measEXTINT1: %u", smgr.messageCfg.bits.measEXTINT1);
92+
Serial.printf("\n maxSlewRate %u (0x%02x)", smgr.maxSlewRate, smgr.maxSlewRate);
93+
Serial.printf("\n flags:");
94+
Serial.printf("\n disableInternal: %u", smgr.flags.bits.disableInternal);
95+
Serial.printf("\n disableExternal: %u", smgr.flags.bits.disableExternal);
96+
Serial.printf("\n preferenceMode: %u", smgr.flags.bits.preferenceMode);
97+
Serial.printf("\n enableGNSS: %u", smgr.flags.bits.enableGNSS);
98+
Serial.printf("\n enableEXTINT0: %u", smgr.flags.bits.enableEXTINT0);
99+
Serial.printf("\n enableEXTINT1: %u", smgr.flags.bits.enableEXTINT1);
100+
Serial.printf("\n enableHostMeasInt: %u", smgr.flags.bits.enableHostMeasInt);
101+
Serial.printf("\n enableHostMeasExt: %u", smgr.flags.bits.enableHostMeasExt);
102+
Serial.printf("\n useAnyFix: %u", smgr.flags.bits.useAnyFix);
103+
Serial.printf("\n disableMaxSlewRate: %u", smgr.flags.bits.disableMaxSlewRate);
104+
Serial.printf("\n issueFreqWarn: %u", smgr.flags.bits.issueFreqWarn);
105+
Serial.printf("\n issueTimeWarn: %u", smgr.flags.bits.issueTimeWarn);
106+
Serial.printf("\n TPCoherent: %u", smgr.flags.bits.TPCoherent);
107+
Serial.printf("\n disableOffset: %u", smgr.flags.bits.disableOffset);
108+
Serial.println("\n");
109+
}
110+
111+
112+
void setup()
113+
{
114+
Serial.begin(115200);
115+
while (!Serial); // wait for Serial ready
116+
Serial.println("SparkFun u-blox Example");
117+
118+
Wire.begin();
119+
120+
if (myGNSS.begin() == false)
121+
{
122+
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
123+
while (1);
124+
}
125+
126+
myGNSS.setI2COutput(COM_TYPE_UBX); // ignore NMEA messages
127+
128+
// setPacketCfgPayloadSize tells the library how many bytes our customPayload can hold.
129+
// It is more memory-efficient to call setPacketCfgPayloadSize before .begin (to avoid creating a new buffer, copying across
130+
// the contents of the old buffer and then deleting the old buffer). But let's call it here just to prove that we can.
131+
myGNSS.setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
132+
133+
uint8_t customPayload[MAX_PAYLOAD_SIZE]; // This array holds the payload data bytes. MAX_PAYLOAD_SIZE defaults to 256. The CFG_RATE payload is only 6 bytes!
134+
135+
// The next line creates and initialises the packet information which wraps around the payload
136+
ubxPacket customCfg = {0, 0, 0, 0, 0, customPayload, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
137+
138+
// The structure of ubxPacket is:
139+
// uint8_t cls : The message Class
140+
// uint8_t id : The message ID
141+
// uint16_t len : Length of the payload. Does not include cls, id, or checksum bytes
142+
// uint16_t counter : Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
143+
// uint16_t startingSpot : The counter value needed to go past before we begin recording into payload array
144+
// uint8_t *payload : The payload
145+
// uint8_t checksumA : Given to us by the module. Checked against the rolling calculated A/B checksums.
146+
// uint8_t checksumB
147+
// sfe_ublox_packet_validity_e valid : Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
148+
// 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
149+
150+
// sendCommand will return:
151+
// SFE_UBLOX_STATUS_DATA_RECEIVED if the data we requested was read / polled successfully
152+
// SFE_UBLOX_STATUS_DATA_SENT if the data we sent was writted successfully (ACK'd)
153+
// Other values indicate errors. Please see the sfe_ublox_status_e enum for further details.
154+
155+
// Referring to the u-blox M8 Receiver Description and Protocol Specification we see that
156+
// the navigation rate is configured using the UBX-CFG-RATE message. So let's load our
157+
// custom packet with the correct information so we can read (poll / get) the current settings.
158+
159+
customCfg.cls = UBX_CLASS_CFG; // This is the message Class
160+
customCfg.id = UBX_CFG_SMGR; // This is the message ID
161+
customCfg.len = 0; // Setting the len (length) to zero let's us poll the current settings
162+
customCfg.startingSpot = 0; // Always set the startingSpot to zero (unless you really know what you are doing)
163+
164+
// We also need to tell sendCommand how long it should wait for a reply
165+
uint16_t maxWait = 250; // Wait for up to 250ms (Serial may need a lot longer e.g. 1100)
166+
167+
// Now let's read the current UBX-CFG-SMGR settings. The results will be loaded into customCfg.
168+
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
169+
{
170+
Serial.println(F("sendCommand (poll / get) failed! Freezing..."));
171+
while (1)
172+
;
173+
}
174+
175+
UBX_CFG_SMGR_data_t cfgSmgrPayload = convertRawBufToCfgSmgr(&customCfg);
176+
177+
printUbxCfgSmgr(cfgSmgrPayload);
178+
179+
cfgSmgrPayload.minGNSSFix = 5; // update the min no. of GNSS fixes to start freq/phase sync
180+
cfgSmgrPayload.flags.bits.useAnyFix = 1; // use any fix
181+
182+
// update the raw payload buffer
183+
memmove(customPayload, &cfgSmgrPayload, sizeof(UBX_CFG_SMGR_data_t));
184+
185+
// Now let's set the updated settings.
186+
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) // We are expecting data and an ACK
187+
{
188+
Serial.println(F("sendCommand set failed! Freezing..."));
189+
while (1)
190+
;
191+
}
192+
193+
Serial.println("UBX-CFG-SMGR successfully updated");
194+
195+
myGNSS.setAutoTIMSMEAcallback(&printTIMSMEASdata);
196+
197+
// Enable info/warns messages
198+
// myGNSS.setVal8(UBLOX_CFG_INFMSG_UBX_I2C, 1);
199+
}
200+
201+
void loop()
202+
{
203+
myGNSS.checkUblox(); //See if new UBX data is available. Process bytes as they come in.
204+
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
205+
206+
delay(250); //Don't pound too hard on the I2C bus
207+
}

0 commit comments

Comments
 (0)