Neo-M8U on Teensy 4.1 via I2C only 5Hz max

Im running this example script and I cant seem to get it reading more than 5Hz.

What am I missing ? The Teensy is connected via the I2C lead, the GPS is recognised immediately but 5Hz is what I was able to get from the cheap chinese GPS I was using. I bought this for use on circuit where speeds are in excess of 170MPH and 5Hz simply isn`t good enough.

Any suggestions are welcome !

/*
  Set update rate to 10Hz
  By: Nathan Seidle
  SparkFun Electronics
  Date: January 3rd, 2019
  License: MIT. See license file for more information but you can
  basically do whatever you want with this code.

  This example shows how to increase the output of the module from 1Hz to 4Hz.
  The max output rate various from model to model. RTFM! But you cannot do harm
  to the module.

  We also disable NMEA output on the I2C bus and use only UBX. This dramatically 
  decreases the amount of data that needs to be transmitted.

  Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!

  Feel like supporting open source hardware?
  Buy a board from SparkFun!
  ZED-F9P RTK2: https://www.sparkfun.com/products/15136
  NEO-M8P RTK: https://www.sparkfun.com/products/15005
  SAM-M8Q: https://www.sparkfun.com/products/15106

  Hardware Connections:
  Plug a Qwiic cable into the GNSS and a BlackBoard
  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 GNSS

#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
SFE_UBLOX_GNSS myGNSS;

unsigned long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
unsigned long startTime = 0; //Used to calc the actual update rate.
unsigned long updateCount = 0; //Used to calc the actual update rate.

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

  Wire.begin();

  // Increase I2C clock speed to 400kHz to cope with the high navigation rate
  // (We normally recommend running the bus at 100kHz)
  Wire.setClock(400000);
  
  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.setNavigationFrequency(25); //Set output to 25 times a second

  uint8_t rate = myGNSS.getNavigationFrequency(); //Get the update rate of this module
  Serial.print("Current update rate: ");
  Serial.println(rate);

  startTime = millis();
}

void loop()
{
  //Query module every 25 ms. Doing it more often will just cause I2C traffic.
  //The module only responds when a new position is available. This is defined
  //by the update freq.
  if (millis() - lastTime > 25)
  {
    lastTime = millis(); //Update the timer
    
    long latitude = myGNSS.getLatitude();
    Serial.print(F("Lat: "));
    Serial.print(latitude);

    long longitude = myGNSS.getLongitude();
    Serial.print(F(" Long: "));
    Serial.print(longitude);

    updateCount++;

    //Calculate the actual update rate based on the sketch start time and the 
    //number of updates we've received.
    Serial.print(F(" Rate: "));
    Serial.print( updateCount / ((millis() - startTime) / 1000.0), 2);
    Serial.print(F("Hz"));

    Serial.println();
  }
}

What GPS are you using? Can you attach photos and a source?

Of the cheap GPS I used to use? Why?

I’m trying to get the M8U to work at speeds higher than 5hz, which is why I bought it in the first place as its advertised as being able to run at higher speed.

If its a limitation of the Teensy, fine, let me know what I need to replace it with, but I didn’t think there was that much processing power required.

Hi @NigeP ,

Please see this topic. I suspect you’re having the same issue… The solution should be to disable NMEA on UART1.

Hope this helps,
Paul

Also, I’d recommend making the PVT message periodic (“Auto”). Please see this example for more details:

I tried that, changed the update frequency to 25 and the wait to 40ms to ensure no pausing in that part of the loop caused an issue.

I removed everything apart from Lat and Long just to prove its not a bottleneck on the I2C (which I dont believe it was, but wanted to prove it)

As you can see, it’s still updating every 0.2 sec. ie 5Hz

If you have a script I can run to test it I`ll happily do so !.

At the moment Im a bit lost as to where the issue is and I dont know how to diagnose it, hence this post. :slight_smile:

