I plan to use my datalogger for several month, even years, so I have to deal with the SD Library beyond hte usual examples: opening and closing a file every day at 00:10, and cleaning files in case the SD card is running out of space.
Unfortunately the Standard SD library is somehow limited, there is a new library version called SDFat, with more functions and possibilities, but I prefer to use the "standar" one. SD - Arduino Reference
My problem is that I would like to get the number of files in the SD card, in this way I can assume the free size of the SD card, since all the files will have a similar size.
Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE);
But I honestly don know how to catch the lines and summarize them.
Also, when I take a look to the SD card in my computer, the files have no correct date and time information, is this normal?, do you need extra configuration of the SD library to deal with dates?
Also, when I take a look to the SD card in my computer, the files have no correct date and time information, is this normal?
Perfectly normal. The SD reader/writer has no idea what time it is, and neither does the Arduino.
The SD library defines the File class. One of the methods of the File class is size(). That should give you a reasonable approximation of any file's size. Add them all up, and you know how much of the card is being used. Sort of. There are block sizes to consider.
I just adapted the code of the listfiles sketch in the library example. I can now get the number of files in an SD Card, and the size of all of them. I can anticipate when the SD card is running out of space and erasing some of the older files.
#include <SPI.h>
#include <SD.h>
File root;
unsigned long SDSize=0;
unsigned long SDFiles=0;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
if (!SD.begin(10)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
root = SD.open("/");
printDirectory(root, 0);
Serial.println("done!");
}
void loop()
{
// nothing happens after setup finishes.
}
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
SDSize = SDSize + entry.size();
SDFiles++;
if (! entry) {
// no more files
Serial.print("Tarjeta SD ocupada (bytes): ");
Serial.println(SDSize);
Serial.print("Num. ficheros: ");
Serial.println(SDFiles-1);
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
I think I can detect the oldest file with the rewindDirectory(), of the File Class, but I have not checked this yet
I finalized my sketch, and I want to share it, in the case somebody wants to have the functionality of a datalogger that is able to check the SD size and erase the oldest files in order to guarantee that there is always enough space and data in the SD card.
I just use the estandard Arduino SD library, next step would be go lower level using the SDFat Library, as far as I know the standard SD library is just a wrapper of the SDFat library.
This is the code very much based on the listfiles example of the SD library, any suggestion is welcomed:
/* Listfiles -> This example shows how print out the files in a directory on a SD card */
#include <SPI.h>
#include <SD.h>
#define SD_MAXSIZE 3723493376 // Maximum Volume Size in FAT32: 3.723.493.376 bytes
void setup()
{
Serial.begin(115200);
if (!SD.begin(10)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
File root=SD.open("/");
printDirectory(root, 0);
}
void loop()
{ }
void printDirectory(File dir, int numTabs) {
unsigned long SDSize=0;
unsigned long SDFiles=0;
// logfile.close();
while(true) {
File entry = dir.openNextFile();
SDSize = SDSize + entry.size();
SDFiles++;
if (! entry) { // No more Files -> File Listing completed
Serial.print("Tarjeta SD ocupada (bytes): ");
Serial.println(SDSize);
Serial.print("Tarjeta SD ocupada (Kbytes): ");
Serial.println(SDSize/1024);
Serial.print("Num. ficheros: ");
Serial.println(SDFiles-1);
// Check SD used Size > 90% x 3.723.493.376 bytes
if (SDSize > 00) { //0.9*SD_MAXSIZE) {
dir.rewindDirectory(); // Moving to Parent Directory
Serial.print("Rebobinando Directorio: ");
Serial.println(dir.name());
for (uint8_t i = 0; i < 2; i++) {
File entry = dir.openNextFile(); // Moving to oldest File in the parent direcotry
Serial.print("\nErasing File: ");
Serial.println(entry.name());
SD.remove(entry.name());
}
}
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}