Trouble with creating folders to store files on an SD card

Hi (again),

I feel like everything is 2 steps forward one step back at the moment.

I'm basically trying to make a datalogger that logs accelerometer data once the ultrasonic sensor detects and object. Everything works fine if I just create a new file in the root folder each time there is a detection.

As soon I I introduce a daily folder to store each set of data for that day it starts to misbehave. (I'm using folders because I'm using an esp32 and sdFat isn't supported and so I have to use short filenames.)

The first set of data gets logged fine and the serial shows me the file path like this...

(//YYMMDD//HH_MM.csv)
//210731//19_12.csv

Once it tries to write a new file to the folder it creates the following path...

//210731//19_12.csv///19_13.csv

However if I reset the device it'll work as I want it but just the once, so it'll create a new file in the correct folder.

The double slash (//) seems to be a esp32-ism, I need one in the actual file path and one in the name for it work for it to write a file. Even if I want to just write to the root I still need the /.

If anyone can help me figure this out it would be appreciated.

I've simplified the recordData() as it's not the focus as it works fine.

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

//-SD Card-
#define SD_CS = 5;
File dataFile;

//Filename
char fileName[20];//Time of vessel arrive time
char folderName[20]; //Dated folder for saving data
char file[20];//store file name
char folder[20];//store folder name
char fileDir[20];//full file path
char filePath[20];//full file path



void setup() {

  Serial.begin(115200);

  //SD Card
  SD.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  createNewFolder();


}

void loop() {

  if (distanceInMM <= 500) {

    recordData();

  }

}

void createFileName() {

  DateTime now = rtc.now();

  int nowHour = now.hour();
  int nowMinute  = now.minute();

  sprintf(fileName, "/%02i_%02i.csv", nowHour, nowMinute);

  delay(200);

  strcpy(file, fileName);


}

void createNewFolder() {

  DateTime now = rtc.now();

  int nowYear = now.year();
  int nowMonth = now.month();
  int nowDay = now.day();

  sprintf(folderName, "/%02i%02i%02i", nowYear - 2000, nowMonth, nowDay);

  strcpy(folder, folderName);

  SD.mkdir(folderName);

  /*Serial.println(nowYear - 2000);
    Serial.println(nowMonth);
    Serial.println(nowDay);
    Serial.println(folderName);*/
}

void getFilePath() {

  createFileName();

  strcat(fileDir, "/");
  strcat(fileDir, folder);
  strcat(fileDir, "/");
  strcat(fileDir, file);

  strcpy(filePath, fileDir);

}

void getAccelData() {
  
  //Accel Sensor code in here
  
  }

void recordData(){

          getFilePath();

          Serial.println(filePath);
          Serial.println(folderName);

          dataFile = SD.open(filePath, FILE_WRITE);

          getAccelData();

          dataFile.close();
  
}


Now I thought I could use SD.exist() then just write straight into the folder, but it doesn't seem to find the folder name, maybe because it's an array?

Thanks :slight_smile:

here's a code fragment i use to create and read a file on esp32

#include "Arduino.h"

#include "cfg.h"
#include "eng.h"
#include "utils.h"
#include "vars.h"

const char *cfgFname = "/spiffs/koala.cfg";

// ...
            cfgSave (cfgFname);
// ...

// ---------------------------------------------------------
int
cfgLoad (
    const char *filename )
{
    int res = 1;
    printf ("%s: %s\n", __func__, filename);

    FILE * fp = fopen (filename, "rb");
    if (NULL == fp)  {
        perror ("cfgLoad - fopen");
        res = 0;
        goto done;
    }

    // verify TLV file format
    byte magic [sizeof(cfgMagic)];

    if (1 != fread ((void*) & magic [0], sizeof(magic), 1, fp))  {
        perror ("cfgLoad - fread hdr\n");
        res = 0;
        goto done;
    };

    if (strncmp ((char*)magic, "TLV", sizeof(cfgMagic)))  {
        printf (" %s: non-TLV file\n", __func__);
        res = 0;
        goto done;
    }

    // read TLVs
    CfgHdr_s hdr;
    CfgVar_s *p;

    while (fread ((void*) &hdr, sizeof(hdr), 1, fp))  {
        if (0 == hdr.size)
            break;

        if (NULL == (p = _cfgFindVar (hdr.id)))  {
            printf (" %s: unknown cfgVar id, %d", __func__, hdr.id);
            break;
        }

 //     printf (" %s: %s\n", __func__, p->desc);

        // read amount written specified by hdr.size
        int nread = fread ((void*) p->p, hdr.size, 1, fp);
        if (! nread)  {
            printf (" %s: fread incomplete, %d %d",
                        __func__, nread, p->nByte);
            perror (" cfgLoad - fread");
            res = 0;
            goto done;
        }
    }

done:
    fclose (fp);
    return res;
}

// ---------------------------------------------------------
#if 1
void
cfgSave (
    const char *filename )
{
    printf ("%s: %s\n", __func__, filename);

    FILE * fp = fopen (filename, "wb+");
    if (NULL == fp)  {
        perror ("cfgSave - fopen");
        return;
    }

    if (1 != fwrite ((void*) cfgMagic, sizeof(cfgMagic), 1, fp)) {
        perror ("cfgSave: fwrite cfgMagic");
        goto done;
    }

    CfgHdr_s  hdr;
    for (CfgVar_s *p = cfgVarTbl; V_NONE != p->type; p++)  {
        hdr.id   = p->id;
        hdr.size = p->nByte;

        if (1 != fwrite ((void*) & hdr, sizeof(hdr), 1, fp)) {
            perror ("cfgSave: fwrite hdr");
            goto done;
        }

        int nwr = fwrite ((void*) p->p, p->nByte, 1, fp);
        if (! nwr)  {
            printf (" %s: fwrite incomplete, %d %d",
                        __func__, nwr, p->nByte);
            perror (" cfgSave - fwrite");
            return;
        }
    }

done:
    fclose (fp);
}
#endif

You forgot to set fileDir to the empty string before building it:

You could change this to:

Also is 20 chars enough for the full path? What if you later change to 8.3 file name and 8 char directory name?

1 Like

Mark! Thanks mate! This had me going crazy over 2 nights believe it or not. I polished off a bottle of Kraken and still didn't find the solution. Thanks for your time, it's appreciated.

With regards to the 20 chars, it seems to be enough? I've increased it to 50, but out of curiosity does making the array bigger than it needs to be have any detrimental effects?