Sdfat Library (Sd Card Size & Free Space)

Hello guys,

Until a while back I was using the SD.h library, that as fat16lib says, it’s just a wraper for a old version of Sdfat.
So, the first time I was trying to understand the Sdfat library, it was updated to be “compatible” with the SD.h, so I tought, “how lucky I’m I can still use the same code with the new and improved library without any extra work”.

I’m not a programmer, and I have almost no experience in programming, everything I learned, I learned alone with the try and error techinique and ALOT of copy / paste and Google research. That the way I’m, and I like to think that I learn this way, and I’m very glad with the results I got so far. I can’t say that my code have the best pratices, but at least I mannage to do what I want (with the help of everyone here, I would dare to say almost everything I want :P).

So, now the time as came, and I finally decided to study the SdFat library, that as I see, is ALOT more complex and much more difficult to understand, with all that classes and everything else. But I finnaly manage to change my code from the old File class, to the new SdFile class and it’s commands. Once I finnaly understand it, it isn’t so different, and not so difficult after all, because the really nice documentation available.

But I’m struggling with a little piece of code.
Every where I look here on the forum give some different way of calculating the Sd Card Size and the Free Space Available, and I couldn’t manage any of these to return me the correct values for my card.

Here is the output I have from SdInfo as base.

cardSize: 1952.45 MB (MB = 1,000,000 bytes)
freeSpace: 1951.89 MB (MB = 1,000,000 bytes)

Ok, now I know that the SdInfo example calculates the free space based on the free clusters, so I tried to make this code below to suit my needs.

#include <SdFat.h>
SdFat SD;

void setup() {
  Serial.print(F("SD Card"));
  if (SD.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) {
    Serial.printf(F(" Size: %d MB"), SD.card()->cardSize() / 2048);
    Serial.printfn(F(" (Free: %d MB)."), SD.card()->cardSize() / 2048 - SD.vwd()->fileSize() / 512);
    SD.ls(LS_SIZE);
  }
}

void loop() {}

That outputs:

SD Card Size: 1862 MB (Free: 1830 MB).
1.TXT       2486
2.TXT       381
3.TXT    403
4.HTM    5836
5.HTM     6062
6.HTM    4716
7.PNG   19321

So my questions are, Am I doing right? That values of 2048 and 512, I found to give the closest results, but even that doesn’t represent the true, since Sd Card Size value isn’t the same I got from the SdInfo (1952 MB). And the fileSize, seens to be close the real, but it isn’t, the files have a size of 39 MB, and it says 32MB.

So, how can I do that?
Can I use the SD.vwd()->fileSize() to get the actual size of the entire root directory?
That size really means all the used space from the Sd Card as I tought it to be?

SD.card()->cardSize() returns the number of 512 byte blocks on the card.

The size in MB (MB = 1,000,000 bytes) is 0.000512 times the size in blocks.

You divided by 2048 so you get a result that is too small.

Your card has 18622048 blocks. The size in MB is 1,952.45 = 18622048*0.000512

SD.vwd()->fileSize() has nothing to do with used space on the SD. fileSize() is not meaningful for directory files.

You must use SD.vol()->freeClusterCount() to get the number of free clusters in the volume and calculate the size using the number of blocks in a cluster as in the SdInfo example.

Note that the SD.h CardInfo example gives card size in KiB (KiB = 1024 bytes) and MiB (MiB = 1048576 bytes).

See this Nist page.

fat16lib: Note that the SD.h CardInfo example gives card size in KiB (KiB = 1024 bytes) and MiB (MiB = 1048576 bytes).

That output I got from SdInfo from SdFat library, not the SD.h one.

cardSize: 1952.45 MB (MB = 1,000,000 bytes)
freeSpace: 1951.89 MB (MB = 1,000,000 bytes)

fat16lib: SD.card()->cardSize() returns the number of 512 byte blocks on the card.

The size in MB (MB = 1,000,000 bytes) is 0.000512 times the size in blocks.

You divided by 2048 so you get a result that is too small.

Your card has 1862*2048 blocks. The size in MB is 1,952.45 = 1862*2048*0.000512

I have tried this on my skecth, and it outputs 3767 MB.

SD.card()->cardSize() * 0.000512

fat16lib: SD.vwd()->fileSize() has nothing to do with used space on the SD. fileSize() is not meaningful for directory files.

You must use SD.vol()->freeClusterCount() to get the number of free clusters in the volume and calculate the size using the number of blocks in a cluster as in the SdInfo example.

Ok, but the freeSpace from SdInfo is wrong, isn't it?

SD.vol()->freeClusterCount() * SD.vol()->blocksPerCluster() * 0.000512

My files had 38MB at that time, and it was saying that it was using only 0.56 MB space?

I have tried this on my skecth, and it outputs 3767 MB.

This is how I calculate the size in SdInfo, put this code in your sketch.

  uint32_t cardSize;
  cardSize = sd.card()->cardSize();
  cout << F("cardSize: ") << 0.000512*cardSize;

My files had 38MB at that time, and it was saying that it was using only 0.56 MB space?

How did you get 38MB? The listing shows very little use.

1.TXT 2486
2.TXT 381
3.TXT 403
4.HTM 5836
5.HTM 6062
6.HTM 4716
7.PNG 19321

File sizes are in bytes but you can’t just add the sizes. Each file has at least one cluster allocated.

The 0.56 MB includes the File Allocation Table and your files.

How did you format your SD card? Unless you use the SD formatter utility there may be hidden files or you may have a non-standard format with hidden space.

Please post the entire output from the SdInfo example.

fat16lib:
This is how I calculate the size in SdInfo, put this code in your sketch.

  uint32_t cardSize;

cardSize = sd.card()->cardSize();
  cout << F("cardSize: ") << 0.000512*cardSize;

Ok, I’ll try exactly that when I get home.

fat16lib:
How did you format your SD card? Unless you use the SD formatter utility there may be hidden files or you may have a non-standard format with hidden space.

Actually I formatted it using the SdFormatter example of the SdFat library, it’s the same thing, right?!

The SdFormatter example should produce the same format as the SD Association formatter.

I think it wasn't doing the calculation inside the printf.

Now it works.

    float cardSize = SD.card()->cardSize() * 0.000512;
    float used = cardSize - SD.vol()->freeClusterCount() * SD.vol()->blocksPerCluster() * 0.000512;
    Serial.printf(F(" Size: %d.%02d MB"), (unsigned int)cardSize, (unsigned int)(cardSize * 100.0) % 100);
    Serial.printfn(F(" (Used: %d.%02d MB)."), (unsigned int)used, (unsigned int)(used * 100.0) % 100);

Output: SD Card Size: 1952.72 MB (Used: 0.55 MB).

Thanks fat16lib.