Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 64ba650

Browse files
authoredJul 1, 2021
Merge pull request #49 from sparkfun/release_candidate
v2.0.8
2 parents 929a9ee + e3d9bc3 commit 64ba650

File tree

12 files changed

+637
-18
lines changed

12 files changed

+637
-18
lines changed
 

‎README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</tr>
1818
</table>
1919

20-
u-blox makes some incredible GNSS receivers covering everything from low-cost, highly configurable modules such as the SAM-M8Q all the way up to the surveyor grade ZED-F9P with precision of the diameter of a dime. This library focuses on configuration and control of u-blox devices over I<sup>2</sup>C (called DDC by u-blox) and Serial. The UBX protocol is supported over both I<sup>2</sup>C and serial, and is a much easier and lighterweight interface to a GNSS module. Stop polling messages and parsing NMEA data! Simply ask for the datums you need and receive an automatic callback when they arrive.
20+
u-blox makes some incredible GNSS receivers covering everything from low-cost, highly configurable modules such as the SAM-M8Q all the way up to the surveyor grade ZED-F9P with precision of the diameter of a dime. This library supports configuration and control of u-blox devices over I<sup>2</sup>C (called DDC by u-blox), Serial and - as of v2.0.8 (thank you @aberridg) - SPI too! The UBX protocol is a much easier and lighterweight interface to a GNSS module. Stop polling messages and parsing NMEA data! Simply ask for the datums you need and receive an automatic callback when they arrive.
2121

2222
This library can be installed via the Arduino Library manager. Search for **SparkFun u-blox GNSS**.
2323

@@ -53,6 +53,18 @@ Migrating to v2.0 is easy. There are two small changes all users will need to ma
5353

5454
If you are using the Dead Reckoning Sensor Fusion or High Dynamic Rate messages, you will need to make more small changes to your code. Please see the [dead reckoning examples](./examples/Dead_Reckoning) for more details. There is more detail available in [Theory.md](./Theory.md#migrating-your-code-to-v20) if you need it.
5555

56+
## SPI Support
57+
58+
In v2.0.8 we added support for SPI, based on a contribution by @aberridg. Thank you Andrew!
59+
60+
We have tested the SPI interface on as many platforms and modules as we could pull together. It works perfectly on most but not quite all combinations.
61+
For reasons we don't understand yet, the ZED-F9P and Teensy 3.2 don't seem to get along. But Teensy 3.2 and the ZOE-M8Q do play nicely together.
62+
If you notice a combination that does not seem to work, please raise an [issue](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/issues) and we will investigate.
63+
64+
The SPI examples have their [own folder](./examples/SPI).
65+
66+
Please check the module datasheets for details on what clock speeds and data rates each module supports. The maximum clock speed is typically 5.5MHz and the maximum transfer rate is typically 125kBytes/s.
67+
5668
## Max (400kHz) I<sup>2</sup>C Support
5769

5870
To achieve 400kHz I<sup>2</sup>C speed please be sure to remove all pull-ups on the I<sup>2</sup>C bus. Most, if not all, u-blox modules include internal pull ups on the I<sup>2</sup>C lines (sometimes called DDC in their manuals). Cut all I<sup>2</sup>C pull up jumpers and/or remove them from peripheral boards. Otherwise, various data glitches can occur. See issues [38](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/38) and [40](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/issues/40) for more information. If possible, run the I<sup>2</sup>C bus at 100kHz.

‎examples/Example18_PowerSaveMode/Example18_PowerSaveMode.ino

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,22 @@ void loop()
8585
if (myGNSS.powerSaveMode()) // Defaults to true
8686
Serial.println(F("Power Save Mode enabled."));
8787
else
88-
Serial.println(F("***!!! Power Save Mode FAILED !!!***"));
88+
Serial.println(F("*** Power Save Mode FAILED ***"));
8989
}
9090
else if (incoming == '2')
9191
{
9292
//Go to normal power mode (not power saving mode)
9393
if (myGNSS.powerSaveMode(false))
9494
Serial.println(F("Power Save Mode disabled."));
9595
else
96-
Serial.println(F("***!!! Power Save Disable FAILED !!!***"));
96+
Serial.println(F("*** Power Save Disable FAILED ***"));
9797
}
9898

