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+ }
0 commit comments