SDFat data logging error

Hi all,

I've got an interesting bug here I'm hoping I can get help with. I've built a GPS datalogger using the Arduino Mega, the Arduino Ethernet Shield, and a standard GPS module. The TinyGPS, SDFat, and SDFatUtil libraries do most of the work. The Mega pareses NMEA sentences from the GPS and logs the data onto the SD Card at a preset interval (roughly once every 5 seconds). Everything was working great so I took the unit out on a road test. The first trip worked fine, but on the second attempt the program froze up. Upon closer inspection via serial debugging the program is unable to log data onto the card and halts. This is the error code:

error: write data failed
SD errorCode: 0X6

I've tried other microSD cards with the same result. Being that this code is basically a mash-up of the included analogger example with a TinyGPS example, I loaded the analogger code onto the Arduino. It worked without problem. This makes me think it's a software issue, but then why would it have originally worked and then suddenly quit? The entire code is printed below. There are a few adjustments I still plan to make, but it was fully functional. It hangs at the "if (timer==300)" condition near the bottom. The GPS input data is fine so there's no issue with that. I'm really stumped on this one so any help would be greatly appreciated.

Thanks!

-Jeff

 // GPS datalogger by Rocket_Man_Jeff
// 2012

#include "TinyGPS.h"
#include "SoftwareSerial.h"
#include <SdFat.h>
#include <SdFatUtil.h>  // define FreeRam()

#define CHIP_SELECT SS_PIN  // SD chip select pin
#define ECHO_TO_SERIAL   1  // echo data to serial port if nonzero


TinyGPS gps;

// NMEA Data to pin 19

int RedPin = 5;
int GrnPin = 6;
int BluPin = 7;
int timer = 0;

// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))

//**********************************************************

void setup() {
  Serial.begin(115200);  // Serial Output
  Serial1.begin(4800);  // To read NMEA from GPS
   // pstr stores strings in flash to save RAM
  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;
  
   if (!sd.init(SPI_HALF_SPEED, CHIP_SELECT)) sd.initErrorHalt();

  // create a new file in root, the current working directory
  char name[] = "LOGGER00.CSV";

  for (uint8_t i = 0; i < 100; i++) {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

  cout << pstr("Logging to: ") << name << endl;

  // format header in buffer
  obufstream bout(buf, sizeof(buf));

  bout << pstr("Time,Latitude,Longitude,Altitude,Speed,Heading,Direction,SatNum");

  logfile << buf << endl;

#if ECHO_TO_SERIAL
  cout << buf << endl;
#endif  // ECHO_TO_SERIAL
}

//**********************************************************

void loop() {
  uint32_t m;
  pinMode(RedPin, OUTPUT);
  pinMode(GrnPin, OUTPUT);
  pinMode(BluPin, OUTPUT);
  
  while (Serial1.available()) {
    int c = Serial1.read();
    gps.encode(c);
    //Serial.println("oh no, I'm never gonna exit this while loop");
  }

  long latitude, longitude;
  unsigned long fix_age;

 // gps.get_position(&latitude, &longitude, NULL);
  gps.get_position(&latitude, &longitude, &fix_age);

  //Serial.print("Fix Age:  "); Serial.println(fix_age);
  Serial.print("Latitude:  "); Serial.println(latitude);
  Serial.print("Longitude:  "); Serial.println(longitude);
  
  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);
  
  int hour_int=hour;
  int minute_int=minute;
  int second_int=second;
  
  Serial.print("Altitude (meters): "); Serial.println(gps.f_altitude()); 
  
  Serial.print("Course (degrees): "); Serial.println(gps.f_course()); 
  
  Serial.print("Course (cardinal): "); Serial.println(TinyGPS::cardinal(gps.f_course())); 
  
  Serial.print("Speed(knots): "); Serial.println(gps.f_speed_knots());
  
  Serial.print("Satellites: "); Serial.println(gps.satellites());
  Serial.println();
  
  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();
  
  //  Check status of fix and light LEDs accordingly
  
  if (fix_age == TinyGPS::GPS_INVALID_AGE) {
  Serial.println("No fix detected");
    digitalWrite(BluPin, HIGH);
    digitalWrite(RedPin, LOW);
    digitalWrite(GrnPin, LOW);
    }
    else if (fix_age > 5000) {
  Serial.println("Warning: possible stale data!");
    digitalWrite(BluPin, LOW);
    digitalWrite(RedPin, HIGH);
    digitalWrite(GrnPin, LOW);
    }
    else {
  Serial.println("Data is current.");
    digitalWrite(BluPin, LOW);
    digitalWrite(RedPin, LOW);
    digitalWrite(GrnPin, HIGH);
    
  timer++;  // Rough timer to increment data logging rate
  
  if (timer==300) {
    
    digitalWrite(BluPin, HIGH);  // Light all LEDs when data logs
    digitalWrite(RedPin, HIGH);
    digitalWrite(GrnPin, HIGH);
  

  // use buffer stream to format line
  obufstream bout(buf, sizeof(buf));
  
    long lat_num=(latitude/100000);  // Splits lat/lon from GPS
    long lat_dec=(latitude%100000);  // into xx.xxxxx
    
    long lon_num=(latitude/100000);
    long lon_dec=(latitude%100000);
  
//  long lat_num=(latitude/100000);
//  long lat_dec=(lat_num*100000);
//  lat_dec=(latitude-lat_dec);
//  if (lat_dec<0) {
//    lat_dec=-lat_dec;
//  }
//
//  long lon_num=(longitude/100000);
//  long lon_dec=(lon_num*100000);
//  lon_dec=(longitude-lon_dec);
//  if (lon_dec<0) {
//    lon_dec=-lon_dec;
//  }

  bout << hour_int;
  bout << ':' << minute_int;
  bout << ':' << second_int;
  bout << ',' << lat_num;
  bout << '.' << lat_dec;
  bout << ',' << lon_num;
  bout << '.' << lon_dec;
  bout << ',' << (gps.f_altitude());
  bout << ',' << (gps.f_speed_knots());
  bout << ',' << (gps.f_course());
  bout << ',' << (TinyGPS::cardinal(gps.f_course()));
  bout << ',' << (gps.satellites());

  bout << endl;

  // log data and flush to SD
  logfile << buf << flush;

  // check for error
  if (!logfile) error("write data failed");

#if ECHO_TO_SERIAL
  cout << buf;
#endif  // ECHO_TO_SERIAL

delay (1);

timer=0;
  }  // closes if timer == 300 statement

    }  // closes else statement
  Serial.println();
}  // closes void loop 
[code/]
  pinMode(RedPin, OUTPUT);
  pinMode(GrnPin, OUTPUT);
  pinMode(BluPin, OUTPUT);

