Arduino GPS and Accelerometer Data Problem

With any sensor, make sure you can read it correctly using a stand alone program, before attempting to add code for it to a more complex program.

Be sure to remove these lines from the magnetometer code, as they are wrong and will result in uninterpretable data. It is critical to determine the magnetometer offsets separately.

 if (a > maxX) maxX = (int)a;
  if (a < minX) minX = (int)a;
  if (b > maxY) maxY = (int)b;
  if (b < minY) minY = (int)b;
  if (c > maxZ) maxZ = (int)c;
  if (c < minZ) minZ = (int)c;
  offX = (maxX + minX) / 2;
  offY = (maxY + minY) / 2;
  offZ = (maxZ + minZ) / 2;

Just to add to the above, as a first port of call I'd try skipping all the manipulation of the received bytes to begin with, and just dump what you got over I2C. If that looks reasonable, then you probably have an issue with the manipulation code.

Serial.print's can seriously 'delay' your loop if you print a lot of debug. Increasing to 115200 is the first step, but even then you can have problems.
My tutorial Arduino Serial I/O for the Real World
shows you how to add a non-blocking Serial print buffer and includes an example of GPS parsing and debugging
But start with printing less debugging and then adding a loopTimer (from the tutorial) to see how slow the loop() is running.

Here is the code for the accelerometer coded alone:

#include <Wire.h>

unsigned long currentMillis;
short x,y,z;
float g_constant2 = 0.00241102;       // if accel set to 2G
float g_constant4 = 0.00482204;       // if accel set to 4G
float g_constant8 = 0.00964408;       // if accel set to 8G
float gx,gy,gz,grav;

int period = 199;
unsigned long time_now = 0;

void setup() {
  Wire.begin(4,5);
  Serial.begin(115200);
  Wire.beginTransmission(0x1c);        // put in standby mode
  Wire.write(0x2a);
  Wire.write(0x10);
  Wire.endTransmission();
  Wire.beginTransmission(0x1c);        // set scale to 8G
  Wire.write(0x0e);
  Wire.write(0x02);                    // 0x00 for 2G, 0x01 for 4G, 0x02 for 8G
  Wire.endTransmission();
  Wire.beginTransmission(0x1c);        // put in active mode
  Wire.write(0x2a);
  Wire.write(0x11);
  Wire.endTransmission();
}

void get_accel() {
  currentMillis = millis();
  int reg[6];
  int i;
  Wire.beginTransmission(0x1c);
  Wire.write(0x01);
  Wire.endTransmission(false);
  Wire.requestFrom(0x1c,6);
//  while(Wire.available() < 6) {
//    delay(1);
//  }
  for(i=0;i<6;i++) reg[i] = Wire.read();
  x = (reg[0] << 8) | reg[1];
  y = (reg[2] << 8) | reg[3];
  z = (reg[4] << 8) | reg[5];
  x = x >> 2;
  y = y >> 2;
  z = z >> 2;
  gx = x*g_constant8;
  gy = y*g_constant8;
  gz = z*g_constant8;
  grav = sqrt(sq(gx)+sq(gy)+sq(gz));
  Serial.print(gx,2); Serial.print(" ");
  Serial.print(gy,2); Serial.print(" ");
  Serial.print(gz,2); Serial.print(" ");
  Serial.println(grav,2); Serial.print(" ");
}

void loop() {
  if(millis() > time_now + period){
    time_now = millis();
    get_accel();
  }
}

Here is the result I get:

-0.41 0.41 9.79 9.81
 -0.35 0.42 9.80 9.81
 -0.39 0.44 9.77 9.79
 -0.38 0.42 9.80 9.81
 -0.41 0.37 9.82 9.83
 -0.35 0.37 9.83 9.84
 -0.35 0.39 9.83 9.84
 -0.39 0.42 9.78 9.80
 -0.36 0.39 9.81 9.82
 -0.37 0.43 9.80 9.81
 -0.39 0.41 9.81 9.82
 -0.37 0.43 9.73 9.75
.....continued

Here is the code for the everything together including magnetometer, accelerometer, GPS, and SD card with the GPS function in void loop commented out:

#include "NMEAGPS.h"
#include "SoftwareSerial.h"
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

File fd;

