NEO-M9N GPS Breakout Odotometer call

Hello support community,

I have been checking all manuals, examplse and going deep into the SparkFun_u-blox_GNSS_Arduino_Library to understand how the internal odometer in the library functions, but with no success. How can I call and access the odometer value?

Thanks a lot!

I have noticed the following functions in the library:

bool SFE_UBLOX_GNSS::resetOdometer(uint16_t maxWait);
bool getNAVODO(uint16_t maxWait = defaultMaxWait);                                                                  // NAV ODO
  bool setAutoNAVODO(bool enabled, uint16_t maxWait = defaultMaxWait);                                                // Enable/disable automatic ODO reports at the navigation frequency
  bool setAutoNAVODO(bool enabled, bool implicitUpdate, uint16_t maxWait = defaultMaxWait);                           // Enable/disable automatic ODO reports at the navigation frequency, 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 setAutoNAVODOrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait = defaultMaxWait);                // Set the rate for automatic ODO reports
  bool setAutoNAVODOcallback(void (*callbackPointer)(UBX_NAV_ODO_data_t), uint16_t maxWait = defaultMaxWait);         // Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback.
  bool setAutoNAVODOcallbackPtr(void (*callbackPointerPtr)(UBX_NAV_ODO_data_t *), uint16_t maxWait = defaultMaxWait); // Enable automatic ODO reports at the navigation frequency. Data is accessed from the callback.
  bool assumeAutoNAVODO(bool enabled, bool implicitUpdate = true);                                                    // In case no config access to the GPS is possible and ODO is send cyclically already
  void flushNAVODO();                                                                                                 // Mark all the data as read/stale
  void logNAVODO(bool enabled = true);                                                                                // Log data to file buffer

Call the “UBX-LOG-RETRIEVEPOSEXTRA” Odometer position data msg

Check out pg 19 here https://content.u-blox.com/sites/defaul … 014286.pdf - you can also access this info in u-blox’s u-center software

Hello @ george.kudor,

Please see this example:

https://github.com/sparkfun/SparkFun_u- … AV_ODO.ino

Best wishes,

Paul

^Ok yea that’s a way better idea

Thank you very much!

PaulZC:
Hello @ george.kudor,

Please see this example:

https://github.com/sparkfun/SparkFun_u- … AV_ODO.ino

Best wishes,

Paul

Hello, I tried this example, but unfortunately I am doing something wrong. I keep getting 0 for all odometers. I am simply trying to pass the values to a global or local variable, and then display it on a screen, but probably my understanding of callback functions is limited. Can you please give me a little bit more hints on this? Thank you!

#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: printODOdata will be called when new NAV ODO data arrives
// See u-blox_structs.h for the full definition of UBX_NAV_ODO_data_t
//         _____  You can use any name you like for the callback. Use the same name when you call setAutoNAVODOcallback
//        /                  _____  This _must_ be UBX_NAV_ODO_data_t
//        |                 /                   _____ You can use any name you like for the struct
//        |                 |                  /
//        |                 |                  |
void printODOdata(UBX_NAV_ODO_data_t *ubxDataStruct)
{
    Serial.println();

    Serial.print(F("TOW: ")); // Print the Time Of Week
    unsigned long iTOW = ubxDataStruct->iTOW; // iTOW is in milliseconds
    Serial.print(iTOW);
    Serial.print(F(" (ms)"));

    Serial.print(F(" Distance: "));
    unsigned long distance = ubxDataStruct->distance; // Print the distance
    Serial.print(distance);
    [b]distanceLog3 = distance;[/b]
    Serial.print(F(" (m)"));

    Serial.print(F(" Total Distance: "));
    unsigned long totalDistance = ubxDataStruct->totalDistance; // Print the total distance
    Serial.print(totalDistance);
    distanceLog4 = totalDistance;
    Serial.println(F(" (m)"));
}

void setup()
{
  Serial.begin(115200);
  while (!Serial); //Wait for user to open terminal
  Serial.println("SparkFun u-blox Example");

  Wire.begin();

  //myGNSS.enableDebugging(); // Uncomment this line to enable helpful 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.setNavigationFrequency(1); //Produce one solution per second

  //myGNSS.resetOdometer(); //Uncomment this line to reset the odometer

  myGNSS.setAutoNAVODOcallbackPtr(&printODOdata); // Enable automatic NAV ODO messages with callback to printODOdata
}

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.

  Serial.print(".");
  delay(50);
}

