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

Commit 185b7a6

Browse files
committed
Add support for serial protocol, plus factory reset command
1 parent 77130a9 commit 185b7a6

File tree

3 files changed

+233
-25
lines changed

3 files changed

+233
-25
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
Reading lat and long via UBX binary commands using UART @38400 baud - free from I2C
3+
By: Nathan Seidle, Adapted from Example3_GetPosition by Thorsten von Eicken
4+
SparkFun Electronics
5+
Date: January 28rd, 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 configure the library and U-Blox for serial port use as well as
10+
switching the module from the default 9600 baud to 38400.
11+
12+
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
13+
to something google maps understands simply divide the numbers by 10,000,000. We
14+
do this so that we don't have to use floating point numbers.
15+
16+
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
17+
18+
Feel like supporting open source hardware?
19+
Buy a board from SparkFun!
20+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
21+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
22+
SAM-M8Q: https://www.sparkfun.com/products/15106
23+
24+
Hardware Connections:
25+
Connect the U-Blox serial port to Serial1
26+
Open the serial monitor at 115200 baud to see the output
27+
*/
28+
29+
#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
30+
SFE_UBLOX_GPS myGPS;
31+
32+
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to Ublox module.
33+
34+
void setup()
35+
{
36+
Serial.begin(115200);
37+
while (!Serial); //Wait for user to open terminal
38+
Serial.println("SparkFun Ublox Example");
39+
40+
//Assume that the U-Blox GPS is running at 9600 baud (the default) or at 38400 baud.
41+
//Loop until we're in sync and then ensure it's at 38400 baud.
42+
do {
43+
Serial.println("GPS: trying 38400 baud");
44+
Serial1.begin(38400);
45+
if (myGPS.begin(Serial1)) break;
46+
47+
delay(100);
48+
Serial.println("GPS: trying 9600 baud");
49+
Serial1.begin(9600);
50+
if (myGPS.begin(Serial1)) {
51+
Serial.println("GPS: connected at 9600 baud, switching to 38400");
52+
myGPS.setSerialRate(38400);
53+
delay(100);
54+
} else {
55+
//gps.factoryReset();
56+
delay(2000); //Wait a bit before trying again to limit the Serial output
57+
}
58+
} while(1);
59+
Serial.println("GPS serial connected");
60+
61+
myGPS.setUART1Output(COM_TYPE_UBX); //Set the UART port to output UBX only
62+
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
63+
myGPS.saveConfiguration(); //Save the current settings to flash and BBR
64+
}
65+
66+
void loop()
67+
{
68+
//Query module only every second. Doing it more often will just cause I2C traffic.
69+
//The module only responds when a new position is available
70+
if (millis() - lastTime > 1000)
71+
{
72+
lastTime = millis(); //Update the timer
73+
74+
long latitude = myGPS.getLatitude();
75+
Serial.print(F("Lat: "));
76+
Serial.print(latitude);
77+
78+
long longitude = myGPS.getLongitude();
79+
Serial.print(F(" Long: "));
80+
Serial.print(longitude);
81+
Serial.print(F(" (degrees * 10^-7)"));
82+
83+
long altitude = myGPS.getAltitude();
84+
Serial.print(F(" Alt: "));
85+
Serial.print(altitude);
86+
Serial.print(F(" (mm)"));
87+
88+
byte SIV = myGPS.getSIV();
89+
Serial.print(F(" SIV: "));
90+
Serial.print(SIV);
91+
92+
Serial.println();
93+
}
94+
}

src/SparkFun_Ublox_Arduino_Library.cpp

Lines changed: 130 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,70 @@ boolean SFE_UBLOX_GPS::begin(TwoWire &wirePort, uint8_t deviceAddress)
4848
//_i2cPort->begin();
4949

5050
_gpsI2Caddress = deviceAddress; //Store the I2C address from user
51-
51+
52+
return(isConnected());
53+
}
54+
55+
//Initialize the Serial port
56+
boolean SFE_UBLOX_GPS::begin(Stream &serialPort)
57+
{
58+
commType = COMM_TYPE_SERIAL;
59+
_serialPort = &serialPort; //Grab which port the user wants us to use
60+
5261
return(isConnected());
5362
}
5463

