variable name for SD file

Hello,

I'm having a problem to name an SD file with a variable name.

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

DS1302 rtc(2, 3, 5); //pins van rtc definiëren

const int chipSelect = 4;
boolean SD_connected;

void setup() {
  rtc.halt(false);
  rtc.writeProtect(false);

  Serial.begin(9600);
  while (!Serial) {
    //wacht tot Serial port is verbonden
  }
  if (SD.begin(chipSelect)) { //SD-kaart verbonden
    Serial.print("Initializing SD card...");
    Serial.println("card initialized.");
    SD_connected = false;
  }

  //Nadat je de datum en tijd hebt ingesteld moet je deze 3 onderste lijnen 'outcommenten'
  //rtc.setDOW(TUESDAY);        //dag van de week
  //rtc.setDate(24, 9, 2018);   //datum (dag, maand, jaar)
  //rtc.setTime(14, 37, 15);    //tijd (uur, minuten, seconden)
}

void loop() {
  if (!SD.begin(chipSelect)) {
    Serial.print("Initializing SD card...");
    Serial.println("Card failed, or not present");
    SD_connected = true;
    return;
  } else if ((SD.begin(chipSelect)) && (SD_connected == true)) {
    //Als de sd-kaart verbonden is zou deze functie blijven lopen, dus heb ik een boolean toegevoegd.
    //Als deze 'false' is zal de functie niet meer herhalen nadat het al is uitgevoerd is.
    Serial.print("Initializing SD card...");
    Serial.println("card initialized.");
    SD_connected = false;
  }

  String fileName = rtc.getDateStr();
  //de naam van het bestand is de dag wanneer het gelogd word;
  File dataFile = SD.open(fileName, FILE_WRITE);
  if (dataFile) {
    dataFile.println(rtc.getTimeStr());
    dataFile.close();
    Serial.println(rtc.getTimeStr());
  }
}

If I do:
File dataFile = SD.open("test", FILE_WRITE);
it works, but when I replace "test" by fileName not.

I don't understand why it doesn't work, can you please help me.

Thank you!

filename.ino (1.75 KB)

Because rtc.getDateStr() doesn't return a String type, but returns a char array.

thanks for your quick response

But how can It be fixed?

Since DS1302 library is not a native Arduino library you will need to tell us where you got the library. Or since you have the library installed, you can look at the examples that came with the library to see how to use the commands.

I have the library installed since the 29 of June 2018, but I don't know where I installed it from.
It's weird that it doesn't work, cause when i replace:

String fileName = rtc.getDateStr();

By:

String fileName = rtc.getTimeStr();

It does work. But it shows the time ofcourse, not the date.

Do you maybe know another library I can use?

I would suggest trying an native Arduino library. A search for '1302' return RTCLib.

What are the chances getDateStr() is returning a date string (lower case 's') with invalid filename characters? Try printing the result to the serial monitor and see what it is returning.

Serial.println(getDateStr()); -->25.09.2018
Serial.println(getTimeStr()); --> 20:24:22

There's your answer, too many periods in the file name when using the date.

If you read through the library there may be function call parameters to getDateStr() that will allow you to change . to - (or something else legal).

I tried some things to make it work, but without any result.
Is it ok I place the ds1302.cpp and the ds1302.h here?
Maybe you can find it.

Why not? What do you have to lose, since you don't remember where you got it from.

Here they are.

DS1302.cpp (9.49 KB)

DS1302.h (2.75 KB)

Did you try reading the cpp file you posted, specifically the getDateStr function?

stijn123:
Serial.println(getDateStr()); -->25.09.2018

I see. It has nothing to do with if it's a String or a char array, but it has to do with the name itself.

The SD library has a limitation in the file naming, if you know what's "8.3 name", then you know the problem.
If not, lemme tell you that "25.09.2018" doesn't follow the 8.3 standard; altough I'm not totally sure if the library automatically converts it into a valid one, or since it isn't valid to begin with, open() simply fails just because of that.

Converted to a valid name, the file would be called "2509.201". If you think such name doesn't make any sense, then you have to do something about it.
I will suggest you the following:

  • Obtain the string as normal.
  • Remove all periods, leaving just the numbers without any separation. At this point you should have at most 8 characteres, which barely fits in the 8.3 standard.
  • Append (concatenate) the ".txt" suffix. Without it, the file still should open; but OS like Windows then complain there's not a known program to open it, despite of having plain text in it.

After these three steps, you are good to go.

Step 1 is the issue, the function returns the date with periods by default. Once The OP reads the function definition in the cpp file, then he can fix the problem.

I'm not sure the filename is limited to 8.3 but does have similar restrictions (only one period allowed) as I'm using very_long_file_names.txt and it works (but only one period).

I don't know how to write in cpp.
Can you please show me in the code what I have to chance, cause I really don't know.