9999
// Read and print the new low power mode
100100
uint8_t lowPowerMode = myGNSS.getPowerSaveMode();
101101
if (lowPowerMode == 255)
102102
{
103-
Serial.println(F("***!!! getPowerSaveMode FAILED !!!***"));
103+
Serial.println(F("*** getPowerSaveMode FAILED ***"));
104104
}
105105
else
106106
{

‎examples/Example19_DynamicModel/Example19_DynamicModel.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void setup()
6868

6969
if (myGNSS.setDynamicModel(DYN_MODEL_PORTABLE) == false) // Set the dynamic model to PORTABLE
7070
{
71-
Serial.println(F("***!!! Warning: setDynamicModel failed !!!***"));
71+
Serial.println(F("*** Warning: setDynamicModel failed ***"));
7272
}
7373
else
7474
{
@@ -79,7 +79,7 @@ void setup()
7979
uint8_t newDynamicModel = myGNSS.getDynamicModel();
8080
if (newDynamicModel == DYN_MODEL_UNKNOWN)
8181
{
82-
Serial.println(F("***!!! Warning: getDynamicModel failed !!!***"));
82+
Serial.println(F("*** Warning: getDynamicModel failed ***"));
8383
}
8484
else
8585
{

‎examples/Example1_BasicNMEARead/Example1_BasicNMEARead.ino

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ void setup()
3939
while (1);
4040
}
4141

42+
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages
43+
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
44+
4245
//This will pipe all NMEA sentences to the serial port so we can see them
4346
myGNSS.setNMEAOutputPort(Serial);
4447
}

‎examples/Example24_GetUnixEpochAndMicros/Example24_GetUnixEpochAndMicros.ino

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ void loop()
9191
Serial.print(myGNSS.getSecond());
9292

9393
Serial.print(" Time is ");
94+
if (myGNSS.getTimeFullyResolved() == false)
95+
{
96+
Serial.print("not fully resolved but ");
97+
} else {
98+
Serial.print("fully resolved and ");
99+
}
94100
if (myGNSS.getTimeValid() == false)
95101
{
96102
Serial.print("not ");

‎examples/Example2_NMEAParsing/Example2_NMEAParsing.ino

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ void setup()
4646
while (1);
4747
}
4848

49+
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages
50+
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
51+
4952
myGNSS.setProcessNMEAMask(SFE_UBLOX_FILTER_NMEA_ALL); // Make sure the library is passing all NMEA messages to processNMEA
5053

5154
myGNSS.setProcessNMEAMask(SFE_UBLOX_FILTER_NMEA_GGA); // Or, we can be kind to MicroNMEA and _only_ pass the GGA messages to it
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
Reading lat and long via UBX binary commands over SPI
3+
By: Andrew Berridge
4+
Date: 27th June 2021
5+
License: MIT. See license file for more information but you can
6+
basically do whatever you want with this code.
7+
8+
This example shows how to query a u-blox module for its lat/long/altitude over SPI. We also
9+
turn off the NMEA output on the SPI port. This decreases the amount of SPI traffic
10+
dramatically.
11+
12+
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
13+
to something google maps understands simply divide the numbers by 10,000,000. We
14+
do this so that we don't have to use floating point numbers.
15+
16+
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
17+
18+
Feel like supporting open source hardware?
19+
Buy a board from SparkFun!
20+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
21+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
22+
NEO-M8U: https://www.sparkfun.com/products/16329
23+
NEO-M9N: https://www.sparkfun.com/products/17285
24+
25+
Hardware Connections:
26+
You need to connect the SPI pins from your microcontroller to the specific pins on your SparkFun product.
27+
Connections will vary based on your microcontroller, but for reference please refer to this tutorial on SPI:
28+
https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all
29+
30+
Most new boards now use the terms:
31+
CS - Chip Select
32+
COPI - Controller Out, Peripheral In
33+
CIPO - Controller in, Peripheral Out
34+
SCK - Serial Clock
35+
36+
You can choose any pin for Chip Select, but the others are likely either defined by the library you are using
37+
(see here for the standard Arduino one: https://www.arduino.cc/en/reference/SPI) or the microcontroller. The
38+
ESP32 has two standard, selectable SPI ports, for example.
39+
40+
To enable SPI communication, you will need to solder the DSEL/SPI jumper closed on your u-blox board.
41+
42+
IMPORTANT: there have been reports that some u-blox devices do not respond to the UBX protocol over SPI
43+
with the factory settings. You may find you need to connect to the device via USB and u-center and set
44+
the incoming protocol to UBX only. Make sure you disable all other protocols as inputs if you can't
45+
get things to work! Hopefully this is just a bug in the u-blox firmware that will be fixed soon ;-)
46+
47+
*/
48+
49+
#include <SPI.h> //Needed for SPI to GNSS
50+
51+
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
52+
SFE_UBLOX_GNSS myGNSS;
53+
54+
// #########################################
55+
56+
// Instantiate an instance of the SPI class.
57+
// Your configuration may be different, depending on the microcontroller you are using!
58+
59+
#define spiPort SPI // This is the SPI port on standard Ardino boards. Comment this line if you want to use a different port.
60+
61+
//SPIClass spiPort (HSPI); // This is the default SPI interface on some ESP32 boards. Uncomment this line if you are using ESP32.
62+
63+
// #########################################
64+
65+
const uint8_t csPin = 10; // On ATmega328 boards, SPI Chip Select is usually pin 10. Change this to match your board.
66+
67+
// #########################################
68+
69+
long lastTime = 0; //Simple local timer. Limits amount of SPI traffic to u-blox module.
70+
71+
void setup()
72+
{
73+
Serial.begin(115200);
74+
while (!Serial); //Wait for user to open terminal
75+
Serial.println(F("SparkFun u-blox Example"));
76+
77+
spiPort.begin(); // begin the SPI port
78+
79+
//myGNSS.enableDebugging(); // Uncomment this line to see helpful debug messages on Serial
80+
81+
// Connect to the u-blox module using SPI port, csPin and speed setting
82+
// ublox devices generally work up to 5MHz. We'll use 4MHz for this example:
83+
if (myGNSS.begin(spiPort, csPin, 4000000) == false)
84+
{
85+
Serial.println(F("u-blox GNSS not detected on SPI bus. Please check wiring. Freezing."));
86+
while (1);
87+
}
88+
89+
//myGNSS.factoryDefault(); delay(5000); // Uncomment this line to reset the module back to its factory defaults
90+
91+
myGNSS.setPortOutput(COM_PORT_SPI, COM_TYPE_UBX); //Set the SPI port to output UBX only (turn off NMEA noise)
92+
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
93+
}
94+
95+
void loop()
96+
{
97+
//Query module only every second. Doing it more often will just cause SPI traffic.
98+
//The module only responds when a new position is available
99+
if (millis() - lastTime > 1000)
100+
{
101+
lastTime = millis(); //Update the timer
102+
103+
long latitude = myGNSS.getLatitude();
104+
Serial.print(F("Lat: "));
105+
Serial.print(latitude);
106+
107+
long longitude = myGNSS.getLongitude();
108+
Serial.print(F(" Long: "));
109+
Serial.print(longitude);
110+
Serial.print(F(" (degrees * 10^-7)"));
111+
112+
long altitude = myGNSS.getAltitude();
113+
Serial.print(F(" Alt: "));
114+
Serial.print(altitude);
115+
Serial.print(F(" (mm)"));
116+
117+
byte SIV = myGNSS.getSIV();
118+
Serial.print(F(" SIV: "));
119+
Serial.print(SIV);
120+
121+
Serial.println();
122+
}
123+
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
Configuring the GNSS to automatically send position reports over SPI
3+
Based on code by: Nathan Seidle and Thorsten von Eicken
4+
SparkFun Electronics
5+
Date: January 3rd, 2019
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 shows how to configure the U-Blox GNSS the send navigation reports automatically
10+
and retrieving the latest one via getPVT. This eliminates the blocking in getPVT while the GNSS
11+
produces a fresh navigation solution at the expense of returning a slighly old solution.
12+
13+
Feel like supporting open source hardware?
14+
Buy a board from SparkFun!
15+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
16+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
17+
NEO-M8U: https://www.sparkfun.com/products/16329
18+
NEO-M9N: https://www.sparkfun.com/products/17285
19+
20+
Hardware Connections:
21+
You need to connect the SPI pins from your microcontroller to the specific pins on your SparkFun product.
22+
Connections will vary based on your microcontroller, but for reference please refer to this tutorial on SPI:
23+
https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all
24+
25+
Most new boards now use the terms:
26+
CS - Chip Select
27+
COPI - Controller Out, Peripheral In
28+
CIPO - Controller in, Peripheral Out
29+
SCK - Serial Clock
30+
31+
You can choose any pin for Chip Select, but the others are likely either defined by the library you are using
32+
(see here for the standard Arduino one: https://www.arduino.cc/en/reference/SPI) or the microcontroller. The
33+
ESP32 has two standard, selectable SPI ports, for example.
34+
35+
To enable SPI communication, you will need to solder the DSEL/SPI jumper closed on your u-blox board.
36+
37+
IMPORTANT: there have been reports that some u-blox devices do not respond to the UBX protocol over SPI
38+
with the factory settings. You may find you need to connect to the device via USB and u-center and set
39+
the incoming protocol to UBX only. Make sure you disable all other protocols as inputs if you can't
40+
get things to work! Hopefully this is just a bug in the u-blox firmware that will be fixed soon ;-)
41+
42+
*/
43+
44+
#include <SPI.h> //Needed for SPI to GNSS
45+
46+
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
47+
SFE_UBLOX_GNSS myGNSS;
48+
49+
// #########################################
50+
51+
// Instantiate an instance of the SPI class.
52+
// Your configuration may be different, depending on the microcontroller you are using!
53+
54+
#define spiPort SPI // This is the SPI port on standard Ardino boards. Comment this line if you want to use a different port.
55+
56+
//SPIClass spiPort (HSPI); // This is the default SPI interface on some ESP32 boards. Uncomment this line if you are using ESP32.
57+
58+
// #########################################
59+
60+
const uint8_t csPin = 10; // On ATmega328 boards, SPI Chip Select is usually pin 10. Change this to match your board.
61+
62+
// #########################################
63+
64+
void setup()
65+
{
66+
Serial.begin(115200);
67+
while (!Serial); //Wait for user to open terminal
68+
Serial.println("SparkFun u-blox Example");
69+
70+
spiPort.begin(); // begin the SPI port
71+
72+
//myGNSS.enableDebugging(); // Uncomment this line to see helpful debug messages on Serial
73+
74+
// Connect to the u-blox module using SPI port, csPin and speed setting
75+
// ublox devices generally work up to 5MHz. We'll use 4MHz for this example:
76+
if (myGNSS.begin(spiPort, csPin, 4000000) == false)
77+
{
78+
Serial.println(F("u-blox GNSS not detected on SPI bus. Please check wiring. Freezing."));
79+
while (1);
80+
}
81+
82+
//myGNSS.factoryDefault(); delay(5000); // Uncomment this line to reset the module back to its factory defaults
83+
84+
myGNSS.setPortOutput(COM_PORT_SPI, COM_TYPE_UBX); //Set the SPI port to output UBX only (turn off NMEA noise)
85+
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
86+
87+
myGNSS.setNavigationFrequency(2); //Produce two solutions per second
88+
myGNSS.setAutoPVT(true); //Tell the GNSS to "send" each solution
89+
//myGNSS.saveConfiguration(); //Optional: Save _all_ the current settings to flash and BBR
90+
}
91+
92+
void loop()
93+
{
94+
// Calling getPVT returns true if there actually is a fresh navigation solution available.
95+
// Start the reading only when valid LLH is available
96+
if (myGNSS.getPVT() && (myGNSS.getInvalidLlh() == false))
97+
{
98+
Serial.println();
99+
long latitude = myGNSS.getLatitude();
100+
Serial.print(F("Lat: "));
101+
Serial.print(latitude);
102+
103+
long longitude = myGNSS.getLongitude();
104+
Serial.print(F(" Long: "));
105+
Serial.print(longitude);
106+
Serial.print(F(" (degrees * 10^-7)"));
107+
108+
long altitude = myGNSS.getAltitude();
109+
Serial.print(F(" Alt: "));
110+
Serial.print(altitude);
111+
Serial.print(F(" (mm)"));
112+
113+
byte SIV = myGNSS.getSIV();
114+
Serial.print(F(" SIV: "));
115+
Serial.print(SIV);
116+
117+
int PDOP = myGNSS.getPDOP();
118+
Serial.print(F(" PDOP: "));
119+
Serial.print(PDOP);
120+
Serial.print(F(" (10^-2)"));
121+
122+
int nedNorthVel = myGNSS.getNedNorthVel();
123+
Serial.print(F(" VelN: "));
124+
Serial.print(nedNorthVel);
125+
Serial.print(F(" (mm/s)"));
126+
127+
int nedEastVel = myGNSS.getNedEastVel();
128+
Serial.print(F(" VelE: "));
129+
Serial.print(nedEastVel);
130+
Serial.print(F(" (mm/s)"));
131+
132+
int nedDownVel = myGNSS.getNedDownVel();
133+
Serial.print(F(" VelD: "));
134+
Serial.print(nedDownVel);
135+
Serial.print(F(" (mm/s)"));
136+
137+
int verticalAccEst = myGNSS.getVerticalAccEst();
138+
Serial.print(F(" VAccEst: "));
139+
Serial.print(verticalAccEst);
140+
Serial.print(F(" (mm)"));
141+
142+
int horizontalAccEst = myGNSS.getHorizontalAccEst();
143+
Serial.print(F(" HAccEst: "));
144+
Serial.print(horizontalAccEst);
145+
Serial.print(F(" (mm)"));
146+
147+
int speedAccEst = myGNSS.getSpeedAccEst();
148+
Serial.print(F(" SpeedAccEst: "));
149+
Serial.print(speedAccEst);
150+
Serial.print(F(" (mm/s)"));
151+
152+
int headAccEst = myGNSS.getHeadingAccEst();
153+
Serial.print(F(" HeadAccEst: "));
154+
Serial.print(headAccEst);
155+
Serial.print(F(" (degrees * 10^-5)"));
156+
157+
if (myGNSS.getHeadVehValid() == true) {
158+
int headVeh = myGNSS.getHeadVeh();
159+
Serial.print(F(" HeadVeh: "));
160+
Serial.print(headVeh);
161+
Serial.print(F(" (degrees * 10^-5)"));
162+
163+
int magDec = myGNSS.getMagDec();
164+
Serial.print(F(" MagDec: "));
165+
Serial.print(magDec);
166+
Serial.print(F(" (degrees * 10^-2)"));
167+
168+
int magAcc = myGNSS.getMagAcc();
169+
Serial.print(F(" MagAcc: "));
170+
Serial.print(magAcc);
171+
Serial.print(F(" (degrees * 10^-2)"));
172+
}
173+
174+
Serial.println();
175+
} else {
176+
Serial.print(".");
177+
delay(50);
178+
}
179+
}

‎keywords.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,13 @@ setPacketCfgPayloadSize KEYWORD2
5353
begin KEYWORD2
5454
end KEYWORD2
5555
setI2CpollingWait KEYWORD2
56+
setSPIpollingWait KEYWORD2
5657
setI2CTransactionSize KEYWORD2
5758
getI2CTransactionSize KEYWORD2
59+
setSpiTransactionSize KEYWORD2
60+
getSpiTransactionSize KEYWORD2
61+
setMaxNMEAByteCount KEYWORD2
62+
getMaxNMEAByteCount KEYWORD2
5863
isConnected KEYWORD2
5964
enableDebugging KEYWORD2
6065
disableDebugging KEYWORD2
@@ -66,6 +71,7 @@ disableUBX7Fcheck KEYWORD2
6671
checkUblox KEYWORD2
6772
checkUbloxI2C KEYWORD2
6873
checkUbloxSerial KEYWORD2
74+
checkUbloxSPI KEYWORD2
6975

7076
process KEYWORD2
7177
processNMEA KEYWORD2
@@ -425,6 +431,7 @@ getNanosecond KEYWORD2
425431
getUnixEpoch KEYWORD2
426432
getDateValid KEYWORD2
427433
getTimeValid KEYWORD2
434+
getTimeFullyResolved KEYWORD2
428435
getConfirmedDate KEYWORD2
429436
getConfirmedTime KEYWORD2
430437
getFixType KEYWORD2

‎library.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=SparkFun u-blox GNSS Arduino Library
2-
version=2.0.7
2+
version=2.0.8
33
author=SparkFun Electronics <techsupport@sparkfun.com>
44
maintainer=SparkFun Electronics <sparkfun.com>
55
sentence=Library for I2C and Serial Communication with u-blox GNSS modules<br/><br/>
6-
paragraph=An Arduino Library to enable both I2C and Serial communication for both NMEA reception and binary UBX sending to u-blox modules. Useful for interfacing to the <a href="https://www.sparkfun.com/products/15136">SparkFun GPS-RTK2</a> ZED-F9P, <a href="https://www.sparkfun.com/products/15005">SparkFun GPS-RTK</a> NEO-M8P-2, the <a href="https://www.sparkfun.com/products/15210">SparkFun SAM-M8Q</a>, and the <a href="https://www.sparkfun.com/products/15193">SparkFun ZOE-M8Q</a>. Library also works with other u-blox based boards.<br/><br/>The ZED-F9P and NEO-M8P-2 modules are top-of-the-line modules for high accuracy GNSS and GPS location solutions including RTK. The ZED-F9P is unique in that it is capable of both rover and base station operations allowing the module to become a base station and produce RTCM 3.x correction data.<br/>
6+
paragraph=An Arduino Library to enable I2C, Serial and SPI communication for both NMEA reception and binary UBX sending to u-blox modules. Useful for interfacing to the <a href="https://www.sparkfun.com/products/15136">SparkFun GPS-RTK2</a> ZED-F9P, <a href="https://www.sparkfun.com/products/15005">SparkFun GPS-RTK</a> NEO-M8P-2, the <a href="https://www.sparkfun.com/products/15210">SparkFun SAM-M8Q</a>, and the <a href="https://www.sparkfun.com/products/15193">SparkFun ZOE-M8Q</a>. Library also works with other u-blox based boards.<br/><br/>The ZED-F9P and NEO-M8P-2 modules are top-of-the-line modules for high accuracy GNSS and GPS location solutions including RTK. The ZED-F9P is unique in that it is capable of both rover and base station operations allowing the module to become a base station and produce RTCM 3.x correction data.<br/>
77
category=Sensors
88
url=https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library
99
architectures=*

‎src/SparkFun_u-blox_GNSS_Arduino_Library.cpp

Lines changed: 248 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,60 @@ boolean SFE_UBLOX_GNSS::begin(Stream &serialPort)
451451
return (connected);
452452
}
453453

454+
// Initialize for SPI
455+
boolean SFE_UBLOX_GNSS::begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed)
456+
{
457+
commType = COMM_TYPE_SPI;
458+
_spiPort = &spiPort;
459+
_csPin = csPin;
460+
_spiSpeed = spiSpeed;
461+
462+
// Initialize the chip select pin
463+
pinMode(_csPin, OUTPUT);
464+
digitalWrite(_csPin, HIGH);
465+
466+
//New in v2.0: allocate memory for the packetCfg payload here - if required. (The user may have called setPacketCfgPayloadSize already)
467+
if (packetCfgPayloadSize == 0)
468+
setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
469+
470+
createFileBuffer();
471+
472+
//Create the SPI buffer
473+
if (spiBuffer == NULL) //Memory has not yet been allocated - so use new
474+
{
475+
spiBuffer = new uint8_t[getSpiTransactionSize()];
476+
}
477+
478+
if (spiBuffer == NULL)
479+
{
480+
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
481+
{
482+
_debugSerial->print(F("begin (SPI): memory allocation failed for SPI Buffer!"));
483+
return (false);
484+
}
485+
}
486+
else
487+
{
488+
// Initialize/clear the SPI buffer - fill it with 0xFF as this is what is received from the UBLOX module if there's no data to be processed
489+
for (uint8_t i = 0; i < getSpiTransactionSize(); i++)
490+
{
491+
spiBuffer[i] = 0xFF;
492+
}
493+
}
494+
495+
// Call isConnected up to three times
496+
boolean connected = isConnected();
497+
498+
if (!connected)
499+
connected = isConnected();
500+
501+
if (!connected)
502+
connected = isConnected();
503+
504+
return (connected);
505+
}
506+
507+
454508
// Allow the user to change I2C polling wait (the minimum interval between I2C data requests - to avoid pounding the bus)
455509
// i2cPollingWait defaults to 100ms and is adjusted automatically when setNavigationFrequency()
456510
// or setHNRNavigationRate() are called. But if the user is using callbacks, it might be advantageous
@@ -460,6 +514,13 @@ void SFE_UBLOX_GNSS::setI2CpollingWait(uint8_t newPollingWait_ms)
460514
i2cPollingWait = newPollingWait_ms;
461515
}
462516

