GPS Logging w/ Seeed SD Shield

***Updated
Got the code to work with GPS UP501 and Seeed Studio SD Shield (using Arduino Uno R3)

The text file produced does not have a decimal point or headers to specify latitude or longitude (if you don't know the first column will be latitude and second will be longitude, GPS visualizer needs the column to be specified).

The way to work around this is to open your text file in MS Excel once you are done tracking.

Move the two columns down and enter Latitude for the first column and Longitude for the second.

Then scroll to the last entry of your coordinates and next to them (column 3) write 0.00001.

Select that one cell and hit ctrl+C to copy the cell (not the number but the cell itself).

Select the last two coordinates and hit ctrl+shift+HOME (this should select all values in columns one and two.

Right click the highlighted area and select Paste Special. Select Multiply and hit okay. Now your values should look right.

Save this and select yes when MS asks if you want to keep format. Now when you check back to your SD file it should have been modified. You can exit Excel and select no when it asks to save again. Now go to GPSvisualizer.com and select plain text file and upload it from your SD and BAM there is your GPS trail.

This code does not show speed, elevation, or duration but it will show the length of the distance traveled.

    #include <SoftwareSerial.h>
    #include <TinyGPS.h>
    #include <SD.h>
    //created by adrenaline360
    const int chipSelect = 10;

    long lat,lon; // create variable for latitude and longitude object
     
    SoftwareSerial gpsSerial(2, 3); // create gps sensor connection
    TinyGPS gps; // create gps object
     
    void setup(){
    Serial.begin(57600); // try 9600 if this does not work, check w/your gps data sheet
    gpsSerial.begin(9600); // try 4800 if this does not work, check w/ your gps data sheet
    Serial.print("Initializing SD card...");
    pinMode(10, OUTPUT);
    if (!SD.begin(chipSelect)) {
    Serial.println("Is your card plugged in, FAT16/32 formatted, are you DRUNK?, , unplug your Arduino then plug in your SD to your computer if it works disconnect it THEN plug in your Arduino, if not run ReadWrite to see if your SD works");
    return; //Sometimes Windows7 will confuse the SD card if that and the Arduino is plug in and it will ask to reformat the disk.
    }
    Serial.println("card initialized.");
    }
     
    void loop(){
    while(gpsSerial.available()){ // check for gps data
    if(gps.encode(gpsSerial.read())){ // encode gps data
    gps.get_position(&lat,&lon); // get latitude and longitude
    // display position
    Serial.print("lat: ");Serial.print(lat);Serial.print(" ");// print latitude
    Serial.print("lon: ");Serial.println(lon); // print longitude
    File dataFile = SD.open("Tracking.txt", FILE_WRITE);
    if (dataFile) {
    dataFile.print(lat);
    dataFile.print('\t');
    dataFile.print(lon);
    dataFile.println();
    dataFile.close();
    }
    }

    }
    }

***ORIGINAL QUESTION

:fearful: :fearful: :fearful: :fearful:

Hello Arduino World,

I have a standalone GPS Module (UP501) connected to an Arduino Uno R3 in this configuration:

However, I do have a Seeed Studio SD Shield connected to the Arduino as well.

I have been working for around 10 hours trying to get GPS data written to the SD card but to no avail. I am using a MicroSD with a normal SD adapter. I went through all the examples and I can read and write to the MicroSD no problem. I also tested the GPS module and I do get the correct strings in the Serial Monitor (at 57600 baud).

I have used every conceivable sketch available online for GPS loggers to no avail. I settled on trying to get this following sketch to work because it makes much more sense than others. When I upload the sketch and open the serial monitor I get:

Reading GPS
Initializing SD card...initialization done.

After that nothing happens, the RX or TX leds do not flash (indicating no GPS signal is being received)

You will notice in the code there is NSS instead of Serial, well I did try replacing nss with serial but I get the same results.

I then remove the SD card to see if at least a file was created and NOTHING at all. After spending 10+ hours I decided I need the more experienced community to help me out. Please :frowning:

#include <SoftwareSerial.h>
#include <TinyGPS.h>               
#include <SD.h>                        // Standard Arduino SD card library

File myFile;


TinyGPS gps;
SoftwareSerial nss(2, 3);           
                                       

void setup() {
  Serial.begin(57600);
  nss.begin(4800);
  Serial.println("Reading GPS");

// Initialize SD card

 Serial.print("Initializing SD card...");
 
   pinMode(10, OUTPUT);
   
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
// End initialize SD Card

}

void loop() {
  bool newdata = false;
  unsigned long start = millis();
  while (millis() - start < 5000) {  // Update every 5 seconds
    if (feedgps())
      newdata = true;
  }
  if (newdata) {
    gpsdump(gps);
    
  }
}

// Get and process GPS data
void gpsdump(TinyGPS &gps) {
  float flat, flon;
  unsigned long age;
  gps.f_get_position(&flat, &flon, &age);
  Serial.print(flat, 4); 
  Serial.print(", "); 
  Serial.println(flon, 4);
  
   /// And write it to SD card
       myFile = SD.open("tracking.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to tracking.txt...");
    myFile.print(flat, 4);
    myFile.print(", ");
    myFile.println(flon, 4);
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening tracking.txt");
  }
    ///  
  
}

// Feed data as it becomes available 
bool feedgps() {
  while (nss.available()) {
    if (gps.encode(nss.read()))
      return true;
      
  }
  return false;
}

The schematic for the Seeed SD shield looks like pin 5 is the chip select, have you checked this?
http://www.seeedstudio.com/wiki/images/1/1f/SD_Card_Shiled_v4.0.pdf

Also, just looking at your circuit, why have you got the 10k resistor between pin 6 and the Arduino?

Hi, I greatly appreciate your response.

The 10k resistor is how Adafruit connects it, not sure why it is needed but works with and without it.

As for PIN 5 being "chipSelect" does that mean I need to change pin 5 to output? When I do this the SD card fails to initialize.

As for PIN 5 being "chipSelect" does that mean I need to change pin 5 to output?

You can't set the pin HIGH or LOW unless it is an OUTPUT pin. So, it does seem logical that you need to make it an output pin.

So I made some progress! Now there is a file on the SD card and there is text being written to it.

But it's writing the same thing though, over and over again:
$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28

And in the serial monitor I get :

à à ààà àà ààà ààà à ààà àà ààà àà ààà à à E card...initialization done.
Reading GPS
Recording coordinates.txt...dË«ÿ.
¹Reading GPS
Recording coordinates.txt...dË«ÿ.
ÂReading GPS
Recording coordinates.txt...done.
ÊReading GPS
Recording coordinates.txt...done.
?Reading GPS
Recording coordinates.txt...done.
¢Reading GPS
Recording coordinates.txt...done.
bReading GPS
Recording coordinates.txt...done.
rReading GPS
Recording coordinates.txt...done.
bReading GPS
Recording coordinates.txt...done.
?Reading GPS
Recording coordinates.txt...done.
?Reading GPS
Recording coordinates.txt...done.
?Reading GPS
Recording coordinates.txt...done.
nReading GPS
Recording coordinates.txt...done.
ÉReading GPS
Recording coordinates.txt...done.
Reading GPS
Recording coordinates.txt...done.
ÓReading GPS
Recording coordinates.txt...done.
Reading GPS
Recording coordinates.txt...done.
Reading GPS

Here is the code so far:

#include <SoftwareSerial.h>            
#include <SD.h>                        // Standard Arduino SD card library

File myFile;


SoftwareSerial mySerial(2, 3);            // Yellow wire to pin 6. (Based on using 
                                       // Parallax 28500-RT PMB-648 GPS SiRF Internal Antenna)
const int chipSelect = 10;

#define PMTK_SET_NMEA_UPDATE_1HZ  "$PMTK220,1000*1F"
#define PMTK_SET_NMEA_UPDATE_5HZ  "$PMTK220,200*2C"
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"

#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on ALL THE DATA
#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"

// Initialize SD card
void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

 Serial.print("Initializing SD card...");
 
  pinMode(10, OUTPUT);
   
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
// End initialize SD Card

}

