Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Update to AutoPVT functionality #18

Merged
merged 6 commits into from
Jul 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
Configuring the GPS to automatically send position reports over I2C, with explicit data parsing calls
By: Nathan Seidle Thorsten von Eicken and Felix Jirka
SparkFun Electronics
Date: July 1st, 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 GPS the send navigation reports automatically
and retrieving the latest one via checkUblox when available.
This eliminates the implicit update in getPVT when accessing data fields twice.
Also this reduces the memory overhead of a separate buffer while introducing a slight error by inconsistencies because of the unsynchronized updates (on a multi core system).

This can be used over serial or over I2C, this example shows the I2C use. With serial the GPS
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 GPS 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 GPS

#include <SparkFun_Ublox_Arduino_Library.h> //http://librarymanager/All#SparkFun_Ublox_GPS
SFE_UBLOX_GPS myGPS;

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

Wire.begin();

if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
{
Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
while (1);
}

myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
myGPS.setNavigationFrequency(2); //Produce two solutions per second
myGPS.setAutoPVT(true, false); //Tell the GPS to "send" each solution and the lib not to update stale data implicitly
myGPS.saveConfiguration(); //Save the current settings to flash and BBR
}

/*
Calling getPVT would return false now (compare to Example 13 where it would return true), so we just use the data provided
If you are using a threaded OS eg. FreeRTOS on an ESP32, the explicit mode of autoPVT allows you to use the data provided on both cores and inside multiple threads
The data update in background creates an inconsistent state, but that should not cause issues for most applications as they usually won't change the GPS location significantly within a 2Hz - 5Hz update rate.
Also you could oversample (10Hz - 20Hz) the data to smooth out such issues...
*/
void loop()
{
static uint16_t counter = 0;

if (counter % 10 == 0) {
// update your AHRS filter here for a ~100Hz update rate
// GPS data will be quasi static but data from your IMU will be changing
}
// debug output each half second
if (counter % 500 == 0) {
Serial.println();
long latitude = myGPS.getLatitude();
Serial.print(F("Lat: "));
Serial.print(latitude);

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

long altitude = myGPS.getAltitude();
Serial.print(F(" Alt: "));
Serial.print(altitude);
Serial.print(F(" (mm)"));

byte SIV = myGPS.getSIV();
Serial.print(F(" SIV: "));
Serial.print(SIV);

Serial.println();
}
// call checkUblox all 50ms to capture the gps data
if (counter % 50 == 0) {
myGPS.checkUblox();
}
delay(1);
counter++;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
Reading lat and long via UBX binary commands using an RX-only UART
By: Nathan Seidle, Adapted from Example11 by Felix Jirka
SparkFun Electronics
Date: July 2nd, 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 library for serial port use with a single wire connection using the assumeAutoPVT method.
Saving your pins for other stuff :-)

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

Preconditions:
U-Blox module is configured to send cyclical PVT message
Hardware Connections:
Connect the U-Blox serial TX pin to Rx of Serial2 (default: GPIO16) on your ESP32
Open the serial monitor at 115200 baud to see the output
*/

#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
SFE_UBLOX_GPS myGPS;

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

//Use any Serial port with at least a Rx Pin connected or a receive only version of SoftwareSerial here
//Assume that the U-Blox GPS is running at 9600 baud (the default)
Serial2.begin(9600);
// no need to check return value as internal call to isConnected() will not succeed
myGPS.begin(Serial2);

// tell lib, we are expecting the module to send PVT messages by itself to our Rx pin
// you can set second parameter to "false" if you want to control the parsing and eviction of the data (need to call checkUblox cyclically)
myGPS.assumeAutoPVT(true, true);

}

void loop()
{
// if implicit updates are allowed, this will trigger parsing the incoming messages
// and be true once a PVT message has been parsed
// In case you want to use explicit updates, wrap this in a timer and call checkUblox as often as needed, not to overflow your UART buffers
if (myGPS.getPVT())
{
long latitude = myGPS.getLatitude();
Serial.print(F("Lat: "));
Serial.print(latitude);

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

long altitude = myGPS.getAltitude();
Serial.print(F(" Alt: "));
Serial.print(altitude);
Serial.print(F(" (mm)"));

byte SIV = myGPS.getSIV();
Serial.print(F(" SIV: "));
Serial.print(SIV);

Serial.println();
}
else {
Serial.println(F("Wait for GPS data"));
delay(500);
}
}
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ debugPrintln KEYWORD2