What parameters have you tried using when calling getDateStr()?

adwsystems:
Step 1 is the issue, the function returns the date with periods by default.

It is not, specially when it returns a String object.
Removing or replacing characters in a String is a breeze; in a char array you'll have to create a function but is not that difficult either.

adwsystems:
I'm not sure the filename is limited to 8.3 but does have similar restrictions (only one period allowed) as I'm using very_long_file_names.txt and it works (but only one period).

For opening existing files should work as long as the converted SFN matches the SFN version of the target file.

For creating files, I always believed the library will use only the SFN version anyway.
For example, I believe creating a file called "very_long_file_names.txt" will show up as "VERY_L~1.TXT" in the Windows file explorer. If not, then prove me that I'm wrong.
What I do know for sure, is that SdFat supports LFNs by default and for everything.

Lucario448:
It is not, specially when it returns a String object.

Not according to the code.

 char *getDateStr(uint8_t slformat=FORMAT_LONG, uint8_t eformat=FORMAT_LITTLEENDIAN, char divider='.');


char *DS1302::getDateStr(uint8_t slformat, uint8_t eformat, char divider)
{
 char *output= "xxxxxxxxxx";
 int yr, offset;
 Time t;
 t=getTime();
 switch (eformat)
 {
 case FORMAT_LITTLEENDIAN:
 if (t.date<10)
 output[0]=48;
 else
 output[0]=char((t.date / 10)+48);
 output[1]=char((t.date % 10)+48);
 output[2]=divider;
 if (t.mon<10)
 output[3]=48;
 else
 output[3]=char((t.mon / 10)+48);
 output[4]=char((t.mon % 10)+48);
 output[5]=divider;
 if (slformat==FORMAT_SHORT)
 {
 yr=t.year-2000;
 if (yr<10)
 output[6]=48;
 else
 output[6]=char((yr / 10)+48);
 output[7]=char((yr % 10)+48);
 output[8]=0;
 }
 else
 {
 yr=t.year;
 output[6]=char((yr / 1000)+48);
 output[7]=char(((yr % 1000) / 100)+48);
 output[8]=char(((yr % 100) / 10)+48);
 output[9]=char((yr % 10)+48);
 output[10]=0;
 }
 break;
 case FORMAT_BIGENDIAN:
 if (slformat==FORMAT_SHORT)
 offset=0;
 else
 offset=2;
 if (slformat==FORMAT_SHORT)
 {
 yr=t.year-2000;
 if (yr<10)
 output[0]=48;
 else
 output[0]=char((yr / 10)+48);
 output[1]=char((yr % 10)+48);
 output[2]=divider;
 }
 else
 {
 yr=t.year;
 output[0]=char((yr / 1000)+48);
 output[1]=char(((yr % 1000) / 100)+48);
 output[2]=char(((yr % 100) / 10)+48);
 output[3]=char((yr % 10)+48);
 output[4]=divider;
 }
 if (t.mon<10)
 output[3+offset]=48;
 else
 output[3+offset]=char((t.mon / 10)+48);
 output[4+offset]=char((t.mon % 10)+48);
 output[5+offset]=divider;
 if (t.date<10)
 output[6+offset]=48;
 else
 output[6+offset]=char((t.date / 10)+48);
 output[7+offset]=char((t.date % 10)+48);
 output[8+offset]=0;
 break;
 case FORMAT_MIDDLEENDIAN:
 if (t.mon<10)
 output[0]=48;
 else
 output[0]=char((t.mon / 10)+48);
 output[1]=char((t.mon % 10)+48);
 output[2]=divider;
 if (t.date<10)
 output[3]=48;
 else
 output[3]=char((t.date / 10)+48);
 output[4]=char((t.date % 10)+48);
 output[5]=divider;
 if (slformat==FORMAT_SHORT)
 {
 yr=t.year-2000;
 if (yr<10)
 output[6]=48;
 else
 output[6]=char((yr / 10)+48);
 output[7]=char((yr % 10)+48);
 output[8]=0;
 }
 else
 {
 yr=t.year;
 output[6]=char((yr / 1000)+48);
 output[7]=char(((yr % 1000) / 100)+48);
 output[8]=char(((yr % 100) / 10)+48);
 output[9]=char((yr % 10)+48);
 output[10]=0;
 }
 break;
 }
 return output;
}

I don't see String anywhere in this code and the divider is defaulted to a period.

You may be correct on the filenames using SD versus SDFat. I have SDFat included in my sketches.

adwsystems:
I don't see String anywhere in this code

Not in the function, but in the caller. Assigning a char array to a String is possible (because it copies the character sequence).

adwsystems:
You may be correct on the filenames using SD versus SDFat. I have SDFat included in my sketches.

Hmm, don't cheat on me.
Well looks like I have to test it myself...