This tutorial was featured on the Cooking-Hacks website on 07/18/2012
This was easily the most time I’ve spent producing an Arduino Tutorial. I’ve been sporadically walking around NYC with this GPS for weeks as I’ve tweaked the code and gotten it just right. If it wasn’t obvious from the title, this tutorial will teach you how to use an arduino paired with a GPS Module and an SD Card Module to log your latitude and longitude over the course of a day. As a bonus, I’ll also show you how to easily overlay this data onto a map using services like Google Earth and Google Fusion Tables. I added a short “history lesson” to this episode to explain how GPS came to be; it’s the first time I’ve done that, so please let me know if you like the extra knowledge. Grab some popcorn and your Arduino, because this tutorial is pretty long – GPS is complicated! The schematics, programs, parts list, sample data, and important links are available for below.
I used the tinyGPS library to decode the NMEA GPS Data. Cooking-Hacks generously supplied both the GPS shield and SD Card shield that I used in this tutorial.
You can download the files associated with this episode here: Arduino Tutorial 15 Files
Source materials for all my arduino tutorials can be found in my github repository.
Distributed under the GNU General Public (Open-Source) License.
Please Attribute and Share-Alike.
This video can also be viewed at element14.com.













March 8, 2013 at 7:54 pm
Hi jeremy,
I notice that the time is incorrect. How do I fix it in the software?
March 14, 2013 at 8:05 pm
Hi,
I just made the tutorial entirely but i have one problem:
The setup procedure start all over again for several times and then all the serial monitor printout stops and nothing more happens. The only difference between your example script and my script is that i use SoftwareSerial on Port 2 and 3 for the GPS. And i use an skylab GPS Module that needs a bauderate of 9600. Also my chipselectpin for the SD is on pin 4 since i am using an Ethernet Shield because i have no separate SD Shield. That are the only changes i made to the workshop scirpt. But as mentioned i only get a couple repeats of the setup part. What am i doing wrong? Here is the code (actually your code with small changes):
//Jeremy Blum’s Arduino Tutorial Series – Episode 15 – GPS Tracking
//Sample Code 2 – Logging GPS Data to an SD Card
//http://www.jeremyblum.com
//TinyGPS Library and Helper Functions by Mikal Hart http://arduiniana.org/libraries/tinygps/
#include
#include
#include
#include
/* This sample code demonstrates the normal use of a TinyGPS object.
It uses an Arduino UNO with a GPS (Skylab) attached to nss at 9600 buad.
*/
TinyGPS gps;
SoftwareSerial nss(2, 3);
static char dtostrfbuffer[20];
int CS = 4;
int LED = 13;
//Define String
String SD_date_time = “invalid”;
String SD_lat = “invalid”;
String SD_lon = “invalid”;
String dataString =”";
static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec, int SD_val);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
void setup()
{
pinMode(CS, OUTPUT); //Chip Select Pin for the SD Card
pinMode(LED, OUTPUT); //LED Indicator
pinMode(10, OUTPUT);
//Serial interfaces
Serial.begin(9600);
nss.begin(9600);
//Connect to the SD Card
if(!SD.begin(CS))
{
Serial.println(“Card Failure”);
return;
}
Serial.print(“Testing TinyGPS library v. “); Serial.println(TinyGPS::library_version());
Serial.println(“by Mikal Hart”);
Serial.println();
Serial.print(“Sizeof(gpsobject) = “); Serial.println(sizeof(TinyGPS));
Serial.println();
Serial.println(“Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum”);
Serial.println(” (deg) (deg) Age Age (m) — from GPS —- —- to London —- RX RX Fail”);
Serial.println(“————————————————————————————————————————————–”);
}
void loop()
{
bool newdata = false;
unsigned long start = millis();
// Every second we print an update
while (millis() – start < 1000)
{
if (feedgps())
newdata = true;
}
gpsdump(gps);
//Write the newest information to the SD Card
dataString = SD_date_time + "," + SD_lat + "," + SD_lon;
if(SD_date_time != "invalid")
digitalWrite(LED, HIGH);
else
digitalWrite(LED, LOW);
//Open the Data CSV File
File dataFile = SD.open("LOG.csv", FILE_WRITE);
if (dataFile)
{
dataFile.println(dataString);
Serial.println(dataString);
dataFile.close();
}
else
{
Serial.println("
Couldn't open the log file!");
}
}
static void gpsdump(TinyGPS &gps)
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
gps.f_get_position(&flat, &flon, &age);
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5, 1); //LATITUDE
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5, 2); //LONGITUDE
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
print_date(gps); //DATE AND TIME
print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2, 0);
print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2, 0);
print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);
gps.stats(&chars, &sentences, &failed);
print_int(chars, 0xFFFFFFFF, 6);
print_int(sentences, 0xFFFFFFFF, 10);
print_int(failed, 0xFFFFFFFF, 9);
Serial.println();
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i 0)
sz[len-1] = ‘ ‘;
Serial.print(sz);
feedgps();
}
static void print_float(float val, float invalid, int len, int prec, int SD_val)
{
char sz[32];
if (val == invalid)
{
strcpy(sz, “*******”);
sz[len] = 0;
if (len > 0)
sz[len-1] = ‘ ‘;
for (int i=7; i<len; ++i)
sz[i] = ' ';
Serial.print(sz);
if(SD_val == 1) SD_lat = sz;
else if(SD_val == 2) SD_lon = sz;
}
else
{
Serial.print(val, prec);
if (SD_val == 1) SD_lat = dtostrf(val,10,5,dtostrfbuffer);
else if (SD_val == 2) SD_lon = dtostrf(val,10,5,dtostrfbuffer);
int vi = abs((int)val);
int flen = prec + (val = 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(" ");
}
feedgps();
}
static void print_date(TinyGPS &gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
if (age == TinyGPS::GPS_INVALID_AGE)
{
Serial.print("******* ******* ");
SD_date_time = "invalid";
}
else
{
char sz[32];
sprintf(sz, "d/d/d d:d:d ",
month, day, year, hour, minute, second);
Serial.print(sz);
SD_date_time = sz;
}
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
feedgps();
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
feedgps();
}
static bool feedgps()
{
while (nss.available())
{
if (gps.encode(nss.read()))
return true;
}
return false;
}
I have an self build version of the script that functions a little better (i can post it if you like) but in that script i have the problem that i cant convert the month, year, etc values to put it on the SD String. I get 2-3 good readings and after that i got nonsense from all parameters. If i put the date and time lines under comment the script gives me good readings for a long time. i tested the thing on a 9 volt battery on my day today and i got a pretty precise gps track made with this tool: http://www.gpsvisualizer.com/map_input?form=google (only with latitude and lontitude colums).
Maybe you can help me to make this work. I am not (yet) a real pro in this thing. i started this a couple of months ago and bought all kind of weird sensors and switches and i think its a great hobby and fun. But now i am a little stuck with this gps thing.
at last: i wanna thank you for your tutorials. i did follow thorough most of them and succeeded and learned a lot about the background of what am i sketching.
greetings Stephan
March 14, 2013 at 8:34 pm
Hi me again,
I Just commented out the Hole Part:
/*
Serial.print(“Testing TinyGPS library v. “); Serial.println(TinyGPS::library_version());
Serial.println(“by Mikal Hart”);
Serial.println();
Serial.print(“Sizeof(gpsobject) = “); Serial.println(sizeof(TinyGPS));
Serial.println();
*/
// Serial.println(“Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum”);
// Serial.println(” (deg) (deg) Age Age (m) — from GPS —- —- to London —- RX RX Fail”);
// Serial.println(“————————————————————————————————————————————–”);
And now i got good readings. i am really confused what the reason could be for that….
March 15, 2013 at 2:01 am
Plz tell me the best and cheaper GPS module for arduino
March 18, 2013 at 2:54 am
Hi Jeremy
I solved the first problem with the weird output but now I have another problem.
This is my code at the moment, i’m using an Arduino Uno:
#include
#include
#include
#include
/* This sample code demonstrates the normal use of a TinyGPS object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/
TinyGPS gps;
SoftwareSerial nss(3, 4);
static char dtostrfbuffer[20];
int CS = 53;
int LED = 13;
//Define String
String SD_date_time = “invalid”;
String SD_lat = “invalid”;
String SD_lon =”invalid”;
String dataString =”";
static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
void setup()
{
pinMode(CS, OUTPUT);//Chip Select Pin for the SD Card
pinMode(LED, OUTPUT);//LED Indicator
Serial.begin(115200);
nss.begin(4800);
//Connect to the SD Card
if(!SD.begin(4))
{
Serial.println(“Card Failure”);
}
Serial.print(“Testing TinyGPS library v. “); Serial.println(TinyGPS::library_version());
Serial.println(“by Mikal Hart”);
Serial.println();
Serial.print(“Sizeof(gpsobject) = “); Serial.println(sizeof(TinyGPS));
Serial.println();
Serial.println(“Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum”);
Serial.println(” (deg) (deg) Age Age (m) — from GPS —- —- to London —- RX RX Fail”);
Serial.println(“————————————————————————————————————————————–”);
}
void loop()
{
bool newdata = false;
unsigned long start = millis();
// Every second we print an update
while (millis() – start < 1000)
{
if (feedgps())
newdata = true;
}
gpsdump(gps);
//Write the newest information to the SD Card
dataString = SD_date_time + "," + SD_lat + "," + SD_lon;
if(SD_date_time != "invalid")
{
digitalWrite(LED, HIGH);
}
else
{
digitalWrite(LED, LOW);
}
//Open the Data CSV File
File dataFile = SD.open("LOG.csv", FILE_WRITE);
if (dataFile)
{
dataFile.println(dataString);
Serial.println(dataString);
dataFile.close();
}
else
{
Serial.println("\nCouldn't open the log file!");
}
}
static void gpsdump(TinyGPS &gps)
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
gps.f_get_position(&flat, &flon, &age);
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5); //LATITUDE
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5);//LONGITUDE
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
print_date(gps); //DATE AND TIME
print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2);
print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);
gps.stats(&chars, &sentences, &failed);
print_int(chars, 0xFFFFFFFF, 6);
print_int(sentences, 0xFFFFFFFF, 10);
print_int(failed, 0xFFFFFFFF, 9);
Serial.println();
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i 0)
sz[len-1] = ‘ ‘;
Serial.print(sz);
feedgps();
}
static void print_float(float val, float invalid, int len, int prec)
{
char sz[32];
if (val == invalid)
{
strcpy(sz, “*******”);
sz[len] = 0;
if (len > 0)
sz[len-1] = ‘ ‘;
for (int i=7; i<len; ++i)
sz[i] = ' ';
Serial.print(sz);
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val = 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(" ");
}
feedgps();
}
static void print_date(TinyGPS &gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
if (age == TinyGPS::GPS_INVALID_AGE)
Serial.print("******* ******* ");
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
month, day, year, hour, minute, second);
Serial.print(sz);
}
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
feedgps();
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
feedgps();
}
static bool feedgps()
{
while (nss.available())
{
if (gps.encode(nss.read()))
return true;
}
return false;
}
I do get an output like you do but again I get some weird output beneath: Course Speed Card, Distance Course Card, Chars RX, Sentences RX and Checksum Fail. This output looks like some weird symbols again with some squares in between (I can't copy paste the weird output and can't post an image).
Hopefully you can give me some help
Thanks
March 23, 2013 at 7:36 am
car tracking with gps skylap + arduino2560 + sim 300 + (16*2 lcd)
can any one help me to give me the code of this project please???
i interfaced gsm but the i cant interface gps
and i want the code please and thank you Very Happy
March 23, 2013 at 10:53 am
Can you suggest a GPS module for arduino uno.
March 25, 2013 at 10:20 am
Zett,
I am using an Adafruit Ultimate GPS Logger Shield with an Arduino Uno, and I had similar inconsistent problems. It turned out that I had used up all of the SRAM. I discovered this by searching the Web and found the following routine
int freeRam () // SRAM Testing
{
extern int __heap_start, *__brkval;
int v;
return (int) &v – (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
If you call it like this
Serial.println(freeRam());
then you will see the amount of free SRAM available.
So to get this tutorial to work I had to comment out all of the calls to Serial.print and Serial.println, especially the ones with the text in them. This increased the amount of free SRAM to 489 and the program runs fine.
Regards
Jasea
March 28, 2013 at 1:36 pm
You can deal with this by moving static print statements to flash. Like this:
Serial.print(F(“Hello there!”));
March 28, 2013 at 5:28 pm
iam student and that apart of my graduation project
i want arduino code
car tracking with gps skylap + arduino2560 + sim 300
can any one help me to give me the code of this project please???
i interfaced gsm but the i cant interface gps
and i want the code please and thank you Very much
March 28, 2013 at 5:29 pm
arduino code to receive sms with sim300
can anyone help me please???
March 30, 2013 at 1:03 am
I just implemented and tested this GPS tracker while walking around on my balcony . I mapped it using Google’s fusion and visualization tools but it seems like the error surrounding my movements are pretty large (about a 100 feet). I’ll be fiddling with it some more to see where the problem could be. In general, my application of the tutorial went without a hitch. The background behind the fundamentals of GPS was informative and interesting. Great job, Jeremy!
March 30, 2013 at 10:59 am
Glad to hear it! You’ll improve accuracy by locking onto more satellites. If you are on your balcony, try moving into an open area.
March 30, 2013 at 11:48 am
The errors that I observed were strictly in the longitude readings – I had some blockage that probably reduced the triangulation properties along that axis. I went out into into an open field and the accuracy improved tremendously. More satellites did the trick! Next up, I’m going to modify the telemetry outputs and mount it on my RC plane to see more dimensions to analyze (like altitude and speed).
March 30, 2013 at 9:23 pm
cool! Post a video when you get that working!
April 15, 2013 at 2:54 pm
Still trying to get a video of what I’ve been working on – I’m in tweak mode. In addition to recording gps telemetry, I added a gyroscope module to simultaneously record rate of change in pitch, roll, and yaw. Using the student edition of Matlab, I put together a rudimentary 3D animation of all of the telemetry and I got a pretty good playback of my flight for the 3D spatial parameters. Regarding orientation, my gyro interpretations are kind of twitchy but maybe I could improve the post processing and then work towards onboard filtering. This has been nothing but fun – there are so many directions that I’d like to go with this. So much to do. So little time. Thanks for getting me started, Jeremy!
March 30, 2013 at 1:26 pm
Dear All, good morning!!
I am working hard to understand my gps antenna.
I do have an Arduino Uno which will be replace by an Arduino Mini Pro 5V
I also have a GPRS module connected to the arduino Uno.
On Pin 4 and 5 I connected a GPS antena. First, I tried with this one:
https://www.sparkfun.com/products/465
then I ordered and try this one
https://www.sparkfun.com/products/11571
Both are connected through this connector breakout
https://www.sparkfun.com/products/10402
On my Sketch I define pin4 as RX and pin5 as TX
SoftwareSerial uart_gps(4, 5);
I have now the RX wire of the breakout connected to the pin 5 and TX wire connected to pin 4.
I also try to invert it. RX wire of the breakout, connected to the 4, and TX wire tp pin5.
Finaly I am using a simple code to display position
[code]
/*
6-8-10
Aaron Weiss
SparkFun Electronics
Example GPS Parser based off of arduiniana.org TinyGPS examples.
Parses NMEA sentences from an EM406 running at 4800bps into readable
values for latitude, longitude, elevation, date, time, course, and
speed.
For the SparkFun GPS Shield. Make sure the switch is set to DLINE.
Once you get your longitude and latitude you can paste your
coordinates from the terminal window into Google Maps. Here is the
link for SparkFun's location.
http://maps.google.com/maps?q=40.06477,+-105.20997
Uses the NewSoftSerial library for serial communication with your GPS,
so connect your GPS TX and RX pin to any digital pin on the Arduino,
just be sure to define which pins you are using on the Arduino to
communicate with the GPS module.
REVISIONS:
1-17-11
changed values to RXPIN = 2 and TXPIN = to correspond with
hardware v14+. Hardware v13 used RXPIN = 3 and TXPIN = 2.
*/
// In order for this sketch to work, you will need to download
// TinyGPS library from arduiniana.org and put them
// into the hardware->libraries folder in your ardiuno directory.
#include
#include
// Define which pins you will use on the Arduino to communicate with your
// GPS. In this case, the GPS module's TX pin will connect to the
// Arduino's RXPIN which is pin 3.
#define RXPIN 4
#define TXPIN 5
//Set this value equal to the baud rate of your GPS
#define GPSBAUD 4800
// Create an instance of the TinyGPS object
TinyGPS gps;
// Initialize the NewSoftSerial library to the pins you defined above
SoftwareSerial uart_gps(RXPIN, TXPIN);
// This is where you declare prototypes for the functions that will be
// using the TinyGPS library.
void getgps(TinyGPS &gps);
// In the setup function, you need to initialize two serial ports; the
// standard hardware serial port (Serial()) to communicate with your
// terminal program an another serial port (NewSoftSerial()) for your
// GPS.
void setup()
{
// This is the serial rate for your terminal program. It must be this
// fast because we need to print everything before a new sentence
// comes in. If you slow it down, the messages might not be valid and
// you will likely get checksum errors.
Serial.begin(4800);
//Sets baud rate of your GPS
uart_gps.begin(GPSBAUD);
Serial.println(F(""));
Serial.println(F("GPS Shield QuickStart Example Sketch v12"));
Serial.println(F(" ...waiting for lock... "));
Serial.println(F(""));
}
// This is the main loop of the code. All it does is check for data on
// the RX pin of the ardiuno, makes sure the data is valid NMEA sentences,
// then jumps to the getgps() function.
void loop()
{
//while(Serial.available())
while(uart_gps.available()) // While there is data on the RX pin...
{
// int c = Serial.read();
byte c = uart_gps.read(); // load the data into a variable...
if(gps.encode(c)) // if there is a new valid sentence...
{
getgps(gps); // then grab the data.
}
}
}
// The getgps function will get and print the values we want.
void getgps(TinyGPS &gps)
{
Serial.println("getGPS");
// To get all of the data into varialbes that you can use in your code,
// all you need to do is define variables and query the object for the
// data. To see the complete list of functions see keywords.txt file in
// the TinyGPS and NewSoftSerial libs.
// Define the variables that will be used
float latitude, longitude;
// Then call this function
gps.f_get_position(&latitude, &longitude);
// You can now print variables latitude and longitude
Serial.print("Lat/Long: ");
Serial.print(latitude,5);
Serial.print(", ");
Serial.println(longitude,5);
// Same goes for date and time
int year;
byte month, day, hour, minute, second, hundredths;
gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
// Print data and time
Serial.print("Date: "); Serial.print(month, DEC); Serial.print("/");
Serial.print(day, DEC); Serial.print("/"); Serial.print(year);
Serial.print(" Time: "); Serial.print(hour, DEC); Serial.print(":");
Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC);
Serial.print("."); Serial.println(hundredths, DEC);
//Since month, day, hour, minute, second, and hundr
// Here you can print the altitude and course values directly since
// there is only one value for the function
Serial.print("Altitude (meters): "); Serial.println(gps.f_altitude());
// Same goes for course
Serial.print("Course (degrees): "); Serial.println(gps.f_course());
// And same goes for speed
Serial.print("Speed(kmph): "); Serial.println(gps.f_speed_kmph());
Serial.println();
// Here you can print statistics on the sentences.
unsigned long chars;
unsigned short sentences, failed_checksum;
gps.stats(&chars, &sentences, &failed_checksum);
//Serial.print("Failed Checksums: ");Serial.print(failed_checksum);
//Serial.println(); Serial.println();
}
[/code]
As well with the fist antena, than with the second, it very rarely works!
[b]When it works:[/b]
Last week, I was in my sofa. I am leaving on 7th floor. I was seeting at 3m of the big window. The fix/positions were not displayed.
Then I put my module on the table whihc is a 0.2m from thew window, and the module start displaying fix. OK, I understand the the building can stop the signal. But it not beacuse it works once, that it always work. It’s not working each time. Also a Cellular antena/provder is close to my building. may be it can make interference
[b]When it does not work (While I am not at home)[/b]
What it frustred me, and when I am teaveling in the train. Right now I am maming 2hour train. Then I am moving. I am seeting close to the window. The Antenna is at 1cm of the window and it never display fix!!!!!
Once I will try to be in a midlle of a field, but my goal is to provide a tool which work any where.
Is there someone who can provide me some advice.
For exemple:
Is correct to connect the antena from RX to TX, or the wire should be connect RX to RX?
IS correct to define pin 4 and 5, instead of 0 and 1, or 2 and 3
Someone know the best and correct use of this antenna : https://www.sparkfun.com/products/11571
Many thnak for any advise you can provide and I hope I provided enougth information
Cheers
April 2, 2013 at 12:10 pm
Hi,
Good tutorial, thanks!
I’m looking for components and I’d like to ask what’s the main difference between these 2 microsd shields and why is there a big price difference.
http://www.cooking-hacks.com/index.php/microsd-2gb-module-for-arduino.html
http://www.cooking-hacks.com/index.php/microsd-card-module-for-arduino.html
April 2, 2013 at 1:10 pm
There isn’t a huge difference. One comes with an SD Card and the other doesn’t.
April 2, 2013 at 1:26 pm
Thanks!
And is there any difference between an internal or an embedded gps antenna?
April 2, 2013 at 1:32 pm
I’m not sure
April 15, 2013 at 3:01 am
Hi Jeremy
I retried making this program work but i still have the same problems. still getting a weird output once in a while and I don’t know why but the program stays repeating “Sats, HDOP, Latitude, Longitute,… ” until “by Mikal Hart” over and over again.
I’m using an Arduino Uno, maybe you can help me changing the code a little bit so it works on the Arduino Uno?
Here is the code I use:
#include
#include
#include
#include
/* This sample code demonstrates the normal use of a TinyGPS object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/
TinyGPS gps;
SoftwareSerial nss(3, 4);
static char dtostrfbuffer[20];
//int CS = 4;
int LED = 13;
//Define String
String SD_date_time = “invalid”;
String SD_lat = “invalid”;
String SD_lon = “invalid”;
String dataString =”";
static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec, int SD_val);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
void setup()
{
pinMode(4,OUTPUT); //ChipSelect Pin for the SD Card
pinMode(LED, OUTPUT); //LED Indicator
//Serial interfaces
Serial.begin(115200);
nss.begin(4800);
//Connect to the SD Card
if(!SD.begin(4))
{
Serial.println(“Card Failure”);
return;
}
Serial.print(“Testing TinyGPS library v. “); Serial.println(TinyGPS::library_version());
Serial.println(“by Mikal Hart”);
Serial.println();
Serial.print(“Sizeof(gpsobject) = “); Serial.println(sizeof(TinyGPS));
Serial.println();
Serial.println(“Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum”);
Serial.println(” (deg) (deg) Age Age (m) — from GPS —- —- to London —- RX RX Fail”);
Serial.println(“————————————————————————————————————————————–”);
}
void loop()
{
bool newdata = false;
unsigned long start = millis();
// Every second we print an update
while (millis() – start < 1000)
{
if (feedgps())
newdata = true;
}
gpsdump(gps);
//Write the newest information to the SD Card
dataString = SD_date_time + "," + SD_lat + "," + SD_lon;
if(SD_date_time != "invalid")
digitalWrite(LED, HIGH);
else
digitalWrite(LED, LOW);
//Open the Data CSV File
File dataFile = SD.open("LOG.csv", FILE_WRITE);
if (dataFile)
{
dataFile.println(dataString);
Serial.println(dataString);
dataFile.close();
}
else
{
Serial.println("\nCouldn't open the log file!");
}
}
static void gpsdump(TinyGPS &gps)
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
gps.f_get_position(&flat, &flon, &age);
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5, 1); //LATITUDE
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5, 2); //LONGITUDE
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
print_date(gps); //DATE AND TIME
print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2, 0);
print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2, 0);
print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);
gps.stats(&chars, &sentences, &failed);
print_int(chars, 0xFFFFFFFF, 6);
print_int(sentences, 0xFFFFFFFF, 10);
print_int(failed, 0xFFFFFFFF, 9);
Serial.println();
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i 0)
sz[len-1] = ‘ ‘;
Serial.print(sz);
feedgps();
}
static void print_float(float val, float invalid, int len, int prec, int SD_val)
{
char sz[32];
if (val == invalid)
{
strcpy(sz, “*******”);
sz[len] = 0;
if (len > 0)
sz[len-1] = ‘ ‘;
for (int i=7; i<len; ++i)
sz[i] = ' ';
Serial.print(sz);
if(SD_val == 1) SD_lat = sz;
else if(SD_val == 2) SD_lon = sz;
}
else
{
Serial.print(val, prec);
if (SD_val == 1) SD_lat = dtostrf(val,10,5,dtostrfbuffer);
else if (SD_val == 2) SD_lon = dtostrf (val,10,5,dtostrfbuffer);
int vi = abs((int)val);
int flen = prec + (val = 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(" ");
}
feedgps();
}
static void print_date(TinyGPS &gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
if (age == TinyGPS::GPS_INVALID_AGE)
{
Serial.print("******* ******* ");
SD_date_time = "invalid";
}
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
month, day, year, hour, minute, second);
Serial.print(sz);
SD_date_time = sz;
}
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
feedgps();
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
feedgps();
}
static bool feedgps()
{
while (nss.available())
{
if (gps.encode(nss.read()))
return true;
}
return false;
}
Hopefully you can help me let it work
thanks in advance
April 20, 2013 at 6:11 am
Hi Jeremy,
your tutorial was very helpful.I want to directly use the gps data output and plot it in google earth real-time rather than logging it in the SD card and making the path later.Can you help me with this?
Thanks
April 22, 2013 at 4:28 am
Great tutorial Jeremy, thanks for posting.
I have built a few of these and everything works perfectly. I have changed the string being saved to SD card to include speed, course etc etc…
I am not a programmer, but I seem to be able to get things working, but I cannot work out how to change the date string to change the date to my timezone? I need date and time in GMT+10. I am assuming that the date I am seeing is UTC?
Also, I was trying to output the speed to a serial, 4 digit, 7 seg display? From the way I am reading the documentation, I think I have to break down the variable “speed” into separate digits, and output them separately to the 7 seg display?
Any advice would be awesome.
Pingback: Tutorials for Arduino Getting Acquainted with Arduino - Arduino for ProjectsArduino for Projects
May 6, 2013 at 4:47 am
HI,
How do I log the gps data into a kml file directly in the computer than to the SD card. I am new to arduino so i dont know how to implement that.Your help would be greatly appreciated.
thanks
May 16, 2013 at 5:57 pm
Reagan was not in the white house in the 90′s. Bush Snr was.
Pingback: Arduino GPS Tracking System -Arduino for Projects