So, maybe I'm too tired to see the obvious issue here, but my SD card script is causing a "blank" file to be created, then a secondary file to be correctly created.

I'm trying to store data logs, and I don't want to overwrite old logs, I just want to "move" them to the back of the queue. So I start with six files on the SD card:


Everything writes to DATA.TXT, and DATA~1.TXT through DATA~5.TXT are "old" logs, from oldest to newest. This means that, the next time I boot up the Arduino, I want the contents of DATA.TXT to be read into a new file called DATA~6.TXT, I want the old DATA.TXT to be deleted, and I want a new DATA.TXT to be created for the rest of the program. It should look like this:

DATA.TXT <=== New, blank file, primed for logging new data
DATA~6.TXT <=== "Old" DATA.TXT

In reality, it's creating two files: instead of DATA~6.TXT holding the contents it should, it's blank -- and a file called DATA~7.TXT is created with the contents of the "old" DATA.TXT. After that, it's writing to the "new" DATA.TXT as it should. Something is lost (or added) in shifting the data, for some reason, looking like this:

DATA.TXT <=== New, blank file, primed for logging new data
DATA~6.TXT <=== Blank, unused "new" file?
DATA~7.TXT <=== "Old" DATA.TXT

EDIT: Each file contains test data ( e.g. - file DATA~1.TXT contains a line like This is "DATA~1.TXT") So I can track which files are "moved," and where they go. That's how I know where the "old" DATA.TXT file is going, and how I know DATA~6.TXT is "blank." It's actually a blank file, with no data in it.

EDIT #2: As stated in the comments below, the Uno doesn't actually wait for a serial connection. I just tested this, and it is true... that being said: I'm still getting a blank DATA~6.TXT and DATA.TXT is being moved into DATA~7.TXT without cause.

Now that you know the goal, and (probably) see the issue, here's the code:

 * Tests the SD card slot, assuring no functional code is missing
 * for BIB process to correctly log data.

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

String fileName = "DATA.TXT";                       // Declare a filename with FAT 8.3 naming conventions
File dataLog;                                       // Store our "opened" file in an object

void setup(){
    Serial.begin( 115200 );
    while( !Serial ){                               // Wait for serial port to open before doing anything

    Serial.println( "\nInitializing SD card..." );  // Start SD card
    if( !SD.begin( 4 ) ){
        Serial.println( "Initialization failed!" );
        while( 1 );
    Serial.println( "Initialization done." );

    Serial.println( "\nChecking if we have a unique filename..." );
    if( SD.exists( fileName ) )                     // Give our data log a unique filename if the current filename already exists

    dataLog = SD.open( fileName, FILE_WRITE );      // Open our file for editing if it doesn't already exist
    Serial.println( "Created save file!" );

    // Write to file the first time
    if( dataLog ){
        Serial.println( "\nWriting int test to file..." );
        dataLog.println( "Testing Sequence1..." );
        dataLog.println( "\tSequence1 complete." );
        Serial.println( "\tFirst test written!" );
        Serial.println( "\tData log closed." );
        Serial.println( "---Error opening data log file!---" );

void loop(){

// Moves the last `DATA.TXT` to `DATA~x.TXT` where `x` is the largest integer.
// This makes the "highest" numbered file the last data log, and `DATA.TXT` the current data log.
// Follows SFN8.3 standards of naming, with 8 chars for filename, 4 chars for extension, and preceeding
// periods converted to `~` chars.
// This leaves us with only 999 possible "backup" data logs.
void moveFiles(){
    bool sdCardFull = false;                            // Keep track of if our SD card is "full" or not
    byte num = 1;
    File newFile;

    String existingFile = String( "DATA~" ) + String( num ) + String( ".TXT" );     // Creates a filename of `DATA~num.TXT` to test

    // Check if this filename exists, too.  Iterate `num` to avoid overwriting currently existing files
    while( SD.exists( existingFile ) ){
        if( num == 999 ){          // If the SD card is full
            sdCardFull = true;
            noMoreRoom( sdCardFull );

        existingFile = String( "DATA~" ) + String( num ) + String( ".TXT" );

    dataLog = SD.open( fileName );
    // Create the new file, with the new filename
    newFile = SD.open( existingFile, FILE_WRITE );

    // Move the old data log into the new filename
    while( dataLog.available() )
        newFile.write( dataLog.read() );

    // Close, remove, then re-open the data log
    SD.remove( fileName );                          // Deletes the old data log

// We cannot find a good filename for the SFN8.3 format, since all of the available filenames have been
// used up, so we will stop the program from running until the SD card is cleaned up, before we "destroy"
// the last backup file.
void noMoreRoom( bool sdCardFull ){
    lcd.setCursor( 0, 0 );
    lcd.print( "   SD card is   " );
    lcd.setCursor( 0, 1 );
    lcd.print( "   too full!!   " );

    Serial.println( "The SD card is full and we will not proceed until it is cleaned up." );

    while( sdCardFull ){}       // Do absolutely nothing until the SD card is "cleaned up"
  • 1
    Let me guess... you plug the board in (or program the board), then you open the serial terminal, and the program "starts running"...? What about the period between plugging it in (or programming it) and you opening the serial terminal? It runs then too you know... (assuming an Uno - but you don't specify which board you are using...)
    – Majenko
    Commented Aug 14, 2019 at 19:00
  • Yes, it's an Uno... and a Nano... and a Pro-Mini. And the sketch should be caught in the while( !Serial ) loop until the Serial Monitor is attached, right? Commented Aug 14, 2019 at 19:07
  • No, that line is only for native USB boards as I remember. It will not wait for anything on an Uno or Nano
    – chrisl
    Commented Aug 14, 2019 at 19:17
  • Maybe you should first test for the file to actually contain data, before you move it.
    – chrisl
    Commented Aug 14, 2019 at 19:19
  • while (!Serial) works only for MCU with native USB (32u4, SAMD), not for Uno, Nano, Mega, Mini. Uno & co. reset on new connection. they start to run and then they are reset on new connection
    – Juraj
    Commented Aug 14, 2019 at 19:19


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.