Increasing maximum number of SD-card logfiles

Hi all!

I'm working on a datalogging system and I am using the Adafruit Ultimate GPS Logger Shield to write data to a SD-card.

The existing code example has the following lines of code for naming the logfiles:

char filename[15];
strcpy(filename, "GPSLOG000.CSV");
for (uint8_t i = 0; i < 1000; i++) {
filename[6] = '0' + (i/100)%10;
filename[7] = '0' + (i/10)%10;
filename[8] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename)) {
break;
}
}

logfile = SD.open(filename, FILE_WRITE);
if( ! logfile ) {
Serial.print("Could not create ");
Serial.println(filename);
error(3);
}
Serial.print("Writing to ");
Serial.println(filename);

While this is great, it only allows for a maximum of 100 unique logfiles, before things go haywire. I would like to increase this maximum number to 1000, and I tried to change the format as in the code below:

char filename[16];
strcpy(filename, "GPSLOG000.CSV");
for (uint8_t i = 0; i < 1000; i++) {
filename[6] = '0' + ((i/100)%10);
filename[7] = '0' + ((i/10)%10);
filename[8] = '0' + (i%10);
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename)) {
break;
}
}

logfile = SD.open(filename, FILE_WRITE);
if( ! logfile ) {
Serial.print("Could not create ");
Serial.println(filename);
error(3);
}
Serial.print("Writing to ");
Serial.println(filename);

However, it doesn't seem to work and I keep getting the 'Could not create' message in the serial monitor.

Does anyone have any ideas on how to tackle this?
Thanks!

At the very least you need to change

  strcpy(filename, "GPSLOG000.CSV");

to

  strcpy(filename, "GPSLOG0000.CSV");

and you have not changed the index values (6, 7 and 8 ) when inserting the digits

Try this

void setup()
{
  Serial.begin(115200);
  char filename[15];
  strcpy(filename, "GPSLOG0000.CSV");
  for (int i = 0; i < 1000; i++)
  {
    filename[6] = '0' + ((i / 1000) % 10);
    filename[7] = '0' + ((i / 100) % 10);
    filename[8] = '0' + ((i / 10) % 10);
    filename[9] = '0' + (i % 10);
    Serial.println(filename);
  }
}

void loop()
{
}

but I am not sure that the SD library will actually work with the long filenames

Keep in mind that the file name needs to stay under the 8 character (8.3 format names) length limit. Using Gxxxxxxx.csv would allow you to have 10,000,000 unique names in one folder.

Of course, that is nonsense. Create the files in folders, to keep the number of files in a folder to reasonable amounts.

Keep in mind that the file name needs to stay under the 8 character (8.3 format names) length limit

That is what I had in mind as a problem but it appears that the original code had longer filenames
strcpy(filename, "GPSLOG000.CSV");and the implication was that it worked.

Sorry guys, I just realised I posted the same code twice... :confused:

This is the original:

char filename[15];
strcpy(filename, "GPSLOG00.CSV");
for (uint8_t i = 0; i < 100; i++) {
filename[6] = '0' + i/10;
filename[7] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename)) {
break;

And this is the one I used in an attempt to modify it:

char filename[15];
strcpy(filename, "GPSLOG000.CSV");
for (uint8_t i = 0; i < 1000; i++) {
filename[6] = '0' + (i/100)%10;
filename[7] = '0' + (i/10)%10;
filename[8] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename)) {
break;

Sorry for the confusion earlier on, anyone got any ideas?

See reply #1 and the subsequent comments about the length of the filename.

I think I solved the issue using the code below:

char filename[15];
strcpy(filename, "KOLOG000.CSV");
for (uint8_t i = 0; i < 1000; i++) {
filename[5] = '0' + (i/100)%10;
filename[6] = '0' + (i/10)%10;
filename[7] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename)) {
break;

I'm not getting any errors anymore, I haven't tried to surpass the 100 logfiles yet to see if the code holds, but it seems to work fine.

Thanks!

How many different values fit in a byte (in below snippet from your code); you will never get a value greater than 255.

for (uint8_t i = 0; i < 1000; i++) {

You also have a very complicated way of creating the filename

char filename[13];
for(int cnt=0;cnt<1000;cnt++)
{
  snprintf(filename, sizeof(filename), "KOLOG%03d.CSV", cnt);

  if (! SD.exists(filename)) {
    break;

  ...
  ...

Also consider what happens when KOLOG999.CSV exists; can't see as you did not post the full code.

Hi sterretje,

Thanks for your reply, please know that I have no experience with writing code for this application and that the solution I posted is something I put together from other people's code and the Adafruit/Arduino sample codes. For the majority of the code, I have only minimal understanding as to what is happening :confused: let alone that I know whether I could be writing a more efficient and effective code

Putting that aside, for your first comment on the maximum of 255; do I understand correctly that just defining the variable as a unsigned 16 bit integer (uint16_t) would suffice to surpass the max value of 255?

On your example code, I can't seem to find a direct explanation of 'snprintf' on the Arduino page, so I'm not sure what the format of this should be or what it does exactly, can you explain maybe?

Regarding your comment on taking into account what happens after KOLOG999.CSV; this is a situation that will not ever occur since the SD-cards are switched out at regular intervals. However, the original of a maximum of 100 unique filenames per SD was a little bit on the low side, so I thought I might as well bump it up to 1000 files while I was changing it anyway.

Everything related to the coding of the SD-card logging is in the code below. If you could share your wisdom on how and where to improve (and maybe also the 'why') I would be very grateful!

File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
if (c < '0')
return 0;
if (c <= '9')
return c - '0';
if (c < 'A')
return 0;
if (c <= 'F')
return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
while(1) {
uint8_t i;
for (i=0; i<errno; i++) {
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(100);
}
for (i=errno; i<10; i++) {
delay(200);
}
}
}

void setup() {
Serial.begin(115200);

// see if the card is present and can be initialized:
if (!SD.begin(chipSelect, 11, 12, 13)) {
Serial.println("Card init. failed!");
error(2);
}
char filename[15];
strcpy(filename, "KOLOG000.CSV");
for (uint8_t i = 0; i < 1000; i++) {
filename[5] = '0' + (i/100)%10;
filename[6] = '0' + (i/10)%10;
filename[7] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename)) {
break;
}
}

logfile = SD.open(filename, FILE_WRITE);
if( ! logfile ) {
Serial.print("Could not create ");
Serial.println(filename);
error(3);
}
Serial.print("Writing to ");
Serial.println(filename);