Why do you feel it necessary to set the mode of these pins on every pass through loop? They don't forget their mode, you know.

I don't know why you need all that streaming stuff. The normal write() and print() functions work well enough.

  bout << ',' << (gps.f_altitude());
  bout << ',' << (gps.f_speed_knots());
  bout << ',' << (gps.f_course());
  bout << ',' << (TinyGPS::cardinal(gps.f_course()));
  bout << ',' << (gps.satellites());

Extraneous parentheses make your code hard to read. Get rid of them.

It hangs at the "if (timer==300)" condition near the bottom.

I have no idea what you are doing with this variable named timer. It is NOT timing anything. Using millis() to do things at the proper time is a much better idea.

Thanks for the reply. Good catch on the pinmode in the loop - I've since moved them where they should be. The timer variable was just more of a counting variable. I didn't know about the millis function, which works much better as suggested, so I fixed that too. I have a lot of data streaming to the serial port for debugging and (eventually) to be read by other equipment. I'm still not understanding though what would cause the unit to be working fine one moment and then freeze up the next. Even with your code suggestions the same problem still occurs.

Thanks again!
-Jeff

// GPS datalogger by Rocket_Man_Jeff
// 2012

#include "TinyGPS.h"
#include "SoftwareSerial.h"
#include <SdFat.h>
#include <SdFatUtil.h>  // define FreeRam()

#define CHIP_SELECT SS_PIN  // SD chip select pin
#define ECHO_TO_SERIAL   1  // echo data to serial port if nonzero


TinyGPS gps;

// NMEA Data to pin 19

int RedPin = 5;
int GrnPin = 6;
int BluPin = 7;
int timer = 0;
uint32_t m = 0;

// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))

//**********************************************************

