writing on SD card works but filedate is always 1.1.2000

Hello all,

I’m using SD.h, tried both with UNO and MEGA2560.

As the subj. sais, the file writes ok, but the date is wrong.
Well, the SDlib does not know that I have a RTC connected also :slight_smile:
So date/time is available.

Could anyone help please?


…the second question I need help, I tried to search for “sd.h” or ‘sd.h’ in the forum, but the search engine brings up single ‘h’ characters first, does not search for the string. How to overcome? Thanks.

maraio:
...the second question I need help, I tried to search for "sd.h" or 'sd.h' in the forum, but the search engine brings up single 'h' characters first, does not search for the string. How to overcome? Thanks.

Don't use the rather useless forum search. Google for:

sd.h site:arduino.cc

See: Which SD library to create file with date? - #4 by fat16lib - Storage - Arduino Forum

A more recent code from my project:
The RTC library is from adafruit. It has some nice EPOCH features that I like.

#include <RTClib.h>
RTC_DS1307 RTC; // define the Real Time Clock object
SdFat sd;
SdFile imgFile;

//This function returns the date and time for SD card file access and modify time. One needs to call in setup() to register this callback function: SdFile::dateTimeCallback(file_date_time);
void file_date_time(uint16_t* date, uint16_t* time) 
{
  DateTime now = RTC.now();
  *date=FAT_DATE(now.year(),now.month(),now.day());
  *time=FAT_TIME(now.hour(),now.minute(),now.second());
}

void setup() 
{
  // see if the card is present and can be initialized:
  if (!sd.begin(chipSelect, SPI_HALF_SPEED))
  {
    Serial.println(F("SD init Failed"));
    // don't do anything more:
    while(1){}
  }
  else
  {
    Serial.println(F("SD init success"));
  }
  SdFile::dateTimeCallback(file_date_time); // Attach callback function to provide date time to files. 
}

this forum is such fast... unbelievable! :smiley:

Thanks for the suggestions. Bad luck, I am using DS1307.h for the RTC.
Is there a solution for this library as well?
Otherwise I would have to change my code... but I WILL, if that is the best/easiest solution.
Thanks

@Nick, noted about the search!

I don't see what difference the library makes.

