Help needed using sprintf to create a variable file name on an SD card

Hi all,

I'm pretty much a beginner to Arduino coding, and I'm trying to get a very simple proof of concept program working to upscale to an accelerometer datalogger. I am combining the SD example library and my own code to do this, using an Arduino MEGA 2560.

Basically, the function I want for this program is:

  1. Press the button once and a new file of name "Session_XX.txt" is made on the card, where XX is an incrementing integer

  2. A simple 'everything's working ok' line of text saved within the file along the lines of "Test complete"

I have used the sprintf() command to create a variable string and assigned it to a character array for the SD.open() function to use. The character array works fine, producing a file name that increments with every button press. The problem seems to lie with the SD.open() command not creating a new file with this char array as its name. Can anyone help with this? When I change to a definite file name, eg SD.open("New_File.txt", FILE_WRITE); it creates a file with this name and saves everything ok, so it shows the problem is with the char array.

The picture I have attached shows the SerialMonitor when the program is run and the button is pressed a few times. This proves that the char array increments as I want. It doesn't show anything about the dataFile being present, because the if statement looks for the presence of "NewFile_name" not the "dataFile". When the if statement is changed to see if "dataFile" has been created, it shows that there has been an error.

I have read many of the posts on here already that deal with variable filenames. It seems that people are having the same problems, then advised to use sprintf() and it somehow works for them.

I'm sure I'm missing something simple, but I don't have enough experience to know exactly what. If anyone can take the time to point me in the right direction, that'd be really appreciated. I'm in a bit of a fix here.

My entire code is shown below to give you an idea of what I'm dealing with

Many thanks
CR

#include <Debounce.h> // Extra library included to smooth spikes when the button has been pressed
#define SWITCH 3 //Define Input pin for switch

#include <SPI.h> //For SD Card Datalogging
#include <SD.h>



Debounce debouncer = Debounce( 20 , SWITCH ); 
int switch_state = 0;
int record_session = 0; //Integers to do with button switch


int session_num = 1; // Counter corresponds with number of file
File dataFile; // File for SD to save to
char NewFile_name[] = ""; //Array of variable length that holds the name of the file. NOTE: EVEN IF THE SIZE OF THE ARRAY IS DEFINED AND LARGER THAN THE CONTENTS BY 1, IT DOESN'T WORK


void setup() {
  pinMode(SWITCH,INPUT);
     Serial.begin(115200);
     
     Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(SS, OUTPUT);
   
  if (!SD.begin(10,11,12,13)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");


}

void loop() {

       if ( debouncer.update (  ) ) {// Debounce routine looks for when the button state has changed
     if (debouncer.read() == 1){
       if (record_session == 1){
         record_session = 0;
         Serial.println("Stopped recording"); 
       }
       else {
         record_session = 1;
 sprintf (NewFile_name, "Session_%02d.txt", session_num); //assign NewFile_name array the text "Session_XX.txt" with the session number integer as XX
           dataFile = SD.open(NewFile_name, FILE_WRITE); //**PROBLEM HERE FOR SOME REASON**. Assign dataFile as a new file (create new one because no current name exists) of name NewFile_name 
           if(NewFile_name) {                          // Check that NewFile_name array is correct, have changed this to if(dataFile) and this throws problems because no file has been made
            Serial.println ("File Created, saving data"); 
            Serial.println(NewFile_name);
      dataFile.println("Testing complete. Congrats");   //DOES NOT OCCUR BECAUSE FILE HAS NOT BEEN MADE. Intended to save a few lines in the file
      dataFile.println("222");
      
      dataFile.close();
           }
           session_num++;          //increment session_num counter
  if (! NewFile_name) {
    Serial.println("error with NewFile_name");
    // Wait forever since we cant write data
    while (1) ;
  }
         Serial.println("recording");
       }
     }

     }

   }

Hello and welcome :slight_smile:

Maybe because the file name is longer than 8 characters ?

guix:
Maybe because the file name is longer than 8 characters ?

Hi guix,

Thanks a lot for the response. I reduced the size of the array variable string name to just "S_XX.txt":
sprintf (NewFile_name, "S_%02d.txt", session_num);

and it saved a file of that name to my SD card. This is getting in the right direction, however no text was saved within the file and the serial monitor froze after pressing the button. Nothing worked from then on.

I tried with names "Se_%02d.txt", "Sess_%02d.txt", "Sessi_%02d.txt", and it continued to save empty files of those names, and continued to freeze in the SerialMonitor after the first button press.

If I returned it to "Session_%02d.txt", it would work as normal again, looping through the on and off and incrementing in the SerialMonitor as I pressed the button, but would not save any files.

Bit of a head scratcher! Any further thoughts?

Thanks again
CR

char NewFile_name[] = ""; //Array of variable length that holds the name of the file. NOTE: EVEN IF THE SIZE OF THE ARRAY IS DEFINED AND LARGER THAN THE CONTENTS BY 1, IT DOESN'T WORK

That comment is wrong. That is an array of size 1. You can not fit any characters other than the existing terminating NULL in the array.

You KNOW the maximum number of characters in the file name (8 before the dot, 3 after the dot, the dot, and a terminating NULL). So, make the array size 13! Do not expect the compiler to determine the size.

Righto folks,

Thanks for the advice there, I managed to get the file names to work by reducing the size of the fixed part from "Session_" to "SET_".

This is below the 8 characters that you both mentioned and now I don't have a problem with the file name allocation.

As it always is, the solving of one problem leads to another rather soon after. I won't clog this feed up with something unrelated, but if you could keep an eye out for the question I have regarding the MPU6050 and Jeff Rowberg's DMP code, it'd be nice to have your opinions. You guys certainly know more than I, so it'd be great to pick your brains!

Thanks again

CR