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

Add support for serial protocol, plus factory reset command #2

Merged
merged 4 commits into from
Jan 30, 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
94 changes: 94 additions & 0 deletions examples/Example11_UseUart/Example11_UseUart.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
Reading lat and long via UBX binary commands using UART @38400 baud - free from I2C
By: Nathan Seidle, Adapted from Example3_GetPosition by Thorsten von Eicken
SparkFun Electronics
Date: January 28rd, 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 and U-Blox for serial port use as well as
switching the module from the default 9600 baud to 38400.

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:
Connect the U-Blox serial port to Serial1
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;

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");

//Assume that the U-Blox GPS is running at 9600 baud (the default) or at 38400 baud.
//Loop until we're in sync and then ensure it's at 38400 baud.
do {
Serial.println("GPS: trying 38400 baud");
Serial1.begin(38400);
if (myGPS.begin(Serial1)) break;

delay(100);
Serial.println("GPS: trying 9600 baud");
Serial1.begin(9600);
if (myGPS.begin(Serial1)) {
Serial.println("GPS: connected at 9600 baud, switching to 38400");
myGPS.setSerialRate(38400);
delay(100);
} else {
//gps.factoryReset();
delay(2000); //Wait a bit before trying again to limit the Serial output
}
} while(1);
Serial.println("GPS serial connected");

myGPS.setUART1Output(COM_TYPE_UBX); //Set the UART port to output UBX only
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
myGPS.saveConfiguration(); //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)"));

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

Serial.println();
}
}
94 changes: 94 additions & 0 deletions examples/Example12_Reset/src/Example12_Reset.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
Test baud rate changes on serial, factory reset, and hard reset.
By: Thorsten von Eicken
Date: January 29rd, 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 reset the U-Box module.

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:
Connect the U-Blox serial port to Serial1
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;

int state = 0; // steps through auto-baud, reset, etc states

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

void loop()
{
Serial.print("===== STATE ");
Serial.println(state);
switch (state) {
case 0: // auto-baud connection, then switch to 38400 and save config
do {
Serial.println("GPS: trying 38400 baud");
Serial1.begin(38400);
if (myGPS.begin(Serial1)) break;

delay(100);
Serial.println("GPS: trying 9600 baud");
Serial1.begin(9600);
if (myGPS.begin(Serial1)) {
Serial.println("GPS: connected at 9600 baud, switching to 38400");
myGPS.setSerialRate(38400);
delay(100);
} else {
delay(2000); //Wait a bit before trying again to limit the Serial output flood
}
} while(1);
myGPS.setUART1Output(COM_TYPE_UBX); //Set the UART port to output UBX only
myGPS.saveConfiguration(); //Save the current settings to flash and BBR
Serial.println("GPS serial connected, saved config");
state++;
break;
case 1: // hardReset, expect to see GPS back at 38400 baud
Serial.println("Issuing hardReset (cold start)");
myGPS.hardReset();
delay(1000);
Serial1.begin(38400);
if (myGPS.begin(Serial1)) {
Serial.println("Success.");
state++;
} else {
Serial.println("*** GPS did not respond at 38400 baud, starting over.");
state = 0;
}
break;
case 2: // factoryReset, expect to see GPS back at 9600 baud
Serial.println("Issuing factoryReset");
myGPS.factoryReset();
delay(2000); // takes more than one second... a loop to resync would be best
Serial1.begin(9600);
if (myGPS.begin(Serial1)) {
Serial.println("Success.");
state++;
} else {
Serial.println("*** GPS did not come back at 9600 baud, starting over.");
state = 0;
}
break;
case 3: // print version info
Serial.print("GPS protocol version: ");
Serial.print(myGPS.getProtocolVersionHigh());
Serial.print('.');
Serial.print(myGPS.getProtocolVersionLow());
state = 0;
}
delay(1000);
}
144 changes: 129 additions & 15 deletions src/SparkFun_Ublox_Arduino_Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,75 @@ boolean SFE_UBLOX_GPS::begin(TwoWire &wirePort, uint8_t deviceAddress)
return(isConnected());
}

//Initialize the Serial port
boolean SFE_UBLOX_GPS::begin(Stream &serialPort)
{
commType = COMM_TYPE_SERIAL;
_serialPort = &serialPort; //Grab which port the user wants us to use

return(isConnected());
}

void SFE_UBLOX_GPS::factoryReset()
{
// Copy default settings to permanent
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_CFG;
packetCfg.len = 13;
packetCfg.startingSpot = 0;
for (uint8_t i=0; i<4; i++) {
payloadCfg[0+i] = 0xff; // clear mask: copy default config to permanent config
payloadCfg[4+i] = 0x00; // save mask: don't save current to permanent
payloadCfg[8+i] = 0x00; // load mask: don't copy permanent config to current
}
payloadCfg[12] = 0xff; // all forms of permanent memory
sendCommand(packetCfg, 0); // don't expect ACK
hardReset(); // cause factory default config to actually be loaded and used cleanly
}

void SFE_UBLOX_GPS::hardReset()
{
// Issue hard reset
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_RST;
packetCfg.len = 4;
packetCfg.startingSpot = 0;
payloadCfg[0] = 0xff; // cold start
payloadCfg[1] = 0xff; // cold start
payloadCfg[2] = 0; // 0=HW reset
payloadCfg[3] = 0; // reserved
sendCommand(packetCfg, 0); // don't expect ACK
}