void setup() {
  Serial.begin(115200);  // Serial Output
  Serial1.begin(4800);  // To read NMEA from GPS
  pinMode(RedPin, OUTPUT);
  pinMode(GrnPin, OUTPUT);
  pinMode(BluPin, OUTPUT);
   // pstr stores strings in flash to save RAM
  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;
  
   if (!sd.init(SPI_HALF_SPEED, CHIP_SELECT)) sd.initErrorHalt();

  // create a new file in root, the current working directory
  char name[] = "LOGGER00.CSV";

  for (uint8_t i = 0; i < 100; i++) {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

  cout << pstr("Logging to: ") << name << endl;

  // format header in buffer
  obufstream bout(buf, sizeof(buf));

  bout << pstr("Time,Latitude,Longitude,Altitude,Speed,Heading,Direction,SatNum");

  logfile << buf << endl;

#if ECHO_TO_SERIAL
  cout << buf << endl;
#endif  // ECHO_TO_SERIAL
}

//**********************************************************

void loop() {
  
  while (Serial1.available()) {
    int c = Serial1.read();
    gps.encode(c);
    //Serial.println("oh no, I'm never gonna exit this while loop");
  }

  long latitude, longitude;
  unsigned long fix_age;

 // gps.get_position(&latitude, &longitude, NULL);
  gps.get_position(&latitude, &longitude, &fix_age);

  //Serial.print("Fix Age:  "); Serial.println(fix_age);
  Serial.print("Latitude:  "); Serial.println(latitude);
  Serial.print("Longitude:  "); Serial.println(longitude);
  
  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);
  
  int hour_int=hour;
  int minute_int=minute;
  int second_int=second;
  
  Serial.print("Altitude (meters): "); Serial.println(gps.f_altitude()); 
  
  Serial.print("Course (degrees): "); Serial.println(gps.f_course()); 
  
  Serial.print("Course (cardinal): "); Serial.println(TinyGPS::cardinal(gps.f_course())); 
  
  Serial.print("Speed(knots): "); Serial.println(gps.f_speed_knots());
  
  Serial.print("Satellites: "); Serial.println(gps.satellites());
  Serial.println();
  
  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();
  
  //  Check status of fix and light LEDs accordingly
  
  if (fix_age == TinyGPS::GPS_INVALID_AGE) {
  Serial.println("No fix detected");
    digitalWrite(BluPin, HIGH);
    digitalWrite(RedPin, LOW);
    digitalWrite(GrnPin, LOW);
    }
    else if (fix_age > 5000) {
  Serial.println("Warning: possible stale data!");
    digitalWrite(BluPin, LOW);
    digitalWrite(RedPin, HIGH);
    digitalWrite(GrnPin, LOW);
    }
    else {
  Serial.println("Data is current.");
    digitalWrite(BluPin, LOW);
    digitalWrite(RedPin, LOW);
    digitalWrite(GrnPin, HIGH);
    
  if (millis()%500==0){  
    digitalWrite(BluPin, HIGH);  // Light all LEDs when data logs
    digitalWrite(RedPin, HIGH);
    digitalWrite(GrnPin, HIGH);
  

  // use buffer stream to format line
  obufstream bout(buf, sizeof(buf));
  
    long lat_num=(latitude/100000);  // Splits lat/lon from GPS
    long lat_dec=(latitude%100000);  // into xx.xxxxx
    
    long lon_num=(latitude/100000);
    long lon_dec=(latitude%100000);

  bout << hour_int;
  bout << ':' << minute_int;
  bout << ':' << second_int;
  bout << ',' << lat_num;
  bout << '.' << lat_dec;
  bout << ',' << lon_num;
  bout << '.' << lon_dec;
  bout << ',' << gps.f_altitude();
  bout << ',' << gps.f_speed_knots();
  bout << ',' << gps.f_course();
  bout << ',' << TinyGPS::cardinal(gps.f_course());
  bout << ',' << gps.satellites();

  bout << endl;

  // log data and flush to SD
  logfile << buf << flush;

  // check for error
  if (!logfile) error("write data failed");

#if ECHO_TO_SERIAL
  cout << buf;
#endif  // ECHO_TO_SERIAL

delay (1);

  }  // closes if millis statement

    }  // closes else statement
  Serial.println();
}  // closes void loop

I'm still not understanding though what would cause the unit to be working fine one moment and then freeze up the next.

How do you know that the "unit has frozen"? I don't trust the streaming stuff. You don't get something for nothing.

I don't see what use a 1 millisecond delay is, after all that Serial.print()ing, either.

