Skip to content

I2C held up for over 1sec #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pitchuk opened this issue Aug 1, 2024 · 4 comments
Closed

I2C held up for over 1sec #62

pitchuk opened this issue Aug 1, 2024 · 4 comments

Comments

@pitchuk
Copy link

pitchuk commented Aug 1, 2024

Hi There,
I have a SparkFun MAX-M10S wired via i2c to a Pi Pico running earlephilhower core 3.9.4. I am using different I2C lines but confirm this works with all other devices on the circuit.

However when I run my code to get data, the first function (normally myGNSS.getPVT(), but seems to be any function) will take over 1 second to return anything. After which all remaining commands will take 0ms.

It is preventing access to the I2C lines and stalling the processor for too long, preventing button recognition and screen refresh. Making device very laggy.

I have simplified my code as show below, my serial output come back as:
1010 0
1006 0
1005 0
1006 0
1004 0
Got Fix 904 0
Got Fix 906 0
Got Fix 1010 0

Showing that both with and without satellite fix the first poll of the Max10S takes ~1000ms and rest of functions take 0ms

#include <Wire.h>  //Needed for I2C to GNSS

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

long lastTime1 = 0;  //Simple local timer. Limits amount if I2C traffic to u-blox module.
long lastTime2 = 0;
long now = 0;
int32_t latitudeTX;
int32_t longitudeTX;
int min_check;
int Broadcast_Int = 2;  //has to be greater than number oof nodes
int t_sec;
int t_min;
int t_hour;
int fixType;

void setup() {
  Serial.begin(115200);
  Serial.println("SparkFun u-blox Example");
  delay(2);
  Wire.setClock(400000);
  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.saveConfiguration();        //Optional: Save the current settings to flash and BBR
}

void loop() {

  lastTime1 = millis();
  if (myGNSS.getPVT() == true) {
    lastTime2 = millis();
    if (myGNSS.getTimeValid()) {
      t_hour = myGNSS.getHour();
      t_min = myGNSS.getMinute();
      fixType = myGNSS.getFixType();
      if (fixType == 5) {
        fixType = 0;
      }
      if (fixType >= 2) {
        latitudeTX = myGNSS.getLatitude();
        longitudeTX = myGNSS.getLongitude();
      }
    }
  }
  now = millis();
  if (fixType >= 2) {
    Serial.print("Got Fix "); //print if we get a sat fix
  }
  long change = now - lastTime1;
  Serial.print(change); //Time in millis of every GPS command
  Serial.print("  ");
  change = now - lastTime2;
  Serial.println(change);//Time in millis of every GPS command besides first one
  delay(3000);
}

@PaulZC
Copy link
Collaborator

PaulZC commented Aug 2, 2024

Hi @pitchuk ,

By default, the u-blox GNSS calculates a solution every second. With the code above, you are polling (requesting) the Position Velocity Time with getPVT. Depending on when you send the poll request within that one second interval, it can take up to the full second for the PVT to be returned. getHour, getLatitude etc. are then extracting the relevant data from the complete PVT message and return immediately.

To prevent the stall, you need to make PVT periodic - set the module to output PVT every second automatically. In the library we refer to this as "Auto". Once set to "Auto", getPVT will return false almost immediately if no new PVT is available. There is a small delay because the code still needs to check how much data is waiting in the module's I2C buffer. Please see Example7. Callbacks may be a better solution for you - see this example.

Closing...

Best wishes,
Paul

@PaulZC PaulZC closed this as completed Aug 2, 2024
@pitchuk
Copy link
Author

pitchuk commented Aug 2, 2024

Thanks Paul, Really useful and speedy response. I will give them a go.

If you don't mind and to save me a bit of time. I have a few questions:

  1. What are callbacks and why are they better possibly?
  2. This is a battery device outputting GPS every minute so can I save battery by
    a) making the PVT output slower and if it is per second then can you do decimal values?
    b) powering off using example 22 (or will this affect hotstart)
  3. I don't actually need any travel velocity data can you save time/resorses by disabling?

Many Thanks
David

@PaulZC
Copy link
Collaborator

PaulZC commented Aug 2, 2024

Hi David,

  1. It depends on your coding style / needs. The callbacks keep the loop very clean. Without them, you need to call getPVT in the loop. There's no speed increase with callbacks. Only elegance...

2a) this won't change the current draw
2b) this will reduce the current draw, but the module will still draw mA while "asleep"
3) no, the module always calculates velocity as part of the solution. It's just how it is...

The only way to truly minimise the current is to turn the power to the module off and rely on the battery-backed RAM to maintain the clock.

Best,
Paul

@pitchuk
Copy link
Author

pitchuk commented Aug 2, 2024

Thanks for all the above. All seems to be working well. Will think about turning power off after everythign is working and I am just doing the power optimisations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants