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

Commit df7da25

Browse files
committed
Adding configuration save and factory reset functions.
1 parent e106c22 commit df7da25

File tree

3 files changed

+137
-9
lines changed

3 files changed

+137
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Reading lat and long via UBX binary commands - no more NMEA parsing!
3+
By: Nathan Seidle
4+
SparkFun Electronics
5+
Date: January 3rd, 2019
6+
License: MIT. See license file for more information but you can
7+
basically do whatever you want with this code.
8+
9+
This example shows how to reset a module to its factory defaults. This includes
10+
changing all the ports back to UBX+NMEA input/output and nav updates back to 1Hz.
11+
12+
Helpful if you just need to get back to a sane state.
13+
14+
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
15+
to something google maps understands simply divide the numbers by 10,000,000. We
16+
do this so that we don't have to use floating point numbers.
17+
18+
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
19+
20+
Feel like supporting open source hardware?
21+
Buy a board from SparkFun!
22+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
23+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
24+
SAM-M8Q: https://www.sparkfun.com/products/15106
25+
26+
Hardware Connections:
27+
Plug a Qwiic cable into the GPS and a BlackBoard
28+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
29+
Open the serial monitor at 115200 baud to see the output
30+
*/
31+
32+
#include <Wire.h> //Needed for I2C to GPS
33+
34+
#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
35+
SFE_UBLOX_GPS myGPS;
36+
37+
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to Ublox module.
38+
39+
void setup()
40+
{
41+
Serial.begin(115200);
42+
while (!Serial); //Wait for user to open terminal
43+
Serial.println("SparkFun Ublox Example");
44+
45+
Wire.begin();
46+
47+
if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
48+
{
49+
Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
50+
while (1);
51+
}
52+
53+
myGPS.factoryDefault(); //Return module to default settings (1Hz update, NMEA+UBX on all ports, etc)
54+
}
55+
56+
void loop()
57+
{
58+
59+
}

src/SparkFun_Ublox_Arduino_Library.cpp

+73-7
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C()
113113
}
114114

115115
if (bytesAvailable == 0)
116+
{
117+
Serial.println("No bytes available");
116118
lastCheck = millis(); //Put off checking to avoid I2C bus traffic
119+
}
117120

