Merge pull request #100 from adafruit/i2c
Add support for 'uart over i2c' GPS modules
This commit is contained in:
commit
b985f2ed1d
149
Adafruit_GPS.cpp
149
Adafruit_GPS.cpp
|
|
@ -28,10 +28,6 @@
|
|||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
// Only include software serial on AVR platforms and ESP8266 (i.e. not on Due).
|
||||
#include <SoftwareSerial.h>
|
||||
#endif
|
||||
#include <Adafruit_GPS.h>
|
||||
|
||||
#define MAXLINELENGTH 120 ///< how long are max NMEA lines to parse?
|
||||
|
|
@ -385,6 +381,57 @@ float Adafruit_GPS::secondsSinceDate() {
|
|||
return (millis()-lastDate) / 1000.;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief How many bytes are available to read - part of 'Print'-class functionality
|
||||
@return Bytes available, 0 if none
|
||||
*/
|
||||
/**************************************************************************/
|
||||
size_t Adafruit_GPS::available(void) {
|
||||
if (paused) return 0;
|
||||
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
if (gpsSwSerial) {
|
||||
return gpsSwSerial->available();
|
||||
}
|
||||
#endif
|
||||
if (gpsHwSerial) {
|
||||
return gpsHwSerial->available();
|
||||
}
|
||||
if (gpsI2C) {
|
||||
return 1; // I2C doesnt have 'availability' so always has a byte at least to read!
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Write a byte to the underlying transport - part of 'Print'-class functionality
|
||||
@param c A single byte to send
|
||||
@return Bytes written - 1 on success, 0 on failure
|
||||
*/
|
||||
/**************************************************************************/
|
||||
size_t Adafruit_GPS::write(uint8_t c) {
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
if (gpsSwSerial) {
|
||||
return gpsSwSerial->write(c);
|
||||
}
|
||||
#endif
|
||||
if (gpsHwSerial) {
|
||||
return gpsHwSerial->write(c);
|
||||
}
|
||||
if (gpsI2C) {
|
||||
gpsI2C->beginTransmission(_i2caddr);
|
||||
if (gpsI2C->write(c) != 1) {
|
||||
return 0;
|
||||
}
|
||||
if (gpsI2C->endTransmission(true) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Read one character from the GPS device
|
||||
|
|
@ -400,21 +447,48 @@ char Adafruit_GPS::read(void) {
|
|||
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
if(gpsSwSerial) {
|
||||
if(!gpsSwSerial->available()) return c;
|
||||
if (!gpsSwSerial->available())
|
||||
return c;
|
||||
c = gpsSwSerial->read();
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
{
|
||||
if(!gpsHwSerial->available()) return c;
|
||||
if (gpsHwSerial) {
|
||||
if (!gpsHwSerial->available())
|
||||
return c;
|
||||
c = gpsHwSerial->read();
|
||||
}
|
||||
|
||||
if (gpsI2C) {
|
||||
if (_i2cbuff_idx <= _i2cbuff_max) {
|
||||
c = _i2cbuffer[_i2cbuff_idx];
|
||||
_i2cbuff_idx++;
|
||||
} else {
|
||||
// refill the buffer!
|
||||
if (Wire.requestFrom(0x10, GPS_MAX_I2C_TRANSFER, true) == GPS_MAX_I2C_TRANSFER) {
|
||||
// got data!
|
||||
_i2cbuff_max = 0;
|
||||
char curr_char = 0;
|
||||
for (int i=0; i<GPS_MAX_I2C_TRANSFER; i++) {
|
||||
curr_char = Wire.read();
|
||||
if ((curr_char == 0x0A) && (last_char != 0x0D)) {
|
||||
// skip duplicate 0x0A's - but keep as part of a CRLF
|
||||
continue;
|
||||
}
|
||||
last_char = curr_char;
|
||||
_i2cbuffer[_i2cbuff_max] = curr_char;
|
||||
_i2cbuff_max++;
|
||||
}
|
||||
_i2cbuff_max--; // back up to the last valid slot
|
||||
if ((_i2cbuff_max == 0) && (_i2cbuffer[0] == 0x0A)) {
|
||||
_i2cbuff_max = -1; // ahh there was nothing to read after all
|
||||
}
|
||||
_i2cbuff_idx = 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
//Serial.print(c);
|
||||
|
||||
// if (c == '$') { //please don't eat the dollar sign - rdl 9/15/14
|
||||
// currentline[lineidx] = 0;
|
||||
// lineidx = 0;
|
||||
// }
|
||||
|
||||
currentline[lineidx++] = c;
|
||||
if (lineidx >= MAXLINELENGTH)
|
||||
lineidx = MAXLINELENGTH-1; // ensure there is someplace to put the next received character
|
||||
|
|
@ -470,6 +544,17 @@ Adafruit_GPS::Adafruit_GPS(HardwareSerial *ser) {
|
|||
gpsHwSerial = ser; // ...override gpsHwSerial with value passed.
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Constructor when using I2C
|
||||
@param theWire Pointer to an I2C TwoWire object
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Adafruit_GPS::Adafruit_GPS(TwoWire *theWire) {
|
||||
common_init(); // Set everything to common state, then...
|
||||
gpsI2C = theWire; // ...override gpsI2C
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Initialization code used by all constructor types
|
||||
|
|
@ -480,6 +565,7 @@ void Adafruit_GPS::common_init(void) {
|
|||
gpsSwSerial = NULL; // Set both to NULL, then override correct
|
||||
#endif
|
||||
gpsHwSerial = NULL; // port pointer in corresponding constructor
|
||||
gpsI2C = NULL;
|
||||
recvdflag = false;
|
||||
paused = false;
|
||||
lineidx = 0;
|
||||
|
|
@ -498,19 +584,33 @@ void Adafruit_GPS::common_init(void) {
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Start the HW or SW serial port
|
||||
@param baud Baud rate
|
||||
@param baud_or_i2caddr Baud rate if using serial, I2C address if using I2C
|
||||
@returns True on successful hardware init, False on failure
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_GPS::begin(uint32_t baud)
|
||||
bool Adafruit_GPS::begin(uint32_t baud_or_i2caddr)
|
||||
{
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
if(gpsSwSerial)
|
||||
gpsSwSerial->begin(baud);
|
||||
else
|
||||
if(gpsSwSerial) {
|
||||
gpsSwSerial->begin(baud_or_i2caddr);
|
||||
}
|
||||
#endif
|
||||
gpsHwSerial->begin(baud);
|
||||
|
||||
if (gpsHwSerial) {
|
||||
gpsHwSerial->begin(baud_or_i2caddr);
|
||||
}
|
||||
if (gpsI2C) {
|
||||
gpsI2C->begin();
|
||||
if (baud_or_i2caddr > 0x7F) {
|
||||
_i2caddr = GPS_DEFAULT_I2C_ADDR;
|
||||
} else {
|
||||
_i2caddr = baud_or_i2caddr;
|
||||
}
|
||||
// A basic scanner, see if it ACK's
|
||||
gpsI2C->beginTransmission(_i2caddr);
|
||||
return (gpsI2C->endTransmission () == 0);
|
||||
}
|
||||
delay(10);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
@ -520,12 +620,7 @@ void Adafruit_GPS::begin(uint32_t baud)
|
|||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_GPS::sendCommand(const char *str) {
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
if(gpsSwSerial)
|
||||
gpsSwSerial->println(str);
|
||||
else
|
||||
#endif
|
||||
gpsHwSerial->println(str);
|
||||
println(str);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
|
|||
|
|
@ -27,11 +27,15 @@
|
|||
#define _ADAFRUIT_GPS_H
|
||||
|
||||
#define USE_SW_SERIAL ///< comment this out if you don't want to include software serial in the library
|
||||
#define GPS_DEFAULT_I2C_ADDR 0x10 ///< The default address for I2C transport of GPS data
|
||||
#define GPS_MAX_I2C_TRANSFER 32 ///< The max number of bytes we'll try to read at once
|
||||
|
||||
#include "Arduino.h"
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
#include <SoftwareSerial.h>
|
||||
#endif
|
||||
#include <Wire.h>
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**
|
||||
|
|
@ -98,14 +102,15 @@
|
|||
/*!
|
||||
@brief The GPS class
|
||||
*/
|
||||
class Adafruit_GPS {
|
||||
class Adafruit_GPS : public Print{
|
||||
public:
|
||||
void begin(uint32_t baud);
|
||||
bool begin(uint32_t baud_or_i2caddr);
|
||||
|
||||
#if (defined(__AVR__) || defined(ESP8266)) && defined(USE_SW_SERIAL)
|
||||
Adafruit_GPS(SoftwareSerial *ser); // Constructor when using SoftwareSerial
|
||||
#endif
|
||||
Adafruit_GPS(HardwareSerial *ser); // Constructor when using HardwareSerial
|
||||
Adafruit_GPS(TwoWire *theWire); // Constructor when using I2C
|
||||
|
||||
char *lastNMEA(void);
|
||||
boolean newNMEAreceived();
|
||||
|
|
@ -118,6 +123,9 @@ class Adafruit_GPS {
|
|||
uint8_t parseHex(char c);
|
||||
|
||||
char read(void);
|
||||
size_t write(uint8_t);
|
||||
size_t available(void);
|
||||
|
||||
boolean parse(char *);
|
||||
float secondsSinceFix();
|
||||
float secondsSinceTime();
|
||||
|
|
@ -195,6 +203,11 @@ class Adafruit_GPS {
|
|||
SoftwareSerial *gpsSwSerial;
|
||||
#endif
|
||||
HardwareSerial *gpsHwSerial;
|
||||
TwoWire *gpsI2C;
|
||||
uint8_t _i2caddr;
|
||||
char _i2cbuffer[GPS_MAX_I2C_TRANSFER];
|
||||
int8_t _i2cbuff_max = -1, _i2cbuff_idx = 0;
|
||||
char last_char = 0;
|
||||
};
|
||||
/**************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// Test code for Adafruit GPS That Support Using I2C
|
||||
//
|
||||
// This code shows how to test a passthru between USB and I2C
|
||||
//
|
||||
// Pick one up today at the Adafruit electronics shop
|
||||
// and help support open source hardware & software! -ada
|
||||
|
||||
#include <Adafruit_GPS.h>
|
||||
|
||||
// Connect to the GPS on the hardware I2C port
|
||||
Adafruit_GPS GPS(&Wire);
|
||||
|
||||
|
||||
void setup() {
|
||||
// wait for hardware serial to appear
|
||||
while (!Serial);
|
||||
|
||||
// make this baud rate fast enough to we aren't waiting on it
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("Adafruit GPS library basic I2C test!");
|
||||
GPS.begin(0x10); // The I2C address to use is 0x10
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
char c = Serial.read();
|
||||
GPS.write(c);
|
||||
}
|
||||
if (GPS.available()) {
|
||||
char c = GPS.read();
|
||||
Serial.write(c);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Test code for Adafruit GPS That Support Using I2C
|
||||
//
|
||||
// This code shows how to test a passthru between USB and I2C
|
||||
//
|
||||
// Pick one up today at the Adafruit electronics shop
|
||||
// and help support open source hardware & software! -ada
|
||||
|
||||
#include <Adafruit_GPS.h>
|
||||
|
||||
// Connect to the GPS on the hardware I2C port
|
||||
Adafruit_GPS GPS(&Wire);
|
||||
|
||||
|
||||
void setup() {
|
||||
// wait for hardware serial to appear
|
||||
while (!Serial);
|
||||
|
||||
// make this baud rate fast enough to we aren't waiting on it
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("Adafruit GPS library basic I2C test!");
|
||||
GPS.begin(0x10); // The I2C address to use is 0x10
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
char c = Serial.read();
|
||||
GPS.write(c);
|
||||
}
|
||||
if (GPS.available()) {
|
||||
char c = GPS.read();
|
||||
Serial.write(c);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
// Test code for Adafruit GPS That Support Using I2C
|
||||
//
|
||||
// This code shows how to parse data from the I2C GPS
|
||||
//
|
||||
// Pick one up today at the Adafruit electronics shop
|
||||
// and help support open source hardware & software! -ada
|
||||
|
||||
#include <Adafruit_GPS.h>
|
||||
|
||||
// Connect to the GPS on the hardware I2C port
|
||||
Adafruit_GPS GPS(&Wire);
|
||||
|
||||
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
|
||||
// Set to 'true' if you want to debug and listen to the raw GPS sentences
|
||||
#define GPSECHO false
|
||||
|
||||
uint32_t timer = millis();
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
//while (!Serial); // uncomment to have the sketch wait until Serial is ready
|
||||
|
||||
// connect at 115200 so we can read the GPS fast enough and echo without dropping chars
|
||||
// also spit it out
|
||||
Serial.begin(115200);
|
||||
Serial.println("Adafruit I2C GPS library basic test!");
|
||||
|
||||
// 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
|
||||
GPS.begin(0x10); // The I2C address to use is 0x10
|
||||
// uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
|
||||
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
|
||||
// uncomment this line to turn on only the "minimum recommended" data
|
||||
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
|
||||
// For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
|
||||
// the parser doesn't care about other sentences at this time
|
||||
// Set the update rate
|
||||
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
|
||||
// For the parsing code to work nicely and have time to sort thru the data, and
|
||||
// print it out we don't suggest using anything higher than 1 Hz
|
||||
|
||||
// Request updates on antenna status, comment out to keep quiet
|
||||
GPS.sendCommand(PGCMD_ANTENNA);
|
||||
|
||||
delay(1000);
|
||||
|
||||
// Ask for firmware version
|
||||
GPS.println(PMTK_Q_RELEASE);
|
||||
}
|
||||
|
||||
void loop() // run over and over again
|
||||
{
|
||||
// read data from the GPS in the 'main loop'
|
||||
char c = GPS.read();
|
||||
// if you want to debug, this is a good time to do it!
|
||||
if (GPSECHO)
|
||||
if (c) Serial.print(c);
|
||||
// if a sentence is received, we can check the checksum, parse it...
|
||||
if (GPS.newNMEAreceived()) {
|
||||
// a tricky thing here is if we print the NMEA sentence, or data
|
||||
// we end up not listening and catching other sentences!
|
||||
// so be very wary if using OUTPUT_ALLDATA and trying to print out data
|
||||
Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
|
||||
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
|
||||
return; // we can fail to parse a sentence in which case we should just wait for another
|
||||
}
|
||||
// if millis() or timer wraps around, we'll just reset it
|
||||
if (timer > millis()) timer = millis();
|
||||
|
||||
// approximately every 2 seconds or so, print out the current stats
|
||||
if (millis() - timer > 2000) {
|
||||
timer = millis(); // reset the timer
|
||||
Serial.print("\nTime: ");
|
||||
if (GPS.hour < 10) { Serial.print('0'); }
|
||||
Serial.print(GPS.hour, DEC); Serial.print(':');
|
||||
if (GPS.minute < 10) { Serial.print('0'); }
|
||||
Serial.print(GPS.minute, DEC); Serial.print(':');
|
||||
if (GPS.seconds < 10) { Serial.print('0'); }
|
||||
Serial.print(GPS.seconds, DEC); Serial.print('.');
|
||||
if (GPS.milliseconds < 10) {
|
||||
Serial.print("00");
|
||||
} else if (GPS.milliseconds > 9 && GPS.milliseconds < 100) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.println(GPS.milliseconds);
|
||||
Serial.print("Date: ");
|
||||
Serial.print(GPS.day, DEC); Serial.print('/');
|
||||
Serial.print(GPS.month, DEC); Serial.print("/20");
|
||||
Serial.println(GPS.year, DEC);
|
||||
Serial.print("Fix: "); Serial.print((int)GPS.fix);
|
||||
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
|
||||
if (GPS.fix) {
|
||||
Serial.print("Location: ");
|
||||
Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
|
||||
Serial.print(", ");
|
||||
Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
|
||||
Serial.print("Speed (knots): "); Serial.println(GPS.speed);
|
||||
Serial.print("Angle: "); Serial.println(GPS.angle);
|
||||
Serial.print("Altitude: "); Serial.println(GPS.altitude);
|
||||
Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue