sparkfun / SparkFun_u-blox_GNSS_Arduino_Library

An Arduino library which allows you to communicate seamlessly with the full range of u-blox GNSS modules
Other
221 stars 100 forks source link

ZED-F9R issues #166

Closed hannsadrian closed 1 year ago

hannsadrian commented 1 year ago

Subject of the issue

I have multiple issues with my ZED-F9R installed in my car. The biggest problem at the moment is that the data randomly stops coming in after varying intervals of time while driving. No new data is received in my code and the only option is to unplug the setup and essentially restart it.

Additionally, I am unable to get High-Navigation-Rate data out of the module. When I try to activate it like in the examples it only produces errors. The code I'm now running on works at a kind-of high interval (maybe twice per second) but only ever stays in 3D Fix instead of going to Fix 4 :(

Your workbench

I am using an Arduino Due together with a ZED-F9R Breaktout (ublox multiband antenna) hooked up via a Qwiic Connector and the GPIO Pins. It is installed in my car and wired to the sparkfun alphanumeric display for a digital speedometer.

Steps to reproduce

I'm running the following code and after a random interval (maybe minutes maybe half an hour) the display stops updating.

#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;

#include <SparkFun_Alphanumeric_Display.h> //Click here to get the library: http://librarymanager/All#SparkFun_Qwiic_Alphanumeric_Display by SparkFun
HT16K33 display;

#include <BH1750.h>
BH1750 lightMeter;

// global variables
long fix = 0;
long speed = 0;
long distance = 0;
long prevFusionMode = -1;

void displayFrame() {
  // ...
  // startup animation
}

void displayAll() {
  // ...
  // display utility funciton
}

void setup()
{
  delay(2000);

  Serial.begin(115200);

  Wire.begin();
  Wire.setClock(400000);

  if (display.begin() == false)
  {
    Serial.println("Device did not acknowledge! Freezing.");
    while (1);
  }

  display.setBrightness(1);
  displayFrame();

  //myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial

  if (myGNSS.begin(Wire, 66U, 5000U, true) == 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."));
    display.print("FAIL");
    while (1);
  }

  myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)

  myGNSS.getESFAutoAlignment(); //Get the current ESF-AUTOALIGNMENT settings
  myGNSS.setESFAutoAlignment(true); //Enable UBX-CFG-ESFALG Automatic IMU-mount Alignment

  myGNSS.setMeasurementRate(50); //Set the measurement rate to 50 ms (50 Hz)
  myGNSS.setI2CpollingWait(25); //Set the I2C polling wait to 25 ms (40 Hz)
  myGNSS.setNavigationRate(1); //Set the navigation rate to 1 (every measurement)
  myGNSS.setNavigationFrequency(20); //Set navigation frequency to 10Hz
  myGNSS.setAutoPVT(true, false, 1100U);
  myGNSS.saveConfiguration(); //Save the current settings to flash and BBR

  displayAll();

  lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE);
}

void updateDisplay()
{
  char speedString[4];
  sprintf(speedString, "%03.0ld", speed);
  if (speed == 0) {
    display.print("  0 ");
  } else {
    display.print(speedString);
  }

  if (fix == 0) {
    display.decimalOff();
    display.colonOff();
    display.setBlinkRate(2);
    // ... 
    // display all types of fix states on the display
  } else {
    display.decimalOff();
    display.colonOff();
    display.setBlinkRate(0);
  }
}

void loop()
{
  static uint16_t counter = 0;

  if (counter % 10 == 0) {
    // ...
    // adjust display brightness
  }

  myGNSS.checkUblox(); //Check for new data on the I2C port

  fix = myGNSS.getFixType();

  speed = myGNSS.getGroundSpeed() * 0.0036; // convert to km/h

  if (Serial) {
    Serial.print("Fix " + String(fix) + "; ");
    Serial.println("Speed: " + String(speed) + " km/h");
    Serial.println(millis());
  }

  updateDisplay();
  counter++;
  delay(1);
}

Expected behavior

