Skip to content

Commit cb81d37

Browse files
authored
Merge pull request #81 from sparkfun/release_candidate
v3.0.11
2 parents e48fd3a + de4a437 commit cb81d37

File tree

5 files changed

+153
-15
lines changed

5 files changed

+153
-15
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
Demonstrate how to 'process' any UBX message - without needing the Auto methods
3+
By: Paul Clark
4+
SparkFun Electronics
5+
Date: July 14th, 2025
6+
License: MIT. See license file for more information.
7+
8+
This example shows how to configure the u-blox GNSS to output (e.g.) UBX_MON_SYS
9+
and process those messages within your own code. This is cool because UBX_MON_SYS
10+
does not have full "Auto" support. There are no setAutoMONSYS or setAutoMONSYScallbackPtr methods.
11+
But we can process it anyway...!
12+
13+
** Please note: processLoggedUBX is called by the library's internal processUBXpacket method. **
14+
** The library will stall while processLoggedUBX is executing. **
15+
** For best results, avoid Serial prints and delays etc. within processLoggedUBX. **
16+
17+
Hardware Connections:
18+
Plug a Qwiic cable into the GPS and a Redboard Qwiic
19+
If you don't have a platform with a Qwiic connection use the
20+
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
21+
22+
To minimise I2C bus errors, it is a good idea to open the I2C pull-up split pad links on
23+
the u-blox module breakout.
24+
25+
Feel like supporting open source hardware?
26+
Buy a board from SparkFun!
27+
SparkFun GPS-RTK2 - ZED-F9P (GPS-15136) https://www.sparkfun.com/products/15136
28+
SparkFun GPS-RTK-SMA - ZED-F9P (GPS-16481) https://www.sparkfun.com/products/16481
29+
SparkFun MAX-M10S Breakout (GPS-18037) https://www.sparkfun.com/products/18037
30+
SparkFun ZED-F9K Breakout (GPS-18719) https://www.sparkfun.com/products/18719
31+
SparkFun ZED-F9R Breakout (GPS-16344) https://www.sparkfun.com/products/16344
32+
33+
*/
34+
35+
#include <Wire.h> //Needed for I2C to GNSS
36+
37+
#include <SparkFun_u-blox_GNSS_v3.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS_v3
38+
39+
// Define a custom class so we can override processLoggedUBX
40+
class my_SFE_UBLOX_GNSS : public SFE_UBLOX_GNSS
41+
{
42+
public:
43+
void processLoggedUBX(ubxPacket *incomingUBX)
44+
{
45+
// processLoggedUBX will stall the library while it is executing
46+
// For best results, quickly copy the data elsewhere. Avoid Serial prints, delays etc..
47+
// incomingUBX->len contains the payload length (uint16_t)
48+
// incomingUBX->payload points to the payload (uint8_t *)
49+
// The ubxPacket struct is defined in u-blox_external_typedefs.h
50+
51+
Serial.printf("UBX message received: Class 0x%02x ID 0x%02x", incomingUBX->cls, incomingUBX->id);
52+
if ((incomingUBX->cls == UBX_CLASS_MON) && (incomingUBX->id == UBX_MON_SYS))
53+
{
54+
// We can use the "extract" helper functions to read the data - useful for 16, 32 and 64-bit values
55+
// The full list is:
56+
// uint64_t extractLongLong(ubxPacket *msg, uint16_t spotToStart); // Combine eight bytes from payload into uint64_t
57+
// uint64_t extractSignedLongLong(ubxPacket *msg, uint16_t spotToStart); // Combine eight bytes from payload into int64_t
58+
// uint32_t extractLong(ubxPacket *msg, uint16_t spotToStart); // Combine four bytes from payload into long
59+
// int32_t extractSignedLong(ubxPacket *msg, uint16_t spotToStart); // Combine four bytes from payload into signed long (avoiding any ambiguity caused by casting)
60+
// uint16_t extractInt(ubxPacket *msg, uint16_t spotToStart); // Combine two bytes from payload into int
61+
// int16_t extractSignedInt(ubxPacket *msg, uint16_t spotToStart);
62+
// uint8_t extractByte(ubxPacket *msg, uint16_t spotToStart); // Get byte from payload
63+
// int8_t extractSignedChar(ubxPacket *msg, uint16_t spotToStart); // Get signed 8-bit value from payload
64+
// float extractFloat(ubxPacket *msg, uint16_t spotToStart); // Get 32-bit float from payload
65+
// double extractDouble(ubxPacket *msg, uint16_t spotToStart); // Get 64-bit double from payload
66+
67+
uint8_t cpuLoad = extractByte(incomingUBX, 2);
68+
uint32_t runTime = extractLong(incomingUBX, 8);
69+
int8_t tempValue = extractSignedChar(incomingUBX, 18);
70+
71+
Serial.printf(" : UBX-MON-SYS : cpuLoad %d%% runTime %ds tempValue %dC", (int)cpuLoad, (int)runTime, (int)tempValue);
72+
}
73+
Serial.println();
74+
}
75+
};
76+
my_SFE_UBLOX_GNSS myGNSS;
77+
78+
void setup()
79+
{
80+
delay(1000);
81+
82+
Serial.begin(115200);
83+
Serial.println("SparkFun u-blox Example");
84+
85+
Wire.begin(); // Start I2C communication
86+
87+
//myGNSS.enableDebugging(); // Uncomment this line to enable lots of helpful GNSS debug messages on Serial
88+
//myGNSS.enableDebugging(Serial, true); // Or, uncomment this line to enable only the important GNSS debug messages on Serial
89+
90+
while (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
91+
{
92+
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring..."));
93+
}
94+
95+
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
96+
// This will (re)enable the standard NMEA messages too
97+
// This will also disable any "auto" UBX messages that were enabled and saved by other examples and reduce the load on the I2C bus
98+
//myGNSS.factoryDefault(); delay(5000);
99+
100+
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); //Set the I2C port to output UBX, NMEA and RTCM messages
101+
102+
//myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Optional: save (only) the communications port settings to flash and BBR
103+
104+
myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second
105+
106+
myGNSS.newCfgValset(VAL_LAYER_RAM_BBR); // Use cfgValset to disable / enable individual messages
107+
myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_UBX_MON_SYS_I2C, 1); // Enable the UBX-MON-SYS message on I2C
108+
myGNSS.sendCfgValset(); // Send the configuration VALSET
109+
110+
myGNSS.enableUBXlogging(UBX_CLASS_MON, UBX_MON_SYS, false, true); // Disable logging of MON-SYS. Enable processing
111+
}
112+
113+
void loop()
114+
{
115+
myGNSS.checkUblox(); // Check for the arrival of new data. MON-SYS data will be processed by processLoggedUBX
116+
}

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=SparkFun u-blox GNSS v3
2-
version=3.1.10
2+
version=3.1.11
33
author=SparkFun Electronics <techsupport@sparkfun.com>
44
maintainer=SparkFun Electronics <sparkfun.com>
55
sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules<br/><br/>

