Skip to content

Commit 746ad2b

Browse files
authored
Merge pull request #44 from sparkfun/release_candidate
v3.1.0
2 parents 05eea98 + 79b665f commit 746ad2b

23 files changed

+4155
-305
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
u-blox Example: ESF MEAS (Wheel Ticks)
3+
By: Paul Clark
4+
SparkFun Electronics
5+
Date: December 19th, 2023
6+
License: MIT. See license file for more information
7+
8+
This example configures the External Sensor Fusion MEAS sensor messages on the ZED-F9R and
9+
shows how to access the ESF data using callbacks.
10+
11+
Feel like supporting open source hardware?
12+
Buy a board from SparkFun!
13+
ZED-F9R: https://www.sparkfun.com/products/22660
14+
15+
Hardware Connections:
16+
Plug a Qwiic cable into the GPS and a Redboard Qwiic
17+
If you don't have a platform with a Qwiic connection use the
18+
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
19+
20+
Open the serial monitor at >>> 230400 <<< baud to see the output
21+
22+
*/
23+
24+
#include <Wire.h> //Needed for I2C to GPS
25+
26+
#include <SparkFun_u-blox_GNSS_v3.h> //http://librarymanager/All#SparkFun_u-blox_GNSS_v3
27+
SFE_UBLOX_GNSS myGNSS;
28+
29+
// Callback: printESFMEASdata will be called when new ESF MEAS data arrives
30+
// See u-blox_structs.h for the full definition of UBX_ESF_MEAS_data_t
31+
// _____ You can use any name you like for the callback. Use the same name when you call setAutoESFMEAScallback
32+
// / _____ This _must_ be UBX_ESF_MEAS_data_t
33+
// | / _____ You can use any name you like for the struct
34+
// | | /
35+
// | | |
36+
void printESFMEASdata(UBX_ESF_MEAS_data_t *ubxDataStruct)
37+
{
38+
// New ESF MEAS data has arrived:
39+
40+
// Print the timeTag
41+
Serial.print(F("Time: "));
42+
Serial.println(ubxDataStruct->timeTag);
43+
44+
// ubxDataStruct->flags.bits.numMeas indicates how many sensor groups the UBX_ESF_MEAS_data_t contains.
45+
for (uint8_t i = 0; i < ubxDataStruct->flags.bits.numMeas; i++)
46+
{
47+
// Print the sensor data type
48+
// From the M8 interface description:
49+
// 0: None
50+
// 1-4: Reserved
51+
// 5: z-axis gyroscope angular rate deg/s * 2^-12 signed
52+
// 6: front-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
53+
// 7: front-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
54+
// 8: rear-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
55+
// 9: rear-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
56+
// 10: speed ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
57+
// 11: speed m/s * 1e-3 signed
58+
// 12: gyroscope temperature deg Celsius * 1e-2 signed
59+
// 13: y-axis gyroscope angular rate deg/s * 2^-12 signed
60+
// 14: x-axis gyroscope angular rate deg/s * 2^-12 signed
61+
// 16: x-axis accelerometer specific force m/s^2 * 2^-10 signed
62+
// 17: y-axis accelerometer specific force m/s^2 * 2^-10 signed
63+
// 18: z-axis accelerometer specific force m/s^2 * 2^-10 signed
64+
switch (ubxDataStruct->data[i].data.bits.dataType)
65+
{
66+
case 5:
67+
Serial.print(F("Z Gyro: "));
68+
break;
69+
case 6:
70+
Serial.print(F("Front Left: "));
71+
break;
72+
case 7:
73+
Serial.print(F("Front Right: "));
74+
break;
75+
case 8:
76+
Serial.print(F("Rear Left: "));
77+
break;
78+
case 9:
79+
Serial.print(F("Rear Right: "));
80+
break;
81+
case 10:
82+
Serial.print(F("Speed Ticks: "));
83+
break;
84+
case 11:
85+
Serial.print(F("Speed: "));
86+
break;
87+
case 12:
88+
Serial.print(F("Temp: "));
89+
break;
90+
case 13:
91+
Serial.print(F("Y Gyro: "));
92+
break;
93+
case 14:
94+
Serial.print(F("X Gyro: "));
95+
break;
96+
case 16:
97+
Serial.print(F("X Accel: "));
98+
break;
99+
case 17:
100+
Serial.print(F("Y Accel: "));
101+
break;
102+
case 18:
103+
Serial.print(F("Z Accel: "));
104+
break;
105+
default:
106+
break;
107+
}
108+
109+
// Tick data
110+
if ((ubxDataStruct->data[i].data.bits.dataType >= 6) && (ubxDataStruct->data[i].data.bits.dataType <= 10))
111+
{
112+
if ((ubxDataStruct->data[i].data.bits.dataField & (1 << 23)) > 0)
113+
Serial.print(F("-")); // Backward
114+
else
115+
Serial.print(F("+")); // Forward
116+
Serial.println(ubxDataStruct->data[i].data.bits.dataField & 0x007FFFFF);
117+
}
118+
// Speed
119+
else if (ubxDataStruct->data[i].data.bits.dataType == 11)
120+
{
121+
union
122+
{
123+
int32_t signed32;
124+
uint32_t unsigned32;
125+
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
126+
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
127+
signedUnsigned.unsigned32 = ubxDataStruct->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
128+
float speed = signedUnsigned.signed32; // Extract the signed data. Convert to float
129+
speed /= 256.0; // Divide by 256 to undo the shift
130+
speed *= 0.001; // Convert from m/s * 1e-3 to m/s
131+
Serial.println(speed, 3);
132+
}
133+
// Gyro data
134+
else if ((ubxDataStruct->data[i].data.bits.dataType == 5) || (ubxDataStruct->data[i].data.bits.dataType == 13) || (ubxDataStruct->data[i].data.bits.dataType == 14))
135+
{
136+
union
137+
{
138+
int32_t signed32;
139+
uint32_t unsigned32;
140+
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
141+
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
142+
signedUnsigned.unsigned32 = ubxDataStruct->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
143+
float rate = signedUnsigned.signed32; // Extract the signed data. Convert to float
144+
rate /= 256.0; // Divide by 256 to undo the shift
145+
rate *= 0.000244140625; // Convert from deg/s * 2^-12 to deg/s
146+
Serial.println(rate);
147+
}
148+
// Accelerometer data
149+
else if ((ubxDataStruct->data[i].data.bits.dataType == 16) || (ubxDataStruct->data[i].data.bits.dataType == 17) || (ubxDataStruct->data[i].data.bits.dataType == 18))
150+
{
151+
union
152+
{
153+
int32_t signed32;
154+
uint32_t unsigned32;
155+
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
156+
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
157+
signedUnsigned.unsigned32 = ubxDataStruct->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
158+
float force = signedUnsigned.signed32; // Extract the signed data. Convert to float
159+
force /= 256.0; // Divide by 256 to undo the shift
160+
force *= 0.0009765625; // Convert from m/s^2 * 2^-10 to m/s^2
161+
Serial.println(force);
162+
}
163+
// Gyro Temperature
164+
else if (ubxDataStruct->data[i].data.bits.dataType == 12)
165+
{
166+
union
167+
{
168+
int32_t signed32;
169+
uint32_t unsigned32;
170+
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
171+
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
172+
signedUnsigned.unsigned32 = ubxDataStruct->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
173+
float temperature = signedUnsigned.signed32; // Extract the signed data. Convert to float
174+
temperature /= 256.0; // Divide by 256 to undo the shift
175+
temperature *= 0.01; // Convert from C * 1e-2 to C
176+
Serial.println(temperature);
177+
}
178+
}
179+
}
180+
181+
void setup()
182+
{
183+
Serial.begin(230400); // <-- Use a fast baud rate to avoid the Serial prints slowing the code
184+
185+
while (!Serial)
186+
; // Wait for user to open terminal
187+
Serial.println(F("SparkFun u-blox Example"));
188+
189+
Wire.begin();
190+
Wire.setClock(400000); // <-- Use 400kHz I2C
191+
192+
// myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
193+
194+
if (myGNSS.begin() == false) // Connect to the u-blox module using Wire port
195+
{
196+
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
197+
while (1)
198+
;
199+
}
200+
201+
myGNSS.setI2COutput(COM_TYPE_UBX); // Set the I2C port to output UBX only (turn off NMEA noise)
202+
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); // Save (only) the communications port settings to flash and BBR
203+
204+
if (myGNSS.setAutoESFMEAScallbackPtr(&printESFMEASdata) == true) // Enable automatic ESF MEAS messages with callback to printESFMEASdata
205+
Serial.println(F("setAutoESFMEAScallback successful"));
206+
}
207+
208+
void loop()
209+
{
210+
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
211+
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
212+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
Use the NEO-D9S L-Band receiver to provide corrections as PMP over Serial
3+
By: SparkFun Electronics / Paul Clark
4+
Based on original code by: u-blox AG / Michael Ammann
5+
v3 updates: Decembe 22nd, 2022
6+
License: MIT. See license file for more information.
7+
8+
This example shows how to obtain PMP correction data from a NEO-D9S L-Band receiver and push it over Serial (UART).
9+
10+
Feel like supporting open source hardware?
11+
Buy a board from SparkFun!
12+
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
13+
NEO-D9S: https://www.sparkfun.com/products/19390
14+
Combo Board: https://www.sparkfun.com/products/20167
15+
16+
Hardware Connections:
17+
Use a Qwiic cable to connect the NEO-D9S to your board
18+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
19+
Open the serial monitor at 115200 baud to see the output
20+
*/
21+
22+
#include <driver/uart.h> //Required for uart_set_rx_full_threshold() on cores <v2.0.5
23+
HardwareSerial serialGNSS(2); // TX on 17, RX on 16
24+
25+
#include <SparkFun_u-blox_GNSS_v3.h> //http://librarymanager/All#SparkFun_u-blox_GNSS_v3
26+
SFE_UBLOX_GNSS myLBand; // NEO-D9S
27+
28+
const uint32_t myLBandFreq = 1556290000; // Uncomment this line to use the US SPARTN 1.8 service
29+
//const uint32_t myLBandFreq = 1545260000; // Uncomment this line to use the EU SPARTN 1.8 service
30+
31+
#define OK(ok) (ok ? F(" -> OK") : F(" -> ERROR!")) // Convert uint8_t into OK/ERROR
32+
33+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
34+
35+
// Callback: pushRXMPMP will be called when new PMP data arrives
36+
// See u-blox_structs.h for the full definition of UBX_RXM_PMP_message_data_t
37+
// _____ You can use any name you like for the callback. Use the same name when you call setRXMPMPmessageCallbackPtr
38+
// / _____ This _must_ be UBX_RXM_PMP_message_data_t
39+
// | / _____ You can use any name you like for the struct
40+
// | | /
41+
// | | |
42+
void pushRXMPMP(UBX_RXM_PMP_message_data_t *pmpData)
43+
{
44+
//Extract the raw message payload length
45+
uint16_t payloadLen = ((uint16_t)pmpData->lengthMSB << 8) | (uint16_t)pmpData->lengthLSB;
46+
47+
uint16_t numBytesUserData = pmpData->payload[2] | ((uint16_t)pmpData->payload[3] << 8);
48+
uint16_t fecBits = pmpData->payload[20] | ((uint16_t)pmpData->payload[21] << 8);
49+
float ebno = (float)pmpData->payload[22] / 8;
50+
51+
Serial.print(F("New RXM-PMP data received. userData: "));
52+
Serial.print(numBytesUserData);
53+
Serial.print(F(" Bytes. fecBits: "));
54+
Serial.print(fecBits);
55+
Serial.print(F(". ebno (dB): "));
56+
Serial.print(ebno);
57+
Serial.println(F("."));
58+
59+
Serial.println(F("Pushing PMP to Serial..."));
60+
61+
serialGNSS.write(&pmpData->payload[24], (size_t)numBytesUserData); // Push only the raw PMP userData
62+
(void)payloadLen;
63+
64+
//serialGNSS.write(&pmpData->sync1, (size_t)payloadLen + 6); // Push the sync chars, class, ID, length and payload
65+
//serialGNSS.write(&pmpData->checksumA, (size_t)2); // Push the checksum bytes
66+
}
67+
68+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
69+
70+
void setup()
71+
{
72+
delay(1000);
73+
74+
Serial.begin(115200);
75+
Serial.println(F("NEO-D9S SPARTN Corrections"));
76+
77+
serialGNSS.begin(38400); // UART2 on pins 16/17.
78+
79+
Wire.begin(); //Start I2C
80+
81+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
82+
// Begin and configure the NEO-D9S L-Band receiver
83+
84+
//myLBand.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
85+
86+
while (myLBand.begin(Wire, 0x43) == false) //Connect to the u-blox NEO-D9S using Wire port. The D9S default I2C address is 0x43 (not 0x42)
87+
{
88+
Serial.println(F("u-blox NEO-D9S not detected at default I2C address. Please check wiring."));
89+
delay(2000);
90+
}
91+
Serial.println(F("u-blox NEO-D9S connected"));
92+
93+
myLBand.newCfgValset(); // Create a new Configuration Interface message - this defaults to VAL_LAYER_RAM_BBR (change in RAM and BBR)
94+
myLBand.addCfgValset(UBLOX_CFG_PMP_CENTER_FREQUENCY, myLBandFreq); // Default 1539812500 Hz
95+
myLBand.addCfgValset(UBLOX_CFG_PMP_SEARCH_WINDOW, 2200); // Default 2200 Hz
96+
myLBand.addCfgValset(UBLOX_CFG_PMP_USE_SERVICE_ID, 0); // Default 1
97+
myLBand.addCfgValset(UBLOX_CFG_PMP_SERVICE_ID, 21845); // Default 50821
98+
myLBand.addCfgValset(UBLOX_CFG_PMP_DATA_RATE, 2400); // Default 2400 bps
99+
myLBand.addCfgValset(UBLOX_CFG_PMP_USE_DESCRAMBLER, 1); // Default 1
100+
myLBand.addCfgValset(UBLOX_CFG_PMP_DESCRAMBLER_INIT, 26969); // Default 23560
101+
myLBand.addCfgValset(UBLOX_CFG_PMP_USE_PRESCRAMBLING, 0); // Default 0
102+
myLBand.addCfgValset(UBLOX_CFG_PMP_UNIQUE_WORD, 16238547128276412563ull);
103+
myLBand.addCfgValset(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 1); // Ensure UBX-RXM-PMP is enabled on the I2C port
104+
myLBand.addCfgValset(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 1); // Output UBX-RXM-PMP on UART1
105+
myLBand.addCfgValset(UBLOX_CFG_UART2OUTPROT_UBX, 1); // Enable UBX output on UART2
106+
myLBand.addCfgValset(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2, 1); // Output UBX-RXM-PMP on UART2
107+
myLBand.addCfgValset(UBLOX_CFG_UART1_BAUDRATE, 38400); // match baudrate with ZED default
108+
myLBand.addCfgValset(UBLOX_CFG_UART2_BAUDRATE, 38400); // match baudrate with ZED default
109+
bool ok = myLBand.sendCfgValset(); // Apply the settings
110+
111+
Serial.print(F("L-Band: configuration "));
112+
Serial.println(OK(ok));
113+
114+
myLBand.softwareResetGNSSOnly(); // Do a restart
115+
116+
myLBand.setRXMPMPmessageCallbackPtr(&pushRXMPMP); // Call pushRXMPMP when new PMP data arrives. Push it to the GNSS
117+
118+
}
119+
120+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
121+
122+
void loop()
123+
{
124+
myLBand.checkUblox(); // Check for the arrival of new PMP data and process it.
125+
myLBand.checkCallbacks(); // Check if any LBand callbacks are waiting to be processed.
126+
}

0 commit comments

Comments
 (0)