118121
while (bytesAvailable)
119122
{
@@ -221,9 +224,9 @@ void SFE_UBLOX_GPS::process(uint8_t incoming)
221224

222225
//Depending on this frame's class, pass different structs and payload arrays
223226
if (ubxFrameClass == CLASS_ACK)
224-
processUBX(incoming, &packetAck);
227+
processUBX(incoming, &packetAck);
225228
else if (ubxFrameClass == CLASS_NOT_AN_ACK)
226-
processUBX(incoming, &packetCfg);
229+
processUBX(incoming, &packetCfg);
227230
}
228231
else if (currentSentence == NMEA)
229232
{
@@ -311,7 +314,7 @@ void SFE_UBLOX_GPS::processRTCM(uint8_t incoming)
311314
//Set valid = true once sentence is completely received and passes CRC
312315
//The payload portion of the packet can be 100s of bytes but the max array
313316
//size is roughly 64 bytes. startingSpot can be set so we only record
314-
//interim bytes.
317+
//a subset of bytes within a larger packet.
315318
void SFE_UBLOX_GPS::processUBX(uint8_t incoming, ubxPacket *incomingUBX)
316319
{
317320
//Add all incoming bytes to the rolling checksum
@@ -470,7 +473,8 @@ boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
470473

471474
if (maxWait > 0)
472475
{
473-
if (waitForResponse(maxWait) == false) //Wait for Ack response
476+
//Give waitForResponse the cls/id to check for
477+
if (waitForResponse(outgoingUBX.cls, outgoingUBX.id, maxWait) == false) //Wait for Ack response
474478
return (false);
475479
}
476480
return (true);
@@ -549,18 +553,37 @@ void SFE_UBLOX_GPS::printPacket(ubxPacket *packet)
549553

550554

551555
//Poll the module until and ack is received
552-
boolean SFE_UBLOX_GPS::waitForResponse(uint16_t maxTime)
556+
boolean SFE_UBLOX_GPS::waitForResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime)
553557
{
554558
commandAck = false; //Reset flag
555559
packetCfg.valid = false; //This will go true when we receive a response to the packet we sent
556560

557-
long startTime = millis();
561+
unsigned long startTime = millis();
558562
while (millis() - startTime < maxTime)
559563
{
560564
checkUblox(); //See if new data is available. Process bytes as they come in.
561565

562566
if (commandAck == true) return (true); //If the packet we just sent was a CFG packet then we'll get an ACK
563-
if (packetCfg.valid == true) return (true); //If the packet we just sent was a NAV packet then we'll just get data back
567+
if (packetCfg.valid == true)
568+
{
569+
//Did we receive a config packet that matches the cls/id we requested?
570+
if(packetCfg.cls == requestedClass && packetCfg.id == requestedID)
571+
{
572+
#ifdef DEBUG
573+
debug.println(F("CLS/ID match!"));
574+
#endif
575+
return (true); //If the packet we just sent was a NAV packet then we'll just get data back
576+
}
577+
#ifdef DEBUG
578+
else
579+
{
580+
debug.print(F("Packet didn't match CLS/ID"));
581+
printPacket(&packetCfg);
582+
}
583+
#endif
584+
}
585+
586+
delay(1);
564587
}
565588

566589
#ifdef DEBUG
@@ -570,6 +593,49 @@ boolean SFE_UBLOX_GPS::waitForResponse(uint16_t maxTime)
570593
return (false);
571594
}
572595

596+
//Save current configuration to flash and BBR (battery backed RAM)
597+
//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods
598+
boolean SFE_UBLOX_GPS::saveConfiguration(uint16_t maxWait)
599+
{
600+
packetCfg.cls = UBX_CLASS_CFG;
601+
packetCfg.id = UBX_CFG_CFG;
602+
packetCfg.len = 12;
603+
packetCfg.startingSpot = 0;
604+
605+
//Clear packet payload
606+
for(uint8_t x = 0 ; x < packetCfg.len ; x++)
607+
packetCfg.payload[x] = 0;
608+
609+
packetCfg.payload[4] = 0xFF; //Set any bit in the saveMask field to save current config to Flash and BBR
610+
611+
if(sendCommand(packetCfg, maxWait) == false)
612+
return(false); //If command send fails then bail
613+
614+
return(true);
615+
}
616+
617+
//Reset module to factory defaults
618+
//This still works but it is the old way of configuring ublox modules. See getVal and setVal for the new methods
619+
boolean SFE_UBLOX_GPS::factoryDefault(uint16_t maxWait)
620+
{
621+
packetCfg.cls = UBX_CLASS_CFG;
622+
packetCfg.id = UBX_CFG_CFG;
623+
packetCfg.len = 12;
624+
packetCfg.startingSpot = 0;
625+
626+
//Clear packet payload
627+
for(uint8_t x = 0 ; x < packetCfg.len ; x++)
628+
packetCfg.payload[x] = 0;
629+
630+
packetCfg.payload[0] = 0xFF; //Set any bit in the clearMask field to clear saved config
631+
packetCfg.payload[8] = 0xFF; //Set any bit in the loadMask field to discard current config and rebuild from lower non-volatile memory layers
632+
633+
if(sendCommand(packetCfg, maxWait) == false)
634+
return(false); //If command send fails then bail
635+
636+
return(true);
637+
}
638+
573639
//Given a key, return its value
574640
//This is how the new Ublox modules are communicating, ie protocol v27 and above found on ZED-F9P
575641
uint8_t SFE_UBLOX_GPS::getVal(uint16_t group, uint16_t id, uint8_t size, uint8_t layer, uint16_t maxWait)

src/SparkFun_Ublox_Arduino_Library.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ const uint8_t UBX_CLASS_HNR = 0x28;
9494

9595
const uint8_t UBX_CFG_PRT = 0x00; //Used to configure port specifics
9696
const uint8_t UBX_CFG_RATE = 0x08; //Used to set port baud rates
97+
const uint8_t UBX_CFG_CFG = 0x09; //Used to save current configuration
9798
const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version Ublox modules (ie protocol v27 and above)
9899
const uint8_t UBX_CFG_VALGET = 0x8B; //Used for config of higher version Ublox modules (ie protocol v27 and above)
99100
const uint8_t UBX_CFG_VALDEL = 0x8C; //Used for config of higher version Ublox modules (ie protocol v27 and above)
@@ -189,7 +190,7 @@ class SFE_UBLOX_GPS
189190
void processRTCM(uint8_t incoming) __attribute__((weak)); //Given rtcm byte, do something with it. User can overwrite if desired to pipe bytes to radio, internet, etc.
190191

191192
void processUBXpacket(ubxPacket *msg); //Once a packet has been received and validated, identify this packet's class/id and update internal flags
192-
void processNMEA(char incoming) __attribute__((weak)); //Given a nmea character, do something with it. User can overwrite if desired to use something like tinyGPS or MicroNMEA libraries
193+
void processNMEA(char incoming) __attribute__((weak)); //Given a NMEA character, do something with it. User can overwrite if desired to use something like tinyGPS or MicroNMEA libraries
193194

194195
void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages
195196
boolean sendCommand(ubxPacket outgoingUBX, uint16_t maxWait = 250); //Given a packet and payload, send everything including CRC bytes
@@ -201,8 +202,10 @@ class SFE_UBLOX_GPS
201202

202203
boolean setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = 250); //Set the number of nav solutions sent per second
203204
uint8_t getNavigationFrequency(uint16_t maxWait = 250); //Get the number of nav solutions sent per second currently being output by module
205+
boolean saveConfiguration(uint16_t maxWait = 250); //Save current configuration to flash and BBR (battery backed RAM)
206+
boolean factoryDefault(uint16_t maxWait = 250); //Reset module to factory defaults
204207

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

207210
boolean getPVT(uint16_t maxWait = 1000); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc.
208211
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.

0 commit comments

Comments
 (0)