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

Commit 8edc8f2

Browse files
committed
Adding I2C address change support.
1 parent 3d3df64 commit 8edc8f2

File tree

4 files changed

+168
-57
lines changed

4 files changed

+168
-57
lines changed

examples/Example3_GetPosition/Example3_GetPosition.ino

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ void setup()
4545

4646
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
4747

48-
4948
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
49+
50+
myGPS.setUSBOutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
51+
5052
myGPS.setNavigationFrequency(4); //Set output to 4 times a second
5153

5254
/*long pos = myGPS.getPositionAccuracy();
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Change the I2C address of a Ublox module using I2C
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 change the I2C address of a Ublox module
10+
11+
Feel like supporting open source hardware?
12+
Buy a board from SparkFun!
13+
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
14+
NEO-M8P RTK: https://www.sparkfun.com/products/15005
15+
SAM-M8Q: https://www.sparkfun.com/products/15106
16+
17+
Hardware Connections:
18+
Plug a Qwiic cable into the GPS and a BlackBoard
19+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
20+
Open the serial monitor at 115200 baud to see the output
21+
*/
22+
23+
#include <Wire.h> //Needed for I2C to GPS
24+
25+
#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
26+
SFE_UBLOX_GPS myGPS;
27+
28+
long lastTime = 0; //Tracks the passing of 2000ms (2 seconds)
29+
30+
void setup()
31+
{
32+
Serial.begin(115200);
33+
while (!Serial); //Wait for user to open terminal
34+
Serial.println("Reading Lat/Long Example");
35+
36+
Wire.begin();
37+
38+
byte oldAddress = 0x42; //The default address for Ublox modules is 0x42
39+
byte newAddress = 0x3F; //Address you want to change to. Valid is 0x08 to 0x77.
40+
41+
while (Serial.available()) Serial.read(); //Trash any incoming chars
42+
Serial.print("Press a key to change address to 0x");
43+
Serial.println(newAddress, HEX);
44+
while (Serial.available() == false) ; //Wait for user to send character
45+
46+
if (myGPS.begin(Wire, oldAddress) == true) //Connect to the Ublox module using Wire port and the old address
47+
{
48+
Serial.print("GPS found at address 0x");
49+
Serial.println(oldAddress, HEX);
50+
51+
myGPS.setI2CAddress(newAddress); //Change I2C address of this device
52+
//Device's I2C address is stored to memory and loaded on each power-on
53+
54+
if (myGPS.begin(Wire, newAddress) == true)
55+
{
56+
Serial.print("Address successfully changed to 0x");
57+
Serial.println(newAddress, HEX);
58+
Serial.print("Now load another example sketch using .begin(Wire, 0x");
59+
Serial.print(newAddress, HEX);
60+
Serial.println(") to use this GPS module");
61+
Serial.println("Freezing...");
62+
while (1);
63+
}
64+
}
65+
66+
//Something went wrong, begin looking for the I2C device
67+
Serial.println("Address change failed. Beginning an I2C scan.");
68+
69+
Wire.begin();
70+
}
71+
72+
void loop() {
73+
74+
byte address;
75+
int nDevices;
76+
77+
Serial.println("Scanning...");
78+
79+
nDevices = 0;
80+
for (address = 1; address < 127; address++ )
81+
{
82+
Wire.beginTransmission(address);
83+
byte error = Wire.endTransmission();
84+
85+
if (error == 0)
86+
{
87+
Serial.print("I2C device found at address 0x");
88+
if (address < 16)
89+
Serial.print("0");
90+
Serial.print(address, HEX);
91+
Serial.println(" !");
92+
93+
nDevices++;
94+
}
95+
else if (error == 4)
96+
{
97+
Serial.print("Unknown error at address 0x");
98+
if (address < 16)
99+
Serial.print("0");
100+
Serial.println(address, HEX);
101+
}
102+
}
103+
104+
if (nDevices == 0)
105+
Serial.println("No I2C devices found\n");
106+
else
107+
Serial.println("done\n");
108+
109+
delay(5000); // wait 5 seconds for next scan
110+
}

src/SparkFun_Ublox_Arduino_Library.cpp

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ SFE_UBLOX_GPS::SFE_UBLOX_GPS(void)
3434
}
3535

3636
//Initialize the Serial port
37-
void SFE_UBLOX_GPS::begin(TwoWire &wirePort)
37+
boolean SFE_UBLOX_GPS::begin(TwoWire &wirePort, uint8_t deviceAddress)
3838
{
3939
commType = COMM_TYPE_I2C;
4040
_i2cPort = &wirePort; //Grab which port the user wants us to use
@@ -46,14 +46,34 @@ void SFE_UBLOX_GPS::begin(TwoWire &wirePort)
4646
//ie, there are some platforms that don't handle multiple starts to the wire hardware. Also, every time you start the wire
4747
//hardware the clock speed reverts back to 100kHz regardless of previous Wire.setClocks().
4848
//_i2cPort->begin();
49+
50+
_gpsI2Caddress = deviceAddress; //Store the I2C address from user
51+
52+
return(isConnected());
4953
}
5054

51-
//Sets the internal global variable that is the I2C address we read from
52-
//This does not change the I2C address of the module
53-
//0x42 is the default but can be changed via software command
54-
void SFE_UBLOX_GPS::setI2CReadAddress(uint8_t deviceAddress)
55+
//Changes the I2C address that the Ublox module responds to
56+
//0x42 is the default but can be changed with this command
57+
boolean SFE_UBLOX_GPS::setI2CAddress(uint8_t deviceAddress, uint16_t maxWait)
5558
{
56-
_gpsI2Caddress = deviceAddress; //Store the I2C address from user
59+
//Get the current config values for the I2C port
60+
getPortSettings(COM_PORT_I2C); //This will load the payloadCfg array with current port settings
61+
62+
packetCfg.cls = UBX_CLASS_CFG;
63+
packetCfg.id = UBX_CFG_PRT;
64+
packetCfg.len = 20;
65+
packetCfg.startingSpot = 0;
66+
67+
//payloadCfg is now loaded with current bytes. Change only the ones we need to
68+
payloadCfg[4] = deviceAddress << 1; //DDC mode LSB
69+
70+
if( sendCommand(packetCfg, maxWait) == true)
71+
{
72+
//Success! Now change our internal global.
73+
_gpsI2Caddress = deviceAddress; //Store the I2C address from user
74+
return(true);
75+
}
76+
return(false);
5777
}
5878

