Teensy 3.1 Ultimate GPS code

Status
Not open for further replies.

rvnash

Member
Hi All,

I've been working on using the Teensy 3.1 as an Arduino replacement for an APRS project. I must say, the Teensy is great. Things are so much easier as I am not struggling to save every byte of Flash and RAM through all sorts of code trickery.

I have the Adafruit Ultimate GPS breakout coded up and working the way I like. It runs mostly autonomously using IntervalTimer, you just have to poll for new sentences and parse them "fast enough" to not miss any. The GPS code is here. I'll put the APRS code in a different post when I clean it up a bit.

Code:
/*
 * Copyright (C) 2014 by KC3ARY Richard Nash
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#ifndef _GPS_H
#define _GPS_H

#include <WProgram.h>

// Return from "parseSentence()"
#define PARSED_NONE     0
#define PARSED_UNKNOWN  1
#define PARSED_ERROR    2
#define PARSED_GGA      3
#define PARSED_RMC      4
#define PARSED_ACK      5

// different commands to set the update rate from once per ten seconds (0.1 Hz) to 10 times a second (10Hz)
#define UPDATE_RATE_10000   "$PMTK220,10000*2F"
#define UPDATE_RATE_5000    "$PMTK220,5000*1B"
#define UPDATE_RATE_2000    "$PMTK220,2000*1C"
#define UPDATE_RATE_1000    "$PMTK220,1000*1F"
#define UPDATE_RATE_200     "$PMTK220,200*2C"
#define UPDATE_RATE_100     "$PMTK220,100*2F"

// turn on only the second sentence (GPRMC)
#define OUTPUT_RMC      "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on just GGA
#define OUTPUT_GGA      "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on GPRMC and GGA
#define OUTPUT_RMC_GGA  "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn on ALL THE DATA
#define OUTPUT_ALLDATA  "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn off output
#define OUTPUT_OFF      "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"

class GPS {
public:
    GPS(HardwareSerial * const, bool ); // Constructor
    void startSerial(const uint16_t);
    void poll(void);
    uint8_t parseSentence(void);
    bool sentenceAvailable(void);

    void standby();
    void setUpdateRate(const char*);
    void setSentencesToReceive(const char*);

    void dataRead();
    bool newValuesSinceDataRead();
    
    // No accessors, just feel free to read this stuff directly.
    // Don't set it though
    uint32_t millisHeadingAcquired, millisAltitudeAcquired, millisPositionAcquired, millisDataRead;
    uint8_t hour, minute, seconds, year, month, day;
    float latitudeDegreesAndFractionalMinutes; 
    float longitudeDegreesAndFractionalMinutes;
    float latitude; // In decimal degrees (no funny degrees and fractional minutes)
    float longitude; // In degrees
    float altitude; // In meters
    float speed; // In knots
    uint16_t heading; // Degrees 0-North, 90-East, 180-South, 270-West
    boolean fix;
    uint8_t fixquality, satellites;

private:
    // Private Methods
    uint8_t parseGGA(const char*, const uint32_t);
    uint8_t parseRMC(const char*, const uint32_t);
    uint8_t parse(const char*, const uint32_t);
    void sendCommand(const char*, bool, const uint32_t);
    void waitForAck(const uint32_t);

    // Private Members
    IntervalTimer pollTimer;
    bool runTimer;
    float degreesAndFractionalMinutesToDegrees(float, const char);
    HardwareSerial *  gpsSwSerial;

#ifdef SIMULATE
    long millisSinceLastSend;
    int simCount;
#endif
};


#endif

Code:
/*
 * Copyright (C) 2014 by KC3ARY Richard Nash
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "GPS.h"

#define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C"
#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17"
#define PMTK_SET_BAUD_4800 "$PMTK251,4800*14"

// standby command & boot successful message
#define PMTK_STANDBY "$PMTK161,0*28"
#define PMTK_STANDBY_SUCCESS "$PMTK001,161,3*3"
#define PMTK_AWAKE "$PMTK010,002*2D"

// ask for the release and version
#define PMTK_Q_RELEASE "$PMTK605*31"

// Max number of characters we can read in a GPS sentence
#define GPS_BUFFER_SIZE 100

#define POLL_TIME 10000  // In microseconds, 1/10th of a seconds should be fast enough

// Double buffered interrupt driven reading
static char buf1[GPS_BUFFER_SIZE];
static char buf2[GPS_BUFFER_SIZE];
static char *onBuffer;
static int nCharsRead;
static char *bufferComplete;

// Constructor using SoftwareSerial
// Note: interruptDrivenPolling uses up an IntervalTimer, which will
// be running constantly.
// Note: There is a known race condition in this interrupt driven code
//       In the polling loop which is called at 10 Hz when the buffer fills
//       up, the state of the variable "bufferComplete" is assigned which
//       buffer just filled. That is also the flag for indicating a sentence
//       is ready for parsing. If you check that variable, make sure you
//       parse the sentence before the next one completes or the double
//       buffering could get corrupted.
// Note: If you are not using interruptDrivenPolling, then make sure you
// call the "poll" function fast enough to keep up with the incoming data.
// Ohterwise you can lose characters and get corrupted sentences.
//
// Finally: When using interruptDrivenPolling, just check for "sentenceAvailable"
// and call "parseSentence" faster than the next sentence coming available.
GPS::GPS(HardwareSerial * const ser, bool interruptDrivenPolling )
{
    runTimer = interruptDrivenPolling;
    bufferComplete = 0;
    onBuffer = buf1;
    nCharsRead = 0;
    hour = minute = seconds = year = month = day =
    fixquality = satellites = 0; // uint8_t
    fix = false; // boolean
    latitude = longitude = altitude = speed = 0.0; // float
    heading = 0;
    gpsSwSerial = ser;
    millisHeadingAcquired = 0;
    millisAltitudeAcquired = 0;
    millisPositionAcquired = 0;
#ifdef SIMULATE
    millisSinceLastSend = millis();
    simCount = 0;
#endif
}

void GPS::dataRead()
{
  millisDataRead = millis();
}

bool GPS::newValuesSinceDataRead()
{
  if (millisHeadingAcquired > millisDataRead && millisAltitudeAcquired > millisDataRead && millisPositionAcquired > millisDataRead) return true;
  return false;
}

static GPS *mainGPS; // The only GPS instance that gets callbacks. It's probably best to only have one
// Turn the function call into a method call on this class;
static void poll_fun()
{
  mainGPS->poll();
}

void GPS::startSerial(const uint16_t baud)
{
    gpsSwSerial->begin(baud);
    delay(10);
    sendCommand(OUTPUT_OFF, true, 500);
    if (runTimer) {
      delay(500);
      mainGPS = this;
      pollTimer.begin( poll_fun, POLL_TIME );
    }
}

void GPS::standby()
{
    sendCommand(PMTK_STANDBY, true, 500);
}

void GPS::setUpdateRate(const char*updateString)
{
    sendCommand(updateString, true, 500);
}

void GPS::setSentencesToReceive(const char*sentences)
{
    sendCommand(sentences, true, 500);
}

float GPS::degreesAndFractionalMinutesToDegrees(float deg, const char hemi)
{
    const float degPart = (int)(deg/100.0);
    deg = (deg - degPart*100.0) / 60.0 + degPart;
    if (hemi == 'S' || hemi == 'W') {
        return -deg;
    } else {
        return deg;
    }
}

uint8_t GPS::parseGGA(const char* nmea, const uint32_t now)
{
    // Assuming a GGA sentence
    const char* p = nmea;
    // get time
    p = strchr(p, ',')+1;
    float timef = atof(p);
    uint32_t time = timef;
    hour = time / 10000;
    minute = (time % 10000) / 100;
    seconds = (time % 100);
    
    // parse out latitude
    p = strchr(p, ',')+1;
    latitude = atof(p);
    
    p = strchr(p, ',')+1; // Should be 'N' or 'S'
    latitude = degreesAndFractionalMinutesToDegrees(latitude, p[0]);
    
    // parse out longitude
    p = strchr(p, ',')+1;
    longitude = atof(p);
    
    p = strchr(p, ',')+1; // Should be 'W' or 'E'
    longitude = degreesAndFractionalMinutesToDegrees(longitude, p[0]);
    
    p = strchr(p, ',')+1;
    fixquality = atoi(p);
    
    p = strchr(p, ',')+1;
    satellites = atoi(p);
    
    p = strchr(p, ',')+1; // HDOP, throw away
    
    p = strchr(p, ',')+1;
    altitude = atof(p);
    
    millisAltitudeAcquired = now;
    millisPositionAcquired = now;
    
    return PARSED_GGA;    
}

uint8_t GPS::parseRMC(const char* nmea, const uint32_t now)
{
    // found RMC
    const char* p = nmea;
    
    // get time
    p = strchr(p, ',')+1;
    float timef = atof(p);
    uint32_t time = timef;
    hour = time / 10000;
    minute = (time % 10000) / 100;
    seconds = (time % 100);
    
    p = strchr(p, ',')+1;
    fix = (p[0] == 'A');
    
    // parse out latitude
    p = strchr(p, ',')+1;
    latitude = atof(p);
    
    p = strchr(p, ',')+1; // Should be 'N' or 'S'
    latitude = degreesAndFractionalMinutesToDegrees(latitude, p[0]);
    
    // parse out longitude
    p = strchr(p, ',')+1;
    longitude = atof(p);
    
    p = strchr(p, ',')+1; // Should be 'W' or 'E'
    longitude = degreesAndFractionalMinutesToDegrees(longitude, p[0]);
    
    // speed
    p = strchr(p, ',')+1;
    speed = atof(p); // Speed in knots
    
    // heading
    p = strchr(p, ',')+1;
    heading = (uint16_t)atof(p);
    
    p = strchr(p, ',')+1;
    uint32_t fulldate = atof(p);
    day = fulldate / 10000;
    month = (fulldate % 10000) / 100;
    year = (fulldate % 100);
    
    millisHeadingAcquired = now;
    millisPositionAcquired = now;
    
    return PARSED_RMC;
}

uint8_t GPS::parse(const char* nmea, const uint32_t now)
{
  //Serial.print("P: ");
  //Serial.println(nmea);
    if (*nmea != '$') {
        return PARSED_ERROR;
    }
    if (strstr(nmea, "$GPGGA") == nmea) {
        if (strlen(nmea) < 65) return PARSED_UNKNOWN; // No fix
        return parseGGA(nmea, now);
    } else if (strstr(nmea, "$GPRMC") == nmea) {
        if (strlen(nmea) < 65) return PARSED_UNKNOWN; // No fix
        return parseRMC(nmea, now);
    } else if (strstr(nmea, "$PMTK001") == nmea) {
        return PARSED_ACK;
    }
    return PARSED_UNKNOWN;
}

void GPS::sendCommand(const char* str, const bool wait, const uint32_t timeout) {
#ifdef SIMULATE
    // Do nothing if in simulation mode
#else
  //Serial.print("GPS(");
  //Serial.print(str);
  //Serial.println(")");
    gpsSwSerial->println(str);
    if (wait) waitForAck(timeout);
#endif
}

// Wait until the command sent gets an ACK back
void GPS::waitForAck(const uint32_t timeout)
{
    uint32_t giveUpTime = 0;
    if (timeout) {
        giveUpTime = millis()+timeout;
    }
    while (!giveUpTime || millis() < giveUpTime) {
        if (parseSentence() == PARSED_ACK) break;
    }
    
}

// Call to check for available characters
void GPS::poll(void)
{
  while (gpsSwSerial->available()) {
    const char c = gpsSwSerial->read();
    if (c != -1) {
        onBuffer[nCharsRead++] = c;
        if (nCharsRead == GPS_BUFFER_SIZE-1 || c == '\n') {
            onBuffer[nCharsRead] = 0;
            nCharsRead = 0;
            if (onBuffer == buf1) {
                onBuffer = buf2;
                bufferComplete = buf1;
            } else {
                onBuffer = buf1;
                bufferComplete = buf2;
            }
        }
    }
  }
}

 // Has a sentence been made available?
bool GPS::sentenceAvailable(void)
{
  return bufferComplete != NULL;
}

// Call this from loop to parse any available sentences
uint8_t GPS::parseSentence(void)
{
    uint8_t retVal = PARSED_NONE;
    if (sentenceAvailable()) {
      retVal = parse(bufferComplete, millis());
      bufferComplete = 0;
    }
    return retVal;
}

Code:
// GPSExample.cpp

/*
 * Copyright (C) 2014 by Richard Nash (KC3ARY)
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <WProgram.h>
#include <GPS.h>

HardwareSerial &gpsSerial = Serial1;
GPS gps(&gpsSerial,true);

// setup() method runs once, when the sketch starts
void setup()
{
  Serial.begin(38400); // For debugging output over the USB port
  gps.startSerial(9600);
  delay(1000);
  gps.setSentencesToReceive(OUTPUT_RMC_GGA);
}

bool gotGPS = false;
// the loop() methor runs over and over again,
// as long as the board has power
void loop()
{
  if (gps.sentenceAvailable()) gps.parseSentence();

  if (gps.newValuesSinceDataRead()) {
    gotGPS = true;
    gps.dataRead();
    Serial.printf("Location: %f, %f altitude %f\n\r",
		  gps.latitude, gps.longitude, gps.altitude);
  }
}

// Called from the powerup interrupt servicing routine.
int main(void)
{
  setup();
  while (true) {
    loop();
    yield();
  }
  return 0; // Never reached.
}
 
Last edited:
In past GPS vehicle tracking work, I just let the receiver run in the default NMEA baud rate of 4800 baud. Reduces the load on the CPU a bit.
And usually parse only GPRMS to get time and location.
Another thing I've done is read GPRMS only as needed - don't try to parse all incoming messages. Just scan for a $ to synch up after ignoring the incoming.

Changing the baud rate and sentence types desired is not in the NMEA standard; it's proprietary and sometimes under NDA for some silly reason.
 
The FGPMMOPA6H GPS module that the Adafruit Ultimate GPS uses defaults to 9600 baud, despite the NMEA default. I thought it best to not try to change that.

As for the suggestion to not parse all incoming messages, certainly this code can do that. Just call "parseSentence" whenever you want the last one received to be parsed.
 
I'm having fun playing with the same GPS module at the moment, using TinyGPS++ for parsing the NMEA strings.

Code example:
Code:
  TinyGPSPlus gps;

Called from loop():

  bool nmeaReceived = false;
  while (!nmeaReceived && (hardwareSerial->available() > 0)) {
    nmeaReceived = gps.encode(hardwareSerial->read());
  }

  if (gps.location.isUpdated()) {
    // Read GPS data using gps.location.lat() etc.
  }
 
Thank you for this contribution code, I could kiss you for all this work I don't have to do, it's been a bit of a pain in my ass the last two days until I found this post.

Your the man. +1 you, you are an upstanding gentleman, and should be proud to be you.
 
That's some creative thinking there, using a timer. I reckon that will save some people a lot of potential problems. Good work!

Just a quick note on the Ada Ultimate GPS, if you want to get 10Hz updates you must change the baud rate. More details here.
 
Hi rvnash,

I purchased a Teensy3.1 and an Adafruit Ultimate Gps
The Gps works fine on Arduino.
I connected the GPS Rx to the pin 0 and GPS Tx to pin 1 of Teensy.

Launching GPSExample.cpp as shown in your post, I get "Compilation error"

I think it is due to lack of GPS.he Wprogram.h.
In any case, what should I do and where can I download GPS.h and WProgram.h if necessary....! ??

Considering the fact that I am an absolute beginner, could you help me by sending the necessary instructions to make Teensy3.1 and Adafruit Ultimate GPS in comunication.... ???

Thanks
 
Hi rvnash,

I'm working on a small system of sun tracking and positionig of solar panels based Arduino pro mini and Adafruit Ultimate GPS that provides the necessary geographic coordinates.
It would be really interesting to migrate the project to Teensy3.1 for obvious reasons.
This is why I would need a simple little program that runs on Teensy and extract data from the Ultimate GPS that already has been working successfully with Arduino.
I'm not interested in special insights regarding the issues of the GPS, I'm just looking for a way to get Date, Time, Lat, Lon from the GPS itself.
*
If possible, you can send me some detailed instructions necessary to find a program that you know works, and libraries needed for the operation ...?

Many thanks
 
There is no example code for the Teensy, but I suspect if you use the Due examples, and change the wiring as follows, the Due examples should work:

Code:
//   GPS TX to Teensy Serial1 RX pin 0
//   GPS RX to Teensy Serial1 TX pin 1
 
Hi tignix,

I added an INO file to the github repository. You should be able to open that using your Arduino development environment. Set your device to teensy 3.x and hit upload.

Let me know if it works for you.

- Rich
 
Not compiling

Hi, I just bought both a teensy 3.1 an tried to use your code with it. However when I open the .ino and try to compile it, I get the following errors:

Code:
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3.cpp.o: In function `_GLOBAL__sub_I_gpsSerial':
C:\Program Files (x86)\Arduino/ultimate_gps_teensy3.ino:29: multiple definition of `setup'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPSExample.cpp:29: first defined here
c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3.cpp.o: In function `loop':
C:\Program Files (x86)\Arduino/ultimate_gps_teensy3.ino:39: multiple definition of `loop'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPSExample.cpp:39: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3.cpp.o: In function `~IntervalTimer':
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.h:51: multiple definition of `gps'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.h:51: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3.cpp.o:(.rodata.gpsSerial+0x0): multiple definition of `gpsSerial'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:(.rodata.gpsSerial+0x0): first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::setSentencesToReceive(char const*)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:63: multiple definition of `GPS::GPS(HardwareSerial*, bool)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:63: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::setSentencesToReceive(char const*)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:63: multiple definition of `GPS::GPS(HardwareSerial*, bool)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:63: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `millis':
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy3/core_pins.h:1073: multiple definition of `GPS::dataRead()'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy3/core_pins.h:1073: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::parseGGA(char const*, unsigned long)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:89: multiple definition of `GPS::newValuesSinceDataRead()'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:89: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::degreesAndFractionalMinutesToDegrees(float, char)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:128: multiple definition of `GPS::degreesAndFractionalMinutesToDegrees(float, char)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:128: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::parseGGA(char const*, unsigned long)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:139: multiple definition of `GPS::parseGGA(char const*, unsigned long)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:139: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::parseRMC(char const*, unsigned long)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:182: multiple definition of `GPS::parseRMC(char const*, unsigned long)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:182: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::parse(char const*, unsigned long)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:232: multiple definition of `GPS::parse(char const*, unsigned long)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:232: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::poll()':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:277: multiple definition of `GPS::poll()'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:277: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::sentenceAvailable()':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:300: multiple definition of `GPS::sentenceAvailable()'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:300: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::parseSentence()':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:305: multiple definition of `GPS::parseSentence()'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:305: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::waitForAck(unsigned long)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:264: multiple definition of `GPS::waitForAck(unsigned long)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:264: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::sendCommand(char const*, bool, unsigned long)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:250: multiple definition of `GPS::sendCommand(char const*, bool, unsigned long)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:250: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::startSerial(unsigned short)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:101: multiple definition of `GPS::startSerial(unsigned short)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:101: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::standby()':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:114: multiple definition of `GPS::standby()'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:114: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::setUpdateRate(char const*)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:119: multiple definition of `GPS::setUpdateRate(char const*)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:119: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPS.cpp.o: In function `GPS::setSentencesToReceive(char const*)':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.cpp:124: multiple definition of `GPS::setSentencesToReceive(char const*)'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPS.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPS.cpp:124: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPSExample.cpp.o: In function `_GLOBAL__sub_I_gpsSerial':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPSExample.cpp:29: multiple definition of `setup'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPSExample.cpp:29: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPSExample.cpp.o: In function `loop':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPSExample.cpp:39: multiple definition of `loop'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPSExample.cpp:39: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPSExample.cpp.o: In function `main':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPSExample.cpp:51: multiple definition of `main'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp/GPSExample.cpp:51: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPSExample.cpp.o: In function `~IntervalTimer':
C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.h:51: multiple definition of `gps'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:C:\Program Files (x86)\Arduino\libraries\ultimate_gps_teensy3/GPS.h:51: first defined here
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\ultimate_gps_teensy3\GPSExample.cpp.o:(.rodata.gpsSerial+0x0): multiple definition of `gpsSerial'
C:\Users\User\AppData\Local\Temp\build2717069319929464923.tmp\GPSExample.cpp.o:(.rodata.gpsSerial+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
Error compiling.

I wonder if there is a step I missed to get it to work.
Thanks for any help
 
Monty,

Not sure this is the right way to do it, but after doing this it compiled for me.

Move the ino file to a different folder and removed the GPSExample.cpp

On Windows I have:
c:\...\Documents\Arduino\sketches\ultimate_gps_teensy3\ultimate_gps_teensy3.ino

c:\...\Documents\Arduino\libraries\ultimate_gps_teensy3\.gitignore
c:\...\Documents\Arduino\libraries\ultimate_gps_teensy3\GPS.cpp
c:\...\Documents\Arduino\libraries\ultimate_gps_teensy3\GPS.h
c:\...\Documents\Arduino\libraries\ultimate_gps_teensy3\README.md
 
Status
Not open for further replies.
Back
Top