void loop()                     // run over and over again
{
  Serial.begin(57600);
  Serial.println("Reading GPS");
  mySerial.begin(9600);
  
  mySerial.println(PMTK_SET_NMEA_OUTPUT_ALLDATA);
  // Set the update rate
  // 1 Hz update rate
  mySerial.println(PMTK_SET_NMEA_UPDATE_1HZ);

   /// And write it to SD card
  myFile = SD.open("Tracking.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Recording coordinates.txt...");
//    myFile.print(flat, 4);
//    myFile.print(", ");
    myFile.println(PMTK_SET_NMEA_OUTPUT_ALLDATA);
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening tracking.txt");
  }

  if (mySerial.available()) {
      Serial.print((char)mySerial.read());
  }
  if (Serial.available()) {
      mySerial.print((char)Serial.read());
  }
}


    ///
SoftwareSerial mySerial(2, 3);            // Yellow wire to pin 6. (Based on using
                                       // Parallax 28500-RT PMB-648 GPS SiRF Internal Antenna)

I thought you said you had a GPS attached? Do you have a link to the mySerial thing you actually have attached?

If it really is the GPS, why doesn't the instance name reflect that?

    myFile.println(PMTK_SET_NMEA_OUTPUT_ALLDATA);

I thought you wanted to log date read FROM the GPS, not data sent TO the GPS. Did I miss something?

  if (Serial.available()) {
      mySerial.print((char)Serial.read());
  }