5979
//Want to see the NMEA messages on the Serial port? Here's how
@@ -575,17 +595,17 @@ boolean SFE_UBLOX_GPS::disableSurveyMode(uint16_t maxWait)
575595
//Returns true if commands was successful
576596
boolean SFE_UBLOX_GPS::getSurveyStatus(uint16_t maxWait)
577597
{
578-
packetCfg.cls = UBX_CLASS_NAV;
579-
packetCfg.id = UBX_NAV_SVIN;
580-
packetCfg.len = 0;
581-
packetCfg.startingSpot = 0;
582-
583598
//Reset variables
584599
svin.active = false;
585600
svin.valid = false;
586601
svin.observationTime = 0;
587602
svin.meanAccuracy = 0;
588603

604+
packetCfg.cls = UBX_CLASS_NAV;
605+
packetCfg.id = UBX_NAV_SVIN;
606+
packetCfg.len = 0;
607+
packetCfg.startingSpot = 0;
608+
589609
if(sendCommand(packetCfg, maxWait) == false)
590610
return(false); //If command send fails then bail
591611

@@ -633,29 +653,6 @@ boolean SFE_UBLOX_GPS::disableRTCMmessage(uint8_t messageNumber, uint8_t portID,
633653
return(enableRTCMmessage(messageNumber, portID, 0, maxWait));
634654
}
635655

636-
//Enable/Disable RTCM3 (both input and output) for a given port
637-
//Use to enable RTCM3 on I2C port (ID 0)
638-
boolean SFE_UBLOX_GPS::setRTCMport(uint8_t portID, boolean enableRTCM3, uint16_t maxWait)
639-
{
640-
//Get the current config values for this port ID
641-
getPortSettings(portID); //This will load the payloadCfg array with current port settings
642-
643-
packetCfg.cls = UBX_CLASS_CFG;
644-
packetCfg.id = UBX_CFG_PRT;
645-
packetCfg.len = 20;
646-
packetCfg.startingSpot = 0;
647-
648-
//Clear packet payload
649-
for(uint8_t x = 0 ; x < packetCfg.len ; x++)
650-
packetCfg.payload[x] = 0;
651-
652-
//payloadCfg is now loaded with current bytes. Change only the ones we need to
653-
payloadCfg[13] |= (1 << 5); //InProtocolMask LSB - Set inRtcm3
654-
payloadCfg[15] |= (1 << 5); //OutProtocolMask LSB - Set outRtcm3
655-
656-
return ( sendCommand(packetCfg, maxWait) );
657-
}
658-
659656
//Loads the payloadCfg array with the current protocol bits located the UBX-CFG-PRT register for a given port
660657
boolean SFE_UBLOX_GPS::getPortSettings(uint8_t portID, uint16_t maxWait)
661658
{

src/SparkFun_Ublox_Arduino_Library.h

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class SFE_UBLOX_GPS
152152
SFE_UBLOX_GPS(void);
153153

154154
//By default use the default I2C address, and use Wire port
155-
void begin(TwoWire &wirePort = Wire);
155+
boolean begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x42); //Returns true if module is detected
156156

157157
boolean isConnected(); //Returns turn if device answers on _gpsI2Caddress address
158158

@@ -171,20 +171,25 @@ class SFE_UBLOX_GPS
171171
void calcChecksum(ubxPacket *msg); //Sets the checksumA and checksumB of a given messages
172172
boolean sendCommand(ubxPacket outgoingUBX, uint16_t maxWait = 250); //Given a packet and payload, send everything including CRC bytes
173173

174-
void setI2CReadAddress(uint8_t deviceAddress); //Sets the internal variable for the address of ublox module we want to read from
174+
boolean setI2CAddress(uint8_t deviceAddress, uint16_t maxTime = 250); //Changes the I2C address of the Ublox module
175175
void setNMEAOutputPort(Stream &nmeaOutputPort); //Sets the internal variable for the port to direct NMEA characters to
176176

177+
boolean setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = 250); //Set the number of nav solutions sent per second
178+
177179
boolean waitForResponse(uint16_t maxTime = 250); //Poll the module until and ack is received
178180

179-
boolean getSurveyMode(uint16_t maxWait = 250); //Get the current TimeMode3 settings
180-
boolean setSurveyMode(uint8_t mode, uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); //Control survey in mode
181-
boolean enableSurveyMode(uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); //Begin Survey-In for NEO-M8P
182-
boolean disableSurveyMode(uint16_t maxWait = 250); //Stop Survey-In mode
183-
184-
boolean getSurveyStatus(uint16_t maxWait); //Reads survey in status and sets the global variables
185-
boolean enableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint8_t secondsBetweenMessages, uint16_t maxWait = 250); //Given a message number turns on a message ID for output over given PortID
186-
boolean disableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint16_t maxWait = 250); //Turn off given RTCM message from a given port
181+
boolean getPVT(uint16_t maxWait = 1000); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc.
182+
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.
183+
int32_t getLongitude(uint16_t maxWait = 250); //Returns the current longitude in degrees * 10-7. Auto selects between HighPrecision and Regular depending on ability of module.
184+
int32_t getAltitude(uint16_t maxWait = 250); //Returns the current altitude in mm above mean sea level (most common output of GPS receivers).
185+
uint8_t getSIV(uint16_t maxWait = 250); //Returns number of sats used in fix
186+
uint8_t getFixType(uint16_t maxWait = 250); //Returns the type of fix: 0=no, 3=3D, 4=GNSS+Deadreckoning
187+
uint8_t getCarrierSolutionType(uint16_t maxWait = 250); //Returns RTK solution: 0=no, 1=float solution, 2=fixed solution
188+
int32_t getGroundSpeed(uint16_t maxWait = 250); //Returns speed in mm/s
189+
int32_t getHeading(uint16_t maxWait = 250); //Returns heading in degrees * 10^-7
190+
uint16_t getPDOP(uint16_t maxWait = 250); //Returns positional dillution of precision * 10^-2
187191

