Increment file name

Hi guys, I’m trying to increment file names in order to get data1.txt, data2.txt, data3.txt … from the tests I’m doing.

I’ve came up with a simple code, but it’s basically C and I can’t figure out how to make it understandable for the arduino environment.

void setup ()
{
int n=1;
while (SD.exists("data%i.txt",n)) 
{
  n++;
} 
  File dataFile = SD.open("data%i.txt",n,FILE_WRITE);
  
    
}

Also, I was trying to use something more complex, creating another .txt file to count the files, but it didn’t work as well. Here is the code:

#include <SD.h>
File myFile;
File myData;

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  if (SD.exists("num.txt")) {
  }
  else
  {
  myFile = SD.open("num.txt", FILE_WRITE); //TENTAR WRITE AND READ
  if (myFile) {
    Serial.print("Writing...");
    myFile.println("0");
	// close the file:
    myFile.close();
    Serial.println("Done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("Error opening num.txt");
  }
  }
  // re-open the file for reading:
  myFile = SD.open("num.txt");
  if (myFile) {
    Serial.println("Reading...");
    
     // read from the file until there's nothing else in it:
   int num = 0;
    if (myFile.available()) {
      num = myFile.parseInt();
      Serial.println(num);
      }
    num++;
   int num2 = num;
    // close the file:
    
    
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  if (SD.exists("num.txt")) {
  SD.remove("num.txt");
  }

  myFile = SD.open("num.txt",FILE_WRITE);
   if (myFile) {
    Serial.print("Writing...");
   myFile.print(num2);
	// close the file:
    myFile.close();
    Serial.println("Done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("Error opening num.txt");
  }

}
//myFile = SD.open("data%i.txt",n,FILE_WRITE);
}

void loop()
{
	// nothing happens after setup
}

Can anybody help me with that? :think:

Thanks

What, exactly, is the problem you are having? The Arduino IDE is just a wrapper around a C compiler, so standard C compiles just fine.

Create the filename as a string variable first before opening the file, by concatenating the “data” part and the number as text-string (derived from variable i ). Then open the file with that variable as the name. %1 inside quotemarks is considered as a literal text.

Lyndon, my problem is basically syntax.

Valen, I tried to do that in two different ways with some help and got this:

/*
  SD card datalogger
 
 This example shows how to log data from three analog sensors 
 to an SD card using the SD library.
 	
 The circuit:
 * analog sensors on analog ins 0, 1, and 2
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created  24 Nov 2010
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // 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:
    return;
  }
  Serial.println("card initialized.");
  char filename[16]; // make it long enough to hold your longest file name, plus a null terminator
  int n = 0;
  do
     {
        snprintf(filename, sizeof(filename), "data%03d.txt", n); // includes a three-digit sequence number in the file name
     }
  while(SD.exists(filename));
  //now filename[] contains the name of a file that doesn't exist

  }
void loop()
  {
  // make a string for assembling the data to log:
 char *filename;
 int sensorValue = analogRead(A0);
 float dataVoltage = sensorValue*(5.0/1023.0);
 File dataFile = SD.open(filename,FILE_WRITE);
 dataFile.println(dataVoltage);
 dataFile.close();
 Serial.println(dataVoltage);
 }
/*
  SD card datalogger
 
 This example shows how to log data from three analog sensors 
 to an SD card using the SD library.
 	
 The circuit:
 * analog sensors on analog ins 0, 1, and 2
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created  24 Nov 2010
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // 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:
    return;
  }
  Serial.println("card initialized.");
  FILE *fp;
char buffer [16];
int x;
for (x = 0; x < 100; x++) { // 100 should be enough, make it bigger if needed!
    sprintf (buffer, "file%03d.txt", x); // filename format is "file000.txt" to "file099.txt"
    fp = SD.open (buffer, FILE_READ); // try to open file, read only (to avoid creating a new one)
    if (fp) { // if the file exists, close it
        SD.close (fp);
    } else { // does not exist, we found the next free one
        break;
    }
}
// here "buffer" contains the filename of the next NON-EXISTENT FILE (use to open file for write)

  }
void loop()
  {
  // make a string for assembling the data to log:
 char *filename;
 int sensorValue = analogRead(A0);
 float dataVoltage = sensorValue*(5.0/1023.0);
 File dataFile = SD.open(filename,FILE_WRITE);
 dataFile.println(dataVoltage);
 dataFile.close();
 Serial.println(dataVoltage);
 }

Both are not working correctly though.

felipearcaro:
Lyndon, my problem is basically syntax.

Valen, I tried to do that in two different ways with some help and got this:

Both are not working correctly though.

Got what? Both code seems to solve the filename creating in similar ways, with the function snprintf and sprintf. What was the result of each code? Were any files created? Did the file that was supposed to be created initiall already exist? What are the symptoms that make you think it does not work. Any error messages? Don’t forget to mention what files were present before hand. Please be more descriptive than just “didn’t work”. If my magic ball was working I’d use it to predict the World Soccer games.

I’m sorry, I couldn’t be more descriptive because I didn’t really know what was wrong.

I’ve found the “solution” and this is the code:

/*
  SD card datalogger
 
 This example shows how to log data from three analog sensors 
 to an SD card using the SD library.
 	
 The circuit:
 * analog sensors on analog ins 0, 1, and 2
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created  24 Nov 2010
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // 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:
    return;
  }
  Serial.println("card initialized.");
  char filename[16]; // make it long enough to hold your longest file name, plus a null terminator
  int n = 0;
  snprintf(filename, sizeof(filename), "data%03d.csv", n); // includes a three-digit sequence number in the file name
  while(SD.exists(filename)) {
    n++;
    snprintf(filename, sizeof(filename), "data%03d.csv", n);
  }
  Serial.println(n);
  Serial.println(filename);
  //now filename[] contains the name of a file that doesn't exist
  
  File dataFile = SD.open(filename, FILE_WRITE);
  

  }
void loop()
  {
 }

The files are being created as I wanted. The problem is:

  1. Since I’m using the function setup() to create them, I can’t use the “filename” to write in the loop();

  2. If I use my logic inside of the function loop(), it creates a lot of files because it’s a loop and that’s not what I want.

Can I use a variable defined inside of setup(), to manage files inside of the function loop()?

I see. The variables declared inside the Setup function (more specifically inside it’s curly brackets, this goes for all functions actually) only exist there. So if you want to use the filehandle assigned to a file by Setup, in the loop, then the filehandle (dataFile ) would need to be declared outside of Setup. It would need to be a global variable.

Or at least the filename should be global. Setup could figure out the filename that is available and store that in the global filename variable. And create the file initially and then close it. Then loop can open the file to add something to it, and then close it again when done. As keeping a file continuously opened for writing is not a very smart thing to do. Only do so for the time that something needs to be added or changed.

I did exactly what you told me and it worked, and I have to open and close the file in both setup() and loop() to work.

I’m posting the code in case anyone still need it.

#include <SD.h>

const int chipSelect = 10;
char filename[16];

void setup()
  {
    Serial.begin(9600);  // Open serial communications and wait for port to open:
  
  


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // 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:
    return;
  }
  Serial.println("card initialized.");
  //char filename[16]; // make it long enough to hold your longest file name, plus a null terminator
  int n = 0;
  snprintf(filename, sizeof(filename), "data%03d.txt", n); // includes a three-digit sequence number in the file name
  while(SD.exists(filename)) {
    n++;
    snprintf(filename, sizeof(filename), "data%03d.txt", n);
  }
  File dataFile = SD.open(filename,FILE_READ);
  Serial.println(n);
  Serial.println(filename);
  dataFile.close();
  //now filename[] contains the name of a file that doesn't exist
  }
void loop()
  {
    File dataFile = SD.open(filename, FILE_WRITE);
    if (dataFile) {
    int sensorValue = analogRead(A0);
    float voltage = sensorValue * (5.0/1023.0);
    Serial.println(voltage);
    dataFile.println("teste");
    dataFile.println(voltage);
    dataFile.close();
    }
    else {
      Serial.println("error");
 }
  }

Thank you Valen!

On second thought, frequently opening and closing files on a SD card would imply that there is frequent saving done on that card. Flash cards do wear down quicker that way. Though, I also understand that there is a algorithm they use in storing the new clusters in random empty memory locations. So the wear down is shared over al it’s memory locations. So it might not be perceivable. Just something you might need to be aware of.