//Changes the serial baud rate of the Ublox module, can't return success/fail 'cause ACK from modem
//is lost due to baud rate change
void SFE_UBLOX_GPS::setSerialRate(uint32_t baudrate, uint8_t uartPort, uint16_t maxWait)
{
//Get the current config values for the UART port
getPortSettings(uartPort, maxWait); //This will load the payloadCfg array with current port settings
#ifdef DEBUG
debug.print("Current baud rate: ");
debug.println(((uint32_t)payloadCfg[10]<<16) | ((uint32_t)payloadCfg[9]<<8) | payloadCfg[8]);
#endif

packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_PRT;
packetCfg.len = 20;
packetCfg.startingSpot = 0;

//payloadCfg is now loaded with current bytes. Change only the ones we need to
payloadCfg[8] = baudrate;
payloadCfg[9] = baudrate>>8;
payloadCfg[10] = baudrate>>16;
payloadCfg[11] = baudrate>>24;
#ifdef DEBUG
debug.print("New baud rate:");
debug.println(((uint32_t)payloadCfg[10]<<16) | ((uint32_t)payloadCfg[9]<<8) | payloadCfg[8]);
#endif

sendCommand(packetCfg);
}

//Changes the I2C address that the Ublox module responds to
//0x42 is the default but can be changed with this command
boolean SFE_UBLOX_GPS::setI2CAddress(uint8_t deviceAddress, uint16_t maxWait)
Expand Down Expand Up @@ -89,6 +158,7 @@ boolean SFE_UBLOX_GPS::checkUblox()
checkUbloxI2C();
else if(commType == COMM_TYPE_SERIAL)
checkUbloxSerial();
return false;
}

//Polls I2C for data, passing any new bytes to process()
Expand Down Expand Up @@ -150,11 +220,13 @@ boolean SFE_UBLOX_GPS::checkUbloxI2C()

} //end checkUbloxI2C()

//Polls Serial for data, passing any new bytes to process()
//Times out after given amount of time
//Checks Serial for data, passing any new bytes to process()
boolean SFE_UBLOX_GPS::checkUbloxSerial()
{
//Todo
while (_serialPort->available())
{
process(_serialPort->read());
}
return (true);

} //end checkUbloxSerial()
Expand Down Expand Up @@ -406,20 +478,35 @@ void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg)
}
}

//Given a packet and payload, send everything including CRC bytes
//Poll for a response, returning true if command was ack'd, false if we time out waiting for response
//Setting timeout to 0 will skip checking for response - handy if you need to scan a raw response (like checking the PROTVER)
//Given a packet and payload, send everything including CRC bytes via I2C port
boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
{
commandAck = false; //We're about to send a command. Begin waiting for ack.

calcChecksum(&outgoingUBX); //Sets checksum A and B bytes of the packet

#ifdef DEBUG
debug.print("Sending: ");
printPacket(&outgoingUBX);
#endif

if(commType == COMM_TYPE_I2C)
{
if (!sendI2cCommand(outgoingUBX, maxWait)) return false;
} else if(commType == COMM_TYPE_SERIAL)
{
sendSerialCommand(outgoingUBX);
}

if (maxWait > 0)
{
//Give waitForResponse the cls/id to check for
return waitForResponse(outgoingUBX.cls, outgoingUBX.id, maxWait); //Wait for Ack response
}
return true;
}

boolean SFE_UBLOX_GPS::sendI2cCommand(ubxPacket outgoingUBX, uint16_t maxWait)
{
//Point at 0xFF data register
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress); //There is no register to write to, we just begin writing data bytes
_i2cPort->write(0xFF);
Expand Down Expand Up @@ -472,23 +559,50 @@ boolean SFE_UBLOX_GPS::sendCommand(ubxPacket outgoingUBX, uint16_t maxWait)
//All done transmitting bytes. Release bus.
if (_i2cPort->endTransmission() != 0)
return (false); //Sensor did not ACK
return (true);
}

if (maxWait > 0)
//Given a packet and payload, send everything including CRC bytesA via Serial port
void SFE_UBLOX_GPS::sendSerialCommand(ubxPacket outgoingUBX)
{
//Give waitForResponse the cls/id to check for
if (waitForResponse(outgoingUBX.cls, outgoingUBX.id, maxWait) == false) //Wait for Ack response
return (false);
//Write header bytes
_serialPort->write(UBX_SYNCH_1); //μ - oh ublox, you're funny. I will call you micro-blox from now on.
_serialPort->write(UBX_SYNCH_2); //b
_serialPort->write(outgoingUBX.cls);
_serialPort->write(outgoingUBX.id);
_serialPort->write(outgoingUBX.len & 0xFF); //LSB
_serialPort->write(outgoingUBX.len >> 8); //MSB

//Write payload.
for (int i=0; i<outgoingUBX.len; i++)
{
_serialPort->write(outgoingUBX.payload[i]);
}
return (true);

//Write checksum
_serialPort->write(outgoingUBX.checksumA);
_serialPort->write(outgoingUBX.checksumB);
}

//Returns true if I2C device ack's
boolean SFE_UBLOX_GPS::isConnected()
{
if(commType == COMM_TYPE_I2C)
{
_i2cPort->beginTransmission((uint8_t)_gpsI2Caddress);
if (_i2cPort->endTransmission() != 0)
return (false); //Sensor did not ACK
return (true);
return _i2cPort->endTransmission() == 0;
}
else if(commType == COMM_TYPE_SERIAL)
{
// Query navigation rate to see whether we get a meaningful response
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_RATE;
packetCfg.len = 0;
packetCfg.startingSpot = 0;

return sendCommand(packetCfg);
}
return false;
}

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