sparkfun / SparkFun_u-blox_GNSS_v3

An Arduino library which allows you to communicate seamlessly with u-blox GNSS modules using the Configuration Interface
Other
54 stars 24 forks source link

ZED-F9R: UART1 Dying After around 10mins of usage #59

Closed flamerten closed 2 months ago

flamerten commented 2 months ago

Im using the ZED-F9R breakout board(HPS Version 1.3), with a Teensy 32 connected to the UART1 pins of the ZED-F9R, with a baud rate of 115200. When I set a solution rate* higher than the default rate of 1Hz, (myGNSS.getHPPOSLLH()) || (myGNSS.getPVT()) will continuously return false after around 700s of usage.

When restarting the device(power cycle), I notice that a baud rate of 38400 is connected to first, despite 115200 being what was written to configuration. This makes me think that the reason for this issue is that the UART1 port is dying as there are too many UBX messages sent.

The issue is solved by switching back to the default measurement rate of 1Hz, but I would like a solution rate of around 10Hz.

Would it be possible to still do this using UART1 or is switching to SPI/I2C necessary? Can I (or rather should I) enable only relevant messages for GPS coordinate finding and ESF status? Off the top of my head Im thinking UBX-NAV-PVT, UBX-NAV-HPPOSLLH and UBX-ESF-STATUS, but I'm not too sure if this is advisable.

Something interesting I have observed is that I could only reproduce the issue while moving. When leaving the unit there over time, there are no issues. Once I am out with a bike the UART1 port fails.

*My definition of solution rate is $MeasurementRate \times NavigationRate$. By default this is $1000\times1$ so a new solution is produced every 1s.

For example, this fails, but doesnt fail when a ZED-F9P is used.

//Solution rate of 0.1s
GNSS.setMeasurementRate(50);
GNSS.setNavigationRate(2);

Implementation Details

PaulZC commented 2 months ago

Hi Samuel (@flamerten ),

Yes, it sounds like you are overloading the UART. Try disabling the NMEA protocol if you do not need it. Please see this example for more details. The module will produce more NMEA GSV messages when it has a clear sky view. This probably explains why it fails when you are 'moving'.

Closing... Please reopen if you need more help with this.

Best wishes, Paul

flamerten commented 2 months ago

Hi @PaulZC

Thanks for your quick reply.

I am currently doing that by calling myGNSS.setUART1Output(COM_TYPE_UBX). Since this doesn't solve the issue, could I restrict the output of specific UBX messages?

Also, on a related note, given these 2 configurations,

Option 1

GNSS.setMeasurementRate(1000);
GNSS.setNavigationRate(1);

vs

Option 2

GNSS.setMeasurementRate(200);
GNSS.setNavigationRate(5);

Technically, they produce the same number of solutions per second, so GNSS.getPVT() will return true every second. However, will Option 2 overwhelm the UART buffer more compared to Option 1 due to the higher rate of measurements or is it the same?

PaulZC commented 2 months ago

By default, no UBX messages are enabled, only NMEA. I'd recommend doing a "factory reset". Maybe you have enabled other UBX messages previously, and have saved the configuration? If you have enabled (e.g.) RXM-SFRBX, the number of messages will increase with good sky view.

The message rate / volume should be the same for 1000/1 and 200/5.

flamerten commented 2 months ago

Thanks for the clarification! This is my current setup() code. Would this be the most optimal way of setting up the UART port to receive uart messages?

I guess if this is the optimal way, I should switch to SPI/I2C.

Another note, would calling GNSS.setVal8(UBLOX_CFG_RATE_NAV_PRIO, 10) help in not filling the buffer? From my understanding, this should increase the navig

GNSS_Serial_Connect(); // Try different baud rates and connect, then write 115200 as the serial rate
GNSS.factoryDefault(); delay(5000); //Reset the GNSS module
GNSS_Serial_Connect();
if(GNSS.begin(SERIAL_GNSS) == true)
  {
    GNSS.setUART1Output(COM_TYPE_UBX);

    GNSS.setMeasurementRate(200);  
    GNSS.setNavigationRate(5);

    GNSS.setESFAutoAlignment(false); 
    GNSS.setDynamicModel(DYN_MODEL_ESCOOTER);
    GNSS.setVal8(UBLOX_CFG_NAVSPG_SIGATTCOMP, 0);                           //Automatic signal attenuation compensation disabled

    //IMU Alignment
    GNSS.setVal32(UBLOX_CFG_SFIMU_IMU_MNTALG_YAW, IMU_YAW_DEG*100);
    GNSS.setValSigned16(UBLOX_CFG_SFIMU_IMU_MNTALG_ROLL, IMU_ROLL_DEG*100);
    GNSS.setValSigned16(UBLOX_CFG_SFIMU_IMU_MNTALG_PITCH, IMU_PITCH_DEG*100);

    GNSS.setAutoPVT(true);
    GNSS.setAutoHPPOSLLH(true);

    GNSS.saveConfiguration();
  }
PaulZC commented 2 months ago

NAV-PVT is 100 (92+8) bytes. NAV-HPPOSLLH is 44 (36+8) bytes. Together, that's approximately 1440 bits (start, 8 data, stop). At 38400 baud, the UART port should be OK up to ~20Hz.

If you are not using I2C, disabling NMEA on I2C may help: GNSS.setI2COutput(COM_TYPE_UBX);. To disable I2C completely: GNSS.setI2COutput(0);.

The maximum navigation rate depends on which module you have. ZED-F9R-01B is:

image

ZED-F9R-03B is:

image

CFG_RATE_NAV_PRIO sets "Output rate of priority navigation mode messages" in Hz. GNSS.setVal8(UBLOX_CFG_RATE_NAV_PRIO, 10) sets the rate to 10Hz. Both NAV-PVT and NAV-HPPOSLLH are high priority messages, so both should be output at 10Hz.

The standard NMEA messages are also high priority. But you have those disabled.

I'm not sure how the normal measurement rate and navigation rate interact with priority navigation mode. My recommendation would be to leave them set to the default 1000 / 1.

You need to make sure you are reading the microcontroller UART regularly, to avoid overflowing its receive buffer. With the "auto" examples, make sure you are calling GNSS.getPVT and GNSS.getHPPOSLLH often. Callbacks may be a better option for you. See this example. Use GNSS.setAutoHPPOSLLHcallbackPtr for HPPOSLLH. Call GNSS.checkUblox and GNSS.checkCallbacks often in the loop.

flamerten commented 2 months ago

Dear Paul

Thanks for your help. Setting the measurement rate and navigation frequency to their default rates of 1000 and 1, and then setting the priority navigation rate to 10Hz gave me the rate I needed. It seems like the best way to get a high rate is to rely on using priority navigation mode rather than changing the measurement rate, since I am getting unique solutions at a rate higher than 1Hz.

I'm not too sure if that was the actual fix (i.e putting measurement rate back to default and setting priority mode). I was also polling for ESF-STATUS data, so I also set it to non-blocking and called getESFInfo as much as possible. I2C was also disabled

Thanks again for your help.

PaulZC commented 2 months ago

No problem Samuel (@flamerten ) - I am glad it is working. Best wishes, Paul