Why does this code lag so much?

I understand that I am probably doing things inefficient because I am still relatively new to this. I am using an Arduino Mega 2560, an MPL3114A2 and the Adafruit SD card breakout board. I want to log the data as fast as I possibly can, and this is recording data about every 2 seconds, extremely slow considering I have no delay, at least in my opinion. I have no idea what it could be! Is it just how long it takes to receive data from the sensor or write to the SD card? Please help!

#include <SD.h> // So the SD card can be accessed
#include <Wire.h> // So we can communicate over I2C
#include <Adafruit_MPL3115A2.h> // Library for accessing the MPL3115A2 altimeter/barometer/temperature sensor

Adafruit_MPL3115A2 altimeterBoard = Adafruit_MPL3115A2(); // Initializes new altimeter object
const int chipSelect = 53; // Chip select pin (default)
const int chipDetect = 22; // Chip detect pin
String fileName = "log.txt"; // Log file name
int cardInLast = 0; // Variable that stores if the card was in last time the program checked
int altLast = 0; // Variable that stores if the altimeter board was registered last or if it lost connection
int indicatorState = 0;

float altitude = 0.0f; // Stores currect altitude
float pressure = 0.0f; // Stores current pressure
float temperature = 0.0f; // Stores current temperature

void setup() {
      Serial.begin(9600); // 9600 baud rate!!!
      while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  pinMode(13, OUTPUT); // Init for indicator LED
  pinMode(chipDetect, INPUT_PULLUP); // Init for chip detect pin, internal pullup resistor enabled

  //Initializes SD card and returns an error if inititalization fails
  Serial.println("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("Card initialization failed, or card not present");
    return; // Exits setup if the card fails
  }
  Serial.println("card initialized.");
  writeToSD(fileName, "Program Started"); // Writes a message in the log file on the SD card that at this point it starts a new output session
  cardInLast = 1; // Stores that the card was in during first initialization
}


void loop() {
   if (!altimeterBoard.begin()) {
    Serial.println("Couldnt find MPL3115A2 sensor");
    altLast = 0;
  }
  else
  {
    altLast = 1;
    altitude = altimeterBoard.getAltitude(); // Reads altitude in meters
    pressure = altimeterBoard.getPressure(); // Reads pressure in pascals
    temperature = altimeterBoard.getTemperature(); // Reads temperature in degrees celsius
  }
  
  if (digitalRead(chipDetect) == 1 && altLast == 1){ // Checks if there is a SD card insterted into the datalogger and all the sensors are online
    if (cardInLast == 0){ // Checks if the card was just put in
      
      Serial.println("Initializing SD card...");
      if (!SD.begin(chipSelect)) { // Re-inititalizes the SD card
        Serial.println("Card initialization failed, or card not present");
      }
      else
      {
        Serial.println("card initialized."); 
      }
      
      writeToSD(fileName, "Program Restarted"); // Writes a message in the log file on the SD card that at this point it starts a new output session
    }
    cardInLast = 1; // Stores that the card is in for next loop
    digitalWrite(13, LOW); // Sets the LED to low to indicate no attention is needed
    String dataString = String(millis() / 1000) + ", "  + String(altitude) + ", " + String(pressure) + ", " + String(temperature);
    writeToSD(fileName, dataString); // Writes the data to the SD card
  }
  else
  {
    cardInLast = 0; // If the card was not in this time around, store that
    digitalWrite(13, HIGH); // Set the indicator LED to high to indicate the SD card is damaged/removed/corrupt
  }
}

int writeToSD(String fileName, String data) { // Function that writes to the SD card
  File dataFile = SD.open(fileName, FILE_WRITE); // Creates a temporary file variable
  if (dataFile) { // If the file has been opened successfully
    dataFile.println(data); // Writes the data
    dataFile.close(); // Flushes the buffer and closes file
  }
  else {
    return 1; // If the file could not be opened, return an error code
  }
}

How long does it take to read from the sensor? and How long does it take to write to the card?

