Pages: [1]   Go Down
Author Topic: [SOLVED] Writing limitations to SD card after ~250 writings?  (Read 1037 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

###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:

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();
}

« Last Edit: May 23, 2012, 02:54:16 pm by markuman » Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 633
Posts: 50210
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
    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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:

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

just starts startlogging() just one time.

Code:
    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

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



Code:

  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/

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
  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();
}
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 633
Posts: 50210
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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).

Quote
This fails now after ~40 writings.
Please describe how you detect a failure.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
This fails now after ~40 writings.
Please describe how you detect a failure.

Code:
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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 633
Posts: 50210
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
i'm guessing the library gets in trouble when to many files are opened !?
Yes. Why is the close commented out?

Quote
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.

Quote
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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 633
Posts: 50210
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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().
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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?

startlogging() is incorrectly named, since it does not start the logging.
O_o but it starts. that works fine. stopping don't work.

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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 633
Posts: 50210
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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:

Code:
 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();
  }
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'd do something like this:

Ah okey, this works fine. Thank you!
Logged

Pages: [1]   Go Up
Jump to: