diff --git a/README.md b/README.md
index e809c2b..d4523ce 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,14 @@ SparkFun Ublox Arduino Library
 |
 |
 |
+  |
SparkFun GPS-RTK2 - ZED-F9P (GPS-15136) |
SparkFun GPS-RTK - NEO-M8P-2 (GPS-15005) |
SparkFun ZOE-M8Q Breakout (GPS-15193) |
SparkFun SAM-M8Q Breakout (GPS-15210) |
+ SparkFun NEO-M9N Breakout (GPS-15733) |
@@ -30,7 +32,7 @@ Thanks to:
* [tve](https://github.com/tve) for building out serial additions and examples
* [Redstoned](https://github.com/Redstoned) and [davidallenmann](https://github.com/davidallenmann) for adding PVT date and time
* [wittend](https://forum.sparkfun.com/viewtopic.php?t=49874) for pointing out the RTCM print bug
-* Big thanks to [PaulZC](https://github.com/PaulZC) for implementing the combined key ValSet method
+* Big thanks to [PaulZC](https://github.com/PaulZC) for implementing the combined key ValSet method and geofence functions
* [RollieRowland](https://github.com/RollieRowland) for adding HPPOSLLH (High Precision Geodetic Position)
* [tedder](https://github.com/tedder) for moving iTOW to PVT instead of HPPOS and comment cleanup
@@ -89,6 +91,8 @@ Products That Use This Library
* [GPS-15005](https://www.sparkfun.com/products/15005) - SparkFun GPS-RTK NEO-M8P-2
* [GPS-15210](https://www.sparkfun.com/products/15210) - SparkFun GPS Breakout - Chip Antenna, SAM-M8Q (Qwiic)
* [GPS-15193](https://www.sparkfun.com/products/15193) - SparkFun GPS Breakout - Chip Antenna, ZOE-M8Q (Qwiic)
+* [GPS-15733](https://www.sparkfun.com/products/15733) - SparkFun GPS Breakout - NEO-M9N, Chip Antenna (Qwiic)
+* [GPS-15712](https://www.sparkfun.com/products/15712) - SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic)
* [SPX-14980](https://www.sparkfun.com/products/14980) - SparkX GPS-RTK Black
* [SPX-15106](https://www.sparkfun.com/products/15106) - SparkX SAM-M8Q
diff --git a/examples/Example19_DynamicModel/Example19_DynamicModel.ino b/examples/Example19_DynamicModel/Example19_DynamicModel.ino
new file mode 100644
index 0000000..38dd9df
--- /dev/null
+++ b/examples/Example19_DynamicModel/Example19_DynamicModel.ino
@@ -0,0 +1,102 @@
+/*
+ Set Dynamic Model
+ By: Paul Clark (PaulZC)
+ Date: December 18th, 2019
+
+ Based extensively on Example3_GetPosition
+ 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 change the Ublox module's dynamic platform model and then
+ query its lat/long/altitude. We also turn off the NMEA output on the I2C port.
+ This decreases the amount of I2C traffic dramatically.
+
+ Possible values for the dynamic model are: PORTABLE, STATIONARY, PEDESTRIAN, AUTOMOTIVE,
+ SEA, AIRBORNE1g, AIRBORNE2g, AIRBORNE4g, WRIST, BIKE
+
+ 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 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 //Needed for I2C to GPS
+
+#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
+SFE_UBLOX_GPS myGPS;
+
+long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to Ublox module.
+
+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.enableDebugging(); // Uncomment this line to enable debug messages
+
+ // If we are going to change the dynamic platform model, let's do it here.
+ // Possible values are:
+ // PORTABLE, STATIONARY, PEDESTRIAN, AUTOMOTIVE, SEA, AIRBORNE1g, AIRBORNE2g, AIRBORNE4g, WRIST, BIKE
+
+ if (!myGPS.setDynamicModel(myGPS.PORTABLE)) // Set the dynamic model to PORTABLE
+ {
+ Serial.println("***!!! Warning: setDynamicModel failed !!!***");
+ }
+ else
+ {
+ Serial.println("Dynamic platform model changed successfully!");
+ }
+
+ myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
+ //myGPS.saveConfiguration(); //Uncomment this line to save the current 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 = 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)"));
+
+ Serial.println();
+ }
+}
diff --git a/examples/Example20_PowerSaveMode/Example20_PowerSaveMode.ino b/examples/Example20_PowerSaveMode/Example20_PowerSaveMode.ino
new file mode 100644
index 0000000..789e65c
--- /dev/null
+++ b/examples/Example20_PowerSaveMode/Example20_PowerSaveMode.ino
@@ -0,0 +1,120 @@
+/*
+ Power Save Mode
+ By: Paul Clark (PaulZC)
+ Date: December 18th, 2019
+
+ Based extensively on Example3_GetPosition
+ 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 put the Ublox module into power save mode and then
+ query its lat/long/altitude. We also turn off the NMEA output on the I2C port.
+ This decreases the amount of I2C traffic dramatically.
+
+ ** When it is able to ** the module will reduce its current draw.
+ For the ZOE-M8Q with a passive antenna, you should see the current drop
+ from (approx.) 25-28mA to (approx.) 9mA when power save mode kicks in.
+
+ 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 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 //Needed for I2C to GPS
+
+#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
+SFE_UBLOX_GPS myGPS;
+
+long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to Ublox module.
+
+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.enableDebugging(); // Uncomment this line to enable debug messages
+
+ Serial.println(F("Waiting for a 3D fix..."));
+
+ byte fixType = 0;
+
+ while (fixType != 3) // Wait for a 3D fix
+ {
+ fixType = myGPS.getFixType(); // Get the fix type
+ Serial.print(F("Fix: "));
+ Serial.print(fixType);
+ if(fixType == 0) Serial.print(F(" = No fix"));
+ else if(fixType == 1) Serial.print(F(" = Dead reckoning"));
+ else if(fixType == 2) Serial.print(F(" = 2D"));
+ else if(fixType == 3) Serial.print(F(" = 3D"));
+ else if(fixType == 4) Serial.print(F(" = GNSS + Dead reckoning"));
+ Serial.println();
+ delay(1000);
+ }
+
+ Serial.println(F("3D fix found! Engaging power save mode..."));
+
+ // Put the GNSS into power save mode
+ // (If you want to disable power save mode, call myGPS.powerSaveMode(false) instead)
+ if (myGPS.powerSaveMode())
+ {
+ Serial.println(F("Power Save Mode enabled."));
+ }
+ else
+ {
+ Serial.println(F("***!!! Power Save Mode FAILED !!!***"));
+ }
+
+ myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
+ //myGPS.saveConfiguration(); //Uncomment this line to save the current settings to flash and BBR
+}
+
+void loop()
+{
+ //Query module every 10 seconds so it is easier to monitor the current draw
+ if (millis() - lastTime > 10000)
+ {
+ lastTime = millis(); //Update the timer
+
+ 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)"));
+
+ Serial.println();
+ }
+}
diff --git a/keywords.txt b/keywords.txt
index e1c7046..b7620a0 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -121,6 +121,14 @@ getGeoidSeparation KEYWORD2
getHorizontalAccuracy KEYWORD2
getVerticalAccuracy KEYWORD2
+addGeofence KEYWORD2
+clearGeofences KEYWORD2
+getGeofenceState KEYWORD2
+
+setDynamicModel KEYWORD2
+
+powerSaveMode KEYWORD2
+
#######################################
# Constants (LITERAL1)
#######################################
diff --git a/src/SparkFun_Ublox_Arduino_Library.cpp b/src/SparkFun_Ublox_Arduino_Library.cpp
index ac0ca06..14d2147 100644
--- a/src/SparkFun_Ublox_Arduino_Library.cpp
+++ b/src/SparkFun_Ublox_Arduino_Library.cpp
@@ -41,6 +41,7 @@
SFE_UBLOX_GPS::SFE_UBLOX_GPS(void)
{
// Constructor
+ currentGeofenceParams.numFences = 0; // Zero the number of geofences currently in use
}
//Initialize the Serial port
@@ -1638,6 +1639,210 @@ boolean SFE_UBLOX_GPS::setAutoPVT(boolean enable, boolean implicitUpdate, uint16
return ok;
}
+//Add a new geofence using UBX-CFG-GEOFENCE
+boolean SFE_UBLOX_GPS::addGeofence(int32_t latitude, int32_t longitude, uint32_t radius, byte confidence, byte pinPolarity, byte pin, uint16_t maxWait)
+{
+ if (currentGeofenceParams.numFences >= 4) return(false); // Quit if we already have four geofences defined
+
+ // Store the new geofence parameters
+ currentGeofenceParams.lats[currentGeofenceParams.numFences] = latitude;
+ currentGeofenceParams.longs[currentGeofenceParams.numFences] = longitude;
+ currentGeofenceParams.rads[currentGeofenceParams.numFences] = radius;
+ currentGeofenceParams.numFences = currentGeofenceParams.numFences + 1; // Increment the number of fences
+
+ packetCfg.cls = UBX_CLASS_CFG;
+ packetCfg.id = UBX_CFG_GEOFENCE;
+ packetCfg.len = (currentGeofenceParams.numFences * 12) + 8;
+ packetCfg.startingSpot = 0;
+
+ payloadCfg[0] = 0; // Message version = 0x00
+ payloadCfg[1] = currentGeofenceParams.numFences; // numFences
+ payloadCfg[2] = confidence; // confLvl = Confidence level 0-4 (none, 68%, 95%, 99.7%, 99.99%)
+ payloadCfg[3] = 0; // reserved1
+ if (pin > 0)
+ {
+ payloadCfg[4] = 1; // enable PIO combined fence state
+ }
+ else
+ {
+ payloadCfg[4] = 0; // disable PIO combined fence state
+ }
+ payloadCfg[5] = pinPolarity; // PIO pin polarity (0 = low means inside, 1 = low means outside (or unknown))
+ payloadCfg[6] = pin; // PIO pin
+ payloadCfg[7] = 0; //reserved2
+ payloadCfg[8] = currentGeofenceParams.lats[0] & 0xFF;
+ payloadCfg[9] = currentGeofenceParams.lats[0] >> 8;
+ payloadCfg[10] = currentGeofenceParams.lats[0] >> 16;
+ payloadCfg[11] = currentGeofenceParams.lats[0] >> 24;
+ payloadCfg[12] = currentGeofenceParams.longs[0] & 0xFF;
+ payloadCfg[13] = currentGeofenceParams.longs[0] >> 8;
+ payloadCfg[14] = currentGeofenceParams.longs[0] >> 16;
+ payloadCfg[15] = currentGeofenceParams.longs[0] >> 24;
+ payloadCfg[16] = currentGeofenceParams.rads[0] & 0xFF;
+ payloadCfg[17] = currentGeofenceParams.rads[0] >> 8;
+ payloadCfg[18] = currentGeofenceParams.rads[0] >> 16;
+ payloadCfg[19] = currentGeofenceParams.rads[0] >> 24;
+ if (currentGeofenceParams.numFences >= 2) {
+ payloadCfg[20] = currentGeofenceParams.lats[1] & 0xFF;
+ payloadCfg[21] = currentGeofenceParams.lats[1] >> 8;
+ payloadCfg[22] = currentGeofenceParams.lats[1] >> 16;
+ payloadCfg[23] = currentGeofenceParams.lats[1] >> 24;
+ payloadCfg[24] = currentGeofenceParams.longs[1] & 0xFF;
+ payloadCfg[25] = currentGeofenceParams.longs[1] >> 8;
+ payloadCfg[26] = currentGeofenceParams.longs[1] >> 16;
+ payloadCfg[27] = currentGeofenceParams.longs[1] >> 24;
+ payloadCfg[28] = currentGeofenceParams.rads[1] & 0xFF;
+ payloadCfg[29] = currentGeofenceParams.rads[1] >> 8;
+ payloadCfg[30] = currentGeofenceParams.rads[1] >> 16;
+ payloadCfg[31] = currentGeofenceParams.rads[1] >> 24;
+ }
+ if (currentGeofenceParams.numFences >= 3) {
+ payloadCfg[32] = currentGeofenceParams.lats[2] & 0xFF;
+ payloadCfg[33] = currentGeofenceParams.lats[2] >> 8;
+ payloadCfg[34] = currentGeofenceParams.lats[2] >> 16;
+ payloadCfg[35] = currentGeofenceParams.lats[2] >> 24;
+ payloadCfg[36] = currentGeofenceParams.longs[2] & 0xFF;
+ payloadCfg[37] = currentGeofenceParams.longs[2] >> 8;
+ payloadCfg[38] = currentGeofenceParams.longs[2] >> 16;
+ payloadCfg[39] = currentGeofenceParams.longs[2] >> 24;
+ payloadCfg[40] = currentGeofenceParams.rads[2] & 0xFF;
+ payloadCfg[41] = currentGeofenceParams.rads[2] >> 8;
+ payloadCfg[42] = currentGeofenceParams.rads[2] >> 16;
+ payloadCfg[43] = currentGeofenceParams.rads[2] >> 24;
+ }
+ if (currentGeofenceParams.numFences >= 4) {
+ payloadCfg[44] = currentGeofenceParams.lats[3] & 0xFF;
+ payloadCfg[45] = currentGeofenceParams.lats[3] >> 8;
+ payloadCfg[46] = currentGeofenceParams.lats[3] >> 16;
+ payloadCfg[47] = currentGeofenceParams.lats[3] >> 24;
+ payloadCfg[48] = currentGeofenceParams.longs[3] & 0xFF;
+ payloadCfg[49] = currentGeofenceParams.longs[3] >> 8;
+ payloadCfg[50] = currentGeofenceParams.longs[3] >> 16;
+ payloadCfg[51] = currentGeofenceParams.longs[3] >> 24;
+ payloadCfg[52] = currentGeofenceParams.rads[3] & 0xFF;
+ payloadCfg[53] = currentGeofenceParams.rads[3] >> 8;
+ payloadCfg[54] = currentGeofenceParams.rads[3] >> 16;
+ payloadCfg[55] = currentGeofenceParams.rads[3] >> 24;
+ }
+ return (sendCommand(packetCfg, maxWait)); //Wait for ack
+}
+
+//Clear all geofences using UBX-CFG-GEOFENCE
+boolean SFE_UBLOX_GPS::clearGeofences(uint16_t maxWait)
+{
+ packetCfg.cls = UBX_CLASS_CFG;
+ packetCfg.id = UBX_CFG_GEOFENCE;
+ packetCfg.len = 8;
+ packetCfg.startingSpot = 0;
+
+ payloadCfg[0] = 0; // Message version = 0x00
+ payloadCfg[1] = 0; // numFences
+ payloadCfg[2] = 0; // confLvl
+ payloadCfg[3] = 0; // reserved1
+ payloadCfg[4] = 0; // disable PIO combined fence state
+ payloadCfg[5] = 0; // PIO pin polarity (0 = low means inside, 1 = low means outside (or unknown))
+ payloadCfg[6] = 0; // PIO pin
+ payloadCfg[7] = 0; //reserved2
+
+ currentGeofenceParams.numFences = 0; // Zero the number of geofences currently in use
+
+ return (sendCommand(packetCfg, maxWait)); //Wait for ack
+}
+
+//Clear the antenna control settings using UBX-CFG-ANT
+//This function is hopefully redundant but may be needed to release
+//any PIO pins pre-allocated for antenna functions
+boolean SFE_UBLOX_GPS::clearAntPIO(uint16_t maxWait)
+{
+ packetCfg.cls = UBX_CLASS_CFG;
+ packetCfg.id = UBX_CFG_ANT;
+ packetCfg.len = 4;
+ packetCfg.startingSpot = 0;
+
+ payloadCfg[0] = 0x10; // Antenna flag mask: set the recovery bit
+ payloadCfg[1] = 0;
+ payloadCfg[2] = 0xFF; // Antenna pin configuration: set pinSwitch and pinSCD to 31
+ payloadCfg[3] = 0xFF; // Antenna pin configuration: set pinOCD to 31, set reconfig bit
+
+ return (sendCommand(packetCfg, maxWait)); //Wait for ack
+}
+
+//Returns the combined geofence state using UBX-NAV-GEOFENCE
+boolean SFE_UBLOX_GPS::getGeofenceState(geofenceState ¤tGeofenceState, uint16_t maxWait)
+{
+ packetCfg.cls = UBX_CLASS_NAV;
+ packetCfg.id = UBX_NAV_GEOFENCE;
+ packetCfg.len = 0;
+ packetCfg.startingSpot = 0;
+
+ if (sendCommand(packetCfg, maxWait) == false) //Ask module for the geofence status. Loads into payloadCfg.
+ return (false);
+
+ currentGeofenceState.status = payloadCfg[5]; // Extract the status
+ currentGeofenceState.numFences = payloadCfg[6]; // Extract the number of geofences
+ currentGeofenceState.combState = payloadCfg[7]; // Extract the combined state of all geofences
+ if (currentGeofenceState.numFences > 0) currentGeofenceState.states[0] = payloadCfg[8]; // Extract geofence 1 state
+ if (currentGeofenceState.numFences > 1) currentGeofenceState.states[1] = payloadCfg[10]; // Extract geofence 2 state
+ if (currentGeofenceState.numFences > 2) currentGeofenceState.states[2] = payloadCfg[12]; // Extract geofence 3 state
+ if (currentGeofenceState.numFences > 3) currentGeofenceState.states[3] = payloadCfg[14]; // Extract geofence 4 state
+
+ return(true);
+}
+
+//Changes the dynamic platform model using UBX-CFG-NAV5
+//Possible values are:
+//PORTABLE,STATIONARY,PEDESTRIAN,AUTOMOTIVE,SEA,
+//AIRBORNE1g,AIRBORNE2g,AIRBORNE4g,WRIST,BIKE
+//WRIST is not supported in protocol versions less than 18
+//BIKE is supported in protocol versions 19.2
+
+boolean SFE_UBLOX_GPS::setDynamicModel(uint8_t newDynamicModel, uint16_t maxWait)
+{
+ packetCfg.cls = UBX_CLASS_CFG;
+ packetCfg.id = UBX_CFG_NAV5;
+ packetCfg.len = 0;
+ packetCfg.startingSpot = 0;
+
+ if (sendCommand(packetCfg, maxWait) == false) //Ask module for the current navigation model settings. Loads into payloadCfg.
+ return (false);
+
+ payloadCfg[0] = 0x01; // mask: set only the dyn bit (0)
+ payloadCfg[1] = 0x00; // mask
+ payloadCfg[2] = newDynamicModel; // dynModel
+
+ packetCfg.len = 36;
+ packetCfg.startingSpot = 0;
+
+ return (sendCommand(packetCfg, maxWait)); //Wait for ack
+}
+
+//Power Save Mode
+//Enables/Disables Low Power Mode using UBX-CFG-RXM
+boolean SFE_UBLOX_GPS::powerSaveMode(bool power_save, uint16_t maxWait)
+{
+ packetCfg.cls = UBX_CLASS_CFG;
+ packetCfg.id = UBX_CFG_RXM;
+ packetCfg.len = 0;
+ packetCfg.startingSpot = 0;
+
+ if (sendCommand(packetCfg, maxWait) == false) //Ask module for the current power management settings. Loads into payloadCfg.
+ return (false);
+
+ if (power_save)
+ {
+ payloadCfg[1] = 1; // Power Save Mode
+ }
+ else
+ {
+ payloadCfg[1] = 0; // Continuous Mode
+ }
+
+ packetCfg.len = 2;
+ packetCfg.startingSpot = 0;
+
+ return (sendCommand(packetCfg, maxWait)); //Wait for ack
+}
+
//Given a spot in the payload array, extract four bytes and build a long
uint32_t SFE_UBLOX_GPS::extractLong(uint8_t spotToStart)
{
diff --git a/src/SparkFun_Ublox_Arduino_Library.h b/src/SparkFun_Ublox_Arduino_Library.h
index 2c2292b..bdd342a 100644
--- a/src/SparkFun_Ublox_Arduino_Library.h
+++ b/src/SparkFun_Ublox_Arduino_Library.h
@@ -99,10 +99,17 @@ const uint8_t UBX_CFG_PRT = 0x00; //Used to configure port specifics
const uint8_t UBX_CFG_RST = 0x04; //Used to reset device
const uint8_t UBX_CFG_RATE = 0x08; //Used to set port baud rates
const uint8_t UBX_CFG_CFG = 0x09; //Used to save current configuration
+const uint8_t UBX_CFG_RXM = 0x11; //Used to set receiver power management (power save mode)
const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version Ublox modules (ie protocol v27 and above)
const uint8_t UBX_CFG_VALGET = 0x8B; //Used for config of higher version Ublox modules (ie protocol v27 and above)
const uint8_t UBX_CFG_VALDEL = 0x8C; //Used for config of higher version Ublox modules (ie protocol v27 and above)
+const uint8_t UBX_CFG_GEOFENCE = 0x69; //Used to configure a geofence
+const uint8_t UBX_CFG_ANT = 0x13; //Used to configure the antenna control settings
+const uint8_t UBX_NAV_GEOFENCE = 0x39; //Used to poll the geofence status
+
+const uint8_t UBX_CFG_NAV5 = 0x24; //Used to configure the navigation engine including the dynamic model
+
const uint8_t UBX_CFG_TMODE3 = 0x71; //Used to enable Survey In Mode
const uint8_t SVIN_MODE_DISABLE = 0x00;
const uint8_t SVIN_MODE_ENABLE = 0x01;
@@ -189,6 +196,22 @@ typedef struct
boolean valid; //Goes true when both checksums pass
} ubxPacket;
+// Struct to hold the results returned by getGeofenceState (returned by UBX-NAV-GEOFENCE)
+typedef struct {
+ uint8_t status; // Geofencing status: 0 - Geofencing not available or not reliable; 1 - Geofencing active
+ uint8_t numFences; // Number of geofences
+ uint8_t combState; // Combined (logical OR) state of all geofences: 0 - Unknown; 1 - Inside; 2 - Outside
+ uint8_t states[4]; // Geofence states: 0 - Unknown; 1 - Inside; 2 - Outside
+} geofenceState;
+
+// Struct to hold the current geofence parameters
+typedef struct {
+ uint8_t numFences; // Number of active geofences
+ int32_t lats[4]; // Latitudes of geofences (in degrees * 10^-7)
+ int32_t longs[4]; // Longitudes of geofences (in degrees * 10^-7)
+ uint32_t rads[4]; // Radii of geofences (in m * 10^-2)
+} geofenceParams;
+
class SFE_UBLOX_GPS
{
public:
@@ -319,6 +342,17 @@ class SFE_UBLOX_GPS
void debugPrint(char *message); //Safely print debug statements
void debugPrintln(char *message); //Safely print debug statements
+ //Support for geofences
+ boolean addGeofence(int32_t latitude, int32_t longitude, uint32_t radius, byte confidence = 0, byte pinPolarity = 0, byte pin = 0, uint16_t maxWait = 2000); // Add a new geofence
+ boolean clearGeofences(uint16_t maxWait = 2000); //Clears all geofences
+ boolean getGeofenceState(geofenceState ¤tGeofenceState, uint16_t maxWait = 2000); //Returns the combined geofence state
+
+ //Change the dynamic platform model using UBX-CFG-NAV5
+ boolean setDynamicModel(uint8_t newDynamicModel = PEDESTRIAN, uint16_t maxWait = 2000);
+
+ //Power Save Mode
+ boolean powerSaveMode(bool power_save = true, uint16_t maxWait = 2000);
+
//Survey-in specific controls
struct svinStructure
{
@@ -392,6 +426,21 @@ class SFE_UBLOX_GPS
uint16_t rtcmFrameCounter = 0; //Tracks the type of incoming byte inside RTCM frame
+ enum dynModel // Possible values for the dynamic platform model
+ {
+ PORTABLE = 0,
+ // 1 is not defined
+ STATIONARY = 2,
+ PEDESTRIAN,
+ AUTOMOTIVE,
+ SEA,
+ AIRBORNE1g,
+ AIRBORNE2g,
+ AIRBORNE4g,
+ WRIST, // Not supported in protocol versions less than 18
+ BIKE // Supported in protocol versions 19.2
+ };
+
private:
//Depending on the sentence type the processor will load characters into different arrays
enum SentenceTypes
@@ -499,6 +548,10 @@ class SFE_UBLOX_GPS
} highResModuleQueried;
uint16_t rtcmLen = 0;
+
+ //Support for geofences
+ boolean clearAntPIO(uint16_t maxWait = 2000); //Clears the antenna control pin settings to release the PIOs
+ geofenceParams currentGeofenceParams; // Global to store the geofence parameters
};
#endif