The gps should produce high interval navigation resolutions with 4d fix (GNSS + IMU) and not hang up after random intervals.

Actual behavior

The gps only goes into 3d fix with a kind of slow updating interval (~2Hz) and stops updating at all after varying lengths of time. The latter recovers by unplugging and replugging (restarting) the setup.

PaulZC commented 1 year ago

Hi Hanns (@Adwirawien ),

Please open the I2C split-jumper pads on the bottom of the ZED-F9R PCB, to disconnect the extra pull-up resistors from the I2C bus. The extra resistors may be causing bus errors. Does that help?

IIRC the Due is "fussy" about I2C communication. Do you have another board you can try? I can recommend ESP32-based boards.

You are updating the display each time the code goes around the loop. How about adding if (counter % 100 == 0) before updateDisplay(); to update the display at ~10Hz?

Best wishes, Paul

hannsadrian commented 1 year ago

Hey Paul,

thank you for your input. I will definitely move to a slower update rate on the display.

I've originally wanted to use a Redboard Plus in the project, but sadly the internal storage isn't enough let alone for this library 😕 Now I ordered a Redboard Turbo and will try that in the coming days. If the problem persist I will try to open the jumpers. What is unclear to me is, how one can open these. Do you scratch them away or is there a proper solution? 🛠️

Lastly, I really would like the module to go into 4D Fix. I've achieved it previously in this setup with very similar code, that monitored sensor fusion/calibration state in loop. What is the ingredient to making it work on my current code?

Again, thank you!

Kind regards, (Hanns) Adrian ;)

PaulZC commented 1 year ago

Hi Adrian (@Adwirawien ),

We have a tutorial on working with jumpers: https://learn.sparkfun.com/tutorials/how-to-work-with-jumper-pads-and-pcb-traces

I'm mostly a "desk jockey". It is difficult for me to take our GNSS boards "on the road". So, I'm afraid I don't have much experience with the dead-reckoning boards and 4D fixes. You might find this discussion helpful - from my (only) road test?

https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/issues/143

My advice would be to try opening the jumpers first. It may help with the I2C communication on Due. After that, the RedBoard Turbo is a good choice. But I still recommend opening the jumpers - the u-blox module has built-in pull-ups which are perfect on their own.

Another test you can try is to disconnect your display, and use the Serial port to display messages instead. Having the Qwiic Alphanumeric and the u-blox module on the same I2C bus may be creating a "bottleneck".

Best wishes, Paul

hannsadrian commented 1 year ago

Wow! I am stunned by the RedBoard Turbo! The speed of the gps updates is incredible and I think I also figured out that my non working Sensor Calibration comes down to calling setAutoPVT with implicitUpdate set to true.

As I was installing the RedBoard I also noticed errors with the alphanumeric display not properly connecting and displaying gibberish. At first I thought it had something to do with the different processor on the Turbo. However, it turns out that I had the 500mm Qwiic Cable between the GPS and the Display. By replacing it with a shorter wire everything works wonderfully! Is the I2C affected by a long cable or is it the voltage drop caused by the really thin cable that brings the display into trouble?

Anyways, thank you very much for your competent help – you've solved all my problems 🌟

Best regards Adrian

PaulZC commented 1 year ago

Hi Adrian (@Adwirawien ),

I'm glad that's working for you!

The SAMD21 supports multiple ports (Serial, SPI and I2C), so, with a little code hacking, it is ~easy to create a second I2C port. That would allow you to have the GNSS and display on separate ports, without and with external pull-up resistors.

I2C was introduced by Philips back in the 1980's. The specification makes interesting bedtime reading. The maximum cable length is dictated mostly by capacitance, which slows down the rising and falling edges of the signals. Slower speeds can be used to communicate over longer distances.

When you are using the library's "Auto" feature, calls to (e.g.) myGNSS.getFixType will check if new data is available from the GNSS. If not, the previous "stale" data is returned. If you want to guarantee having "fresh" data each time, you need to call myGNSS.getPVT and wait until it returns true. PVT Example1 shows how to do this.

Have fun with your project! Paul