Are you really expecting to enter something in the Serial Monitor application that the GPS needs to know?

  Serial.begin(57600);
  Serial.println("Reading GPS");
  mySerial.begin(9600);

How many times do you need to begin? At some point, you want to be done with starting and get on to doing.

I am very new to programming so still trying to figure out what you mean Paul.

The following code works 100% with my GPS, this is where I am getting some of my code from:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);


// command to set the update rate to (1 Hz)
#define PMTK_SET_NMEA_UPDATE_1HZ  "$PMTK220,1000*1F"


// turn on ALL THE DATA
#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"


void setup()  
{
  Serial.begin(57600);
  Serial.println("Displaying your current location...");

  // 9600 NMEA is the default baud rate
  mySerial.begin(9600);


  mySerial.println(PMTK_SET_NMEA_OUTPUT_ALLDATA);
  
  // Set the update rate
  // 1 Hz update rate
  mySerial.println(PMTK_SET_NMEA_UPDATE_1HZ);

}

void loop()                     // run over and over again
{

  if (mySerial.available()) {
      Serial.print((char)mySerial.read());
  }
  if (Serial.available()) {
      mySerial.print((char)Serial.read());
  }
}
SoftwareSerial mySerial(2, 3);

SoftwareSerial is a type. It is a class. mySerial is an instance of that class. That name can be anything. Usually, people choose a name that reflects what it attached to the pins. Names like cell or phone or gps make a lot more sense. You can see gps.read() and know that the data is GPS data.

You see a call like mySerial.read() and you have to think about what that data is. You should be thinking about other things, instead. Like what is wrong with your program.

void loop()                     // run over and over again
{

  if (mySerial.available()) {
      Serial.print((char)mySerial.read());
  }
  if (Serial.available()) {
      mySerial.print((char)Serial.read());
  }
}

should be:

void loop()                     // run over and over again
{

  if (gps.available()) {
      Serial.print((char)gps.read());
  }
  if (Serial.available()) {
      gps.print((char)Serial.read());
  }
}

So, now it is quite obvious that the gps data is read, written to the serial port, and forgotten about.

In your other code, exactly the same thing happens. The gps data is read, written to the serial port, and forgotten about. It is NOT written to the file. What you write to the file is one of the commands that you send TO the gps. I fail to see why you want to log that data.

The Serial.begin() and gps.begin() calls belong in setup(), not loop().

Okay, so I understood everything you said. I do not want to write what is going TO the gps. I just want the data FROM the gps. This is where I need help. I do not know what code to extract that.

I also have no idea what these final lines of code are supposed to do:

 if (gps.available()) {
      myFile.println((char)gps.read());
  }
  if (Serial.available()) {
      gps.print((char)Serial.read());
  }

This is my current code with a few things clipped out so it won't be too repetitive.

File myFile;


SoftwareSerial gps(2, 3);            

const int chipSelect = 10;


// Initialize SD card
void setup()
{
  Serial.begin(57600);
  gps.begin(4800);
  Serial.println("Reading GPS");

// Initialize SD card

void loop()                  
{


  myFile = SD.open("Tracking.txt", FILE_WRITE);
  


  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Recording to Tracking.txt...");
    myFile.println((char)gps.read());      // This is where I'm confused
    myFile.close();
    Serial.println("done.");
  } else {
    Serial.println("Error opening Tracking.txt");
  }

  if (gps.available()) {
      myFile.println((char)gps.read());
  }
  if (Serial.available()) {
      gps.print((char)Serial.read());
  }
}

//

I also have no idea what these final lines of code are supposed to do:
if (gps.available()) {
myFile.println((char)gps.read());
}
if (Serial.available()) {
gps.print((char)Serial.read());
}

Then you need to comment out one block at a time until you DO understand. That is CRITICAL to you making progress.

I repped you for helping me out.