SoftwareSerial serial_connection(0, 4); //TX_GPS to D0, RX_GPS to D4
NMEAGPS gps;
const unsigned char ubxRate1Hz[] PROGMEM = 
{ 0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate5Hz[] PROGMEM =
{ 0x06,0x08,0x06,0x00,200,0x00,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate10Hz[] PROGMEM =
{ 0x06,0x08,0x06,0x00,100,0x00,0x01,0x00,0x01,0x00 };
const char baud38400 [] PROGMEM = "PUBX,41,1,3,3,38400,0";
int runoncevar = 0;

int maxX, maxY, maxZ;
int minX, minY, minZ;
int offX, offY, offZ;
short a,b,c;
unsigned long currentMillis;
short x,y,z;
float g_constant2 = 0.00241102;       // if accel set to 2G
float g_constant4 = 0.00482204;       // if accel set to 4G
float g_constant8 = 0.00964408;       // if accel set to 8G
float gx,gy,gz,grav,an;

int period = 199;
unsigned long time_now = 0;

void setup()
{
  Wire.begin(4,5);
  Serial.begin(115200);

//  if(!SD.begin(2)) {
//    Serial.println("Error init");
//    return;
//  }
//  SD.remove("data.csv");
//
//  fd = SD.open("data.csv",FILE_WRITE);
//  if(fd) {
//    fd.println("Time (ms),X_accel (m/s2),Y_accel (m/s2),Z_accel (m/s2),Mag_accel (m/s2),Direction (degrees)");
//    fd.close(); } else Serial.println("Error opening");
  
  serial_connection.begin(9600);
  gps.send_P( &serial_connection, (const __FlashStringHelper *) baud38400 );
  serial_connection.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  serial_connection.end();                                // empty the input buffer, too
  serial_connection.begin( 38400 );                      // use the new baud rate

  sendUBX( ubxRate5Hz, sizeof(ubxRate5Hz) );   // change both "ubxRate5Hz" to "ubxRate1Hz" or ubxRate10Hz" for different rates
 
  Serial.println( F("GPS Start") );  // F macro saves RAM

  Wire.beginTransmission(0x1c);        // put in standby mode
  Wire.write(0x2a);
  Wire.write(0x10);
  Wire.endTransmission();
  Wire.beginTransmission(0x1c);        // set scale to 8G
  Wire.write(0x0e);
  Wire.write(0x02);                    // 0x00 for 2G, 0x01 for 4G, 0x02 for 8G
  Wire.endTransmission();
  Wire.beginTransmission(0x1c);        // put in active mode
  Wire.write(0x2a);
  Wire.write(0x11);
  Wire.endTransmission();

  Wire.beginTransmission(0x0d);
  Wire.write(0x09);
  Wire.write(0x05);
  Wire.write(0x00);
  Wire.write(0x01);
  Wire.endTransmission();
  maxX = -32767; maxY = -32767; maxZ = -32767;
  minX = 32767; minY = 32767; minZ = 32767;
  offX = 0; offY = 0; offZ = 0;
}

void get_accel() {
  currentMillis = millis();
  int reg[6];
  int i;
  Wire.beginTransmission(0x1c);
  Wire.write(0x01);
  Wire.endTransmission(false);
  Wire.requestFrom(0x1c,6);
  for(i=0;i<6;i++) reg[i] = Wire.read();
  x = (reg[0] << 8) | reg[1];
  y = (reg[2] << 8) | reg[3];
  z = (reg[4] << 8) | reg[5];
  x = x >> 2;
  y = y >> 2;
  z = z >> 2;
  gx = x*g_constant8;
  gy = y*g_constant8;
  gz = z*g_constant8;
  grav = sqrt(sq(gx)+sq(gy)+sq(gz));

  if(millis() > time_now + period){
    time_now = millis(); 
    Serial.print(gx,2); Serial.print(" ");
    Serial.print(gy,2); Serial.print(" ");
    Serial.print(gz,2); Serial.print(" ");
    Serial.println(grav,2); Serial.print(" "); }
}

void get_mag() {
  int reg[6];
  int k;
  Wire.beginTransmission(0x0d);
  Wire.write(0x00);
  Wire.endTransmission(false);
  Wire.requestFrom(0x0d,6);
  for(k=0;k<6;k++) reg[k] = Wire.read();
  a = (reg[1] << 8) | reg[0];
  b = (reg[3] << 8) | reg[2];
  c = (reg[5] << 8) | reg[4];
  if (a > maxX) maxX = (int)a;
  if (a < minX) minX = (int)a;
  if (b > maxY) maxY = (int)b;
  if (b < minY) minY = (int)b;
  if (c > maxZ) maxZ = (int)c;
  if (c < minZ) minZ = (int)c;
  offX = (maxX + minX) / 2;
  offY = (maxY + minY) / 2;
  offZ = (maxZ + minZ) / 2;
  int fx = (int)a - offX;
  int fy = (int)b - offY;
  int fz = (int)c - offZ;
  an = atan2(fy,fz);
  an += 0.19; //declination angle based in Annapolis, MD
  if(an < 0)
    an += 2*PI;
  if(an > 2*PI)
    an -= 2*PI;
  an = an * 180.0 / PI;
  Serial.println(an);
}

void write_sd() {
  fd = SD.open("data.csv",FILE_WRITE);
  if(fd) {
    fd.print(currentMillis); fd.print(",");
    fd.print(gx,2); fd.print(","); fd.print(gy,2); fd.print(","); fd.print(gz,2); fd.print(",");
    fd.print(grav,2); fd.print(",");
    fd.println(an);
    fd.close(); } else Serial.println("Error opening");
}

void loop()
{
//  if (gps.available( serial_connection ))
//  {
//    //Get the latest info from the gps object which it derived from the data sent by the GPS unit
//    gps_fix fix = gps.read();
//    float ms = 0.447*(fix.speed_mph());
//
//    Serial.print( F("\nSpeed m/s:") );
//    if (fix.valid.speed)
//      Serial.print( ms );
//
//    if (fix.valid.time){
//    Serial.print( F("\nCentiSeconds:") );      
//      Serial.print( fix.dateTime_cs );
//      Serial.println();
//    
//    }
//    Serial.println();
//  }
  get_accel();
}

void sendUBX( const unsigned char *progmemBytes, size_t len )
{
  serial_connection.write( 0xB5 ); // SYNC1
  serial_connection.write( 0x62 ); // SYNC2

  uint8_t s = 0, t = 0;
  while (len-- > 0) {
    uint8_t u = pgm_read_byte( progmemBytes++ );
    s += u;
    t += s;
    serial_connection.write( u );
  }

  serial_connection.write( s ); // CHECKSUM A
  serial_connection.write( t ); // CHECKSUM B

}

Here is the output:

-0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
 -0.01 -0.01 -0.01 0.02
........continued

To me, it seems like the problem is in the initialization/void setup of the concatenated code.

I changed the baud rate to 115200, removing the indicated code out of the magnetometer made it operate incorrectly, and all of the Serial.print statements seem to not be affecting the code because it works in its own code.

Hopefully this helps. I'm not good at debugging and as I said, I'm definitely a beginner. I'm sorry if I'm being too difficult to help! I just don't know where to go from here.

UPDATE:

I commented out the following code at the beginning of the main program and the accelerometer data printed as needed. Obviously, the GPS program was not ran because it wasn't initialized due to commenting out this portion:

  serial_connection.begin(9600);
  gps.send_P( &serial_connection, (const __FlashStringHelper *) baud38400 );
  serial_connection.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  serial_connection.end();                                // empty the input buffer, too
  serial_connection.begin( 38400 );                      // use the new baud rate

  sendUBX( ubxRate5Hz, sizeof(ubxRate5Hz) );   // change both "ubxRate5Hz" to "ubxRate1Hz" or ubxRate10Hz" for different rates
 
  Serial.println( F("GPS Start") );  // F macro saves RAM

So when you have both:

SoftwareSerial serial_connection(0, 4); //TX_GPS to D0, RX_GPS to D4

and:

Wire.begin(4,5);

the I2C connection doesn't work?

What are the arguments to Wire.begin()? Are they pins?

Ha! That's exactly what it was. I just switched the serial_connection pin 4 to pin 2, and that solved the problem. The GPS prints as expected and the accel code prints as expected.

Thank you so much! If I have any other questions, I'll post again. I'm sure I'll have questions once it comes to writing to the SD card.

Alright. I have everything running smoothly and printing out all of the information I need in perfect time with the GPS. The only problem I have now is writing to the SD card.

When I comment the SD card code in, it will successfully write everything but the GPS speed. Sounds like drmpf was correct in that my current method of writing to the SD card would block the GPS data.

I looked at drmpf's link he provided in this post, but it looks like I may need different parts.

drmpf:
A couple of points,
First put you accel/mag sampling is a separate method and call it on a repeating timer (see my links above)
Set the timer to repeat every 200mS. (Also a good way to combine the two sketches)
Second your calls to the SD card can block every now and again for a second or so so that will slow things down and you will miss GPS and accel data.
See my project on High Speed SD data logging It has a link to an Uno Mega version. It logs at much higher speed then you need, but includes code to pre-allocate file blocks to minimize long delays when writing to the SD card.

Is there a simpler way to write all of the data to the SD card? All I need to do is also write the GPS data... everything else is currently accounted for when writing to the SD card.
I've provided my current code below:

#include "NMEAGPS.h"
#include "SoftwareSerial.h"
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

File fd;

SoftwareSerial serial_connection(0, 2); //TX_GPS to D0, RX_GPS to D2
NMEAGPS gps;
const unsigned char ubxRate1Hz[] PROGMEM = 
{ 0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate5Hz[] PROGMEM =
{ 0x06,0x08,0x06,0x00,200,0x00,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate10Hz[] PROGMEM =
{ 0x06,0x08,0x06,0x00,100,0x00,0x01,0x00,0x01,0x00 };
const char baud38400 [] PROGMEM = "PUBX,41,1,3,3,38400,0";
int runoncevar = 0;

int maxX, maxY, maxZ;
int minX, minY, minZ;
int offX, offY, offZ;
short a,b,c;
unsigned long currentMillis;
short x,y,z;
float g_constant2 = 0.00241102;       // if accel set to 2G
float g_constant4 = 0.00482204;       // if accel set to 4G
float g_constant8 = 0.00964408;       // if accel set to 8G
float gx,gy,gz,grav,an;
float speed_ms;

int period = 199;
unsigned long time_now = 0;

void setup()
{
  Wire.begin(4,5);
  Serial.begin(115200);

//  if(!SD.begin(15)) {
//    Serial.println("Error init");
//    return;
//  }
//  SD.remove("data.csv");
//
//  fd = SD.open("data.csv",FILE_WRITE);
//  if(fd) {
//    fd.println("Time (ms),Accel_x (m/s2),Accel_y (m/s2),Accel_z (m/s2),Accel_mag (m/s2),Mag_dir (degrees),Vel (m/s)");
//    fd.close(); } else Serial.println("Error opening");
  
  serial_connection.begin(9600);
  gps.send_P( &serial_connection, (const __FlashStringHelper *) baud38400 );
  serial_connection.flush();                              // wait for the command to go out
  delay( 100 );                                  // wait for the GPS device to change speeds
  serial_connection.end();                                // empty the input buffer, too
  serial_connection.begin( 38400 );                      // use the new baud rate

  sendUBX( ubxRate5Hz, sizeof(ubxRate5Hz) );   // change both "ubxRate5Hz" to "ubxRate1Hz" or ubxRate10Hz" for different rates
 
  Serial.println( F("GPS Start") );  // F macro saves RAM

  Wire.beginTransmission(0x1c);        // put in standby mode
  Wire.write(0x2a);
  Wire.write(0x10);
  Wire.endTransmission();
  Wire.beginTransmission(0x1c);        // set scale to 8G
  Wire.write(0x0e);
  Wire.write(0x02);                    // 0x00 for 2G, 0x01 for 4G, 0x02 for 8G
  Wire.endTransmission();
  Wire.beginTransmission(0x1c);        // put in active mode
  Wire.write(0x2a);
  Wire.write(0x11);
  Wire.endTransmission();

  Wire.beginTransmission(0x0d);
  Wire.write(0x09);
  Wire.write(0x05);
  Wire.write(0x00);
  Wire.write(0x01);
  Wire.endTransmission();
  maxX = -32767; maxY = -32767; maxZ = -32767;
  minX = 32767; minY = 32767; minZ = 32767;
  offX = 0; offY = 0; offZ = 0;
}

void get_accel() {
  currentMillis = millis();
  int reg[6];
  int i;
  Wire.beginTransmission(0x1c);
  Wire.write(0x01);
  Wire.endTransmission(false);
  Wire.requestFrom(0x1c,6);
  for(i=0;i<6;i++) reg[i] = Wire.read();
  x = (reg[0] << 8) | reg[1];
  y = (reg[2] << 8) | reg[3];
  z = (reg[4] << 8) | reg[5];
  x = x >> 2;
  y = y >> 2;
  z = z >> 2;
  gx = x*g_constant8;
  gy = y*g_constant8;
  gz = z*g_constant8;
  grav = sqrt(sq(gx)+sq(gy)+sq(gz));

  Serial.print("Accel_x: "); Serial.println(gx,2);
  Serial.print("Accel_y: "); Serial.println(gy,2);
  Serial.print("Accel_z: "); Serial.println(gz,2);
  Serial.print("Accel_mag: "); Serial.println(grav,2);
}

void get_mag() {
  int reg[6];
  int k;
  Wire.beginTransmission(0x0d);
  Wire.write(0x00);
  Wire.endTransmission(false);
  Wire.requestFrom(0x0d,6);
  for(k=0;k<6;k++) reg[k] = Wire.read();
  a = (reg[1] << 8) | reg[0];
  b = (reg[3] << 8) | reg[2];
  c = (reg[5] << 8) | reg[4];
  if (a > maxX) maxX = (int)a;
  if (a < minX) minX = (int)a;
  if (b > maxY) maxY = (int)b;
  if (b < minY) minY = (int)b;
  if (c > maxZ) maxZ = (int)c;
  if (c < minZ) minZ = (int)c;
  offX = (maxX + minX) / 2;
  offY = (maxY + minY) / 2;
  offZ = (maxZ + minZ) / 2;
  int fx = (int)a - offX;
  int fy = (int)b - offY;
  int fz = (int)c - offZ;
  an = atan2(fy,fz);
  an += 0.19; //declination angle based in Annapolis, MD
  if(an < 0)
    an += 2*PI;
  if(an > 2*PI)
    an -= 2*PI;
  an = an * 180.0 / PI;
  Serial.print("Mag_degrees: "); Serial.println(an);
}

void write_sd() {
  fd = SD.open("data.csv",FILE_WRITE);
  if(fd) {
    fd.print(currentMillis); fd.print(",");
    fd.print(gx,2); fd.print(","); fd.print(gy,2); fd.print(","); fd.print(gz,2); fd.print(",");
    fd.print(grav,2); fd.print(","); fd.print(an); fd.print(","); fd.println(speed_ms);
    fd.close(); } else Serial.println("Error opening");
}

void loop()
{
  if (gps.available( serial_connection ))
  {
    //Get the latest info from the gps object which it derived from the data sent by the GPS unit
    gps_fix fix = gps.read();
    float ms = 0.447*(fix.speed_mph());
    //ms = speed_ms;
  
    Serial.print( F("\nSpeed m/s: ") );
    if (fix.valid.speed)
      Serial.print( ms );

    if (fix.valid.time){
    Serial.print( F("\nCentiSeconds: ") );      
      Serial.print( fix.dateTime_cs );
      Serial.println();
    }
    
  }
  if(millis() > time_now + period){
    time_now = millis(); 
    get_accel();
    get_mag();
  //  write_sd();
  }
}

void sendUBX( const unsigned char *progmemBytes, size_t len )
{
  serial_connection.write( 0xB5 ); // SYNC1
  serial_connection.write( 0x62 ); // SYNC2

  uint8_t s = 0, t = 0;
  while (len-- > 0) {
    uint8_t u = pgm_read_byte( progmemBytes++ );
    s += u;
    t += s;
    serial_connection.write( u );
  }

  serial_connection.write( s ); // CHECKSUM A
  serial_connection.write( t ); // CHECKSUM B

}

Thanks!

Now you are seeing why

It is a really bad idea to open a file, write a few bytes, then close it again. Open the SD file ONCE in setup() and then close it again when you are done collecting data. As it is now, the program will be very slow and the SD card error rate will be high.

Okay this makes sense.

What would be a good method to "close" writing the data to the SD card? My goal is to continue collecting data until the device is turned off.

If necessary, add a button to stop data collection and close the file. Then power off.

This can be the same button as the "start data collection" button, which is always handy. On my loggers, I require that the button be pressed for one second, to prevent accidental start/stops. It is also a good idea to have an LED flash to acknowledge the button press or the logging/not logging machine state.

If the device powers off unexpectedly, you will lose part of the very last block of data, but that is the tradeoff you have to make for fast write access to the SD card.

Do I have to use a button/external component? Or can I solve this issue with just code?

I've looked into flush() as well. I don't know if this could be used instead.

The beauty of Arduino is that you can easily try different things and determine for yourself what is best.

Is there a way to store the measurement for velocity and print it to the SD card file?

My velocity measurement (ms) refreshes inside the statement:

void loop()
{
if (gps.available( serial_connection ))
{
//Get the latest info from the gps object which it derived from the data sent by the GPS unit
gps_fix fix = gps.read();
float ms = 0.447*(fix.speed_mph());

But how I have the code currently configured, since it is inside this if statement, I cannot print it to the SD card.

Do you understand what I’m asking?

See reply #13.

I posted my code, I've tried my method, and it's not working.

jremington:
This part of the forum is usually for helping people fix problems with code they have written.

I'm asking to help fix the problem with the code I have written.

agearha2:
Is there a way to store the measurement for velocity and print it to the SD card file?

My velocity measurement (ms) refreshes inside the statement:

void loop()
{
if (gps.available( serial_connection ))
{
//Get the latest info from the gps object which it derived from the data sent by the GPS unit
gps_fix fix = gps.read();
float ms = 0.447*(fix.speed_mph());

But how I have the code currently configured, since it is inside this if statement, I cannot print it to the SD card.

Do you understand what I’m asking?

You can either:

  • Make the speed reading of global scope (i.e. declare a variable outside any function), and write the speed to that variable. The function writing the SD card can then read from that variable.
  • Pass the speed variable as an argument into the function which writes to the SD card.

I'd personally sooner the latter, and moreover, I would pass in all the data you want to write out as arguments. For a program of this size using globals isn't too big of a deal, but it soon becomes difficult to track what updates which variable when as code becomes more complex.

Or have I misunderstood your question?

Thank you, Tom. I was able to create a global variable, update it every loop, and write that updated variable to the SD card. You've been a really great help, so thank you.

My final ask: I want to wire an LED that turns on while the device is writing data to the SD card and turns off if there's an interruption (i.e. a wire comes loose and stops writing data to the SD card).

I have the LED and everything ready to go, I just don't know where to start with the code. Could I do something like this? (assuming LED is wired to pin 16)

if (fd.close()) {
digitalWrite(16,LOW); }
else digitalWrite(16,HIGH)

Thanks again!

I'm glad you're making progress :slight_smile:

agearha2:
I have the LED and everything ready to go, I just don't know where to start with the code. Could I do something like this? (assuming LED is wired to pin 16)

if (fd.close()) {
digitalWrite(16,LOW); }
else digitalWrite(16,HIGH)

Thanks again!

Not exactly: there are two problems here.

Firstly, the manual for the SD library (SD - Arduino Reference) shows that the File::close() method returns void (i.e. nothing). So the if statement here wouldn't make any sense. (If you're used to POSIX I/O you're possibly thinking of the close() function, which does have a return).

Secondly, File::close() closes the file, which I think you only want to do when the "stop logging" button is pressed. In which case the status LED is maybe not so useful.

In terms of doing what you want, I think you could check the return from the File::print() function, which will tell you how many bytes it wrote. If you know how many it should have written, you can figure out if it failed to write some data (caveat: I think this is probably true; but there may be layers of indirection in the SD library -- I have not checked). That's the path I would look into if I were you.

If you do go down this route, personally I'd probably tweak the writeout approach slightly so that the data is written to an intermediary buffer first. It's then easy to determine how many bytes you expect to be written -- it's possibly a bit tedious figuring out what all the print() calls are going to do.

Tom,

I really appreciate the advice and help because it's going a long way.

As for how many bytes it "should" have printed, that's not an applicable method for what I want to do. Basically, I want the device to continue collecting data until I turn it off (so how many bytes "should" have been written will almost always be different).

Since the wires to my board aren't soldered (and I don't plan to solder them), they can come loose and stop collecting data onto the SD card. I want the LED to come on if this is ever the case (because it happens all the time).

I tried this function, but I don't think it's working:

    if(fd) {
      digitalWrite(16,HIGH); } else digitalWrite(16,LOW);

Where:

  fd = SD.open("data.csv",FILE_WRITE);

Is there a way to constantly read the bytes, and to turn OFF the LED in the event that the bytes are no longer increasing?