64+
void SFE_UBLOX_GPS::factoryReset() {
65+
// Copy default settings to permanent
66+
packetCfg.cls = UBX_CLASS_CFG;
67+
packetCfg.id = UBX_CFG_CFG;
68+
packetCfg.len = 13;
69+
packetCfg.startingSpot = 0;
70+
for (int i=0; i<4; i++) {
71+
payloadCfg[0+i] = 0xff; // clear mask: copy default config to permanent config
72+
payloadCfg[4+i] = 0x00; // save mask: don't save current to permanent
73+
payloadCfg[8+i] = 0x00; // load mask: don't copy permanent config to current
74+
}
75+
payloadCfg[12] = 0xff; // all forms of permanent memory
76+
sendCommand(packetCfg, 0); // don't expect ACK
77+
78+
// Issue hard reset
79+
packetCfg.cls = UBX_CLASS_CFG;
80+
packetCfg.id = UBX_CFG_RST;
81+
packetCfg.len = 4;
82+
packetCfg.startingSpot = 0;
83+
payloadCfg[0] = 0xff; // cold start
84+
payloadCfg[1] = 0xff; // cold start
85+
payloadCfg[2] = 0; // 0=HW reset
86+
payloadCfg[3] = 0; // reserved
87+
sendCommand(packetCfg, 0); // don't expect ACK
88+
}
89+
90+
//Changes the serial baud rate of the Ublox module, can't return success/fail 'cause ACK from modem
91+
//is lost due to baud rate change
92+
void SFE_UBLOX_GPS::setSerialRate(uint32_t baudrate, uint16_t maxWait) {
93+
//Get the current config values for the UART port
94+
getPortSettings(COM_PORT_UART1, maxWait); //This will load the payloadCfg array with current port settings
95+
Serial.printf("Current baud rate: %d\n",
96+
((uint32_t)payloadCfg[10]<<16) | ((uint32_t)payloadCfg[9]<<8) | payloadCfg[8]);
97+
98+
packetCfg.cls = UBX_CLASS_CFG;
99+
packetCfg.id = UBX_CFG_PRT;
100+
packetCfg.len = 20;
101+
packetCfg.startingSpot = 0;
102+
103+
//payloadCfg is now loaded with current bytes. Change only the ones we need to
104+
payloadCfg[8] = baudrate;
105+
payloadCfg[9] = baudrate>>8;
106+
payloadCfg[10] = baudrate>>16;
107+
payloadCfg[11] = baudrate>>24;
108+
Serial.printf("Next baud rate: %d=0x%x\n",
109+
((uint32_t)payloadCfg[10]<<16) | ((uint32_t)payloadCfg[9]<<8) | payloadCfg[8],
110+
((uint32_t)payloadCfg[10]<<16) | ((uint32_t)payloadCfg[9]<<8) | payloadCfg[8]);
111+
112+
sendCommand(packetCfg);
113+
}
114+
55115
//Changes the I2C address that the Ublox module responds to
56116
//0x42 is the default but can be changed with this command
57117
boolean SFE_UBLOX_GPS::setI2CAddress(uint8_t deviceAddress, uint16_t maxWait)
@@ -89,6 +149,7 @@ boolean SFE_UBLOX_GPS::checkUblox()
89149
checkUbloxI2C();
90150
else if(commType == COMM_TYPE_SERIAL)
91151
checkUbloxSerial();
152+
return false;
92153
}
93154

94155
//Polls I2C for data, passing any new bytes to process()
@@ -150,12 +211,14 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C()
150211

151212
} //end checkUbloxI2C()
152213

153-
//Polls Serial for data, passing any new bytes to process()
154-
//Times out after given amount of time
214+
//Checks Serial for data, passing any new bytes to process()
155215
boolean SFE_UBLOX_GPS::checkUbloxSerial()
156216
{
157-
//Todo
158-
return (true);
217+
while (_serialPort->available())
218+
{
219+
process(_serialPort->read());
220+
}
221+
return (true);
159222

160223
} //end checkUbloxSerial()
161224

@@ -406,20 +469,35 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg)
406469
}
407470
}
408471

409-
//Given a packet and payload, send everything including CRC bytes
410-
//Poll for a response, returning true if command was ack'd, false if we time out waiting for response
411-
//Setting timeout to 0 will skip checking for response - handy if you need to scan a raw response (like checking the PROTVER)
472+
//Given a packet and payload, send everything including CRC bytes via I2C port
412473
boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
413474
{
414-
commandAck = false; //We're about to send a command. Begin waiting for ack.
415-
416-
calcChecksum(&outgoingUBX); //Sets checksum A and B bytes of the packet
475+
commandAck = false; //We're about to send a command. Begin waiting for ack.
476+
calcChecksum(&outgoingUBX); //Sets checksum A and B bytes of the packet
417477

418478
#ifdef DEBUG
419-
debug.print("Sending: ");
420-
printPacket(&outgoingUBX);
479+
debug.print("Sending: ");
480+
printPacket(&outgoingUBX);
421481
#endif
422482

483+
if(commType == COMM_TYPE_I2C)
484+
{
485+
if (!sendI2cCommand(outgoingUBX, maxWait)) return false;
486+
} else if(commType == COMM_TYPE_SERIAL)
487+
{
488+
sendSerialCommand(outgoingUBX);
489+
}
490+
491+
if (maxWait > 0)
492+
{
493+
//Give waitForResponse the cls/id to check for
494+
return waitForResponse(outgoingUBX.cls, outgoingUBX.id, maxWait); //Wait for Ack response
495+
}
496+
return true;
497+
}
498+
499+
boolean SFE_UBLOX_GPS::sendI2cCommand(ubxPacket outgoingUBX, uint16_t maxWait)
500+
{
423501
//Point at 0xFF data register
424502
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); //There is no register to write to, we just begin writing data bytes
425503
_i2cPort->write(0xFF);
@@ -468,27 +546,54 @@ boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
468546
if (bytesToSend == 1) _i2cPort->write(outgoingUBX.payload, 1);
469547
_i2cPort->write(outgoingUBX.checksumA);
470548
_i2cPort->write(outgoingUBX.checksumB);
471-
549+
472550
//All done transmitting bytes. Release bus.
473551
if (_i2cPort->endTransmission() != 0)
474552
return (false); //Sensor did not ACK
475-
476-
if (maxWait > 0)
477-
{
478-
//Give waitForResponse the cls/id to check for
479-
if (waitForResponse(outgoingUBX.cls, outgoingUBX.id, maxWait) == false) //Wait for Ack response
480-
return (false);
481-
}
482553
return (true);
483554
}
484555