As long as you can get the date and time (and what is the purpose of the clock if you can't?) you plug it into these two lines:

*date=FAT_DATE(now.year(),now.month(),now.day());
*time=FAT_TIME(now.hour(),now.minute(),now.second());

I've used the DS1307.h library. It can return an array of numbers in the rtc. So instead of the now.year() you will replace it with rtc[6] etc.

I tried:

#include <DS1307.h>
int rtc[7];
byte rr[7];
const byte chipSelectSD_pin = 10;

#include <SD.h>
#include <Wire.h>
//#include <RTClib.h>
//RTC_DS1307 RTC; // define the Real Time Clock object

SdFat sd;
SdFile imgFile;

//This function returns the date and time for SD card file access and modify time. One needs to call in setup() to register this callback function: SdFile::dateTimeCallback(file_date_time);
void file_date_time(uint16_t* date, uint16_t* time) 
{

  *date=FAT_DATE(rtc[6],rtc[5],rtc[4]);
  *time=FAT_TIME(rtc[2],rtc[1],rtc[0]);
}

void setup() 
{
  RTC.get(rtc,true);

  // see if the card is present and can be initialized:
  if (!sd.begin(chipSelectSD_pin, SPI_HALF_SPEED))
  {
    Serial.println(F("SD init Failed"));
    // don't do anything more:
    while(1){}
  }
  else
  {
    Serial.println(F("SD init success"));
  }
  SdFile::dateTimeCallback(file_date_time); // Attach callback function to provide date time to files. 
}

void loop() { while (1) ; }

which throws:

SD_mit_Datum_schreiben:11: error: 'SdFat' does not name a type
SD_mit_Datum_schreiben.ino: In function 'void file_date_time(uint16_t*, uint16_t*)':
SD_mit_Datum_schreiben:19: error: no match for 'operator[]' in 'RTC[6]'
SD_mit_Datum_schreiben:19: error: no match for 'operator[]' in 'RTC[5]'
SD_mit_Datum_schreiben:19: error: no match for 'operator[]' in 'RTC[4]'
SD_mit_Datum_schreiben:20: error: no match for 'operator[]' in 'RTC[2]'
SD_mit_Datum_schreiben:20: error: no match for 'operator[]' in 'RTC[1]'
SD_mit_Datum_schreiben:20: error: no match for 'operator[]' in 'RTC[0]'
SD_mit_Datum_schreiben.ino: In function 'void setup()':
SD_mit_Datum_schreiben:26: error: 'sd' was not declared in this scope

SDfat is not there, RTC are integers, and sd.begin is undefined.

Add the sense RTC code here and int RTC[7]; in this function. You can’t use RTC array without defining it. You can’t be serious if you don’t first fill RTC array with correct data with a DS1307 library call. I’m about to reach out for a spoon but I think you can do it yourself. :wink:

//This function returns the date and time for SD card file access and modify time. One needs to call in setup() to register this callback function: SdFile::dateTimeCallback(file_date_time);
void file_date_time(uint16_t* date, uint16_t* time) 
{

  *date=FAT_DATE(RTC[6],RTC[5],RTC[4]);
  *time=FAT_TIME(RTC[2],RTC[1],RTC[0]);
}

:frowning: !!

it was all done ok, I just confused upper- and lowercase.

RTC.get(rtc,true); fills the array. Code above corrected

errors left are:

10: error: 'SdFat' does not name a type
: In function 'void setup()':
28: error: 'sd' was not declared in this scope

??? Are you using a different SD library than what I have? Mine is from SD - Arduino Reference and 'SD' is to be uppercase.
So, using the library I have, the SD card is to be opened by if (![b]SD[/b].begin(chipSelect, SPI_HALF_SPEED))

Thanks for helping a newbie!

Yeah, that is a noob question. You should install sdfat library and have #include <SdFat.h> on line 1.

This is my version. Change the RTC library to your version.

#include <SdFat.h>
#include <RTClib.h>
RTC_DS1307 RTC; // define the Real Time Clock object
SdFat sd;
SdFile imgFile;

//This function returns the date and time for SD card file access and modify time. One needs to call in setup() to register this callback function: SdFile::dateTimeCallback(file_date_time);
void file_date_time(uint16_t* date, uint16_t* time) 
{
  DateTime now = RTC.now();
  *date=FAT_DATE(now.year(),now.month(),now.day());
  *time=FAT_TIME(now.hour(),now.minute(),now.second());
}

void setup() 
{
  // see if the card is present and can be initialized:
  if (!sd.begin(chipSelect, SPI_HALF_SPEED))
  {
    Serial.println(F("SD init Failed"));
    // don't do anything more:
    while(1){}
  }
  else
  {
    Serial.println(F("SD init success"));
  }
  SdFile::dateTimeCallback(file_date_time); // Attach callback function to provide date time to files. 
}

Yeah, that is a noob question.
YES, and I am one.
But well, none of the posts above showed this include. Up to now I did not know that SDfat.h exists. I am using SD.h from arduino.cc.
Error messages are all gone now, and I'll change my other code for SDfat.
Thanks for your help, you made my day happy! :slight_smile:

No problem. The earlier you reveal you are a noob, the more complete code you will get. It takes time to type up code.

:slight_smile: see the no. of my posts!
Thanks again.

maraio:
Well, the SDlib does not know that I have a RTC connected also :slight_smile:

I find it more convenient to make new files each day which are named by date. This means there is no need to file the date. This uses the library RTClib. I don’t use it for actually checking the time.

#include <SD.h>
#include "RTClib.h"
#include <Wire.h>
#include <string.h>

RTC_DS1307 RTC;
char filename[] = "00000000.CSV";
File myFile;

void setup()
{
Serial.begin(9600);
Wire.begin(); //Important for RTClib.h
RTC.begin();

if (! RTC.isrunning()) {

Serial.println("RTC is NOT running!");
return;
}

Serial.print("Initializing SD card...");

pinMode(10, OUTPUT);

if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
}

void loop()
{

getFileName();
createFileName();
delay(3000);
}

void getFileName(){

DateTime now = RTC.now();

filename[0] = (now.year()/1000)%10 + '0'; //To get 1st digit from year()
filename[1] = (now.year()/100)%10 + '0'; //To get 2nd digit from year()
filename[2] = (now.year()/10)%10 + '0'; //To get 3rd digit from year()
filename[3] = now.year()%10 + '0'; //To get 4th digit from year()
filename[4] = now.month()/10 + '0'; //To get 1st digit from month()
filename[5] = now.month()%10 + '0'; //To get 2nd digit from month()
filename[6] = now.day()/10 + '0'; //To get 1st digit from day()
filename[7] = now.day()%10 + '0'; //To get 2nd digit from day()
}

void createFileName(){
myFile = SD.open(filename, FILE_WRITE);
myFile.close();
}

thats what I am doing also, like this:

holstring="WP";   if (rtc[4] <10) holstring +='0'; holstring += String(rtc[4], DEC);
  if (rtc[5] <10) holstring +='0'; holstring += String(rtc[5], DEC);
  holstring+=String(rtc[6]%100, DEC) + ".TXT";

Anyway I prefer that files have the correct date also.

The SDfat lib works well with a small test sketch.

Now I added it into my 'real' sketch.
And I found SDfat is not compatible with library streaming.h.

This happens:

In file included from D:\arduino-1.0.5\libraries\SdFat/SdStream.h:27,
                 from D:\arduino-1.0.5\libraries\SdFat/SdFat.h:36,            from wpumpe.ino:12:
D:\arduino-1.0.5\libraries\SdFat/iostream.h: In function 'ostream& endl(ostream&)':
D:\arduino-1.0.5\libraries\SdFat/iostream.h:40: error: 'ostream& endl(ostream&)' redeclared as different kind of symbol
D:\arduino-1.0.5\libraries\Streaming/Streaming.h:100: error: previous declaration of '_EndLineCode endl'

I changed the name of 'endl' in streaming.h and now everything compiles and works ok.
A new experience for a Newbie that libraries might be incompatible! :slight_smile:

BTW, may a SD card be removed (and later re-installed) even if the system is not switched off, if I just make sure that there are no write cyles and Chipselect is always HIGH?

Greetz to all!

Make sure you close the file before removing the card. I've not tried with sdfat library but I did with SD library. It works.

yes sure. Close the file and inhibit more writes.
Re-inserting the card and send a command thru SerialMonitor to continue writing seems not to work however. With or without a new sd.begin(). I have to investigate more after my holidays.
Greetings!

maraio:
The SDfat lib works well with a small test sketch.

Now I added it into my ‘real’ sketch.
And I found SDfat is not compatible with library streaming.h.

I changed the name of ‘endl’ in streaming.h and now everything compiles and works ok.
A new experience for a Newbie that libraries might be incompatible! :slight_smile:

Greetz to all!

SDfat has its own streaming features…

ArduinoOutStream cout(Serial);  
cout << setw(4) << x+1 << ")" << setw(65) << place[x].DEF_NAM << setw(65) << place[x].FULL_COUNTY << endl;

for example…

Or a’real’ more useful example may be :-

    if(mysats>0 && age <1000)
    {
      if(logfile.open(logname, O_WRITE | O_CREAT | O_APPEND))
      {
        distanceto=TinyGPS::distance_between(dlat, dlon, Dest_LAT, Dest_LON) / 1609.344;
        courseto=TinyGPS::course_to(dlat, dlon, Dest_LAT, Dest_LON);
        char mydate[25], buf[100];
        sprintf(mydate, "%02d:%02d:%02d,",
        hour(), minute(), second()); 
        logfile.clearWriteError();
        obufstream bout(buf, sizeof(buf));
        bout << mydate << setw(3) << age << ',' << setw(10) << setprecision(6) << dlat << ',' << setprecision(6) << setw(10) << dlon 
          << ',' << setprecision(2) << falt << ',' << East << ',' << North << ','
          << setw(6) << setprecision(2) << courseto << ',' << setw(7) << setprecision(2) << distanceto << ',' << setw(2) << mysats << ',' 
          << setw(4) << myhdop <<endl;   
        SdFile::dateTimeCallback(dateTime);
        logfile.write(buf, sizeof(buf));
        cout << buf ;
        logfile.close();
      }
    }

hope this helps?

Regards,

Graham