Opening and closing a file takes time. As said above, time it to know.

You also have a bug in writeToSD. It only returns a value in failure. As a result, it 'returns' rubbish on success.
As you don't check the return value, it's a none-issue. But it's a bug anyway.

Why are you starting the altimeter each time in loop and not once in setup?

void loop() {
   if (!altimeterBoard.begin()) {

The reinitialization with sd.begin() in loop if the card has been pulled will not work with SD.h.

You have to use the SdFat library or modify the code in SD.h.
http://forum.arduino.cc/index.php?topic=46969.msg339113#msg339113

Okay, first of all I will have to time it this evening I am not able to at the moment, I will do that. All I know is that it takes about 2 seconds for all of it. Thank you for pointing out the bug! I start the altimeter each time because 1, it is what is in the example code in the Adafruit library 2, and I also want, if the sensor looses connection for any reason that would reinitialize it so it can be used again. Also, I modified the SD library that allows the reinitializaction to work. This all works it just is extremely slow... except for the return bug.

filbertwatson:
I start the altimeter each time because 1, it is what is in the example code in the Adafruit library 2, and I also want, if the sensor looses connection for any reason that would reinitialize it so it can be used again.

I have not seen that example code, but I have seen example code that misuses loop as setup extension,
often by having a while(true); at the end, stopping loop from looping.

I still see no reason to do so each cycle of loop (which should be thousands of times a second).

I have seen many begin() functions use delay(), probably because it does not really matter in their normal context, which is setup.
Used in loop this will slow it down badly.

I would reinitialize the altimeter only after failing.

I like your quote there btw, but how would I test if it failed anyway?

I don't know your altimeter, if you don't know how to detect failing how could I?

cattledog:
The reinitialization with sd.begin() in loop if the card has been pulled will not work with SD.h.

You have to use the SdFat library or modify the code in SD.h.
SD lib:SD.exists() returns TRUE if SD is removed - #12 by system - Bugs & Suggestions - Arduino Forum

How could he (or any of us newbs) know that SD.h no longer does what Adafruit thought it did when they wrote the sketch?

I only ask because I have yet to acquire confidence in any of the libraries I have met, most of which seem to alter with time.

Here is the begin() code from the library. As suggested before, you can determine the amount of time it takes to run the function. It doesn't appear like it will be a significant part of two seconds.

boolean Adafruit_MPL3115A2::begin() {
  Wire.begin();
  uint8_t whoami = read8(MPL3115A2_WHOAMI);
  if (whoami != 0xC4) {
    return false;
  }

  write8(MPL3115A2_CTRL_REG1,
 MPL3115A2_CTRL_REG1_SBYB |
 MPL3115A2_CTRL_REG1_OS128 |
 MPL3115A2_CTRL_REG1_ALT);
  write8(MPL3115A2_PT_DATA_CFG, 
 MPL3115A2_PT_DATA_CFG_TDEFE |
 MPL3115A2_PT_DATA_CFG_PDEFE |
 MPL3115A2_PT_DATA_CFG_DREM);
  return true;
}

Since the failure is just dependent upon reading back a fixed WHOAMI register (0x0C) from the device it could reasonably be replaced with a basic i2c bus query.

Wire.beginTransmission (MPL3115A2_ADDRESS);//0x60
  if (Wire.endTransmission () != 0)
  { 
    //error condition
  }

I was finally able to get home to test all of this, so far the data I have collected is that it takes 983 milliseconds to read pressure, 1005 to read altitude, and 11 to read temperature. The re-initialization of the sensor only takes 1 millisecond I have come to find out as well. With this information combined with the SD card write speed I think I have it figured out as to why it takes SO long to do anything, thank you for all of your help I am going to try to implement everything you guys have given me. I will check back if I have any more questions about this

Oh one more question, is Sdfatlib faster than the Adafruit SD library?

Oh one more question, is Sdfatlib faster than the Adafruit SD library?

Yes.