/*
  Configuring the GNSS to automatically send position reports over I2C
  By: Nathan Seidle and Thorsten von Eicken
  SparkFun Electronics
  Date: January 3rd, 2019
  License: MIT. See license file for more information but you can
  basically do whatever you want with this code.

  This example shows how to configure the U-Blox GNSS the send navigation reports automatically
  and retrieving the latest one via getPVT. This eliminates the blocking in getPVT while the GNSS
  produces a fresh navigation solution at the expense of returning a slighly old solution.

  This can be used over serial or over I2C, this example shows the I2C use. With serial the GNSS
  simply outputs the UBX_NAV_PVT packet. With I2C it queues it into its internal I2C buffer (4KB in
  size?) where it can be retrieved in the next I2C poll.

  Feel like supporting open source hardware?
  Buy a board from SparkFun!
  ZED-F9P RTK2: https://www.sparkfun.com/products/15136
  NEO-M8P RTK: https://www.sparkfun.com/products/15005
  SAM-M8Q: https://www.sparkfun.com/products/15106

  Hardware Connections:
  Plug a Qwiic cable into the GNSS and a BlackBoard
  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 GNSS

#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
SFE_UBLOX_GNSS myGNSS;

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

  Wire.begin();

  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.setNavigationFrequency(25); //Produce two solutions per second
  myGNSS.setAutoPVT(true); //Tell the GNSS to "send" each solution
  //myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
}

void loop()
{
  // Calling getPVT returns true if there actually is a fresh navigation solution available.
  // Start the reading only when valid LLH is available
  if (myGNSS.getPVT() && (myGNSS.getInvalidLlh() == false))
  {
    Serial.println();
    long latitude = myGNSS.getLatitude();
    Serial.print(F("Lat: "));
    Serial.print(latitude);

    long longitude = myGNSS.getLongitude();
    Serial.print(F(" Long: "));
    Serial.print(longitude);
    Serial.print(F(" (degrees * 10^-7)"));


    Serial.println();
  } else {
    Serial.print(".");
    delay(40);
  }
}

Oh, I though you were using a cheap GPS in place of the Ublox GPS.

Probably the wrong product…
The UDR/ADR products have a relatively low GNSS rate
For the 30 Hz in the specification you need to be using the UBX-HNR-PVT (High Navigation Rate) messages, and these use the IMU and successful Sensor Fusion to fill the gaps.

You might want to look at the NEO-M9N for higher GNSS rates, and NEO-M9V for the equivalent UDR/GNSS combo, again at the higher rates the M9’s processor affords.

The NEO-M9N can do 10-25 Hz GNSS with 16 satellite solutions. Below that it can do 32 satellite solutions.

On the Series 8 the HNR is configured via UBX-CFG-HNR, and the message via UBX-CFG-MSG
On the Series 9 they have a priority navigation rate setting for a subset of the regular messages outputting position.

Ah, apologies yellowdog, I obviously explained it poorly.

Clive, surely you aren’t saying the M8U can only run at 5hz. The spec says on the sparkfun page up to 30. It’s why I bought it.

Hopefully Paul has a script I can run to test what’s going on

Hi @NigeP ,

Apologies. I shot from the hip earlier…

The NEO-M8U is limited to 2Hz for standard Position Velocity Time messages. 30Hz is available - but only with the High Navigation Rate messages.

Please see this HNR example:

You will need to set your navigation rate back to the standard 1Hz.

Let me know if you need more help with this.

Best wishes,
Paul

Thank you Paul

I’ve been trying to get this to run but I still seem to be getting slow updates.

Anything I can do to get 30Hz as advertised ?

Ok, so let me go over this from first principles.

The GNSS solution rate is relatively slow, I think the minimum time is 128 ms (7.8 Hz), via UBX-CFG-RATE (Navigation Rate), but probably realistically 2 - 5 Hz. Depends on your system, and what works best with integer multiples, common factors, your already dealing with in your control systems and surfaces.

This is the rate at which it establishes an “actual” position when it can.

The 30 Hz rate is a “High Navigation Rate” where it synthesizes a far higher rate that passes thru the GNSS points. How aggressively it does this will depend on the accuracy estimate, for the RTK F9R/F9K type devices this eye-of-the-needle it can thread approaches 2cm.

Use UBX-CFG-HNR to set the higher speed 20 Hz (50 ms) or 30 Hz (30 ms), Default for UDR 1.21 is 10 Hz rather than 0 Hz / Off

Enable UBX-HNR-PVT via UBX-CFG-MSG (I2C = 1 ie message every 30 ms)

The other consideration is the volume of data on ALL/ANY interfaces, if not using UART then disable it, so you don’t get 5 Hz of NMEA GSV trying to jam out at 9600 baud. Use UBX-CFG-PRT

Turn off messages you aren’t using/processing. Use UBX-CFG-MSG.

Watch for $GxTXT “txbuf,alloc” warnings, this is indicative of a slow interface log-jamming on data volume, and packet transmit buffers aren’t available, and potential output messages have been lost because of this.

Parse UBX-HNR-PVT for position, UBX-HNR-ATT for computing pitch, roll, yaw

Establish TIME in your system, use the TIMEPULSE and/or TIMEMARK to relate the time domain for your MCU’s current time [millis()?] is with respect to the time-of-measurement (past) of the sensors and solution from those. You’re moving through time-space, you’re not physically at the reported position as there is computation and reporting latency, and your ability to change control surfaces will occur later (future)

Consider Vehicle Dynamics, these will constrain GNSS and IMU measurement expectations. Use UBX-CFG-NAV5 to configure a use case that most closely matches those of your vehicle. If in the Air, don’t be a Car or Pedestrian…

1 Like

I’ve read that several times. I think I understand the principle of what you are saying. :+1:How to write the code is a different issue. :grin:

I don’t need pitch or yaw.

Realistically I just want to log speed, latitude and longitude as fast as possible to sd card.

Accelerometer X and Y would be nice, but not critical.

I’ve looked at the script above and all the examples I can find online, but none seem to work without modification that is currently beyond my ability :pensive:

I was hoping someone would have the code already and would share it.

Skimming Paul’s code, my guess would be that you need to suppress UART1 output, or set the baud rate super high, so that it’s doesn’t become the choke point. Might take a couple of lines to ensure

IMU data can be collected via UBX-ESF-MEAS or UBX-ESF-RAW, but these won’t neatly sync if your output goal is .CSV file records tying lat, lon, etc together

Perhaps look at UBX-NAV-ATT or UBX-NAV-COV to look at how the receiver is orientated and moving through 3D space, via velocity and acceleration

myGNSS.setUART1Output(0); // Turn off the noise

1 Like

Yeah, I definitely need to save Lat, Long and speed to a .csv, with a time value.

You may just log NMEA RMC. With F9R, I tried to go to 30 Hz. Data were both sent on UART1 for SD card logging and on UART2 to smartphone through HC05/BT. BT connexion collapsed quickly (a few dozen of seconds) but data were well recorded on the SD card. (Details here)

1 Like