I edited the void loop to print out a sentence but I got gibberish on my sd file and in the serial monitor. Obviously something fundamental I cannot realize.

void loop()                     // run over and over again
{
  
  if (gps.available()) {
      Serial.print((char)gps.read());
  }
  if (Serial.available()) {
      gps.print((char)Serial.read());
  }
   /// And write it to SD card
       myFile = SD.open("Tracking.txt, FILE_WRITE");
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to Tracking.txt...");
    myFile.println("IS THIS WORKING?");      //this is the sentence I tried to print
    myFile.close();
    Serial.println("done.");
}
}
//

Okay so I did a little change in my code to get Lat and Long instead of a string of GMC, etc.

#include <SoftwareSerial.h>
    #include <TinyGPS.h>
     
    long lat,lon;
     
    SoftwareSerial gpsSerial(2, 3);
    TinyGPS gps;
     
    void setup(){
    Serial.begin(57600);
    gpsSerial.begin(9600);
    }
     
    void loop(){
    while(gpsSerial.available()){ // check for gps data
    if(gps.encode(gpsSerial.read())){ // encode gps data
    gps.get_position(&lat,&lon); // get latitude and longitude
    // display position
    Serial.print("Position: ");
    Serial.print("lat: ");Serial.print(lat);Serial.print(" ");// print latitude
    Serial.print("lon: ");Serial.println(lon); // print longitude
    }
    }
    }

So now I will try and edit this to write to a SD card.

Apparently you haven't read the stickies at the top of the forum. Or, somehow you think that they don't apply to you. I'll assume the former, and I'll assume that you'll want to remedy that and post your code correctly, AFTER using Tools + Auto Format to make that mess readable.

Okay so I feel as though I am very close to finishing this. A file is written on the SD with what looks to be the latitude but not the longitude.
I express doubt because in the serial monitor 26.XXXX is shown while in the file 27.XXXX is show.

What is wrong

    #include <SoftwareSerial.h>
    #include <TinyGPS.h>
    #include <SD.h>

    const int chipSelect = 10;

    long lat,lon; // create variable for latitude and longitude object
     
    SoftwareSerial gpsSerial(2, 3); // create gps sensor connection
    TinyGPS gps; // create gps object
     
    void setup(){
    Serial.begin(57600); // connect serial
    gpsSerial.begin(9600); // connect gps sensor
    Serial.print("Initializing SD card...");
    pinMode(10, OUTPUT);
    if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    return;
    }
    Serial.println("card initialized.");
    }
     
    void loop(){
    while(gpsSerial.available()){ // check for gps data
    if(gps.encode(gpsSerial.read())){ // encode gps data
    gps.get_position(&lat,&lon); // get latitude and longitude
    // display position
    Serial.print("lat: ");Serial.print(lat);Serial.print(" ");// print latitude
    Serial.print("lon: ");Serial.println(lon); // print longitude
    File dataFile = SD.open("Tracking.txt", FILE_WRITE);
    if (dataFile) {
    dataFile.println(int(lat),int(lon));
    dataFile.close();
    }
    }

    }
    }

I'll paypal $20 for whoever can get me a code that works 100% by 11:59pm today.

And if anyone does try to do it I would like for the txt file on the SD card to look like this when you open it:

45.XXX 74.XXX

Nothing else, no text just that.

Thanks.

Try changing your dataFile.println(int(lat),int(lon)); to:

dataFile.print(lat);
dataFile.print('\t');
dataFile.print(lon);
dataFile.println();

Using the way you've written it is not valid according to the reference (http://arduino.cc/en/Reference/FilePrintln)

And if anyone does try to do it I would like for the txt file on the SD card to look like this when you open it:

45.XXX 74.XXX

Nothing else, no text just that.

Perhaps you SHOULD have some text, for the time being. Assure yourself that the values being written are the ones that you expect. When you are sure, leave the text out.

    dataFile.println(int(lat),int(lon));

Why are you casting the values to int? Why are you passing longs to the function that gets lat and lon? Don't you want the decimal part, too?

And what toby says.

tobyb121:
Try changing your dataFile.println(int(lat),int(lon)); to:

dataFile.print(lat);

dataFile.print('\t');
dataFile.print(lon);
dataFile.println();



Using the way you've written it is not valid according to the reference (http://arduino.cc/en/Reference/FilePrintln)

Hey bro! You just got yourself $20. BUT I need the decimal point. If you can do that then give me your PayPal address.

BUT I need the decimal point.

longs don't have decimal points. floats do. You don't have any floats. I can't imagine why.