192+
//Port configurations
188193
boolean setPortOutput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = 250); //Configure a given port to output UBX, NMEA, RTCM3 or a combination thereof
189194
boolean setPortInput(uint8_t portID, uint8_t comSettings, uint16_t maxWait = 250); //Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof
190195
boolean getPortSettings(uint8_t portID, uint16_t maxWait = 250); //Returns the current protocol bits in the UBX-CFG-PRT command for a given port
@@ -195,21 +200,18 @@ class SFE_UBLOX_GPS
195200
boolean setUSBOutput(uint8_t comSettings, uint16_t maxWait = 250); //Configure USB port to output UBX, NMEA, RTCM3 or a combination thereof
196201
boolean setSPIOutput(uint8_t comSettings, uint16_t maxWait = 250); //Configure SPI port to output UBX, NMEA, RTCM3 or a combination thereof
197202

198-
boolean setNavigationFrequency(uint8_t navFreq, uint16_t maxWait = 250); //Set the number of nav solutions sent per second
203+
//Functions used for RTK and base station setup
204+
boolean getSurveyMode(uint16_t maxWait = 250); //Get the current TimeMode3 settings
205+
boolean setSurveyMode(uint8_t mode, uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); //Control survey in mode
206+
boolean enableSurveyMode(uint16_t observationTime, float requiredAccuracy, uint16_t maxWait = 250); //Begin Survey-In for NEO-M8P
207+
boolean disableSurveyMode(uint16_t maxWait = 250); //Stop Survey-In mode
208+
209+
boolean getSurveyStatus(uint16_t maxWait); //Reads survey in status and sets the global variables
210+
boolean enableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint8_t secondsBetweenMessages, uint16_t maxWait = 250); //Given a message number turns on a message ID for output over given PortID
211+
boolean disableRTCMmessage(uint8_t messageNumber, uint8_t portID, uint16_t maxWait = 250); //Turn off given RTCM message from a given port
199212

200213
uint32_t getPositionAccuracy(uint16_t maxWait = 500); //Returns the 3D accuracy of the current high-precision fix, in mm. Supported on NEO-M8P, ZED-F9P,
201214

202-
boolean getPVT(uint16_t maxWait = 1000); //Query module for latest group of datums and load global vars: lat, long, alt, speed, SIV, accuracies, etc.
203-
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.
204-
int32_t getLongitude(uint16_t maxWait = 250); //Returns the current longitude in degrees * 10-7. Auto selects between HighPrecision and Regular depending on ability of module.
205-
int32_t getAltitude(uint16_t maxWait = 250); //Returns the current altitude in mm above mean sea level (most common output of GPS receivers).
206-
uint8_t getSIV(uint16_t maxWait = 250); //Returns number of sats used in fix
207-
uint8_t getFixType(uint16_t maxWait = 250); //Returns the type of fix: 0=no, 3=3D, 4=GNSS+Deadreckoning
208-
uint8_t getCarrierSolutionType(uint16_t maxWait = 250); //Returns RTK solution: 0=no, 1=float solution, 2=fixed solution
209-
int32_t getGroundSpeed(uint16_t maxWait = 250); //Returns speed in mm/s
210-
int32_t getHeading(uint16_t maxWait = 250); //Returns heading in degrees * 10^-7
211-
uint16_t getPDOP(uint16_t maxWait = 250); //Returns positional dillution of precision * 10^-2
212-
213215
uint8_t getProtocolVersionHigh(uint16_t maxWait = 1000); //Returns the PROTVER XX.00 from UBX-MON-VER register
214216
//uint8_t getProtocolVersionLow(uint16_t maxWait = 1000); //Returns the PROTVER 00.XX from UBX-MON-VER register
215217
//float getProtocolVersion(uint16_t maxWait = 1000); //Returns the combination of high&low portions from PROTVER in UBX-MON-VER register

0 commit comments

Comments
 (0)