src/u-blox_GNSS.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,7 +1702,7 @@ void DevUBLOXGNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t req
17021702
if (packetBuf.cls != UBX_CLASS_ACK)
17031703
{
17041704
bool logBecauseAuto = autoLookup(packetBuf.cls, packetBuf.id, &maxPayload);
1705-
bool logBecauseEnabled = logThisUBX(packetBuf.cls, packetBuf.id);
1705+
bool logBecauseEnabled = logThisUBX(packetBuf.cls, packetBuf.id) || processThisUBX(packetBuf.cls, packetBuf.id);
17061706

17071707
// This is not an ACK so check for a class and ID match
17081708
if ((packetBuf.cls == storedClass) && (packetBuf.id == storedID))
@@ -3260,7 +3260,7 @@ void DevUBLOXGNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t
32603260
//{
32613261

32623262
bool logBecauseAuto = autoLookup(incomingUBX->cls, incomingUBX->id, &maximum_payload_size);
3263-
bool logBecauseEnabled = logThisUBX(incomingUBX->cls, incomingUBX->id);
3263+
bool logBecauseEnabled = logThisUBX(incomingUBX->cls, incomingUBX->id) || processThisUBX(incomingUBX->cls, incomingUBX->id);
32643264
if ((!logBecauseAuto) && (logBecauseEnabled))
32653265
maximum_payload_size = SFE_UBX_MAX_LENGTH;
32663266
if (maximum_payload_size == 0)
@@ -3351,7 +3351,7 @@ void DevUBLOXGNSS::processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t
33513351

33523352
// This is not an ACK and we do not have a complete class and ID match
33533353
// So let's check for an "automatic" message arriving
3354-
else if ((autoLookup(incomingUBX->cls, incomingUBX->id)) || (logThisUBX(incomingUBX->cls, incomingUBX->id)))
3354+
else if ((autoLookup(incomingUBX->cls, incomingUBX->id)) || (logThisUBX(incomingUBX->cls, incomingUBX->id)) || (processThisUBX(incomingUBX->cls, incomingUBX->id)))
33553355
{
33563356
// This isn't the message we are looking for...
33573357
// Let's say so and leave incomingUBX->classAndIDmatch _unchanged_
@@ -5117,10 +5117,14 @@ void DevUBLOXGNSS::processUBXpacket(ubxPacket *msg)
51175117
// Check if this UBX message should be added to the file buffer - if it has not been added already
51185118
if ((!addedToFileBuffer) && (logThisUBX(msg->cls, msg->id)))
51195119
storePacket(msg);
5120+
5121+
// Check if UBX message should be processed
5122+
if (processThisUBX(msg->cls, msg->id))
5123+
processLoggedUBX(msg);
51205124
}
51215125

51225126
// UBX Logging - without needing to have or use "Auto" methods
5123-
void DevUBLOXGNSS::enableUBXlogging(uint8_t UBX_CLASS, uint8_t UBX_ID, bool enable)
5127+
void DevUBLOXGNSS::enableUBXlogging(uint8_t UBX_CLASS, uint8_t UBX_ID, bool logMe, bool processMe)
51245128
{
51255129
// If the list is empty
51265130
if (sfe_ublox_ubx_logging_list_head == nullptr)
@@ -5129,7 +5133,8 @@ void DevUBLOXGNSS::enableUBXlogging(uint8_t UBX_CLASS, uint8_t UBX_ID, bool enab
51295133
sfe_ublox_ubx_logging_list_head = new sfe_ublox_ubx_logging_list_t;
51305134
sfe_ublox_ubx_logging_list_head->UBX_CLASS = UBX_CLASS;
51315135
sfe_ublox_ubx_logging_list_head->UBX_ID = UBX_ID;
5132-
sfe_ublox_ubx_logging_list_head->enable = enable;
5136+
sfe_ublox_ubx_logging_list_head->logMe = logMe;
5137+
sfe_ublox_ubx_logging_list_head->processMe = processMe;
51335138
sfe_ublox_ubx_logging_list_head->next = nullptr;
51345139
return;
51355140
}
@@ -5144,7 +5149,8 @@ void DevUBLOXGNSS::enableUBXlogging(uint8_t UBX_CLASS, uint8_t UBX_ID, bool enab
51445149
if ((sfe_ublox_ubx_logging_list_ptr->UBX_CLASS == UBX_CLASS) // Check for a match
51455150
&& (sfe_ublox_ubx_logging_list_ptr->UBX_ID == UBX_ID))
51465151
{
5147-
sfe_ublox_ubx_logging_list_ptr->enable = enable; // Update enable
5152+
sfe_ublox_ubx_logging_list_ptr->logMe = logMe; // Update logMe
5153+
sfe_ublox_ubx_logging_list_ptr->logMe = processMe; // Update processMe
51485154
return;
51495155
}
51505156

@@ -5159,12 +5165,21 @@ void DevUBLOXGNSS::enableUBXlogging(uint8_t UBX_CLASS, uint8_t UBX_ID, bool enab
51595165
sfe_ublox_ubx_logging_list_ptr = sfe_ublox_ubx_logging_list_ptr->next;
51605166
sfe_ublox_ubx_logging_list_ptr->UBX_CLASS = UBX_CLASS;
51615167
sfe_ublox_ubx_logging_list_ptr->UBX_ID = UBX_ID;
5162-
sfe_ublox_ubx_logging_list_ptr->enable = enable;
5168+
sfe_ublox_ubx_logging_list_ptr->logMe = logMe;
5169+
sfe_ublox_ubx_logging_list_ptr->processMe = processMe;
51635170
sfe_ublox_ubx_logging_list_ptr->next = nullptr;
51645171
}
51655172

51665173
// PRIVATE: Returns true if this UBX should be added to the logging buffer
51675174
bool DevUBLOXGNSS::logThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID)
5175+
{
5176+
return logOrProcessThisUBX(UBX_CLASS, UBX_ID, true);
5177+
}
5178+
bool DevUBLOXGNSS::processThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID)
5179+
{
5180+
return logOrProcessThisUBX(UBX_CLASS, UBX_ID, false);
5181+
}
5182+
bool DevUBLOXGNSS::logOrProcessThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID, bool log)
51685183
{
51695184
// If the list is empty
51705185
if (sfe_ublox_ubx_logging_list_head == nullptr)
@@ -5178,7 +5193,10 @@ bool DevUBLOXGNSS::logThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID)
51785193
if ((sfe_ublox_ubx_logging_list_ptr->UBX_CLASS == UBX_CLASS) // Check for a match
51795194
&& (sfe_ublox_ubx_logging_list_ptr->UBX_ID == UBX_ID))
51805195
{
5181-
return sfe_ublox_ubx_logging_list_ptr->enable;
5196+
if (log)
5197+
return (sfe_ublox_ubx_logging_list_ptr->logMe);
5198+
else
5199+
return (sfe_ublox_ubx_logging_list_ptr->processMe);
51825200
}
51835201