556+
//Given a packet and payload, send everything including CRC bytesA via Serial port
557+
void SFE_UBLOX_GPS::sendSerialCommand(ubxPacket outgoingUBX)
558+
{
559+
//Write header bytes
560+
_serialPort->write(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on.
561+
_serialPort->write(UBX_SYNCH_2); //b
562+
_serialPort->write(outgoingUBX.cls);
563+
_serialPort->write(outgoingUBX.id);
564+
_serialPort->write(outgoingUBX.len & 0xFF); //LSB
565+
_serialPort->write(outgoingUBX.len >> 8); //MSB
566+
567+
//Write payload.
568+
for (int i=0; i<outgoingUBX.len; i++)
569+
{
570+
_serialPort->write(outgoingUBX.payload[i]);
571+
}
572+
573+
//Write checksum
574+
_serialPort->write(outgoingUBX.checksumA);
575+
_serialPort->write(outgoingUBX.checksumB);
576+
}
577+
485578
//Returns true if I2C device ack's
486579
boolean SFE_UBLOX_GPS::isConnected()
487580
{
488-
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress);
489-
if (_i2cPort->endTransmission() != 0)
490-
return (false); //Sensor did not ACK
491-
return (true);
581+
if(commType == COMM_TYPE_I2C)
582+
{
583+
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress);
584+
return _i2cPort->endTransmission() == 0;
585+
}
586+
else if(commType == COMM_TYPE_SERIAL)
587+
{
588+
// Query navigation rate to see whether we get a meaningful response
589+
packetCfg.cls = UBX_CLASS_CFG;
590+
packetCfg.id = UBX_CFG_RATE;
591+
packetCfg.len = 0;
592+
packetCfg.startingSpot = 0;
593+
594+
return sendCommand(packetCfg);
595+
}
596+
return false;
492597
}
493598

494599
//Given a message, calc and store the two byte "8-Bit Fletcher" checksum over the entirety of the message

src/SparkFun_Ublox_Arduino_Library.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ const uint8_t UBX_CLASS_SEC = 0x27;
9393
const uint8_t UBX_CLASS_HNR = 0x28;
9494

9595
const uint8_t UBX_CFG_PRT = 0x00; //Used to configure port specifics
96+
const uint8_t UBX_CFG_RST = 0x04; //Used to reset device
9697
const uint8_t UBX_CFG_RATE = 0x08; //Used to set port baud rates
9798
const uint8_t UBX_CFG_CFG = 0x09; //Used to save current configuration
9899
const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version Ublox modules (ie protocol v27 and above)
@@ -181,6 +182,8 @@ class SFE_UBLOX_GPS
181182

182183
//By default use the default I2C address, and use Wire port
183184
boolean begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42); //Returns true if module is detected
185+
//By default use 9600 baud
186+
boolean begin(Stream &serialPort); //Returns true if module is detected
184187

185188
boolean isConnected(); //Returns turn if device answers on _gpsI2Caddress address
186189

@@ -198,10 +201,15 @@ class SFE_UBLOX_GPS
198201

199202
void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages
200203
boolean sendCommand(ubxPacket outgoingUBX, uint16_t maxWait = 250); //Given a packet and payload, send everything including CRC bytes
204+
boolean sendI2cCommand(ubxPacket outgoingUBX, uint16_t maxWait = 250);
205+
void sendSerialCommand(ubxPacket outgoingUBX);
201206

202207
void printPacket(ubxPacket *packet); //Useful for debugging
203208

209+
void factoryReset(); //Send factory reset sequence
210+
204211
boolean setI2CAddress(uint8_t deviceAddress, uint16_t maxTime = 250); //Changes the I2C address of the Ublox module
212+
void setSerialRate(uint32_t baudrate, uint16_t maxTime = 250); //Changes the serial baud rate of the Ublox module
205213
void setNMEAOutputPort(Stream &nmeaOutputPort); //Sets the internal variable for the port to direct NMEA characters to
206214

207215
boolean setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = 250); //Set the number of nav solutions sent per second
@@ -311,6 +319,7 @@ class SFE_UBLOX_GPS
311319

312320
//Variables
313321
TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
322+
Stream *_serialPort; //The generic connection to user's chosen Serial hardware
314323
Stream *_nmeaOutputPort = NULL; //The user can assign an output port to print NMEA sentences if they wish
315324

316325
uint8_t _gpsI2Caddress = 0x42; //Default 7-bit unshifted address of the ublox 6/7/8/M8/F9 series

0 commit comments

Comments
 (0)