Description
Subject of the issue
When a UBX-ESF-RAW packet is received, the byte offset for the raw sensor data is incorrect, and as a result sensor data is incorrectly parsed/stored.
I am referencing the ZED-F9R Interface Description document (Revision R02) 3.11.4 UBX-ESF-RAW message description. In order to avoid breaching Ublox NDA, I will not reference specific fields on the document.
The F9R module I am using is upgraded to the most recent firmware version HPS1.20.
Your workbench
- What development board or microcontroller are you using?
Issues replicated on ESP32 Dev Module, and a Teensy 4.1.
- What version of hardware or breakout board are you using?
Sparkfun U-blox Zed-F9R GPS-RTK Breakout (Qwiic)
- How is the breakout board wired to your microcontroller?
I2C lines are hard-wired to the microcontroller.
- How is everything being powered?
The GPS board, as well as the micros are powered over the same USB tether.
- Are there any additional details that may help us help you?
I have resolved the issue on a fork and have submitted PR.
Steps to reproduce
- Connect Sparkfun GPS-RTK Zed-F9R breakout (Running firmware HPS1.20) to SDA, SCL, +5V and Ground on micro.
- Upload provided sketch
- Observe garbled sensor data in Serial Monitor
- To compare with UBX-ESF-RAW output in U-center
a. Connect Sparkfun GPS-RTK Zed-F9R to Host PC running U-center over USB-C connection
b. Navigate to View-->Messages View->UBX-->ESF-->RAW
c. Right click, select ‘Enable Message’
Expected behavior
The expected behavior is that the raw sensor data, when parsed from the UBX_ESF_RAW_sensorData_t structs within SFE_UBLOX_GNSS::packetUBXESFRAW, matches what is presented in U-Center when examining UBX-ESF-RAW packet.
Actual behavior
Running the current version of the library on branch main,
The library provides garbled/nonsensical raw sensor data that does NOT match what is presented by U-Center when the UBX-ESF-RAW message is enabled.
Provided Sketch:
//Needed for I2C
#include <Wire.h>
#include "SparkFun_u-blox_GNSS_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
SFE_UBLOX_GNSS myGPS;
UBX_ESF_RAW_sensorData_t gRawSensorDataStruct;
#define X_AXIS_ACCELERATION 0
#define Y_AXIS_ACCELERATION 1
#define Z_AXIS_ACCELERATION 2
#define X_AXIS_ROTATION 3
#define Y_AXIS_ROTATION 4
#define Z_AXIS_ROTATION 5
#define GYRO_TEMPERATURE 6
void setup() {
Serial.begin(9600);
Wire.begin();
while(myGPS.begin() == false) //Connect to the Ublox module using Wire port
{
Serial.println("Ublox GPS not detected at default I2C address. Please check wiring. Freezing.");
delay(100);
}
// //Set comms to be on the I2C port, and contain UBX/RTCM3 packets (turn off NMEA noise)
myGPS.setI2COutput(COM_TYPE_UBX);
myGPS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX);
}
int32_t parseSensorData(uint32_t allData)
{
//the sensor data is a 3 byte, signed integer (bits 0 - 23)
uint32_t sensorData = (allData & 0x00FFFFFF);
//check out the sign bit
uint32_t signBit = (allData & 0x00800000) >> 20;
int32_t signedData = 0;
//if the number is negative, we need to fill the extra byte with 1s
if(signBit != 0)
{
signedData |= 0xFF000000;
}
signedData |= sensorData;
return signedData;
}
void requestRawSensorData()
{
myGPS.getRawSensorMeasurement(&gRawSensorDataStruct, X_AXIS_ACCELERATION);
int32_t xAccelInt = parseSensorData(gRawSensorDataStruct.data.all);
double xAccel = (double)xAccelInt / 1024.0;
Serial.print("Acceleration X, Y, Z: (");
Serial.print(xAccel);
Serial.print(", ");
myGPS.getRawSensorMeasurement(&gRawSensorDataStruct, Y_AXIS_ACCELERATION);
int32_t yAccelInt = parseSensorData(gRawSensorDataStruct.data.all);
//the acceleration values are given in m/s * 2^-10
double yAccel = (double)yAccelInt / 1024.0;
Serial.print(yAccel);
Serial.print(", ");
myGPS.getRawSensorMeasurement(&gRawSensorDataStruct, Z_AXIS_ACCELERATION);
int32_t zAccelInt = parseSensorData(gRawSensorDataStruct.data.all);
double zAccel = (double)zAccelInt / 1024.0;
Serial.print(xAccel);
Serial.println(")");
Serial.print(" Rotation: X, Y, Z: (");
myGPS.getRawSensorMeasurement(&gRawSensorDataStruct, X_AXIS_ROTATION);
int32_t xGyroInt = parseSensorData(gRawSensorDataStruct.data.all);
//angular rate is given in degrees/second * 2^-12
double xGyro = (double)xGyroInt / 4096.0;
Serial.print(xGyro);
Serial.print(", ");
myGPS.getRawSensorMeasurement(&gRawSensorDataStruct, Y_AXIS_ROTATION);
int32_t yGyroInt = parseSensorData(gRawSensorDataStruct.data.all);
double yGyro = (double)yGyroInt / 4096.0;
Serial.print(yGyro);
Serial.print(", ");
myGPS.getRawSensorMeasurement(&gRawSensorDataStruct, Z_AXIS_ROTATION);
int32_t zGyroInt = parseSensorData(gRawSensorDataStruct.data.all);
double zGyro = (double)zGyroInt / 4096.0;
Serial.print(zGyro);
Serial.println(")");
//commented out for a cleaner serial output.
//Serial.print("Gyro temp: ");
// myGPS.getRawSensorMeasurement(&gRawSensorDataStruct, GYRO_TEMPERATURE);
// int32_t gyroTempInt = parseSensorData(gRawSensorDataStruct.data.all);
// double gyroTemp = (double)gyroTempInt;
}
void loop() {
requestRawSensorData();
myGPS.checkUblox();
delay(250);
}