Ultimate GPS Logger SD file fail

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
tom_w
 
Posts: 32
Joined: Mon Mar 03, 2014 11:32 am

Re: Ultimate GPS Logger SD file fail

Post by tom_w »

Code: Select all

#include <SPI.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <avr/sleep.h>

// Ladyada's logger modified by Bill Greiman to use the SdFat library
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Ultimate GPS Shield
// using MTK33x9 chipset
//    ------> http://www.adafruit.com/products/
// Pick one up today at the Adafruit electronics shop 
// and help support open source hardware & software! -ada

SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO  true
/* set to true to only log to SD when GPS has a fix, for debugging, keep it false */
#define LOG_FIXONLY false  

// Set the pins used
#define chipSelect 10
#define ledPin 13

//define the serial interface to the GPS_module (remember GPS RX --> arduino TX)
File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
/*
  if (SD.errorCode()) {
    putstring("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  */
  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

int freeRam () 
{
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

void setup() {
  // for Leonardos, if you want to debug SD issues, uncomment this line
  // to see serial output
  //while (!Serial);
  
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
  Serial.println(F("\r\nUltimate GPSlogger Shield"));
  pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  Serial.print(F("Free ram 1 = ")); Serial.println(freeRam());

  // see if the card is present and can be initialized:
  //if (!SD.begin(chipSelect, 11, 12, 13)) {
  if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println(F("Card init. failed!"));
    error(2);
  }
  char filename[15];
  strcpy(filename, "GPSLOG00.TXT");
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }

Serial.print(F("Free ram 2 = ")); Serial.println(freeRam());


  logfile = SD.open(filename, FILE_WRITE);
  
    Serial.print(F("Free ram 3 = ")); Serial.println(freeRam());

  
  if( ! logfile ) {
    Serial.print(F("Couldnt create ")); Serial.println(filename);
    error(3);
  }
  Serial.print(F("Writing to ")); Serial.println(filename);
  
  // connect to the GPS at the desired rate
  GPS.begin(9600);

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on GGA (fix data) 
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_GGA);
  // uncomment this line to turn on GSV and GGA
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_GGAGSV);
  
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For logging data, we don't suggest using anything but either RMC only or RMC+GGA
  // to keep the log files at a reasonable size
  // Set the update rate
  //GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 or 5 Hz update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_2HZ);   // 1 or 5 Hz update rate
  // Turn off updates on antenna status, if the firmware permits it
  GPS.sendCommand(PGCMD_NOANTENNA);
  
  Serial.println(F("Ready!"));
}

void loop() {
  char c = GPS.read();
  if (GPSECHO)
     if (c)   Serial.print(c);

  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trying to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
    
    // Sentence parsed! 
    Serial.println(F("OK"));
    if (LOG_FIXONLY && !GPS.fix) {
        Serial.print(F("No Fix"));
        return;
    }

    // Rad. lets log it!
    Serial.println(F("Log"));
    
    char *stringptr = GPS.lastNMEA();
    uint8_t stringsize = strlen(stringptr);
    if (stringsize != logfile.write((uint8_t *)stringptr, stringsize))    //write the string to the SD file
      error(4);
    if (strstr(stringptr, "RMC"))   logfile.flush();
    Serial.println();
  }
}


/* End code */
As far as I can tell I am still crashing SRAM. However, I added the freeRAM() to the above and before I begin to write, I have 480 bytes. Still getting new GPSLOG00.TXT files with zero bytes written to them. Not sure what to do here.

User avatar
tom_w
 
Posts: 32
Joined: Mon Mar 03, 2014 11:32 am

Re: Ultimate GPS Logger SD file fail

Post by tom_w »

Code: Select all

// uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on GGA (fix data) 
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_GGA);
  // uncomment this line to turn on GSV and GGA
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_GGAGSV);
I have isolated my problem to the primary change I made to the shield_sdlog sketch. In the above code, There two uncommented PMTK commands, the first and the last. The first uncommented command was in the original code, and when it is the only uncommented command, the shield will write to the SD card. However, when the first is commented out, and the last is uncommented, then the shield will NOT write to the SD card.

I wrote the last command and updated the adafruit_GPS.h header file using the PMTK checksum calculator here: http://www.hhhh.org/wiml/proj/nmeaxor.html. Here is the code I added to the header file:

Code: Select all

// turn on GPGGA & GPGSV (GPGGA) & (GPGSV)
#define PMTK_SET_NMEA_OUTPUT_GGAGSV    "$PMTK314,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
I feel pretty confident that this is correct, but I don't understand why using this command results in the shield not writing to the SD card. It seems to be related to the SRAM crash, because it will create the directory, and it does not throw any errors when viewing the serial monitor.

Anyone?

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Ultimate GPS Logger SD file fail

Post by adafruit_support_bill »

You have defined a long ASCII string with a #define. As long as it is just a #defne it takes up no memory. As soon as you reference it in your call, it becomes a literal string and consumes SRAM.

User avatar
engineercarl
 
Posts: 56
Joined: Fri Nov 22, 2013 6:47 pm

Re: Ultimate GPS Logger SD file fail

Post by engineercarl »

So, I guess you could edit the Adafruit_GPS.h to read

#define PMTK_SET_NMEA_OUTPUT_GGAGSV F("$PMTK314,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28")

You could also F() the other big strings there. If I get a chance, I will try it on my unit.

User avatar
engineercarl
 
Posts: 56
Joined: Fri Nov 22, 2013 6:47 pm

Re: Ultimate GPS Logger SD file fail

Post by engineercarl »

A couple of questions.

When you run the code do you get any error messages on Serial Monitor? Does it say you opened the file?