Hello George,

Apologies… (Nothing in life is ever as simple as it first appears!)

The odometer is disabled by default. You need to enable it…!

Please try adding these two lines to your setup code - after myGNSS.begin :

  myGNSS.setVal8(UBLOX_CFG_ODO_USE_ODO, 1); //Enable ODO
  myGNSS.setVal8(UBLOX_CFG_ODO_PROFILE, 0); //Set profile: 0:RUN, 1:CYCL, 2:SWIM, 3:CAR, 4:CUSTOM

I’m testing it now. I’m still seeing zeros, but my antenna is not moving. I will only see distance and totalDistance increase if the GNSS solution wanders sufficiently…

Please let me know if this works for you. I will of course update the example too.

Best wishes,

Paul

Thanks a lot! You are a god! I will try it as soon as I solve my power issues on my device :slight_smile:

Hi George,

Both v2 and v3 of the GNSS Library have been updated. They now include extra functions which you can use to enable / disable / configure the odometer:

https://github.com/sparkfun/SparkFun_u- … ag/v2.2.22

https://github.com/sparkfun/SparkFun_u- … tag/v3.0.4

If the default settings are OK for you, then you can enable the odometer with:

myGNSS.enableOdometer();

You can disable it again with:

myGNSS.enableOdometer(false);

If you want to change the profile or the filter settings, you can call:

uint8_t flags;        // Odometer/Low-speed COG filter flags
uint8_t odoCfg;       // Odometer filter settings
uint8_t cogMaxSpeed;  // Speed below which course-over-ground (COG) is computed with the low-speed COG filter : m/s * 0.1
uint8_t cogMaxPosAcc; // Maximum acceptable position accuracy for computing COG with the low-speed COG filter
uint8_t velLpGain;    // Velocity low-pass filter level
uint8_t cogLpGain;    // COG low-pass filter level
myGNSS.getOdometerConfig(&flags, &odoCfg, &cogMaxSpeed, &cogMaxPosAcc, &velLpGain, &cogLpGain);

to read the settings, and

myGNSS.setOdometerConfig(flags, odoCfg, cogMaxSpeed, cogMaxPosAcc, velLpGain, cogLpGain);

to change them.

Best wishes,

Paul

Thank you very much! This is wonderful news! Any available documentation on the filters and the odometer’s way of functioning? The manual doesn’t say much about this. I am trying to use it for low speed apps (sailboats)

George

Hi George,

There is a little extra detail in the M8 Interface Description:

"

21.3 Odometer Configuration

The odometer can be enabled/disabled by setting the appropriate flag in UBX-CFG-ODO (flags

field). The algorithm behaviour can be optimized by setting up a profile (odoCfg field)

representative of the context in which the receiver is operated. The implemented profiles together

with their meanings are listed below:

• Running: the algorithm is optimized for typical dynamics encountered while running, i.e the

Doppler-based velocity solution is assumed to be of lower quality;

• Cycling: the algorithm is optimized for typical dynamics encountered while cycling;

• Swimming: the algorithm is optimized for very slow and smooth trajectories typically

encountered while swimming;

• Car: the algorithm assumes that good Doppler measurements are available (i.e. the antenna is

subject to low vibrations) and is optimized for typical dynamics encountered by cars.

"

For your application, I would recommend trying “SWIM” first:

  uint8_t flags;        // Odometer/Low-speed COG filter flags
  uint8_t odoCfg;       // Odometer filter settings
  uint8_t cogMaxSpeed;  // Speed below which course-over-ground (COG) is computed with the low-speed COG filter : m/s * 0.1
  uint8_t cogMaxPosAcc; // Maximum acceptable position accuracy for computing COG with the low-speed COG filter
  uint8_t velLpGain;    // Velocity low-pass filter level
  uint8_t cogLpGain;    // COG low-pass filter level

  myGNSS.getOdometerConfig(&flags, &odoCfg, &cogMaxSpeed, &cogMaxPosAcc, &velLpGain, &cogLpGain);
  flags = UBX_CFG_ODO_USE_ODO; // Enable the odometer
  odoCfg = UBX_CFG_ODO_SWIM; // Use the swim profile (others are RUN, CYCLE, CAR, CUSTOM)
  myGNSS.setOdometerConfig(flags, odoCfg, cogMaxSpeed, cogMaxPosAcc, velLpGain, cogLpGain); // Set the configuration

Best wishes,

Paul