+224
@@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
u-blox Example: ESF MEAS (Wheel Ticks)
|
||||||
|
By: Paul Clark
|
||||||
|
SparkFun Electronics
|
||||||
|
Date: September 8th, 2022
|
||||||
|
License: MIT. See license file for more information but you can
|
||||||
|
basically do whatever you want with this code.
|
||||||
|
|
||||||
|
This example configures the External Sensor Fusion MEAS sensor messages on the NEO-M8U / ZED-F9R and
|
||||||
|
shows how to access the ESF data in the loop - without using the callback.
|
||||||
|
|
||||||
|
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||||
|
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||||
|
|
||||||
|
Feel like supporting open source hardware?
|
||||||
|
Buy a board from SparkFun!
|
||||||
|
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||||
|
|
||||||
|
Hardware Connections:
|
||||||
|
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||||
|
If you don't have a platform with a Qwiic connection use the
|
||||||
|
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||||
|
Open the serial monitor at 115200 baud to see the output
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Wire.h> //Needed for I2C to GPS
|
||||||
|
|
||||||
|
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||||
|
SFE_UBLOX_GNSS myGNSS;
|
||||||
|
|
||||||
|
// Callback: printESFMEASdata will be called when new ESF MEAS data arrives
|
||||||
|
// See u-blox_structs.h for the full definition of UBX_ESF_MEAS_data_t
|
||||||
|
// _____ You can use any name you like for the callback. Use the same name when you call setAutoESFMEAScallback
|
||||||
|
// / _____ This _must_ be UBX_ESF_MEAS_data_t
|
||||||
|
// | / _____ You can use any name you like for the struct
|
||||||
|
// | | /
|
||||||
|
// | | |
|
||||||
|
void printESFMEASdata(UBX_ESF_MEAS_data_t *ubxDataStruct)
|
||||||
|
{
|
||||||
|
Serial.println(F("Hey! The ESF MEAS callback has been called!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(230400); // <-- Use a fast baud rate to avoid the Serial prints slowing the code
|
||||||
|
|
||||||
|
while (!Serial); //Wait for user to open terminal
|
||||||
|
Serial.println(F("SparkFun u-blox Example"));
|
||||||
|
|
||||||
|
Wire.begin();
|
||||||
|
Wire.setClock(400000); // <-- Use 400kHz I2C
|
||||||
|
|
||||||
|
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||||
|
|
||||||
|
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||||
|
{
|
||||||
|
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||||
|
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||||
|
|
||||||
|
if (myGNSS.setAutoESFMEAScallbackPtr(&printESFMEASdata) == true) // Enable automatic ESF MEAS messages with callback to printESFMEASdata
|
||||||
|
Serial.println(F("setAutoESFMEAScallback successful"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||||
|
|
||||||
|
// Check if new ESF MEAS data has arrived:
|
||||||
|
// If myGNSS.packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid is true, it indicates new ESF MEAS data has been received and has been copied.
|
||||||
|
// automaticFlags.flags.bits.callbackCopyValid will be cleared automatically when the callback is called.
|
||||||
|
|
||||||
|
if (myGNSS.packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == true)
|
||||||
|
{
|
||||||
|
// But, we can manually clear the callback flag too. This will prevent the callback from being called!
|
||||||
|
myGNSS.packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid = false; // Comment this line if you still want the callback to be called
|
||||||
|
|
||||||
|
// Print the timeTag
|
||||||
|
Serial.print(F("Time: "));
|
||||||
|
Serial.println(myGNSS.packetUBXESFMEAS->callbackData->timeTag);
|
||||||
|
|
||||||
|
// myGNSS.packetUBXESFMEAS->callbackData->flags.bits.numMeas indicates how many sensor groups the UBX_ESF_MEAS_data_t contains.
|
||||||
|
for (uint8_t i = 0; i < myGNSS.packetUBXESFMEAS->callbackData->flags.bits.numMeas; i++)
|
||||||
|
{
|
||||||
|
// Print the sensor data type
|
||||||
|
// From the M8 interface description:
|
||||||
|
// 0: None
|
||||||
|
// 1-4: Reserved
|
||||||
|
// 5: z-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||||
|
// 6: front-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||||
|
// 7: front-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||||
|
// 8: rear-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||||
|
// 9: rear-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||||
|
// 10: speed ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||||
|
// 11: speed m/s * 1e-3 signed
|
||||||
|
// 12: gyroscope temperature deg Celsius * 1e-2 signed
|
||||||
|
// 13: y-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||||
|
// 14: x-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||||
|
// 16: x-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||||
|
// 17: y-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||||
|
// 18: z-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||||
|
switch (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType)
|
||||||
|
{
|
||||||
|
case 5:
|
||||||
|
Serial.print(F("Z Gyro: "));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
Serial.print(F("Front Left: "));
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
Serial.print(F("Front Right: "));
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
Serial.print(F("Rear Left: "));
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
Serial.print(F("Rear Right: "));
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
Serial.print(F("Speed Ticks: "));
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
Serial.print(F("Speed: "));
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
Serial.print(F("Temp: "));
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
Serial.print(F("Y Gyro: "));
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
Serial.print(F("X Gyro: "));
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
Serial.print(F("X Accel: "));
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
Serial.print(F("Y Accel: "));
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
Serial.print(F("Z Accel: "));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tick data
|
||||||
|
if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType >= 6) && (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType <= 10))
|
||||||
|
{
|
||||||
|
if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField & (1 << 23)) > 0)
|
||||||
|
Serial.print(F("-")); // Backward
|
||||||
|
else
|
||||||
|
Serial.print(F("+")); // Forward
|
||||||
|
Serial.println(myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField & 0x007FFFFF);
|
||||||
|
}
|
||||||
|
// Speed
|
||||||
|
else if (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 11)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int32_t signed32;
|
||||||
|
uint32_t unsigned32;
|
||||||
|
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||||
|
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||||
|
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||||
|
float speed = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||||
|
speed /= 256.0; // Divide by 256 to undo the shift
|
||||||
|
speed *= 0.001; // Convert from m/s * 1e-3 to m/s
|
||||||
|
Serial.println(speed, 3);
|
||||||
|
}
|
||||||
|
// Gyro data
|
||||||
|
else if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 5) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 13) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 14))
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int32_t signed32;
|
||||||
|
uint32_t unsigned32;
|
||||||
|
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||||
|
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||||
|
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||||
|
float rate = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||||
|
rate /= 256.0; // Divide by 256 to undo the shift
|
||||||
|
rate *= 0.000244140625; // Convert from deg/s * 2^-12 to deg/s
|
||||||
|
Serial.println(rate);
|
||||||
|
}
|
||||||
|
// Accelerometer data
|
||||||
|
else if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 16) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 17) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 18))
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int32_t signed32;
|
||||||
|
uint32_t unsigned32;
|
||||||
|
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||||
|
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||||
|
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||||
|
float force = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||||
|
force /= 256.0; // Divide by 256 to undo the shift
|
||||||
|
force *= 0.0009765625; // Convert from m/s^2 * 2^-10 to m/s^2
|
||||||
|
Serial.println(force);
|
||||||
|
}
|
||||||
|
// Gyro Temperature
|
||||||
|
else if (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 12)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int32_t signed32;
|
||||||
|
uint32_t unsigned32;
|
||||||
|
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||||
|
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||||
|
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||||
|
float temperature = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||||
|
temperature /= 256.0; // Divide by 256 to undo the shift
|
||||||
|
temperature *= 0.01; // Convert from C * 1e-2 to C
|
||||||
|
Serial.println(temperature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. There will not be any in this example, unless you commented the line above
|
||||||
|
}
|
||||||
@@ -474,14 +474,11 @@ assumeAutoESFINS KEYWORD2
|
|||||||
flushESFINS KEYWORD2
|
flushESFINS KEYWORD2
|
||||||
logESFINS KEYWORD2
|
logESFINS KEYWORD2
|
||||||
|
|
||||||
getEsfDataInfo KEYWORD2
|
|
||||||
getESFMEAS KEYWORD2
|
|
||||||
setAutoESFMEAS KEYWORD2
|
setAutoESFMEAS KEYWORD2
|
||||||
setAutoESFMEASrate KEYWORD2
|
setAutoESFMEASrate KEYWORD2
|
||||||
setAutoESFMEAScallback KEYWORD2
|
setAutoESFMEAScallback KEYWORD2
|
||||||
setAutoESFMEAScallbackPtr KEYWORD2
|
setAutoESFMEAScallbackPtr KEYWORD2
|
||||||
assumeAutoESFMEAS KEYWORD2
|
assumeAutoESFMEAS KEYWORD2
|
||||||
flushESFMEAS KEYWORD2
|
|
||||||
logESFMEAS KEYWORD2
|
logESFMEAS KEYWORD2
|
||||||
|
|
||||||
setAutoESFRAW KEYWORD2
|
setAutoESFRAW KEYWORD2
|
||||||
@@ -489,7 +486,6 @@ setAutoESFRAWrate KEYWORD2
|
|||||||
setAutoESFRAWcallback KEYWORD2
|
setAutoESFRAWcallback KEYWORD2
|
||||||
setAutoESFRAWcallbackPtr KEYWORD2
|
setAutoESFRAWcallbackPtr KEYWORD2
|
||||||
assumeAutoESFRAW KEYWORD2
|
assumeAutoESFRAW KEYWORD2
|
||||||
flushESFRAW KEYWORD2
|
|
||||||
logESFRAW KEYWORD2
|
logESFRAW KEYWORD2
|
||||||
|
|
||||||
getHNRAtt KEYWORD2
|
getHNRAtt KEYWORD2
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
name=SparkFun u-blox GNSS Arduino Library
|
name=SparkFun u-blox GNSS Arduino Library
|
||||||
version=2.2.14
|
version=2.2.15
|
||||||
author=SparkFun Electronics <techsupport@sparkfun.com>
|
author=SparkFun Electronics <techsupport@sparkfun.com>
|
||||||
maintainer=SparkFun Electronics <sparkfun.com>
|
maintainer=SparkFun Electronics <sparkfun.com>
|
||||||
sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules<br/><br/>
|
sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules<br/><br/>
|
||||||
|
|||||||
@@ -4216,16 +4216,13 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg)
|
|||||||
packetUBXESFMEAS->data.timeTag = extractLong(msg, 0);
|
packetUBXESFMEAS->data.timeTag = extractLong(msg, 0);
|
||||||
packetUBXESFMEAS->data.flags.all = extractInt(msg, 4);
|
packetUBXESFMEAS->data.flags.all = extractInt(msg, 4);
|
||||||
packetUBXESFMEAS->data.id = extractInt(msg, 6);
|
packetUBXESFMEAS->data.id = extractInt(msg, 6);
|
||||||
for (uint16_t i = 0; (i < DEF_NUM_SENS) && (i < packetUBXESFMEAS->data.flags.bits.numMeas) && ((i * 4) < (msg->len - 8)); i++)
|
for (uint16_t i = 0; (i < DEF_MAX_NUM_ESF_MEAS) && (i < packetUBXESFMEAS->data.flags.bits.numMeas) && ((i * 4) < (msg->len - 8)); i++)
|
||||||
{
|
{
|
||||||
packetUBXESFMEAS->data.data[i].data.all = extractLong(msg, 8 + (i * 4));
|
packetUBXESFMEAS->data.data[i].data.all = extractLong(msg, 8 + (i * 4));
|
||||||
}
|
}
|
||||||
if ((uint16_t)msg->len > (uint16_t)(8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4)))
|
if ((uint16_t)msg->len > (uint16_t)(8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4)))
|
||||||
packetUBXESFMEAS->data.calibTtag = extractLong(msg, 8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4));
|
packetUBXESFMEAS->data.calibTtag = extractLong(msg, 8 + (packetUBXESFMEAS->data.flags.bits.numMeas * 4));
|
||||||
|
|
||||||
// Mark all datums as fresh (not read before)
|
|
||||||
packetUBXESFMEAS->moduleQueried.moduleQueried.all = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
// Check if we need to copy the data for the callback
|
// Check if we need to copy the data for the callback
|
||||||
if ((packetUBXESFMEAS->callbackData != NULL) // If RAM has been allocated for the copy of the data
|
if ((packetUBXESFMEAS->callbackData != NULL) // If RAM has been allocated for the copy of the data
|
||||||
&& (packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale
|
&& (packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale
|
||||||
@@ -14515,92 +14512,19 @@ void SFE_UBLOX_GNSS::logESFINS(bool enabled)
|
|||||||
|
|
||||||
// ***** ESF MEAS automatic support
|
// ***** ESF MEAS automatic support
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getEsfDataInfo(uint16_t maxWait)
|
// Enable or disable automatic ESF MEAS message generation by the GNSS
|
||||||
{
|
|
||||||
return (getESFMEAS(maxWait));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getESFMEAS(uint16_t maxWait)
|
|
||||||
{
|
|
||||||
if (packetUBXESFMEAS == NULL)
|
|
||||||
initPacketUBXESFMEAS(); // Check that RAM has been allocated for the ESF MEAS data
|
|
||||||
if (packetUBXESFMEAS == NULL) // Only attempt this if RAM allocation was successful
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (packetUBXESFMEAS->automaticFlags.flags.bits.automatic && packetUBXESFMEAS->automaticFlags.flags.bits.implicitUpdate)
|
|
||||||
{
|
|
||||||
// The GPS is automatically reporting, we just check whether we got unread data
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->println(F("getEsfDataInfo: Autoreporting"));
|
|
||||||
// }
|
|
||||||
checkUbloxInternal(&packetCfg, UBX_CLASS_ESF, UBX_ESF_MEAS);
|
|
||||||
return packetUBXESFMEAS->moduleQueried.moduleQueried.bits.all;
|
|
||||||
}
|
|
||||||
else if (packetUBXESFMEAS->automaticFlags.flags.bits.automatic && !packetUBXESFMEAS->automaticFlags.flags.bits.implicitUpdate)
|
|
||||||
{
|
|
||||||
// Someone else has to call checkUblox for us...
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->println(F("getEsfDataInfo: Exit immediately"));
|
|
||||||
// }
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->println(F("getEsfDataInfo: Polling"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// The GPS is not automatically reporting HNR PVT so we have to poll explicitly
|
|
||||||
packetCfg.cls = UBX_CLASS_ESF;
|
|
||||||
packetCfg.id = UBX_ESF_MEAS;
|
|
||||||
packetCfg.len = 0;
|
|
||||||
packetCfg.startingSpot = 0;
|
|
||||||
|
|
||||||
// The data is parsed as part of processing the response
|
|
||||||
sfe_ublox_status_e retVal = sendCommand(&packetCfg, maxWait);
|
|
||||||
|
|
||||||
if (retVal == SFE_UBLOX_STATUS_DATA_RECEIVED)
|
|
||||||
return (true);
|
|
||||||
|
|
||||||
if (retVal == SFE_UBLOX_STATUS_DATA_OVERWRITTEN)
|
|
||||||
{
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->println(F("getEsfDataInfo: data in packetCfg was OVERWRITTEN by another message (but that's OK)"));
|
|
||||||
// }
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->print(F("getEsfDataInfo retVal: "));
|
|
||||||
// _debugSerial->println(statusString(retVal));
|
|
||||||
// }
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (false); // Trap. We should never get here...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo
|
|
||||||
// works.
|
|
||||||
bool SFE_UBLOX_GNSS::setAutoESFMEAS(bool enable, uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::setAutoESFMEAS(bool enable, uint16_t maxWait)
|
||||||
{
|
{
|
||||||
return setAutoESFMEASrate(enable ? 1 : 0, true, maxWait);
|
return setAutoESFMEASrate(enable ? 1 : 0, true, maxWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo
|
// Enable or disable automatic ESF MEAS message generation by the GNSS
|
||||||
// works.
|
|
||||||
bool SFE_UBLOX_GNSS::setAutoESFMEAS(bool enable, bool implicitUpdate, uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::setAutoESFMEAS(bool enable, bool implicitUpdate, uint16_t maxWait)
|
||||||
{
|
{
|
||||||
return setAutoESFMEASrate(enable ? 1 : 0, implicitUpdate, maxWait);
|
return setAutoESFMEASrate(enable ? 1 : 0, implicitUpdate, maxWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable or disable automatic ESF MEAS message generation by the GNSS. This changes the way getESFDataInfo
|
// Enable or disable automatic ESF MEAS message generation by the GNSS
|
||||||
// works.
|
|
||||||
bool SFE_UBLOX_GNSS::setAutoESFMEASrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::setAutoESFMEASrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait)
|
||||||
{
|
{
|
||||||
if (packetUBXESFMEAS == NULL)
|
if (packetUBXESFMEAS == NULL)
|
||||||
@@ -14625,7 +14549,6 @@ bool SFE_UBLOX_GNSS::setAutoESFMEASrate(uint8_t rate, bool implicitUpdate, uint1
|
|||||||
packetUBXESFMEAS->automaticFlags.flags.bits.automatic = (rate > 0);
|
packetUBXESFMEAS->automaticFlags.flags.bits.automatic = (rate > 0);
|
||||||
packetUBXESFMEAS->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
|
packetUBXESFMEAS->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
|
||||||
}
|
}
|
||||||
packetUBXESFMEAS->moduleQueried.moduleQueried.bits.all = false; // Mark data as stale
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14714,18 +14637,9 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFMEAS()
|
|||||||
packetUBXESFMEAS->callbackPointer = NULL;
|
packetUBXESFMEAS->callbackPointer = NULL;
|
||||||
packetUBXESFMEAS->callbackPointerPtr = NULL;
|
packetUBXESFMEAS->callbackPointerPtr = NULL;
|
||||||
packetUBXESFMEAS->callbackData = NULL;
|
packetUBXESFMEAS->callbackData = NULL;
|
||||||
packetUBXESFMEAS->moduleQueried.moduleQueried.all = 0;
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark all the data as read/stale
|
|
||||||
void SFE_UBLOX_GNSS::flushESFMEAS()
|
|
||||||
{
|
|
||||||
if (packetUBXESFMEAS == NULL)
|
|
||||||
return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
|
|
||||||
packetUBXESFMEAS->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log this data in file buffer
|
// Log this data in file buffer
|
||||||
void SFE_UBLOX_GNSS::logESFMEAS(bool enabled)
|
void SFE_UBLOX_GNSS::logESFMEAS(bool enabled)
|
||||||
{
|
{
|
||||||
@@ -14868,13 +14782,6 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFRAW()
|
|||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark all the data as read/stale
|
|
||||||
void SFE_UBLOX_GNSS::flushESFRAW()
|
|
||||||
{
|
|
||||||
if (packetUBXESFRAW == NULL)
|
|
||||||
return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log this data in file buffer
|
// Log this data in file buffer
|
||||||
void SFE_UBLOX_GNSS::logESFRAW(bool enabled)
|
void SFE_UBLOX_GNSS::logESFRAW(bool enabled)
|
||||||
{
|
{
|
||||||
@@ -18046,21 +17953,6 @@ float SFE_UBLOX_GNSS::getESFyaw(uint16_t maxWait) // Returned as degrees
|
|||||||
return (((float)packetUBXESFALG->data.yaw) / 100.0); // Convert to degrees
|
return (((float)packetUBXESFALG->data.yaw) / 100.0); // Convert to degrees
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait)
|
|
||||||
{
|
|
||||||
if (packetUBXESFMEAS == NULL)
|
|
||||||
initPacketUBXESFMEAS(); // Check that RAM has been allocated for the ESF MEAS data
|
|
||||||
if (packetUBXESFMEAS == NULL) // Bail if the RAM allocation failed
|
|
||||||
return (false);
|
|
||||||
|
|
||||||
if ((packetUBXESFMEAS->moduleQueried.moduleQueried.bits.data & (1 << sensor)) == 0)
|
|
||||||
getESFMEAS(maxWait);
|
|
||||||
packetUBXESFMEAS->moduleQueried.moduleQueried.bits.data &= ~(1 << sensor); // Since we are about to give this to user, mark this data as stale
|
|
||||||
packetUBXESFMEAS->moduleQueried.moduleQueried.bits.all = false;
|
|
||||||
sensorData->data.all = packetUBXESFMEAS->data.data[sensor].data.all;
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, UBX_ESF_MEAS_data_t ubxDataStruct, uint8_t sensor)
|
bool SFE_UBLOX_GNSS::getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, UBX_ESF_MEAS_data_t ubxDataStruct, uint8_t sensor)
|
||||||
{
|
{
|
||||||
sensorData->data.all = ubxDataStruct.data[sensor].data.all;
|
sensorData->data.all = ubxDataStruct.data[sensor].data.all;
|
||||||
|
|||||||
@@ -1272,15 +1272,12 @@ public:
|
|||||||
void flushESFINS(); // Mark all the data as read/stale
|
void flushESFINS(); // Mark all the data as read/stale
|
||||||
void logESFINS(bool enabled = true); // Log data to file buffer
|
void logESFINS(bool enabled = true); // Log data to file buffer
|
||||||
|
|
||||||
bool getEsfDataInfo(uint16_t maxWait = defaultMaxWait); // ESF MEAS Helper
|
|
||||||
bool getESFMEAS(uint16_t maxWait = defaultMaxWait); // ESF MEAS
|
|
||||||
bool setAutoESFMEAS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF MEAS reports
|
bool setAutoESFMEAS(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF MEAS reports
|
||||||
bool setAutoESFMEAS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF MEAS reports, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update
|
bool setAutoESFMEAS(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF MEAS reports, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update
|
||||||
bool setAutoESFMEASrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic MEAS reports
|
bool setAutoESFMEASrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic MEAS reports
|
||||||
bool setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback.
|
bool setAutoESFMEAScallback(void (*callbackPointer)(UBX_ESF_MEAS_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback.
|
||||||
bool setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback.
|
bool setAutoESFMEAScallbackPtr(void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic MEAS reports at the navigation frequency. Data is accessed from the callback.
|
||||||
bool assumeAutoESFMEAS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF MEAS is send cyclically already
|
bool assumeAutoESFMEAS(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF MEAS is send cyclically already
|
||||||
void flushESFMEAS(); // Mark all the data as read/stale
|
|
||||||
void logESFMEAS(bool enabled = true); // Log data to file buffer
|
void logESFMEAS(bool enabled = true); // Log data to file buffer
|
||||||
|
|
||||||
bool setAutoESFRAW(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF RAW reports
|
bool setAutoESFRAW(bool enabled, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF RAW reports
|
||||||
@@ -1289,7 +1286,6 @@ public:
|
|||||||
bool setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback.
|
bool setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait = defaultMaxWait); // Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback.
|
||||||
bool setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback.
|
bool setAutoESFRAWcallbackPtr(void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic RAW reports at the navigation frequency. Data is accessed from the callback.
|
||||||
bool assumeAutoESFRAW(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF RAW is send cyclically already
|
bool assumeAutoESFRAW(bool enabled, bool implicitUpdate = true); // In case no config access to the GPS is possible and ESF RAW is send cyclically already
|
||||||
void flushESFRAW(); // Mark all the data as read/stale
|
|
||||||
void logESFRAW(bool enabled = true); // Log data to file buffer
|
void logESFRAW(bool enabled = true); // Log data to file buffer
|
||||||
|
|
||||||
// High navigation rate (HNR)
|
// High navigation rate (HNR)
|
||||||
@@ -1466,7 +1462,6 @@ public:
|
|||||||
float getESFroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees
|
float getESFroll(uint16_t maxWait = defaultMaxWait); // Returned as degrees
|
||||||
float getESFpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees
|
float getESFpitch(uint16_t maxWait = defaultMaxWait); // Returned as degrees
|
||||||
float getESFyaw(uint16_t maxWait = defaultMaxWait); // Returned as degrees
|
float getESFyaw(uint16_t maxWait = defaultMaxWait); // Returned as degrees
|
||||||
bool getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait = defaultMaxWait);
|
|
||||||
bool getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, UBX_ESF_MEAS_data_t ubxDataStruct, uint8_t sensor);
|
bool getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *sensorData, UBX_ESF_MEAS_data_t ubxDataStruct, uint8_t sensor);
|
||||||
bool getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, UBX_ESF_RAW_data_t ubxDataStruct, uint8_t sensor);
|
bool getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, UBX_ESF_RAW_data_t ubxDataStruct, uint8_t sensor);
|
||||||
bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, uint8_t sensor, uint16_t maxWait = defaultMaxWait);
|
bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, uint8_t sensor, uint16_t maxWait = defaultMaxWait);
|
||||||
|
|||||||
+7
-26
@@ -53,6 +53,10 @@
|
|||||||
#define DEF_MAX_NUM_ESF_RAW_REPEATS 10 // The NEO-M8U sends ESF RAW data in blocks / sets of ten readings. (The ZED-F9R sends them one at a time.)
|
#define DEF_MAX_NUM_ESF_RAW_REPEATS 10 // The NEO-M8U sends ESF RAW data in blocks / sets of ten readings. (The ZED-F9R sends them one at a time.)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEF_MAX_NUM_ESF_MEAS
|
||||||
|
#define DEF_MAX_NUM_ESF_MEAS 31 // numMeas is 5 bits, indicating up to 31 groups could be received
|
||||||
|
#endif
|
||||||
|
|
||||||
// Additional flags and pointers that need to be stored with each message type
|
// Additional flags and pointers that need to be stored with each message type
|
||||||
struct ubxAutomaticFlags
|
struct ubxAutomaticFlags
|
||||||
{
|
{
|
||||||
@@ -2190,7 +2194,8 @@ typedef struct
|
|||||||
|
|
||||||
// UBX-ESF-MEAS (0x10 0x02): External sensor fusion measurements
|
// UBX-ESF-MEAS (0x10 0x02): External sensor fusion measurements
|
||||||
// Note: length is variable
|
// Note: length is variable
|
||||||
const uint16_t UBX_ESF_MEAS_MAX_LEN = 8 + (4 * DEF_NUM_SENS) + 4;
|
// Note: ESF RAW data cannot be polled. It is "Output" only
|
||||||
|
const uint16_t UBX_ESF_MEAS_MAX_LEN = 8 + (4 * DEF_MAX_NUM_ESF_MEAS) + 4;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -2222,38 +2227,14 @@ typedef struct
|
|||||||
} bits;
|
} bits;
|
||||||
} flags;
|
} flags;
|
||||||
uint16_t id; // Identification number of data provider
|
uint16_t id; // Identification number of data provider
|
||||||
UBX_ESF_MEAS_sensorData_t data[DEF_NUM_SENS];
|
UBX_ESF_MEAS_sensorData_t data[DEF_MAX_NUM_ESF_MEAS];
|
||||||
uint32_t calibTtag; // OPTIONAL: Receiver local time calibrated: ms
|
uint32_t calibTtag; // OPTIONAL: Receiver local time calibrated: ms
|
||||||
} UBX_ESF_MEAS_data_t;
|
} UBX_ESF_MEAS_data_t;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t all;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32_t all : 1;
|
|
||||||
|
|
||||||
uint32_t timeMarkSent : 1;
|
|
||||||
uint32_t timeMarkEdge : 1;
|
|
||||||
uint32_t calibTtagValid : 1;
|
|
||||||
uint32_t numMeas : 1;
|
|
||||||
|
|
||||||
uint32_t id : 1;
|
|
||||||
|
|
||||||
uint32_t data : DEF_NUM_SENS;
|
|
||||||
|
|
||||||
uint32_t calibTtag : 1;
|
|
||||||
} bits;
|
|
||||||
} moduleQueried;
|
|
||||||
} UBX_ESF_MEAS_moduleQueried_t;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ubxAutomaticFlags automaticFlags;
|
ubxAutomaticFlags automaticFlags;
|
||||||
UBX_ESF_MEAS_data_t data;
|
UBX_ESF_MEAS_data_t data;
|
||||||
UBX_ESF_MEAS_moduleQueried_t moduleQueried;
|
|
||||||
void (*callbackPointer)(UBX_ESF_MEAS_data_t);
|
void (*callbackPointer)(UBX_ESF_MEAS_data_t);
|
||||||
void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *);
|
void (*callbackPointerPtr)(UBX_ESF_MEAS_data_t *);
|
||||||
UBX_ESF_MEAS_data_t *callbackData;
|
UBX_ESF_MEAS_data_t *callbackData;
|
||||||
|
|||||||
Reference in New Issue
Block a user