Correct support for ESF RAW
This commit is contained in:
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
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 RAW IMU sensor messages on the NEO-M8U/ZED-F9R and
|
||||||
|
uses callbacks to process and display the ESF data automatically. No more polling!
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
On the ZED-F9R, each ESF RAW message contains _one_ set of IMU sensor data, seven readings in total (3 x Accel, 3 x Gyro, 1 x Temperature).
|
||||||
|
However, on the NEO-M8U, each message contains _ten_ sets of IMU sensor data, seventy readings in total.
|
||||||
|
The NEO-M8U data is all timestamped and it is possible to reconstruct the full data stream, you just need to do it
|
||||||
|
ten at a time...
|
||||||
|
Also, note that the sensor data is 24-bit signed (two's complement). You need to be careful when converting to int32_t.
|
||||||
|
Data will arrive at 100Hz. 10Hz x 10 on the NEO-M8U.
|
||||||
|
400kHz I2C is essential.
|
||||||
|
Serial printing needs to be kept short and the baud rate needs to be around 500000.
|
||||||
|
|
||||||
|
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: printESFRAWdata will be called when new ESF RAW data arrives
|
||||||
|
// See u-blox_structs.h for the full definition of UBX_ESF_RAW_data_t
|
||||||
|
// _____ You can use any name you like for the callback. Use the same name when you call setAutoESFRAWcallback
|
||||||
|
// / _____ This _must_ be UBX_ESF_RAW_data_t
|
||||||
|
// | / _____ You can use any name you like for the struct
|
||||||
|
// | | /
|
||||||
|
// | | |
|
||||||
|
void printESFRAWdata(UBX_ESF_RAW_data_t *ubxDataStruct)
|
||||||
|
{
|
||||||
|
Serial.print(F("New ESF RAW data received. Number of sensor readings is: "));
|
||||||
|
Serial.print(ubxDataStruct->numEsfRawBlocks);
|
||||||
|
if (ubxDataStruct->numEsfRawBlocks > 7)
|
||||||
|
Serial.println(F(". (Only the first 7 will be printed.)"));
|
||||||
|
else
|
||||||
|
Serial.println(F("."));
|
||||||
|
|
||||||
|
for (uint8_t i = 0; (i < ubxDataStruct->numEsfRawBlocks) && (i < 7); i++)
|
||||||
|
{
|
||||||
|
switch (ubxDataStruct->data[i].data.bits.dataType)
|
||||||
|
{
|
||||||
|
case 5:
|
||||||
|
Serial.print(F("z-axis gyro: "));
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
Serial.print(F("gyro temperature: "));
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
Serial.print(F("y-axis gyro: "));
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
Serial.print(F("x-axis gyro: "));
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
Serial.print(F("x-axis accel: "));
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
Serial.print(F("y-axis accel: "));
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
Serial.print(F("z-axis accel: "));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((ubxDataStruct->data[i].data.bits.dataType == 5) || (ubxDataStruct->data[i].data.bits.dataType == 13) || (ubxDataStruct->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 = ubxDataStruct->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);
|
||||||
|
}
|
||||||
|
else if ((ubxDataStruct->data[i].data.bits.dataType == 16) || (ubxDataStruct->data[i].data.bits.dataType == 17) || (ubxDataStruct->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 = ubxDataStruct->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^-10 to m/s
|
||||||
|
Serial.println(force);
|
||||||
|
}
|
||||||
|
else if (ubxDataStruct->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 = ubxDataStruct->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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(500000);
|
||||||
|
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
|
||||||
|
|
||||||
|
myGNSS.setI2CpollingWait(5); //Allow checkUblox to poll I2C data every 5ms to keep up with the ESF RAW messages
|
||||||
|
|
||||||
|
if (myGNSS.setAutoESFRAWcallbackPtr(&printESFRAWdata) == true) // Enable automatic ESF RAW messages with callback to printESFRAWdata
|
||||||
|
Serial.println(F("setAutoESFRAWcallback successful"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||||
|
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||||
|
}
|
||||||
@@ -484,8 +484,6 @@ assumeAutoESFMEAS KEYWORD2
|
|||||||
flushESFMEAS KEYWORD2
|
flushESFMEAS KEYWORD2
|
||||||
logESFMEAS KEYWORD2
|
logESFMEAS KEYWORD2
|
||||||
|
|
||||||
getEsfRawDataInfo KEYWORD2
|
|
||||||
getESFRAW KEYWORD2
|
|
||||||
setAutoESFRAW KEYWORD2
|
setAutoESFRAW KEYWORD2
|
||||||
setAutoESFRAWrate KEYWORD2
|
setAutoESFRAWrate KEYWORD2
|
||||||
setAutoESFRAWcallback KEYWORD2
|
setAutoESFRAWcallback KEYWORD2
|
||||||
|
|||||||
@@ -4246,15 +4246,13 @@ void SFE_UBLOX_GNSS::processUBXpacket(ubxPacket *msg)
|
|||||||
// Parse various byte fields into storage - but only if we have memory allocated for it
|
// Parse various byte fields into storage - but only if we have memory allocated for it
|
||||||
if (packetUBXESFRAW != NULL)
|
if (packetUBXESFRAW != NULL)
|
||||||
{
|
{
|
||||||
for (uint16_t i = 0; (i < DEF_NUM_SENS) && ((i * 8) < (msg->len - 4)); i++)
|
packetUBXESFRAW->data.numEsfRawBlocks = (msg->len - 4) / 8; // Record how many blocks were received. Could be 7 or 70 (ZED-F9R vs. NEO-M8U)
|
||||||
|
for (uint16_t i = 0; (i < (DEF_NUM_SENS * DEF_MAX_NUM_ESF_RAW_REPEATS)) && ((i * 8) < (msg->len - 4)); i++)
|
||||||
{
|
{
|
||||||
packetUBXESFRAW->data.data[i].data.all = extractLong(msg, 4 + (i * 8));
|
packetUBXESFRAW->data.data[i].data.all = extractLong(msg, 4 + (i * 8));
|
||||||
packetUBXESFRAW->data.data[i].sTag = extractLong(msg, 8 + (i * 8));
|
packetUBXESFRAW->data.data[i].sTag = extractLong(msg, 8 + (i * 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark all datums as fresh (not read before)
|
|
||||||
packetUBXESFRAW->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 ((packetUBXESFRAW->callbackData != NULL) // If RAM has been allocated for the copy of the data
|
if ((packetUBXESFRAW->callbackData != NULL) // If RAM has been allocated for the copy of the data
|
||||||
&& (packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale
|
&& (packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == false)) // AND the data is stale
|
||||||
@@ -10233,7 +10231,7 @@ bool SFE_UBLOX_GNSS::getVehAtt(uint16_t maxWait)
|
|||||||
bool SFE_UBLOX_GNSS::getNAVATT(uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::getNAVATT(uint16_t maxWait)
|
||||||
{
|
{
|
||||||
if (packetUBXNAVATT == NULL)
|
if (packetUBXNAVATT == NULL)
|
||||||
initPacketUBXNAVATT(); // Check that RAM has been allocated for the ESF RAW data
|
initPacketUBXNAVATT(); // Check that RAM has been allocated for the NAV ATT data
|
||||||
if (packetUBXNAVATT == NULL) // Only attempt this if RAM allocation was successful
|
if (packetUBXNAVATT == NULL) // Only attempt this if RAM allocation was successful
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -10373,7 +10371,7 @@ bool SFE_UBLOX_GNSS::setAutoNAVATTcallbackPtr(void (*callbackPointerPtr)(UBX_NAV
|
|||||||
bool SFE_UBLOX_GNSS::assumeAutoNAVATT(bool enabled, bool implicitUpdate)
|
bool SFE_UBLOX_GNSS::assumeAutoNAVATT(bool enabled, bool implicitUpdate)
|
||||||
{
|
{
|
||||||
if (packetUBXNAVATT == NULL)
|
if (packetUBXNAVATT == NULL)
|
||||||
initPacketUBXNAVATT(); // Check that RAM has been allocated for the ESF RAW data
|
initPacketUBXNAVATT(); // Check that RAM has been allocated for the NAV ATT data
|
||||||
if (packetUBXNAVATT == NULL) // Only attempt this if RAM allocation was successful
|
if (packetUBXNAVATT == NULL) // Only attempt this if RAM allocation was successful
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -14738,92 +14736,23 @@ void SFE_UBLOX_GNSS::logESFMEAS(bool enabled)
|
|||||||
|
|
||||||
// ***** ESF RAW automatic support
|
// ***** ESF RAW automatic support
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getEsfRawDataInfo(uint16_t maxWait)
|
// ESF RAW messages are output only. They cannot be polled.
|
||||||
{
|
|
||||||
return (getESFRAW(maxWait));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getESFRAW(uint16_t maxWait)
|
// Enable or disable automatic ESF RAW message generation by the GNSS.
|
||||||
{
|
|
||||||
if (packetUBXESFRAW == NULL)
|
|
||||||
initPacketUBXESFRAW(); // Check that RAM has been allocated for the ESF RAW data
|
|
||||||
if (packetUBXESFRAW == NULL) // Only attempt this if RAM allocation was successful
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (packetUBXESFRAW->automaticFlags.flags.bits.automatic && packetUBXESFRAW->automaticFlags.flags.bits.implicitUpdate)
|
|
||||||
{
|
|
||||||
// The GPS is automatically reporting, we just check whether we got unread data
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->println(F("getEsfRawDataInfo: Autoreporting"));
|
|
||||||
// }
|
|
||||||
checkUbloxInternal(&packetCfg, UBX_CLASS_ESF, UBX_ESF_RAW);
|
|
||||||
return packetUBXESFRAW->moduleQueried.moduleQueried.bits.all;
|
|
||||||
}
|
|
||||||
else if (packetUBXESFRAW->automaticFlags.flags.bits.automatic && !packetUBXESFRAW->automaticFlags.flags.bits.implicitUpdate)
|
|
||||||
{
|
|
||||||
// Someone else has to call checkUblox for us...
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->println(F("getEsfRawDataInfo: Exit immediately"));
|
|
||||||
// }
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->println(F("getEsfRawDataInfo: Polling"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// The GPS is not automatically reporting HNR PVT so we have to poll explicitly
|
|
||||||
packetCfg.cls = UBX_CLASS_ESF;
|
|
||||||
packetCfg.id = UBX_ESF_RAW;
|
|
||||||
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("getEsfRawDataInfo: data in packetCfg was OVERWRITTEN by another message (but that's OK)"));
|
|
||||||
// }
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (_printDebug == true)
|
|
||||||
// {
|
|
||||||
// _debugSerial->print(F("getEsfRawDataInfo retVal: "));
|
|
||||||
// _debugSerial->println(statusString(retVal));
|
|
||||||
// }
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (false); // Trap. We should never get here...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo
|
|
||||||
// works.
|
|
||||||
bool SFE_UBLOX_GNSS::setAutoESFRAW(bool enable, uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::setAutoESFRAW(bool enable, uint16_t maxWait)
|
||||||
{
|
{
|
||||||
return setAutoESFRAWrate(enable ? 1 : 0, true, maxWait);
|
return setAutoESFRAWrate(enable ? 1 : 0, true, maxWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo
|
// Enable or disable automatic ESF RAW message generation by the GNSS.
|
||||||
// works.
|
|
||||||
bool SFE_UBLOX_GNSS::setAutoESFRAW(bool enable, bool implicitUpdate, uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::setAutoESFRAW(bool enable, bool implicitUpdate, uint16_t maxWait)
|
||||||
{
|
{
|
||||||
return setAutoESFRAWrate(enable ? 1 : 0, implicitUpdate, maxWait);
|
return setAutoESFRAWrate(enable ? 1 : 0, implicitUpdate, maxWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable or disable automatic ESF RAW message generation by the GNSS. This changes the way getESFRawDataInfo
|
// Enable or disable automatic ESF RAW message generation by the GNSS.
|
||||||
// works.
|
// Note: this function can only be used to enable or disable the messages. A rate of zero disables the messages.
|
||||||
|
// A rate of 1 or more causes the messages to be generated at the full 100Hz.
|
||||||
bool SFE_UBLOX_GNSS::setAutoESFRAWrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::setAutoESFRAWrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait)
|
||||||
{
|
{
|
||||||
if (packetUBXESFRAW == NULL)
|
if (packetUBXESFRAW == NULL)
|
||||||
@@ -14848,11 +14777,10 @@ bool SFE_UBLOX_GNSS::setAutoESFRAWrate(uint8_t rate, bool implicitUpdate, uint16
|
|||||||
packetUBXESFRAW->automaticFlags.flags.bits.automatic = (rate > 0);
|
packetUBXESFRAW->automaticFlags.flags.bits.automatic = (rate > 0);
|
||||||
packetUBXESFRAW->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
|
packetUBXESFRAW->automaticFlags.flags.bits.implicitUpdate = implicitUpdate;
|
||||||
}
|
}
|
||||||
packetUBXESFRAW->moduleQueried.moduleQueried.bits.all = false; // Mark data as stale
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable automatic navigation message generation by the GNSS.
|
// Enable automatic message generation by the GNSS.
|
||||||
bool SFE_UBLOX_GNSS::setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait)
|
bool SFE_UBLOX_GNSS::setAutoESFRAWcallback(void (*callbackPointer)(UBX_ESF_RAW_data_t), uint16_t maxWait)
|
||||||
{
|
{
|
||||||
// Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually.
|
// Enable auto messages. Set implicitUpdate to false as we expect the user to call checkUblox manually.
|
||||||
@@ -14937,7 +14865,6 @@ bool SFE_UBLOX_GNSS::initPacketUBXESFRAW()
|
|||||||
packetUBXESFRAW->callbackPointer = NULL;
|
packetUBXESFRAW->callbackPointer = NULL;
|
||||||
packetUBXESFRAW->callbackPointerPtr = NULL;
|
packetUBXESFRAW->callbackPointerPtr = NULL;
|
||||||
packetUBXESFRAW->callbackData = NULL;
|
packetUBXESFRAW->callbackData = NULL;
|
||||||
packetUBXESFRAW->moduleQueried.moduleQueried.all = 0;
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14946,7 +14873,6 @@ void SFE_UBLOX_GNSS::flushESFRAW()
|
|||||||
{
|
{
|
||||||
if (packetUBXESFRAW == NULL)
|
if (packetUBXESFRAW == NULL)
|
||||||
return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
|
return; // Bail if RAM has not been allocated (otherwise we could be writing anywhere!)
|
||||||
packetUBXESFRAW->moduleQueried.moduleQueried.all = 0; // Mark all datums as stale (read before)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log this data in file buffer
|
// Log this data in file buffer
|
||||||
@@ -18141,22 +18067,6 @@ bool SFE_UBLOX_GNSS::getSensorFusionMeasurement(UBX_ESF_MEAS_sensorData_t *senso
|
|||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, uint8_t sensor, uint16_t maxWait)
|
|
||||||
{
|
|
||||||
if (packetUBXESFRAW == NULL)
|
|
||||||
initPacketUBXESFRAW(); // Check that RAM has been allocated for the ESF RAW data
|
|
||||||
if (packetUBXESFRAW == NULL) // Bail if the RAM allocation failed
|
|
||||||
return (false);
|
|
||||||
|
|
||||||
if ((packetUBXESFRAW->moduleQueried.moduleQueried.bits.data & (1 << sensor)) == 0)
|
|
||||||
getESFRAW(maxWait);
|
|
||||||
packetUBXESFRAW->moduleQueried.moduleQueried.bits.data &= ~(1 << sensor); // Since we are about to give this to user, mark this data as stale
|
|
||||||
packetUBXESFRAW->moduleQueried.moduleQueried.bits.all = false;
|
|
||||||
sensorData->data.all = packetUBXESFRAW->data.data[sensor].data.all;
|
|
||||||
sensorData->sTag = packetUBXESFRAW->data.data[sensor].sTag;
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SFE_UBLOX_GNSS::getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, UBX_ESF_RAW_data_t ubxDataStruct, uint8_t sensor)
|
bool SFE_UBLOX_GNSS::getRawSensorMeasurement(UBX_ESF_RAW_sensorData_t *sensorData, UBX_ESF_RAW_data_t ubxDataStruct, uint8_t sensor)
|
||||||
{
|
{
|
||||||
sensorData->data.all = ubxDataStruct.data[sensor].data.all;
|
sensorData->data.all = ubxDataStruct.data[sensor].data.all;
|
||||||
|
|||||||
@@ -1283,8 +1283,6 @@ public:
|
|||||||
void flushESFMEAS(); // Mark all the data as read/stale
|
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 getEsfRawDataInfo(uint16_t maxWait = defaultMaxWait); // ESF RAW Helper
|
|
||||||
bool getESFRAW(uint16_t maxWait = defaultMaxWait); // ESF RAW
|
|
||||||
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
|
||||||
bool setAutoESFRAW(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF RAW 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 setAutoESFRAW(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait); // Enable/disable automatic ESF RAW 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 setAutoESFRAWrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic RAW reports
|
bool setAutoESFRAWrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait); // Set the rate for automatic RAW reports
|
||||||
@@ -1470,7 +1468,6 @@ public:
|
|||||||
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, 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, uint8_t sensor, uint16_t maxWait = defaultMaxWait);
|
|
||||||
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);
|
||||||
bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, UBX_ESF_STATUS_data_t ubxDataStruct, uint8_t sensor);
|
bool getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sensorStatus, UBX_ESF_STATUS_data_t ubxDataStruct, uint8_t sensor);
|
||||||
|
|||||||
+10
-17
@@ -49,6 +49,10 @@
|
|||||||
#define DEF_NUM_SENS 7 // The maximum number of ESF sensors
|
#define DEF_NUM_SENS 7 // The maximum number of ESF sensors
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEF_MAX_NUM_ESF_RAW_REPEATS
|
||||||
|
#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
|
||||||
|
|
||||||
// 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
|
||||||
{
|
{
|
||||||
@@ -2257,7 +2261,10 @@ typedef struct
|
|||||||
|
|
||||||
// UBX-ESF-RAW (0x10 0x03): Raw sensor measurements
|
// UBX-ESF-RAW (0x10 0x03): Raw sensor measurements
|
||||||
// Note: length is variable
|
// Note: length is variable
|
||||||
const uint16_t UBX_ESF_RAW_MAX_LEN = 4 + (8 * DEF_NUM_SENS);
|
// Note: The ZED-F9R sends sets of seven sensor readings one at a time
|
||||||
|
// But the NEO-M8U sends them in sets of ten (i.e. seventy readings per message)
|
||||||
|
// Note: ESF RAW data cannot be polled. It is "Output" only
|
||||||
|
const uint16_t UBX_ESF_RAW_MAX_LEN = 4 + (8 * DEF_NUM_SENS * DEF_MAX_NUM_ESF_RAW_REPEATS);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -2276,28 +2283,14 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t reserved1[4];
|
uint8_t reserved1[4];
|
||||||
UBX_ESF_RAW_sensorData_t data[DEF_NUM_SENS];
|
UBX_ESF_RAW_sensorData_t data[DEF_NUM_SENS * DEF_MAX_NUM_ESF_RAW_REPEATS];
|
||||||
|
uint8_t numEsfRawBlocks; // Note: this is not contained in the ESF RAW message. It is calculated from the message length.
|
||||||
} UBX_ESF_RAW_data_t;
|
} UBX_ESF_RAW_data_t;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t all;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32_t all : 1;
|
|
||||||
|
|
||||||
uint32_t data : DEF_NUM_SENS;
|
|
||||||
} bits;
|
|
||||||
} moduleQueried;
|
|
||||||
} UBX_ESF_RAW_moduleQueried_t;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ubxAutomaticFlags automaticFlags;
|
ubxAutomaticFlags automaticFlags;
|
||||||
UBX_ESF_RAW_data_t data;
|
UBX_ESF_RAW_data_t data;
|
||||||
UBX_ESF_RAW_moduleQueried_t moduleQueried;
|
|
||||||
void (*callbackPointer)(UBX_ESF_RAW_data_t);
|
void (*callbackPointer)(UBX_ESF_RAW_data_t);
|
||||||
void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *);
|
void (*callbackPointerPtr)(UBX_ESF_RAW_data_t *);
|
||||||
UBX_ESF_RAW_data_t *callbackData;
|
UBX_ESF_RAW_data_t *callbackData;
|
||||||
|
|||||||
Reference in New Issue
Block a user