[SOLVED] Writing limitations to SD card after ~250 writings?

###SOLVED###
Failed by design. To many open files
###/SOLVED###

I've wrote a measured value every 0.025 seconds to an sd card.
that works fine so far.
but after ~250 times (+/-25) it fails.
In SerialMonitor it fails e.g. after 266 writings, but the file has just written 237 times.

Any idea why that happened?

SerialMonitor Output: http://paste.osuv.de/index.php/okQs/
TXT Output: http://paste.osuv.de/index.php/EtWt/

And this is my code:

/*
  Voltage-Logger
 
 SD Card Pins
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 10
 
Voltage-Input
analogInput = 1
 	 
 */
#include <SD.h>

File myFile;
  int analogInput = 1;
  int refresh = 200;
  float vout = 0.0;
  float vin = 0.0;
  float R1 = 46300.0;    // !! resistance of R1 !!
  float R2 = 4630.0;     // !! resistance of R2 !!
  int value = 0;
  long startTime;    // to keep track of when the last action was
  int duration = 100; // 0,1 sekunden
    
    
    
    void setup(){

  // declaration of pin modes
  pinMode(analogInput, INPUT);
  // begin sending over serial port
  Serial.begin(9600);
  
   Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

}


void loop()
{
  
  	char ch = '0'; //alles nur nicht 1, damit der loop nicht direkt am anfang ohne eingabe startet
	while (1) //while(true) = endlosschleife 
	{
		if (Serial.available() >0) //wenn Serial Eingabe groesser als 0 ist
		{
			ch = Serial.read(); //lies am seriel inputt
			if (ch == '0') //wenn input == null ist
				halt(); //anhalten
		}
		if (ch == '1') // wenn input == 1 ist
			startlogging(); //start logging
	}
  
}


void startlogging()
{
  startTime = millis();  
  value = analogRead(analogInput);
  vout = (value * 5.0) / 1024.0;
  vin = vout / (R2/(R1+R2));
  
 // if (millis() >= startTime + duration)     // delay

    // {
  		myFile = SD.open("logging2.txt", FILE_WRITE);
  
  		// if the file opened okay, write to it:
  		if (myFile) {
   
    			myFile.print(startTime, 4);
    			myFile.print(", ");
    			myFile.print(vout);
    			myFile.println();
			// close the file:
    			myFile.close();
    			Serial.println("done.");
  		} else {
    		// if the file didn't open, print an error:
    		Serial.println("error opening test.txt");
  	}
  
 delay(25);
  
}
//}

void halt()
{
   myFile.close();
}

The loop() function is called in an endless loop. What purpose does it serve to create an infinite loop inside an infinite loop?

    			myFile.print(startTime, 4);

You want to print the time in base 4? Why? Seems a strange base to me...

Perhaps the thing you need to do is open the file once, then close it in the halt() function, rather than opening and closing the file every 25 milliseconds.

PaulS:
The loop() function is called in an endless loop. What purpose does it serve to create an infinite loop inside an infinite loop?

Yay, because

  if (Serial.available()) //wenn daten am usb port ankommen
  { 
  	ch=Serial.read();
	if(ch == 0)
		{
			halt();
		}
		else
		{
			startlogging();
		}
	}
}

just starts startlogging() just one time.

PaulS:

    			myFile.print(startTime, 4);

You want to print the time in base 4? Why? Seems a strange base to me...

This was just a bit playground. I just need a straight forward timeline

PaulS:
Perhaps the thing you need to do is open the file once, then close it in the halt() function, rather than opening and closing the file every 25 milliseconds.

This fails now after ~40 writings.

markuman:

  if (Serial.available()) //wenn daten am usb port ankommen

{
  ch=Serial.read();
if(ch == 0)
{
halt();
}
else
{
startlogging();
}
}
}

Even if i use this code instead of the while loop, it fails writing after 23 times.

http://paste.osuv.de/index.php/0lM0/

/*
  Voltage-Logger
 
 SD Card Pins
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 10
 
Voltage-Input
analogInput = 1
 	 
 */
#include <SD.h>

File myFile;
  int analogInput = 1;
  int refresh = 200;
  float vout = 0.0;
  float vin = 0.0;
  float R1 = 46300.0;    // !! resistance of R1 !!
  float R2 = 4630.0;     // !! resistance of R2 !!
  int value = 0;
  long startTime;    // to keep track of when the last action was
  int duration = 100; // 0,1 sekunden
  char ch = '0'; //alles nur nicht 1, damit der loop nicht direkt am anfang ohne eingabe startet
  
    
    
    
    void setup(){

  // declaration of pin modes
  pinMode(analogInput, INPUT);
  // begin sending over serial port
  Serial.begin(9600);
  
   Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

}