517+
// Allow the user to change SPI polling wait
518+
// (the minimum interval between SPI data requests when no data is available - to avoid pounding the bus)
519+
void SFE_UBLOX_GNSS::setSPIpollingWait(uint8_t newPollingWait_ms)
520+
{
521+
spiPollingWait = newPollingWait_ms;
522+
}
523+
463524
//Sets the global size for I2C transactions
464525
//Most platforms use 32 bytes (the default) but this allows users to increase the transaction
465526
//size if the platform supports it
@@ -473,6 +534,39 @@ uint8_t SFE_UBLOX_GNSS::getI2CTransactionSize(void)
473534
return (i2cTransactionSize);
474535
}
475536

537+
//Sets the global size for the SPI buffer/transactions.
538+
//Call this **before** begin()!
539+
//Note: if the buffer size is too small, incoming characters may be lost if the message sent
540+
//is larger than this buffer. If too big, you may run out of SRAM on constrained architectures!
541+
void SFE_UBLOX_GNSS::setSpiTransactionSize(uint8_t transactionSize)
542+
{
543+
if (spiBuffer == NULL)
544+
{
545+
spiTransactionSize = transactionSize;
546+
}
547+
else
548+
{
549+
if (_printDebug == true)
550+
{
551+
_debugSerial->println(F("setSpiTransactionSize: you need to call setSpiTransactionSize _before_ begin!"));
552+
}
553+
}
554+
}
555+
uint8_t SFE_UBLOX_GNSS::getSpiTransactionSize(void)
556+
{
557+
return (spiTransactionSize);
558+
}
559+
560+
//Sets the size of maxNMEAByteCount
561+
void SFE_UBLOX_GNSS::setMaxNMEAByteCount(int8_t newMax)
562+
{
563+
maxNMEAByteCount = newMax;
564+
}
565+
int8_t SFE_UBLOX_GNSS::getMaxNMEAByteCount(void)
566+
{
567+
return (maxNMEAByteCount);
568+
}
569+
476570
//Returns true if I2C device ack's
477571
boolean SFE_UBLOX_GNSS::isConnected(uint16_t maxWait)
478572
{
@@ -577,7 +671,7 @@ const char *SFE_UBLOX_GNSS::statusString(sfe_ublox_status_e stat)
577671
return "None";
578672
}
579673