If the answers are no and yes above, then are you sure you ever write to and flush the SD buffer? Perhaps put in a simple line like:
logfile.println("some test text"); logfile.flush(); after the file is initialized for writing. I noticed that your flush() depends on getting a RMC sentence but with the sentences you've chosen I don't think it is ever sent. I would have to go look at the chip datasheet to know for sure.

User avatar
tom_w
 
Posts: 32
Joined: Mon Mar 03, 2014 11:32 am

Re: Ultimate GPS Logger SD file fail

Post by tom_w »

adafruit_support_bill wrote:You have defined a long ASCII string with a #define. As long as it is just a #defne it takes up no memory. As soon as you reference it in your call, it becomes a literal string and consumes SRAM.
True but I'm not sure how to F() these strings. I assume I F() them in my sketch because when I try to F() them in my header file, it will not compile.
EngineerCarl wrote:A couple of questions.

When you run the code do you get any error messages on Serial Monitor? Does it say you opened the file?
I do not get any errors and it says that it is writing to a logfile. See quoted serial monitor output below.
Ultimate GPSlogger Shield
Free ram 1 = 517
Free ram 2 = 517
Free ram 3 = 486
Writing to GPSLOG12.TXT
Ready!
Hˆé BANNED• )‰)‰ “BANNED •U(%LL˜˜˜9.800,V,,,.0000`lÁÅá‚bbbrRjRüA5Q$PGACK,33,0*6E
$GPGGA,000010.300,,,,,0,0,,,M,,M,,*4A
OK
Log

$GPGSV,1,1,00*79
$GPRMC,000010.300,V,,,,,0.00,0.00,060180,,,N*$GPGGA,000010.800,,,,,0,0,,,M,,M,,*41
OK
Log
I noticed that your flush() depends on getting a RMC sentence but with the sentences you've chosen I don't think it is ever sent. I would have to go look at the chip datasheet to know for sure.
This must be the ticket. For the quoted serial monitor output above, I changed my PMTK command to include RMC, GGA and GSV. This wrote successfully to the GPSLOG00.txt. But it is not clean as shown in the quoted serial monitor output above. Now I need figure out how to manipulate flush() because I don't actually need the RMC sentence. I'm happy to keep it but I especially can't tell why there is no new line for the GGA sentences quoted above.

User avatar
engineercarl
 
Posts: 56
Joined: Fri Nov 22, 2013 6:47 pm

Re: Ultimate GPS Logger SD file fail

Post by engineercarl »

Cool. I guess the reason you were having empty files is that you were never flushing the data, and it wasn't an SRAM problem after all. I don't think there is any reason why you couldn't search for GGA in that final if statement.

What are you really trying to do? At 2 Hz you may need to streamline the data flow to accurately catch all the NMEA sentences. If you are doing all three sentences, you may be looking at 6-800 bytes/second. I would suggest that you look again at my "final" code in this thread. The interrupt service routine ISR() takes care of "GPS.read" every millisecond. When a full sentence become available, then the code logs it. In your code, you need to regularly "GPS.read" the data from the GPS and then rarely, on a computer timescale, write the data to the SD card. As it stands, you only do one "GPS.read" per loop() call, which maybe the cause of incomplete sentences.

User avatar
tom_w
 
Posts: 32
Joined: Mon Mar 03, 2014 11:32 am

Re: Ultimate GPS Logger SD file fail

Post by tom_w »

What are you really trying to do?
I need GSV sentences which contain SNR, elevation, and azimuth data about visible satellites in order to model GPS antenna performance. The GPS Logger Shield is our reference antenna for our DUT, and I am using it to normalize the data logged by the DUT.
I don't think there is any reason why you couldn't search for GGA in that final if statement.
I changed that final statement to look for GGA, and that made it work without having to include RMC. However, it is not writing GSV sentences now. I'm not sure if it is just because I'm debugging without a fix or what.

Interestingly enough, when I changed it to GSV, it stopped writing to the SD card.

User avatar
tom_w
 
Posts: 32
Joined: Mon Mar 03, 2014 11:32 am

Re: Ultimate GPS Logger SD file fail

Post by tom_w »

If I put "GGA" in the last if statement, it will write GGA sentences to the SD card, but not GSV sentences. If I put "GSV" in the last if statement, it will not write anything to the SD card.

My guess is that Adafruit_GPS.cpp only parses RMC and GGA sentences. If you want another sentence, then you have to write code to parse those.

User avatar
tom_w
 
Posts: 32
Joined: Mon Mar 03, 2014 11:32 am

Re: Ultimate GPS Logger SD file fail

Post by tom_w »

Adafruit_GPS.cpp only has functionality for RMC and GGA sentences. It will not write to the SD any other types of sentences without modification. Furthermore, it only parses RMC or GGA sentences without further modification.

In Adafruit_GPS.cpp, after the checksum test, the code "looks for NMEA sentences." It is originally configured to only look for RMC and GGA. I simply added the following code to this series of if statements in order to log GSV sentences to the SD card. I did not add any parsing code, because I parse the NMEA sentences in my data reduction program.

Code: Select all

if (strstr(nmea, "$GPGSV")) {
    // found GSV
    char *p = nmea;
        return true;
  }
Thanks, EngineerCarl and adafruit_support_bill for your help. Since this issue did not seem to be affected by SRAM issues, I apologize for dominating the thread with a separate issue.

User avatar
tom_w
 
Posts: 32
Joined: Mon Mar 03, 2014 11:32 am

Re: Ultimate GPS Logger SD file fail

Post by tom_w »

EngineerCarl, I want to draw your attention here: viewtopic.php?f=31&t=52796

because I believe you could help me out.

Thanks,

Tom

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”