what I am trying to do here is writing GPS data in SD card into two stages : First stage is the Initialisation ,which will be logged only for one time. Then the second stage is in the loop... The data inside
logging()
will be logged for many times right after the initialisation - until I press the button to stop and close the file.
Well, doSomeWork
is where the logging (second stage) must take place. If you do it in loop
, you're trying to log the same fix thousands of times. That's because doSomeWork
is only called when a new fix is available. The rest of the time, loop
and GPSloop
are just checking to see is a new fix is available. Most of the time, there is no new fix.
The same is true for the first stage: you should only test for a valid date/time/location when a new fix is available. You would not test this in loop
, for the same reason: fix.valid.date
won't change until there is a new fix.
Here is your sketch, modified to do the first stage and second stage in doSomeWork
.
#include <Arduino.h>
#include <NMEAGPS.h>
#include <SPI.h>
#include <SdFat.h>
NMEAGPS gps; // This parses the GPS characters
gps_fix fix; // This contains all the GPS fields
#define gps_port Serial1
SdFat SD;
File dataFile;
char filename[] = "12345.tcx";
const int xpin = A0; // x-axis of the accelerometer
const int ypin = A1; // y-axis
const int zpin = A2; // z-axis
int x, y, z, total;
void setup() {
Serial.begin(9600);
Serial.flush();
gps_port.begin( 9600 );
gps.send_P( &gps_port, F("PMTK251,115200") ); // set baud rate
gps_port.flush(); // wait for the command to go out
delay( 100 ); // wait for the GPS device to change speeds
gps_port.end(); // empty the input buffer, too
gps_port.begin( 115200 ); // use the new baud rate
gps.send_P( &gps_port, F("PMTK220,100") ); // set 10Hz update rate
pinMode(37, INPUT_PULLUP);
if (!SD.begin(4)) {
Serial.println( F("Card failed, or not present") );
// don't do anything more:
return;
}
Serial.println( F("card initialized.") );
Serial.println( F("Code Running") );
} // setup
void firstStage()
{
Serial.println( F("Co-ordinates Achieved") );
dataFile = SD.open(filename , FILE_WRITE);
Serial.println(filename);
if (dataFile) {
Serial.println( F("File created\n"
"LOGGING DATA!\n") );
dataFile.println( F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<TrainingCenterDatabase xmlns=\""
"http://www.garmin.com/"
"xmlschemas/TrainingCenterDatabase/v2\">\n"
"<Activities>\n"
"<Activity Sport=\"Other\">") );
dataFile.println( F("<Id>") );
dataFile.print ( fix.dateTime.full_year() );
dataFile.print ( '-' );
dataFile.print ( fix.dateTime.month );
dataFile.print ( '-' );
dataFile.print ( fix.dateTime.date );
dataFile.print ( 'T' );
dataFile.print ( fix.dateTime.hours );
dataFile.print ( ':' );
dataFile.print ( fix.dateTime.minutes );
dataFile.print ( ':' );
dataFile.print ( fix.dateTime.seconds );
dataFile.print ( ':' );
dataFile.print ( fix.dateTime_cs );
dataFile.println( F(".000Z"
"</Id>\n"
"<Lap StartTime=\"") );
dataFile.print ( 'T' );
dataFile.println( F(".000Z\">"
"<Track>") );
}
} // firstStage
void secondStage()
{
if (dataFile.isOpen()) {
dataFile.println( F("<Trackpoint>\n"
"<Time>") );
dataFile.print (fix.dateTime.full_year());
dataFile.print ( '-' );
dataFile.print (fix.dateTime.month);
dataFile.print ( '-' );
dataFile.print (fix.dateTime.date);
dataFile.print ( 'T' );
dataFile.print (fix.dateTime.hours);
dataFile.print ( ':' );
dataFile.print (fix.dateTime.minutes);
dataFile.print ( ':' );
dataFile.print (fix.dateTime.seconds);
dataFile.print ( '.' );
if (fix.dateTime_cs < 10)
dataFile.print ( '0' );
dataFile.print ( fix.dateTime_cs );
dataFile.print ( F("0Z"
"</Time>"
"<Position>\n"
"<LatitudeDegrees>") );
dataFile.print ( fix.latitude(), 5 );
dataFile.print ( F("</LatitudeDegrees>\n"
"<LongitudeDegrees>") );
dataFile.print ( fix.longitude(), 5 );
dataFile.print ( F("</LongitudeDegrees>\n"
"</Position>\n"
"<HeartRateBpm>\n"
"<Value>") );
dataFile.print ( '0' );
dataFile.print ( F("</Value>\n"
"</HeartRateBpm>\n"
"<SensorState>"
"Present"
"</SensorState>\n") );
analogReference(EXTERNAL);
x = analogRead(xpin);
y = analogRead(ypin);
z = analogRead(zpin);
total = sqrt( x * x + y * y + z * z );
dataFile.print ( F("<impact>"
"<gforce>") );
dataFile.print ( total );
dataFile.print ( F("</gforce>\n"
"<xaxis>") );
dataFile.print ( x );
dataFile.print ( F("</xaxis>\n"
"<yaxis>") );
dataFile.print ( y );
dataFile.print ( F("</yaxis>\n"
"<zaxis>") );
dataFile.print ( z );
dataFile.println( F("</zaxis>\n"
"</impact>\n"
"</Trackpoint>") );
}
} // secondStage
void doSomeWork() {
if (fix.valid.date && fix.valid.time && fix.valid.location)
{
if (!dataFile.isOpen())
firstStage();
if (dataFile.isOpen())
secondStage();
}
else {
// No valid location data yet!
Serial.print ( '?' );
}
Serial.println();
} // doSomeWork
void GPSloop()
{
while (gps.available( gps_port) ) {
fix = gps.read();
doSomeWork();
}
} // GPSloop
void loop()
{
GPSloop();
// Testing the button could go almost anywhere.
// Putting it here will close dataFile the fastest,
// because it won't have to wait for the next
// GPS update.
if (digitalRead(37) == LOW) {
endtask();
// stop here!
while (1)
;
}
} // loop
void endtask()
{
if (dataFile.isOpen()) {
dataFile.println( F("</Track>\n"
"</Lap>\n"
"</Activity>\n"
"</Activities>\n"
"</TrainingCenterDatabase>") );
dataFile.close();
Serial.println( F("file closed") );
} else {
Serial.println( F("(file never opened)") );
}
} // endtask
I think this does what you described: when it gets a valid date/time/location, it opens the file and writes a few things. Then it writes each fix until the button is pressed, and it stops there. It never does anything else after pressing the button, right?
If you reset the Arduino, it will do it again, to the same file.
I also used the F macro on all "double-quoted strings", changed "A" single-character strings to 'A' single character, and merged sequential string prints into one print of a concatenated string. That is, this:
dataFile.println("</zaxis>");
dataFile.println("</impact>");
dataFile.println("</Trackpoint>");
...can change to this:
dataFile.println( F("</zaxis>\n"
"</impact>\n"
"</Trackpoint>") );
I added newline characters, '\n', when you did a println
.
The original took 22712 bytes of program space and 1694 bytes of RAM.
This version takes 21198 bytes of program space and 1163 bytes of RAM. The string changes saved more than 500 bytes of RAM, and the print changes saved 1600 bytes of program space.
Cheers,
/dev