580-
// Check for the arrival of new I2C/Serial data
674+
// Check for the arrival of new I2C/Serial/SPI data
581675

582676
//Allow the user to disable the "7F" check (e.g.) when logging RAWX data
583677
void SFE_UBLOX_GNSS::disableUBX7Fcheck(boolean disabled)
@@ -598,6 +692,8 @@ boolean SFE_UBLOX_GNSS::checkUbloxInternal(ubxPacket *incomingUBX, uint8_t reque
598692
return (checkUbloxI2C(incomingUBX, requestedClass, requestedID));
599693
else if (commType == COMM_TYPE_SERIAL)
600694
return (checkUbloxSerial(incomingUBX, requestedClass, requestedID));
695+
else if (commType == COMM_TYPE_SPI)
696+
return (checkUbloxSpi(incomingUBX, requestedClass, requestedID));
601697
return false;
602698
}
603699

@@ -755,6 +851,45 @@ boolean SFE_UBLOX_GNSS::checkUbloxSerial(ubxPacket *incomingUBX, uint8_t request
755851

756852
} //end checkUbloxSerial()
757853

854+
855+
//Checks SPI for data, passing any new bytes to process()
856+
boolean SFE_UBLOX_GNSS::checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID)
857+
{
858+
// Process the contents of the SPI buffer if not empty!
859+
for (uint8_t i = 0; i < spiBufferIndex; i++) {
860+
process(spiBuffer[i], incomingUBX, requestedClass, requestedID);
861+
}
862+
spiBufferIndex = 0;
863+
864+
_spiPort->beginTransaction(SPISettings(_spiSpeed, MSBFIRST, SPI_MODE0));
865+
digitalWrite(_csPin, LOW);
866+
uint8_t byteReturned = _spiPort->transfer(0xFF);
867+
868+
// Note to future self: I think the 0xFF check might cause problems when attempting to process (e.g.) RAWX data
869+
// which could legitimately contain 0xFF within the data stream. But the currentSentence check will certainly help!
870+
871+
// If we are not receiving a sentence (currentSentence == NONE) and the byteReturned is 0xFF,
872+
// i.e. the module has no data for us, then delay for
873+
if ((byteReturned == 0xFF) && (currentSentence == NONE))
874+
{
875+
digitalWrite(_csPin, HIGH);
876+
_spiPort->endTransaction();
877+
delay(spiPollingWait);
878+
return (true);
879+
}
880+
881+
while ((byteReturned != 0xFF) || (currentSentence != NONE))
882+
{
883+
process(byteReturned, incomingUBX, requestedClass, requestedID);
884+
byteReturned = _spiPort->transfer(0xFF);
885+
}
886+
digitalWrite(_csPin, HIGH);
887+
_spiPort->endTransaction();
888+
return (true);
889+
890+
} //end checkUbloxSpi()
891+
892+
758893
//PRIVATE: Check if we have storage allocated for an incoming "automatic" message
759894
boolean SFE_UBLOX_GNSS::checkAutomatic(uint8_t Class, uint8_t ID)
760895
{
@@ -2409,7 +2544,7 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg)
24092544
{
24102545
packetUBXESFMEAS->data.data[i].data.all = extractLong(msg, 8 + (i * 4));
24112546
}
2412-
if (msg->len > (8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4)))
2547+
if (msg->len > (8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4))) // IGNORE COMPILER WARNING comparison between signed and unsigned integer expressions
24132548
packetUBXESFMEAS->data.calibTtag = extractLong(msg, 8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4));
24142549