51845202
if (sfe_ublox_ubx_logging_list_ptr->next == nullptr)
@@ -9062,7 +9080,7 @@ bool DevUBLOXGNSS::getESFAutoAlignment(bool *enabled, uint8_t layer, uint16_t ma
90629080
}
90639081
bool DevUBLOXGNSS::getESFAutoAlignment(uint8_t layer, uint16_t maxWait) // Unsafe overload
90649082
{
9065-
uint8_t result;
9083+
uint8_t result = 0;
90669084
getVal8(UBLOX_CFG_SFIMU_AUTO_MNTALG_ENA, &result, layer, maxWait);
90679085
return (bool)result;
90689086
}
@@ -17859,7 +17877,7 @@ bool DevUBLOXGNSS::getMeasurementRate(uint16_t *measRate, uint8_t layer, uint16_
1785917877
}
1786017878
uint16_t DevUBLOXGNSS::getMeasurementRate(uint8_t layer, uint16_t maxWait) // Unsafe overload...
1786117879
{
17862-
uint16_t measurementRate;
17880+
uint16_t measurementRate = 0;
1786317881

1786417882
getMeasurementRate(&measurementRate, layer, maxWait);
1786517883

@@ -17886,7 +17904,7 @@ bool DevUBLOXGNSS::getNavigationRate(uint16_t *navRate, uint8_t layer, uint16_t
1788617904
}
1788717905
uint16_t DevUBLOXGNSS::getNavigationRate(uint8_t layer, uint16_t maxWait) // Unsafe overload...
1788817906
{
17889-
uint16_t navigationRate;
17907+
uint16_t navigationRate = 0;
1789017908

1789117909
getNavigationRate(&navigationRate, layer, maxWait);
1789217910

src/u-blox_GNSS.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ class DevUBLOXGNSS
239239
void processRTCM(uint8_t incoming) __attribute__((weak)); // Given rtcm byte, do something with it. User can overwrite if desired to pipe bytes to radio, internet, etc.
240240
void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Given a character, file it away into the uxb packet structure
241241
void processUBXpacket(ubxPacket *msg); // Once a packet has been received and validated, identify this packet's class/id and update internal flags
242+
virtual void processLoggedUBX(ubxPacket *incomingUBX) {} // Process any UBX message with enableUBXlogging processMe set true
242243

243244
// Send I2C/Serial/SPI commands to the module
244245

@@ -1361,7 +1362,7 @@ void logSECSIG(bool enabled = true);
13611362
#endif
13621363

13631364
// UBX Logging - log any UBX message using packetAuto and avoiding having to have and use "Auto" (setAutonnn and lognnn) methods
1364-
void enableUBXlogging(uint8_t UBX_CLASS, uint8_t UBX_ID, bool enable = true);
1365+
void enableUBXlogging(uint8_t UBX_CLASS, uint8_t UBX_ID, bool logMe = true, bool processMe = false);
13651366

13661367
// Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket
13671368
// From v2.0: These are public. The user can call these to extract data from custom packets
@@ -1663,7 +1664,9 @@ void logSECSIG(bool enabled = true);
16631664

16641665
// UBX logging
16651666
sfe_ublox_ubx_logging_list_t *sfe_ublox_ubx_logging_list_head = nullptr; // Linked list of which messages to log
1666-
bool logThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID); // Returns true if this UBX should be added to the logging buffer
1667+
bool logThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID); // Returns true if this UBX should be added to the logging buffer - for logging
1668+
bool processThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID); // Returns true if this UBX should be added to the logging buffer - for processing
1669+
bool logOrProcessThisUBX(uint8_t UBX_CLASS, uint8_t UBX_ID, bool log); // Called by logThisUBX and processThisUBX
16671670

16681671
// Flag to prevent reentry into checkCallbacks
16691672
// Prevent badness if the user accidentally calls checkCallbacks from inside a callback

src/u-blox_external_typedefs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ struct sfe_ublox_ubx_logging_list_t
245245
{
246246
uint8_t UBX_CLASS;
247247
uint8_t UBX_ID;
248-
bool enable;
248+
bool logMe;
249+
bool processMe;
249250
sfe_ublox_ubx_logging_list_t *next;
250251
};
251252

0 commit comments

Comments
 (0)