Putting each { on it's own line, and using Tools + Auto Format would greatly improve the readability of your code, in my opinion.

  if (millis()%500==0){

Not a really good idea. Record the last time you wrote, and compare that to "now" to see if it is time to log again.

unsigned long lastLogTime;
unsigned long logInterval = 500;

if(millis() - lastLogTime >= logInterval)
{
   // Do the logging...

   lastLogTime = millis();
}

I'm pretty sure the code has halted because I get an error message through the serial monitor and then nothing more. That, and the LEDs stop flashing in the pattern that they are supposed to. Looking in the source code for the SDFat library, the program will halt when an error message is generated. Furthermore, I've confirmed that no data is logging to the SD card. A file is created but that's it. What do you mean about not trusting the streaming content? I'm relatively new to this so I'm curious what's not looking so good.

The 1 millisecond delay was to let the LEDs turn on for long enough to see a 'flash', meaning that a data set has been logged. I've since removed that and made the suggested adjustments. Still no luck, and still the same error message.

// GPS datalogger by Rocket_Man_Jeff
// 2012

#include "TinyGPS.h"
#include "SoftwareSerial.h"
#include <SdFat.h>
#include <SdFatUtil.h>  // define FreeRam()

#define CHIP_SELECT SS_PIN  // SD chip select pin
#define ECHO_TO_SERIAL   1  // echo data to serial port if nonzero


TinyGPS gps;

// NMEA Data to pin 19

int RedPin = 5;
int GrnPin = 6;
int BluPin = 7;
int timer = 0;
uint32_t m = 0;

// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))

unsigned long lastLogTime;
unsigned long logInterval = 500;

//**********************************************************

void setup() 
{
  Serial.begin(115200);  // Serial Output
  Serial1.begin(4800);  // To read NMEA from GPS
  pinMode(RedPin, OUTPUT);
  pinMode(GrnPin, OUTPUT);
  pinMode(BluPin, OUTPUT);
  // pstr stores strings in flash to save RAM
  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;

  if (!sd.init(SPI_HALF_SPEED, CHIP_SELECT)) sd.initErrorHalt();

  // create a new file in root, the current working directory
  char name[] = "LOGGER00.CSV";

  for (uint8_t i = 0; i < 100; i++) 
  {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

  cout << pstr("Logging to: ") << name << endl;

  // format header in buffer
  obufstream bout(buf, sizeof(buf));

  bout << pstr("Time,Latitude,Longitude,Altitude,Speed,Heading,Direction,SatNum");

  logfile << buf << endl;

#if ECHO_TO_SERIAL
  cout << buf << endl;
#endif  // ECHO_TO_SERIAL
}

//**********************************************************

void loop() 
{

  while (Serial1.available()) 
  {
    int c = Serial1.read();
    gps.encode(c);
    //Serial.println("oh no, I'm never gonna exit this while loop");
  }

  long latitude, longitude;
  unsigned long fix_age;

  // gps.get_position(&latitude, &longitude, NULL);
  gps.get_position(&latitude, &longitude, &fix_age);

  //Serial.print("Fix Age:  "); Serial.println(fix_age);
  Serial.print("Latitude:  "); 
  Serial.println(latitude);
  Serial.print("Longitude:  "); 
  Serial.println(longitude);

  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);

  int hour_int=hour;
  int minute_int=minute;
  int second_int=second;

  Serial.print("Altitude (meters): "); 
  Serial.println(gps.f_altitude()); 

  Serial.print("Course (degrees): "); 
  Serial.println(gps.f_course()); 

  Serial.print("Course (cardinal): "); 
  Serial.println(TinyGPS::cardinal(gps.f_course())); 

  Serial.print("Speed(knots): "); 
  Serial.println(gps.f_speed_knots());

  Serial.print("Satellites: "); 
  Serial.println(gps.satellites());
  Serial.println();

  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();

  //  Check status of fix and light LEDs accordingly

  if (fix_age == TinyGPS::GPS_INVALID_AGE) 
  {
    Serial.println("No fix detected");
    digitalWrite(BluPin, HIGH);
    digitalWrite(RedPin, LOW);
    digitalWrite(GrnPin, LOW);
  }
  else if (fix_age > 5000) 
  {
    Serial.println("Warning: possible stale data!");
    digitalWrite(BluPin, LOW);
    digitalWrite(RedPin, HIGH);
    digitalWrite(GrnPin, LOW);
  }
  else 
  {
    Serial.println("Data is current.");
    digitalWrite(BluPin, LOW);
    digitalWrite(RedPin, LOW);
    digitalWrite(GrnPin, HIGH);

    if(millis() - lastLogTime >= logInterval) 
    {  
      digitalWrite(BluPin, HIGH);  // Light all LEDs when data logs
      digitalWrite(RedPin, HIGH);
      digitalWrite(GrnPin, HIGH);


      // use buffer stream to format line
      obufstream bout(buf, sizeof(buf));

      long lat_num=(latitude/100000);  // Splits lat/lon from GPS
      long lat_dec=(latitude%100000);  // into xx.xxxxx

      long lon_num=(latitude/100000);
      long lon_dec=(latitude%100000);

      bout << hour_int;
      bout << ':' << minute_int;
      bout << ':' << second_int;
      bout << ',' << lat_num;
      bout << '.' << lat_dec;
      bout << ',' << lon_num;
      bout << '.' << lon_dec;
      bout << ',' << gps.f_altitude();
      bout << ',' << gps.f_speed_knots();
      bout << ',' << gps.f_course();
      bout << ',' << TinyGPS::cardinal(gps.f_course());
      bout << ',' << gps.satellites();

      bout << endl;

      // log data and flush to SD
      logfile << buf << flush;

      // check for error
      if (!logfile) error("write data failed");

#if ECHO_TO_SERIAL
      cout << buf;
#endif  // ECHO_TO_SERIAL

      lastLogTime = millis();

    }  // closes if millis statement

  }  // closes else statement
  Serial.println();
}  // closes void loop

Still no luck, and still the same error message.

Then, you really should be able to illustrate that with MUCH simpler code.

Have you ever been able to write anything to/read anything from that card?

Yes, surprisingly I can write data to the SD card using the Analogger example included with the SDFat library. I based my GPS logging code off of this, and it was working fine until it stopped. I shortened the code to the following - still produces the same error.

// GPS datalogger by Rocket_Man_Jeff
// 2012

#include "TinyGPS.h"
#include "SoftwareSerial.h"
#include <SdFat.h>
#include <SdFatUtil.h>  // define FreeRam()

#define CHIP_SELECT SS_PIN  // SD chip select pin
#define ECHO_TO_SERIAL   1  // echo data to serial port if nonzero


TinyGPS gps;

// NMEA Data to pin 19

uint32_t m = 0;

// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))

unsigned long lastLogTime;
unsigned long logInterval = 500;

//**********************************************************

void setup() 
{
  Serial.begin(115200);  // Serial Output
  Serial1.begin(4800);  // To read NMEA from GPS
  // pstr stores strings in flash to save RAM
  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;

  if (!sd.init(SPI_HALF_SPEED, CHIP_SELECT)) sd.initErrorHalt();

  // create a new file in root, the current working directory
  char name[] = "LOGGER00.CSV";

  for (uint8_t i = 0; i < 100; i++) 
  {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

  cout << pstr("Logging to: ") << name << endl;

  // format header in buffer
  obufstream bout(buf, sizeof(buf));

  bout << pstr("Time,Latitude,Longitude,Altitude,Speed,Heading,Direction,SatNum");

  logfile << buf << endl;

#if ECHO_TO_SERIAL
  cout << buf << endl;
#endif  // ECHO_TO_SERIAL
}

//**********************************************************

void loop() 
{

  while (Serial1.available()) 
  {
    int c = Serial1.read();
    gps.encode(c);
  }

  long latitude, longitude;
  unsigned long fix_age;

  gps.get_position(&latitude, &longitude, &fix_age);

  if (fix_age == TinyGPS::GPS_INVALID_AGE) 
  {
    Serial.println("No fix detected");
  }
  else if (fix_age > 5000) 
  {
    Serial.println("Warning: possible stale data!");
  }
  else 
  {
    Serial.println("Data is current.");

    if(millis() - lastLogTime >= logInterval) 
    {  

      // use buffer stream to format line
      obufstream bout(buf, sizeof(buf));

      long lat_num=(latitude/100000);  // Splits lat/lon from GPS
      long lat_dec=(latitude%100000);  // into xx.xxxxx

      long lon_num=(latitude/100000);
      long lon_dec=(latitude%100000);

      bout << ',' << lat_num;
      bout << '.' << lat_dec;
      bout << ',' << lon_num;
      bout << '.' << lon_dec;
      bout << ',' << gps.f_altitude();
      bout << ',' << gps.f_speed_knots();
      bout << ',' << gps.f_course();
      bout << ',' << TinyGPS::cardinal(gps.f_course());
      bout << ',' << gps.satellites();

      bout << endl;

      // log data and flush to SD
      logfile << buf << flush;

      // check for error
      if (!logfile) error("write data failed");

//#if ECHO_TO_SERIAL
//      cout << buf;
//#endif  // ECHO_TO_SERIAL

      lastLogTime = millis();

    }  // closes if millis statement

  }  // closes else statement

}  // closes void loop

Then, I really trimmed the code to basically just log a number (seen below) and it worked! So, what is the difference between the two codes that is causing the halt error? Is there a possibility this could be a software induced hardware problem?

// GPS datalogger by Rocket_Man_Jeff
// 2012

#include "TinyGPS.h"
#include "SoftwareSerial.h"
#include <SdFat.h>
#include <SdFatUtil.h>  // define FreeRam()

#define CHIP_SELECT SS_PIN  // SD chip select pin
#define ECHO_TO_SERIAL   1  // echo data to serial port if nonzero

// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];

// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))

unsigned long lastLogTime;
unsigned long logInterval = 500;

//**********************************************************

void setup() 
{
  Serial.begin(115200);  // Serial Output
  Serial1.begin(4800);  // To read NMEA from GPS

  // pstr stores strings in flash to save RAM
  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;

  if (!sd.init(SPI_HALF_SPEED, CHIP_SELECT)) sd.initErrorHalt();

  // create a new file in root, the current working directory
  char name[] = "LOGGER00.CSV";

  for (uint8_t i = 0; i < 100; i++) 
  {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

  cout << pstr("Logging to: ") << name << endl;

  // format header in buffer
  obufstream bout(buf, sizeof(buf));

  bout << pstr("Time,Latitude,Longitude,Altitude,Speed,Heading,Direction,SatNum");

  logfile << buf << endl;

#if ECHO_TO_SERIAL
  cout << buf << endl;
#endif  // ECHO_TO_SERIAL
}

//**********************************************************

void loop() 
{

    if(millis() - lastLogTime >= logInterval) 
    {  
        Serial.println("Attempting Data Log");

      // use buffer stream to format line
      obufstream bout(buf, sizeof(buf));

      long lat_num=1234567;

      bout << ',' << lat_num;

      bout << endl;

      // log data and flush to SD
      logfile << buf << flush;

      // check for error
      if (!logfile) error("write data failed");

      lastLogTime = millis();

    }  // closes if millis statement

}  // closes void loop
      // use buffer stream to format line
      obufstream bout(buf, sizeof(buf));

Is it necessary to do this every time it is time to log data?

  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;

What does this show, in each of the sketches you've posted?

      bout << ',' << lat_num;
      bout << '.' << lat_dec;
      bout << ',' << lon_num;
      bout << '.' << lon_dec;
      bout << ',' << gps.f_altitude();
      bout << ',' << gps.f_speed_knots();
      bout << ',' << gps.f_course();
      bout << ',' << TinyGPS::cardinal(gps.f_course());
      bout << ',' << gps.satellites();

      bout << endl;

Does all this data fit in 80 characters?

Is it necessary to do this every time it is time to log data?

Maybe? I'm not really sure... It was like that in the analogger example I followed so I just copied it along. Is there any reason that I would need to include this every time it logs data?

What does this show, in each of the sketches you've posted?

It varies between 5800 and 6300.

Does all this data fit in 80 characters?

If I counted correctly, yes. I've also increased the buffer size just to see if there's any difference and there isn't.

Also, the code I posted yesterday that worked no longer works. Interestingly, the analogger example code consistently works without failure, so I'm not thinking this is a hardware issue. I was able to get the full GPS code to log data again but then it too quit. I'm not seeing any pattern in what I'm doing that causes the error. It's not always repeatable either.

Is there any reason that I would need to include this every time it logs data?

No. The association between bout and buf only needs to be made once.

It varies between 5800 and 6300.

So, you are using a Mega. Nice of you to mention that...

I'm not seeing any pattern in what I'm doing that causes the error.

Hard to fix problems like that.

So, you are using a Mega. Nice of you to mention that...

Yep - as mentioned in the first paragraph of my first post.

Hard to fix problems like that.

Tell me about it. I'm usually pretty good at debugging my codes but this one has me stumped, hence I posted it up here. I'm wondering if there's some sort of resource collision occurring between the SDFat library and the TinyGPS library. Thanks for taking a look at this though!