void loop()
{
  
  	

  if (Serial.available()) //wenn daten am usb port ankommen
  { 
  	ch=Serial.read();
	if(ch == 0)
		{
			halt();
		}
		else
		{
			startlogging();
		}
	}
}

//	while (1) //while(true) = endlosschleife 
//	{
//		if (Serial.available() >0) //wenn Serial Eingabe groesser als 0 ist
	//	{
	//		ch = Serial.read(); //lies am seriel inputt
	//		if (ch == '0') //wenn input == null ist
	//			halt(); //anhalten
	//	}
	//	if (ch == '1') // wenn input == 1 ist
		//	startlogging(); //start logging
	//}
  
//}


void startlogging()
{
  startTime = millis();  
  value = analogRead(analogInput);
  vout = (value * 5.0) / 1024.0;
  vin = vout / (R2/(R1+R2));
  
 // if (millis() >= startTime + duration)     // delay

    // {
  		myFile = SD.open("logging3.txt", FILE_WRITE);
  
  		// if the file opened okay, write to it:
  		if (myFile) {
   
    			myFile.print(startTime);
    			myFile.print(", ");
    			myFile.print(vout);
    			myFile.println();
			// close the file:
    			//myFile.close();
    			Serial.println("done.");
  		} else {
    		// if the file didn't open, print an error:
    		Serial.println("error opening test.txt");
  	}
  
 delay(25);
  
}
//}

void halt()
{
  Serial.println("Nothing to do here...");
   myFile.close();
}

just starts startlogging() just one time.

It wouldn't if ch was declared static and set at the appropriate time/place (only when there was serial data).

This fails now after ~40 writings.

Please describe how you detect a failure.

PaulS:

This fails now after ~40 writings.

Please describe how you detect a failure.

	if (myFile) {
   
    			myFile.print(startTime);
    			myFile.print(", ");
    			myFile.print(vout);
    			myFile.println();
			// close the file:
    			//myFile.close();
    			Serial.println("done.");
  		} else {
    		// if the file didn't open, print an error:
    		Serial.println("error opening test.txt");
  	}

i get "done" feedback in serial monitor for every print/write until it failed.

i'm guessing the library gets in trouble when to many files are opened !?

so i have to open the file one time in void.setup when start logging and close it in void.setup when stop logging. (not try yet, will do it soon)
but that would not explain why it fails in my first code version, where the file was opened and closed in every measure step.

i'm guessing the library gets in trouble when to many files are opened !?

Yes. Why is the close commented out?

so i have to open the file one time in void.setup when start logging and close it in void.setup when stop logging. (not try yet, will do it soon)

You could do it that way. I wouldn't. I'd open the file when the request came to start logging. I'd close it when the request came to stop logging.

but that would not explain why it fails in my first code version, where the file was opened and closed in every measure step.

No, but opening and closing the file requires searching for the end of the file every time, and is to be avoided if you want to log quickly.

PaulS:

so i have to open the file one time in void.setup when start logging and close it in void.setup when stop logging. (not try yet, will do it soon)

You could do it that way. I wouldn't. I'd open the file when the request came to start logging. I'd close it when the request came to stop logging.

yay, i was wrong with my explanation (bad english skills and interchanged void.setup and void.loop). i've meant just opening one time for logging and closing when stopping. however, like that way it seems to work now. but now i can't stop it anymore with 0 input on serial monitor.

the code looks now like this http://paste.osuv.de/index.php/tIyOO/
but there is a lot of unused waste in it now.

	if(ch == 0)

How are you sending data to the Arduino? Sending a binary 0 seems like a strange thing to do.

startlogging() is incorrectly named, since it does not start the logging. The else clause is misplaced, now, since the file is not created in startlogging().

PaulS:

	if(ch == 0)

How are you sending data to the Arduino? Sending a binary 0 seems like a strange thing to do.

With ch=Serial.read();
and now with char ch = '0';
don't?

PaulS:
startlogging() is incorrectly named, since it does not start the logging.

O_o but it starts. that works fine. stopping don't work.

PaulS:
The else clause is misplaced, now, since the file is not created in startlogging().

i've created the file when checking for ch (serial.read).
and startlogging will just execute when ch get's something else, but not 0. and if ch is not 0, i've opened the file.

With ch=Serial.read();
and now with char ch = '0';
don't?

I'm not sure how, or if, this answers my question.
I'd do something like this:

  if (Serial.available()) //wenn daten am usb port ankommen
  { 
     ch=Serial.read();
     if(ch == 'S')
     {
        myFile = SD.open("logging3.txt", FILE_WRITE);
     }
     else if(ch == 'Q')
     {
        halt();
     }
  }

  if(ch == 'S')
  {
      startlogging();
  }

PaulS:
I'd do something like this:

Ah okey, this works fine. Thank you!