File XXXX = SD.open causes SD card init to repeat

I am trying to pull gps data from my adafruit ultimate gps sheild and datalog it to an sd card using my UNO rev3. I am having an issue where in the serial monitor it shows "Initializing SD card...card initialized." repeating over and over until I disconnect the Arduino. I started with a new sketch, and added small chunks of my code until I found the parts doing it. As soon as I add "File dataFile = SD.open("datalog.csv",FILE_WRITE);" it will throw 4-5 lines of the card initialized, but then when I add else statement at the bottom, thats when it starts doing an endless loop of displaying the card initialized line. Any pointers would be excellent. Im fairly new to this, but have been comparing what I have to other sketches, and I am not seeing where things are going wrong.

The SD card is an 8gig card formated as fat32. I have run the sketches in the SD library, and it will pull the SD card data, so at this point I dont think its the card. I do have a few others on their way to mess with though.

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

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

#define GPSECHO true
#define chipSelect 10

File datafile;

void setup() {
  Serial.begin(115200);
  pinMode(10, OUTPUT);
  pinMode(10, HIGH);

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  GPS.begin(9600);

  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_10HZ);

  delay(250);

}

uint32_t timer = millis();

void loop() {
  char c = GPS.read();
  if (c)
    //Serial.write(c);
    if (GPS.newNMEAreceived()) {
      if (!GPS.parse(GPS.lastNMEA()))
        return;
    }

  if (timer > millis()) timer = millis();
  if (millis() - timer > 250) {
    timer = millis();

  }

float mph;
mph = (GPS.speed) * 1.15;

String timestamp = String(GPS.hour, DEC) + (":") + String(GPS.minute, DEC) + (":") + String(GPS.seconds, DEC);
String date = String(GPS.month, DEC) + ("/") + String(GPS.day, DEC) + ("/20") + String(GPS.year, DEC);

File dataFile = SD.open("datalog.csv",FILE_WRITE);

  if (datafile) {
    if (GPS.fix == 1) {
    Serial.print("Date: ");
    //Serial.print(date);
    Serial.print(", ");
    //Serial.print(timestamp);
    Serial.print(", ");
    Serial.print(GPS.latitudeDegrees, 8);
    Serial.print(", ");
    Serial.print(GPS.longitudeDegrees, 8);
    Serial.print(", ");
    Serial.print("Speed: ");
    Serial.println(mph);
    datafile.print(GPS.latitudeDegrees, 8);
    datafile.print(", ");
    datafile.println(GPS.longitudeDegrees, 8);
    datafile.close();
    }
    // if the file isn't open, pop up an error:
    else {
    Serial.println("error opening datalog.csv");
    }
  }
}

You should not open the file, write a bit of data and close it again, as that vastly increases the error rate and the current draw (an entire sector buffer has be read and written each open/close).

Open the file once in setup(), write a bunch of data, and when you are done collecting, close the file. You should occasionally execute datafile.flush(); (e.g. every hour or day) to keep the file pointers updated.

That may not be not the cause of the .begin() problem, though. Perhaps the Arduino is resetting/rebooting due to an inadequate power supply. Post the details of the setup.

I have the arduino plugged into my surface pro 8 with a usb cable. The adafruit ultimate gps shield is attached to the pins directly on the UNO rev3

So if I open the file in setup() where would I close the file, would that happen in the loop() if some condition is met?

Yes. A button push to start/stop data collection comes to mind.

File datafile;

and

File dataFile = SD.open("datalog.csv",FILE_WRITE);

You seem to have 2 objects of type File named datafile. Could that be a problem ?

What happens of you change the second one to

dataFile = SD.open("datalog.csv",FILE_WRITE);

Good point! The second "dataFile" would be a local variable.

for this project a push button wouldnt be possible. maybe for testing it could, but in the end it needs to start and stop recording based on vehicle speed. I havent got that point of the project though. I just wanted to validate that things could be written to the SD card at this point.

No problem, just write the code.

Get rid of the second "File" keyword as suggested above.

the File dataFile = SD.open was a typo, that should have been

File datafile = SD.open

So in the code now, I have removed the File datafile; and now I have the below. When I compile it, I get an error "Compilation error: 'dataFile' was not declared in this scope". In the IDE it has this highlighted for the error.

  if (datafile) {
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

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

#define GPSECHO true
#define chipSelect 10


void setup() {
  Serial.begin(115200);
  pinMode(10, OUTPUT);
  pinMode(10, HIGH);

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  File datafile = SD.open("datalog.csv",FILE_WRITE);

  GPS.begin(9600);

  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_10HZ);

  delay(250);

}

uint32_t timer = millis();

void loop() {
  char c = GPS.read();
  if (c)
    //Serial.write(c);
    if (GPS.newNMEAreceived()) {
      if (!GPS.parse(GPS.lastNMEA()))
        return;
    }

  if (timer > millis()) timer = millis();
  if (millis() - timer > 250) {
    timer = millis();

  }

float mph;
mph = (GPS.speed) * 1.15;

String timestamp = String(GPS.hour, DEC) + (":") + String(GPS.minute, DEC) + (":") + String(GPS.seconds, DEC);
String date = String(GPS.month, DEC) + ("/") + String(GPS.day, DEC) + ("/20") + String(GPS.year, DEC);



  if (datafile) {
    if (GPS.fix == 1) {
    Serial.print("Date: ");
    //Serial.print(date);
    Serial.print(", ");
    //Serial.print(timestamp);
    Serial.print(", ");
    Serial.print(GPS.latitudeDegrees, 8);
    Serial.print(", ");
    Serial.print(GPS.longitudeDegrees, 8);
    Serial.print(", ");
    Serial.print("Speed: ");
    Serial.println(mph);
    datafile.print(GPS.latitudeDegrees, 8);
    datafile.print(", ");
    datafile.println(GPS.longitudeDegrees, 8);
    datafile.close();
    }
    // if the file isn't open, pop up an error:
    else {
    Serial.println("error opening datalog.csv");
    }
  }
}

Put this above setup() to declare a global variable, and remove the "File" keyword from the open statement.

You are strongly advised to avoid using Strings. They are never necessary, and on AVR-based Arduinos, they lead to memory corruption and program crashes.

okay, I will take a look at doing something different for the date and time stamp then. thanks for pointing that out,

So with the updates you suggested, its now printing something other than the card initialized, but its still repeating things

Looks like the Arduino is rebooting. That is typically a power supply problem.

SD cards are power hungry, and a write operation can draw a hundred mA or more. You may be overloading the 3.3V regulator, if that is where the SD card power is coming from.

Tha'ts because datafile is a local variable declared in setup(). Declare it as a global

File datafile;

Then use it anywhere in the sketch but do not precede its name with File as this will create a second variable with the same name but a different scope

looking at the data sheet, it appears to be 3.3v, so is the SD card something that just isnt going to work with the UNO then do you know? Is there another route that you would suggest that would work for this?

The SD card is strictly 3.3V and cannot be directly connected to a 5V Arduino without logic level shifters. However the card module may have shifters on board.

Please post links to the modules, a wiring diagram and a photo of the setup.

char c = GPS.read();

You should be checking whether characters are available before reading. There appear to be quite a number of problems with the code,

datafile is not the same as dataFile

I dont have a wiring diagram as the shield mounts directly onto to UNO.

ya it was a typo on my part, its been corrected at this point.

Since that is an Adafruit product, you will probably get better advice on the Adafruit customer service forum.

Ok. I appreciate the help you give though. It's much appreciated.