factoryReset KEYWORD2
setAutoPVT KEYWORD2
assumeAutoPVT KEYWORD2

getYear KEYWORD2
getMonth KEYWORD2
Expand Down
31 changes: 30 additions & 1 deletion src/SparkFun_Ublox_Arduino_Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1308,9 +1308,29 @@ uint8_t SFE_UBLOX_GPS::getNavigationFrequency(uint16_t maxWait)
return (measurementRate);
}

//In case no config access to the GPS is possible and PVT is send cyclically already
//set config to suitable parameters
boolean SFE_UBLOX_GPS::assumeAutoPVT(boolean enabled, boolean implicitUpdate)
{
boolean changes = autoPVT != enabled || autoPVTImplicitUpdate != implicitUpdate;
if(changes)
{
autoPVT = enabled;
autoPVTImplicitUpdate = implicitUpdate;
}
return changes;
}

//Enable or disable automatic navigation message generation by the GPS. This changes the way getPVT
//works.
boolean SFE_UBLOX_GPS::setAutoPVT(boolean enable, uint16_t maxWait)
{
return setAutoPVT(enable, true, maxWait);
}

//Enable or disable automatic navigation message generation by the GPS. This changes the way getPVT
//works.
boolean SFE_UBLOX_GPS::setAutoPVT(boolean enable, boolean implicitUpdate, uint16_t maxWait)
{
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_MSG;
Expand All @@ -1322,7 +1342,10 @@ boolean SFE_UBLOX_GPS::setAutoPVT(boolean enable, uint16_t maxWait)

bool ok = sendCommand(packetCfg, maxWait);
if (ok)
{
autoPVT = enable;
autoPVTImplicitUpdate = implicitUpdate;
}
moduleQueried.all = false;
return ok;
}
Expand Down Expand Up @@ -1428,12 +1451,17 @@ int32_t SFE_UBLOX_GPS::getNanosecond(uint16_t maxWait)
//Get the latest Position/Velocity/Time solution and fill all global variables
boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait)
{
if (autoPVT)
if (autoPVT && autoPVTImplicitUpdate)
{
//The GPS is automatically reporting, we just check whether we got unread data
checkUblox();
return moduleQueried.all;
}
else if(autoPVT && !autoPVTImplicitUpdate)
{
//Someone else has to call checkUblox for us...
return (false);
}
else
{
//The GPS is not automatically reporting navigation position so we have to poll explicitly
Expand Down Expand Up @@ -1543,6 +1571,7 @@ uint32_t SFE_UBLOX_GPS::getPositionAccuracy(uint16_t maxWait)

return (tempAccuracy);
}

//Get the current latitude in degrees
//Returns a long representing the number of degrees *10^-7
int32_t SFE_UBLOX_GPS::getLatitude(uint16_t maxWait)
Expand Down
3 changes: 3 additions & 0 deletions src/SparkFun_Ublox_Arduino_Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,10 @@ class SFE_UBLOX_GPS

boolean waitForResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime = 250); //Poll the module until and ack is received

boolean assumeAutoPVT(boolean enabled, boolean implicitUpdate = true); //In case no config access to the GPS is possible and PVT is send cyclically already
boolean setAutoPVT(boolean enabled, uint16_t maxWait = 250); //Enable/disable automatic PVT reports at the navigation frequency
boolean getPVT(uint16_t maxWait = 1000); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Retruns true if new PVT is available.
boolean setAutoPVT(boolean enabled, boolean implicitUpdate, uint16_t maxWait = 250); //Enable/disable automatic PVT reports at the navigation frequency, with implicitUpdate == false accessing stale data will not issue parsing of data in the rxbuffer of your interface, instead you have to call checkUblox when you want to perform an update
boolean getHPPOSLLH(uint16_t maxWait = 1000); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc. If autoPVT is disabled, performs an explicit poll and waits, if enabled does not block. Retruns true if new PVT is available.

int32_t getLatitude(uint16_t maxWait = 250); //Returns the current latitude in degrees * 10^-7. Auto selects between HighPrecision and Regular depending on ability of module.
Expand Down Expand Up @@ -435,6 +437,7 @@ class SFE_UBLOX_GPS

unsigned long lastCheck = 0;
boolean autoPVT = false; //Whether autoPVT is enabled or not
boolean autoPVTImplicitUpdate = true; // Whether autoPVT is triggered by accessing stale data (=true) or by a call to checkUblox (=false)
boolean commandAck = false; //This goes true after we send a command and it's ack'd
uint8_t ubxFrameCounter;

Expand Down