24152550
//Mark all datums as fresh (not read before)
@@ -2675,6 +2810,10 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::sendCommand(ubxPacket *outgoingUBX, uint16_t
26752810
{
26762811
sendSerialCommand(outgoingUBX);
26772812
}
2813+
else if (commType == COMM_TYPE_SPI)
2814+
{
2815+
sendSpiCommand(outgoingUBX);
2816+
}
26782817

26792818
if (maxWait > 0)
26802819
{
@@ -2781,6 +2920,87 @@ void SFE_UBLOX_GNSS::sendSerialCommand(ubxPacket *outgoingUBX)
27812920
_serialPort->write(outgoingUBX->checksumB);
27822921
}
27832922

2923+
2924+
// Transfer a byte to SPI. Also capture any bytes received from the UBLOX device during sending and capture them in a small buffer so that
2925+
// they can be processed later with process
2926+
void SFE_UBLOX_GNSS::spiTransfer(uint8_t byteToTransfer)
2927+
{
2928+
uint8_t returnedByte = _spiPort->transfer(byteToTransfer);
2929+
if ((spiBufferIndex < getSpiTransactionSize()) && (returnedByte != 0xFF || currentSentence != NONE))
2930+
{
2931+
spiBuffer[spiBufferIndex] = returnedByte;
2932+
spiBufferIndex++;
2933+
}
2934+
}
2935+
2936+
// Send a command via SPI
2937+
void SFE_UBLOX_GNSS::sendSpiCommand(ubxPacket *outgoingUBX)
2938+
{
2939+
if (spiBuffer == NULL)
2940+
{
2941+
if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
2942+
{
2943+
_debugSerial->print(F("sendSpiCommand: no memory allocation for SPI Buffer!"));
2944+
}
2945+
return;
2946+
}
2947+
2948+
// Start at the beginning of the SPI buffer
2949+
spiBufferIndex = 0;
2950+
2951+
_spiPort->beginTransaction(SPISettings(_spiSpeed, MSBFIRST, SPI_MODE0));
2952+
digitalWrite(_csPin, LOW);
2953+
//Write header bytes
2954+
spiTransfer(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on.
2955+
spiTransfer(UBX_SYNCH_2); //b
2956+
2957+
spiTransfer(outgoingUBX->cls);
2958+
spiTransfer(outgoingUBX->id);
2959+
spiTransfer(outgoingUBX->len & 0xFF); //LSB
2960+
spiTransfer(outgoingUBX->len >> 8);
2961+
2962+
if (_printDebug)
2963+
{
2964+
_debugSerial->print(F("sendSpiCommand: "));
2965+
_debugSerial->print(UBX_SYNCH_1, HEX);
2966+
_debugSerial->print(F(" "));
2967+
_debugSerial->print(UBX_SYNCH_2, HEX);
2968+
_debugSerial->print(F(" "));
2969+
_debugSerial->print(outgoingUBX->cls, HEX);
2970+
_debugSerial->print(F(" "));
2971+
_debugSerial->print(outgoingUBX->id, HEX);
2972+
_debugSerial->print(F(" "));
2973+
_debugSerial->print(outgoingUBX->len & 0xFF, HEX);
2974+
_debugSerial->print(F(" "));
2975+
_debugSerial->print(outgoingUBX->len >> 8, HEX);
2976+
}
2977+
2978+
//Write payload.
2979+
for (uint16_t i = 0; i < outgoingUBX->len; i++)
2980+
{
2981+
spiTransfer(outgoingUBX->payload[i]);
2982+
if (_printDebug)
2983+
{
2984+
_debugSerial->print(F(" "));
2985+
_debugSerial->print(outgoingUBX->payload[i], HEX);
2986+
}
2987+
}
2988+
2989+
//Write checksum
2990+
spiTransfer(outgoingUBX->checksumA);
2991+
spiTransfer(outgoingUBX->checksumB);
2992+
digitalWrite(_csPin, HIGH);
2993+
_spiPort->endTransaction();
2994+
2995+
if (_printDebug)
2996+
{
2997+
_debugSerial->print(F(" "));
2998+
_debugSerial->print(outgoingUBX->checksumA, HEX);
2999+
_debugSerial->print(F(" "));
3000+
_debugSerial->println(outgoingUBX->checksumB, HEX);
3001+
}
3002+
}
3003+
27843004
//Pretty prints the current ubxPacket
27853005
void SFE_UBLOX_GNSS::printPacket(ubxPacket *packet, boolean alwaysPrintPayload)
27863006
{
@@ -3004,7 +3224,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForACKResponse(ubxPacket *outgoingUBX, ui
30043224

30053225
} //checkUbloxInternal == true
30063226

3007-
delayMicroseconds(500);
3227+
delay(1); // Allow an RTOS to get an elbow in (#11)
30083228
} //while (millis() - startTime < maxTime)
30093229

30103230
// We have timed out...
@@ -3114,7 +3334,7 @@ sfe_ublox_status_e SFE_UBLOX_GNSS::waitForNoACKResponse(ubxPacket *outgoingUBX,
31143334
}
31153335
}
31163336

3117-
delayMicroseconds(500);
3337+
delay(1); // Allow an RTOS to get an elbow in (#11)
31183338
}
31193339

31203340
if (_printDebug == true)
@@ -3404,7 +3624,7 @@ boolean SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, boo
34043624
size_t bytesWritten = _serialPort->write(dataBytes, numDataBytes);
34053625
return (bytesWritten == numDataBytes);
34063626
}
3407-
else
3627+
else if (commType == COMM_TYPE_I2C)
34083628
{
34093629
// I2C: split the data up into packets of i2cTransactionSize
34103630
size_t bytesLeftToWrite = numDataBytes;
@@ -3439,6 +3659,14 @@ boolean SFE_UBLOX_GNSS::pushRawData(uint8_t *dataBytes, size_t numDataBytes, boo
34393659

34403660
return (bytesWrittenTotal == numDataBytes);
34413661
}
3662+
else // SPI
3663+
{
3664+
if (_printDebug == true)
3665+
{
3666+
_debugSerial->println(F("pushRawData: SPI not currently supported"));
3667+
}
3668+
return (false);
3669+
}
34423670
}
34433671

34443672
// Support for data logging
@@ -9782,6 +10010,21 @@ bool SFE_UBLOX_GNSS::getTimeValid(uint16_t maxWait)
978210010
return ((bool)packetUBXNAVPVT->data.valid.bits.validTime);
978310011
}
978410012

10013+
//Check to see if the UTC time has been fully resolved
10014+
bool SFE_UBLOX_GNSS::getTimeFullyResolved(uint16_t maxWait)
10015+
{
10016+
if (packetUBXNAVPVT == NULL) initPacketUBXNAVPVT(); //Check that RAM has been allocated for the PVT data
10017+
if (packetUBXNAVPVT == NULL) //Bail if the RAM allocation failed
10018+
return (false);
10019+
10020+
if (packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fullyResolved == false)
10021+
getPVT(maxWait);
10022+
packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.fullyResolved = false; //Since we are about to give this to user, mark this data as stale
10023+
packetUBXNAVPVT->moduleQueried.moduleQueried1.bits.all = false;
10024+
return ((bool)packetUBXNAVPVT->data.valid.bits.fullyResolved);
10025+
}
10026+
10027+
978510028
//Get the confirmed date validity
978610029
bool SFE_UBLOX_GNSS:: getConfirmedDate(uint16_t maxWait)
978710030
{

‎src/SparkFun_u-blox_GNSS_Arduino_Library.h

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151

5252
#include <Wire.h>
5353

54+
#include <SPI.h>
55+
5456
#include "u-blox_config_keys.h"
5557
#include "u-blox_structs.h"
5658

@@ -492,6 +494,15 @@ enum sfe_ublox_ls_src_e
492494
//#define MAX_PAYLOAD_SIZE 768 //Worst case: UBX_CFG_VALSET packet with 64 keyIDs each with 64 bit values
493495
#endif
494496

497+
// For storing SPI bytes received during sendSpiCommand
498+
#define SFE_UBLOX_SPI_BUFFER_SIZE 128
499+
500+
// Default maximum NMEA byte count
501+
// maxNMEAByteCount was set to 82: https://en.wikipedia.org/wiki/NMEA_0183#Message_structure
502+
// but the u-blox HP (RTK) GGA messages are 88 bytes long
503+
// The user can adjust maxNMEAByteCount by calling setMaxNMEAByteCount
504+
#define SFE_UBLOX_MAX_NMEA_BYTE_COUNT 88
505+
495506
//-=-=-=-=- UBX binary specific variables
496507
struct ubxPacket
497508
{
@@ -560,17 +571,29 @@ class SFE_UBLOX_GNSS
560571
boolean begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42); //Returns true if module is detected
561572
//serialPort needs to be perviously initialized to correct baud rate
562573
boolean begin(Stream &serialPort); //Returns true if module is detected
574+
//SPI - supply instance of SPIClass, chip select pin and SPI speed (in Hz)
575+
boolean begin(SPIClass &spiPort, uint8_t csPin, uint32_t spiSpeed);
563576

564577
void end(void); //Stop all automatic message processing. Free all used RAM
565578

566579
void setI2CpollingWait(uint8_t newPollingWait_ms); // Allow the user to change the I2C polling wait if required
580+
void setSPIpollingWait(uint8_t newPollingWait_ms); // Allow the user to change the SPI polling wait if required
581+
582+
//Set the max number of bytes set in a given I2C transaction
583+
uint8_t i2cTransactionSize = 32; //Default to ATmega328 limit
567584

568585
//Control the size of the internal I2C transaction amount
569586
void setI2CTransactionSize(uint8_t bufferSize);
570587
uint8_t getI2CTransactionSize(void);
571588

572-
//Set the max number of bytes set in a given I2C transaction
573-
uint8_t i2cTransactionSize = 32; //Default to ATmega328 limit
589+
//Control the size of the spi buffer. If the buffer isn't big enough, we'll start to lose bytes
590+
//That we receive if the buffer is full!
591+
void setSpiTransactionSize(uint8_t bufferSize);
592+
uint8_t getSpiTransactionSize(void);
593+
594+
//Control the size of maxNMEAByteCount
595+
void setMaxNMEAByteCount(int8_t newMax);
596+
int8_t getMaxNMEAByteCount(void);
574597

575598
//Returns true if device answers on _gpsI2Caddress address or via Serial
576599
boolean isConnected(uint16_t maxWait = 1100);
@@ -612,6 +635,7 @@ class SFE_UBLOX_GNSS
612635

613636
boolean checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for I2C polling of data, passing any new bytes to process()
614637
boolean checkUbloxSerial(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for serial polling of data, passing any new bytes to process()
638+
boolean checkUbloxSpi(ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Method for spi polling of data, passing any new bytes to process()
615639

616640
// Process the incoming data
617641

@@ -622,12 +646,13 @@ class SFE_UBLOX_GNSS
622646
void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); //Given a character, file it away into the uxb packet structure
623647
void processUBXpacket(ubxPacket *msg); //Once a packet has been received and validated, identify this packet's class/id and update internal flags
624648

625-
// Send I2C/Serial commands to the module
649+
// Send I2C/Serial/SPI commands to the module
626650

627651
void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages
628652
sfe_ublox_status_e sendCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait, boolean expectACKonly = false); //Given a packet and payload, send everything including CRC bytes, return true if we got a response
629653
sfe_ublox_status_e sendI2cCommand(ubxPacket *outgoingUBX, uint16_t maxWait = defaultMaxWait);
630654
void sendSerialCommand(ubxPacket *outgoingUBX);
655+
void sendSpiCommand(ubxPacket *outgoingUBX);
631656

632657
void printPacket(ubxPacket *packet, boolean alwaysPrintPayload = false); //Useful for debugging
633658

@@ -1061,6 +1086,7 @@ class SFE_UBLOX_GNSS
10611086

10621087
bool getDateValid(uint16_t maxWait = defaultMaxWait);
10631088
bool getTimeValid(uint16_t maxWait = defaultMaxWait);
1089+
bool getTimeFullyResolved(uint16_t maxWait = defaultMaxWait);
10641090
bool getConfirmedDate(uint16_t maxWait = defaultMaxWait);
10651091
bool getConfirmedTime(uint16_t maxWait = defaultMaxWait);
10661092

@@ -1235,6 +1261,9 @@ class SFE_UBLOX_GNSS
12351261
//Calculate how much RAM is needed to store the payload for a given automatic message
12361262
uint16_t getMaxPayloadSize(uint8_t Class, uint8_t ID);
12371263

1264+
//Do the actual transfer to SPI
1265+
void spiTransfer(uint8_t byteToTransfer);
1266+
12381267
boolean initGeofenceParams(); // Allocate RAM for currentGeofenceParams and initialize it
12391268
boolean initModuleSWVersion(); // Allocate RAM for moduleSWVersion and initialize it
12401269

@@ -1273,6 +1302,10 @@ class SFE_UBLOX_GNSS
12731302
Stream *_nmeaOutputPort = NULL; //The user can assign an output port to print NMEA sentences if they wish
12741303
Stream *_debugSerial; //The stream to send debug messages to if enabled
12751304

1305+
SPIClass *_spiPort; //The instance of SPIClass
1306+
uint8_t _csPin; //The chip select pin
1307+
uint32_t _spiSpeed; //The speed to use for SPI (Hz)
1308+
12761309
uint8_t _gpsI2Caddress = 0x42; //Default 7-bit unshifted address of the ublox 6/7/8/M8/F9 series
12771310
//This can be changed using the ublox configuration software
12781311

@@ -1292,6 +1325,10 @@ class SFE_UBLOX_GNSS
12921325
uint8_t *payloadCfg = NULL;
12931326
uint8_t *payloadAuto = NULL;
12941327

1328+
uint8_t *spiBuffer = NULL; // A buffer to store any bytes being recieved back from the device while we are sending via SPI
1329+
uint8_t spiBufferIndex = 0; // Index into the SPI buffer
1330+
uint8_t spiTransactionSize = SFE_UBLOX_SPI_BUFFER_SIZE; //Default size of the SPI buffer
1331+
12951332
//Init the packet structures and init them with pointers to the payloadAck, payloadCfg, payloadBuf and payloadAuto arrays
12961333
ubxPacket packetAck = {0, 0, 0, 0, 0, payloadAck, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
12971334
ubxPacket packetBuf = {0, 0, 0, 0, 0, payloadBuf, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
@@ -1308,18 +1345,24 @@ class SFE_UBLOX_GNSS
13081345
sfe_ublox_packet_buffer_e activePacketBuffer = SFE_UBLOX_PACKET_PACKETBUF;
13091346

13101347
//Limit checking of new data to every X ms
1311-
//If we are expecting an update every X Hz then we should check every half that amount of time
1348+
//If we are expecting an update every X Hz then we should check every quarter that amount of time
13121349
//Otherwise we may block ourselves from seeing new data
13131350
uint8_t i2cPollingWait = 100; //Default to 100ms. Adjusted when user calls setNavigationFrequency() or setHNRNavigationRate() or setMeasurementRate()
13141351

1352+
//The SPI polling wait is a little different. checkUbloxSpi will delay for this amount before returning if
1353+
//there is no data waiting to be read. This prevents waitForACKResponse from pounding the SPI bus too hard.
1354+
uint8_t spiPollingWait = 9; //Default to 9ms; waitForACKResponse delays for 1ms on top of this. User can adjust with setSPIPollingWait.
1355+
13151356
unsigned long lastCheck = 0;
13161357

13171358
uint16_t ubxFrameCounter; //Count all UBX frame bytes. [Fixed header(2bytes), CLS(1byte), ID(1byte), length(2bytes), payload(x bytes), checksums(2bytes)]
13181359
uint8_t rollingChecksumA; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes
13191360
uint8_t rollingChecksumB; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes
13201361

13211362
int8_t nmeaByteCounter; //Count all NMEA message bytes.
1322-
const int8_t maxNMEAByteCount = 82; // Abort NMEA message reception if nmeaByteCounter exceeds this (https://en.wikipedia.org/wiki/NMEA_0183#Message_structure)
1363+
// Abort NMEA message reception if nmeaByteCounter exceeds maxNMEAByteCount.
1364+
// The user can adjust maxNMEAByteCount by calling setMaxNMEAByteCount
1365+
int8_t maxNMEAByteCount = SFE_UBLOX_MAX_NMEA_BYTE_COUNT;
13231366
uint8_t nmeaAddressField[6]; // NMEA Address Field - includes the start character (*)
13241367
boolean logThisNMEA(); // Return true if we should log this NMEA message
13251368
boolean processThisNMEA(); // Return true if we should pass this NMEA message to processNMEA

0 commit comments

Comments
 (0)
Please sign in to comment.