Arduino Due slower update rate than Uno over I2C
smithan7 opened this issue · 7 comments
Thanks for a great library and please let me know if there are any details I am leaving out. I searched for old issues on this and the closest I found was Arduino DUE Setup #66 - which was related to Serial connections.
Subject of the issue
I am using the Arduino Due with the SparkFun GPS Dead Reckoning Breakout - NEO-M8U (Qwiic) with the unmodified Example3_GetPosition.
I am wired to the Due using pins 20, 21, 3.3v, and GND (without pullup resistors) and I am able to connect and get GPS data to print on the screen as shown below:
[Deleted]
The issue is that it runs really slowly, from the timestamps it takes ~6s for each update. I originally had this on a Sparkfun redboard Qwiic (~Arduino Uno) (hooked up A5, A4, 3.3v, and GND without pullup resistors) and re-running using the exact same Example3_GetPosition I get:
[Deleted]
This is a simple example, I noticed the slowness on a separate script and am using this to demonstrate a re-creatable difference on a stock example. I have tried increasing the wire speed to 400,000 Hz (Wire.setClock(400000);) and that didn't help. I also notice that the Due is less reliable in detecting the GPS receiver, which I assume is a timeout issue. I have also used the examples to modify the GPS update behavior and on the Uno it behaves as expected and updates but on the Due it frequently does not update OR when it does it does not effect the actual update rate.
I tested running print statements on the Due and it does not lag - it appears to be something in either the i2c or GPS libraries/connections inducing the lag.
Your workbench
- What development board or microcontroller are you using?
* I am using a Sparkfun Redboard Qwiic (~Uno) and Arduino Due - What version of hardware or breakout board are you using?
* SparkFun GPS Dead Reckoning Breakout - NEO-M8U (Qwiic) - How is the breakout board wired to your microcontroller?
* Redboard UNO - A4, A5, 3.3v, GND pins without pullup resistors - direct from Arduino female headers to Qwiic connector
* Have also used the built-in Qwiic connector on the Redboard Uno direct to the GPS Qwiic without issue and went back to this to test the cable used to connect the Due.
* Arduino Due - 20, 21, 3.3v, GND pins without pullup resistors - direct from Arduino female headers to Qwiic connector - How is everything being powered?
* Both boards are powered via USB port to micro-USB connector from my laptop to the board. - Are there any additional details that may help us help you?
* Not that I can think of...
Steps to reproduce
I am using the stock Example3_GetPosition as copied below:
***********************************Begin Code ***************************************************************
/*
Reading lat and long via UBX binary commands - no more NMEA parsing!
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 query a u-blox module for its lat/long/altitude. We also
turn off the NMEA output on the I2C port. This decreases the amount of I2C traffic
dramatically.
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
to something google maps understands simply divide the numbers by 10,000,000. We
do this so that we don't have to use floating point numbers.
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;
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
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
}
void loop()
{
//Query module only every second. Doing it more often will just cause I2C traffic.
//The module only responds when a new position is available
if (millis() - lastTime > 1000)
{
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);
Serial.print(F(" (degrees * 10^-7)"));
long altitude = myGNSS.getAltitude();
Serial.print(F(" Alt: "));
Serial.print(altitude);
Serial.print(F(" (mm)"));
byte SIV = myGNSS.getSIV();
Serial.print(F(" SIV: "));
Serial.print(SIV);
Serial.println();
}
}
*************************************End Code ***************************************************************
Expected behavior
I expected the Arduino Due to have the same update rate as the Uno.
Actual behavior
The Due is significantly slower than the Uno.
Hi @smithan7 ,
I think you are seeing the same thing as this issue: https://forum.sparkfun.com/viewtopic.php?p=239338#p239338 . The u-blox modules use I2C clock stretching, and the Due does not support clock stretching...
Switching to Serial or SPI should solve this issue for you.
I'm going to close this, but please re-open if you need more help or suggestions.
Best wishes,
Paul
Thanks for giving me the answer - I am now trying to use the Serial1 port of the Due to make the connection but have not had any luck getting it to connect. I used the same program from #66
But couldn't get a connection. I looked at the U-Blox Neo M8U protocol sheet and it listed the following possible baud rates:

I stepped through and tried each one without getting past:
SparkFun u-blox Example
..............................................................
I checked again over i2c and there I am able to pull pvt data from the module.
My connections are from the Arduino Due Tx1 (18) -> GPS Rx, Due Rx1(19) -> GPS Tx, Due 3.3v -> GPS 3.3v, Due GND -> GPS GNG.
here is the complete script I am using and change out the baud rate for Serial1:
#include <Wire.h> //Needed for I2C to GNSS
#include <SparkFun_u-blox_GNSS_Arduino_Library.h>
SFE_UBLOX_GNSS myGNSS;
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println("SparkFun u-blox Example");
Serial1.begin(460800);
myGNSS.begin(Serial1);
myGNSS.assumeAutoPVT(true, true);
}
void loop()
{
if (myGNSS.getPVT())
{
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)"));
long altitude = myGNSS.getAltitude();
Serial.print(F(" Alt: "));
Serial.print(altitude);
Serial.print(F(" (mm)"));
byte SIV = myGNSS.getSIV();
Serial.print(F(" SIV: "));
Serial.print(SIV);
Serial.println();
}
else
{
delay(5);
static int counter = 0;
counter++;
if (counter > 10)
{
Serial.print(".");
counter = 0;
}
}
}
Is there something I am missing to enable the Serial on the GPS module? I haven't seen anything but am not sure what else to try. The common guidance is to make sure I am using the right baud rate and get a clear view of the sky. I have verified it gets PVT data river i2c so I would assume I have a clear view of the sky and I have tried every baud rate in the protocol description. Anything I am missing?
To me, this didn't seem worthy of opening a new issue but I will if that is preferred. Thanks again.
Hi @smithan7 ,
I don't have a Due with me, so all I can offer are suggestions which you can test.
The NEO-M8U defaults to 9600 Baud. 9600 should work perfectly. You should not need to change it.
This example is a better starting point:
You are using hardware Serial port Serial1 (pins 18 and 19), so the definition of mySerial becomes:
#define mySerial Serial1
Set the baud rate using:
#define baudRate 9600
I think the main problem is that you are using myGNSS.assumeAutoPVT(true, true);. Please see this comment.
Best wishes,
Paul
Hi Paul,
Thanks for your assistance on this. I made the changes you recommended and used:
with the following changes to use Serial1:
//#include <SoftwareSerial.h>
#define mySerial Serial1 // Uncomment this line to connect via Serial2
// - or -
//SoftwareSerial mySerial(10, 11); // Uncomment this line to connect via SoftwareSerial(RX, TX). Connect pin 10 to GNSS TX pin.
#define baudRate 9600 // Uncomment this line to select 9600 Baud for the M8
// - or -
//#define baudRate 38400 // Uncomment this line to select 38400 Baud for the F9
void setup()
{
Serial.begin(115200);
while (!Serial); //Wait for user to open terminal
Serial.println("SparkFun u-blox Example");
mySerial.begin(baudRate); // Start the Serial port
if (myGNSS.begin(mySerial) == false) //Connect to the u-blox module using Serial
{
Serial.println(F("u-blox GNSS not detected. Please check wiring. Freezing."));
while (1);
}
myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART1 port to output UBX only (turn off NMEA noise)
myGNSS.setNavigationFrequency(2); //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
}
It is not detecting the GPS and is hanging at:
SparkFun u-blox Example
u-blox GNSS not detected. Please check wiring. Freezing.
I tried powering it direct to the 3.3v and gnd pins adjacent to the Rx/Tx on the board and through the i2c port (both acquired and got the blue led for PPS (I assume they're connected on the board but am running out of ideas). I also tried using Serial2 on the Due which had the same result. I verified my jumper cables are ok by using them instead of the Qwiic port on the GPS and going direct to the SDA/SCL pins on the GPS - which worked using the same jumper cables that are not working with the Serial connection.
By my understanding, this should just work at this point and I am not sure what else to try. Really appreciate your patience, quick responses, and help on this. If you see anything I am missing or anything else I might test please let me know.
Please try resetting the NEO-M8U back to its default settings:
Install u-center 22.07 (not u-center2): https://www.u-blox.com/en/product/u-center
Connect to the NEO-M8U via USB
Once connected, you should start to see the satellite signal strengths etc.
Open View \ Messages View
Navigate to UBX \ CFG \ CFG
Select "Revert to default configuration"
Press Send at the bottom of the window
Then select "Save current configuration"
Press Send again to save the default settings
This will reset the module back to 9600 baud and make it output the default NMEA messages on Serial and I2C
Then try your Arduino code again...
That worked!!!!
Thanks for all of your help Paul, I genuinely appreciate your patience and support on this.
