CardInfo reports wrong size on Logger Shield

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
pgrunwald
 
Posts: 36
Joined: Tue Jul 14, 2009 10:32 pm

CardInfo reports wrong size on Logger Shield

Post by pgrunwald »

I have an 8GB Samsung Micro SD Card in an adapter. I formatted the card with the SD Formatted Utility from the SD site and it and Windows reports 7.4GB usable area.

I get this when I run CardInfo:

Code: Select all

Initializing SD card...
Card type: SDHC

Volume type is FAT32

Volume size (bytes): 3658711040
Volume size (Kbytes): 3572960
Volume size (Mbytes): 3489

Files found on the card (name, date and size in bytes): 
DATALOG.TXT   2000-01-01 01:00:00 2886


Datalogger worked find and the file is readable in Windows. What am I missing?

Thanks,
Paul

User avatar
fat16lib
 
Posts: 595
Joined: Wed Dec 24, 2008 1:54 pm

Re: CardInfo reports wrong size on Logger Shield

Post by fat16lib »

CardInfo has a bug that caused it to report the wrong size for cards larger than 4 GB.

CardInfo uses a uint32_t which is limited to 4,294,967,295 so you get some truncated wrong answer.

Code: Select all

  uint32_t volumesize;
You can change the section that prints the volume type and size like this

Code: Select all

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
  
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  if (volumesize < 0X800000) {
    volumesize *= 512;                        // SD card blocks are always 512 bytes
    Serial.print("Volume size (bytes): ");
    Serial.println(volumesize);
    volumesize /= 1024;
  } else {
     volumesize /= 2;
  }
  Serial.print("Volume size (Kbytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
Then an 8GB card will print something like this:
Volume size (Kbytes): 7753728
Volume size (Mbytes): 7572

And a 2GB will print the byte count:
Volume size (bytes): 1977286656
Volume size (Kbytes): 1930944
Volume size (Mbytes): 1885
Last edited by fat16lib on Wed Dec 26, 2012 9:16 pm, edited 1 time in total.

User avatar
pgrunwald
 
Posts: 36
Joined: Tue Jul 14, 2009 10:32 pm

Re: CardInfo reports wrong size on Logger Shield

Post by pgrunwald »

Thanks!

User avatar
PrefontDon
 
Posts: 133
Joined: Sat May 25, 2013 10:45 pm

Re: CardInfo reports wrong size on Logger Shield

Post by PrefontDon »

I'm documenting this for myself and anyone else interested. Researching suggests that the Print function (Serial.print, display.print, lcd.print, etc.) has an issue with counts greater than 4GB or 4,294,967,296. If you are using an 8GB or 16GB or larger SD card and have formatted it with SDFormatter as per https://www.sdcard.org/downloads/formatter_4/, referenced first in https://learn.adafruit.com/adafruit-dat ... he-sd-card, the value achieved will be too big to print and it will "fail" with the wrong value. The reason is because we are multiplying the 'number of bytes per block or sector' by 'number of blocks per cluster' by 'cluster count'. Change your code such that 'bytes per block' is multiplied by 'cluster count' then immediately divided by 1MB, before the result is multiplied by 'blocks per cluster'. Example:
(512 x volume.clusterCount /1048576) and then multiply result by volume.blocksPerCluster. My experience has shown that if this is broken into two operations, the number cannot get larger than the Print limit.

Code: Select all

Serial.print("Bytes per block/sector: "); Serial.println(512);                        // 512.
Serial.print("volume.blocksPerCluster: "); Serial.println(volume.blocksPerCluster()); // 64
Serial.print("volume.clusterCount: "); Serial.println(volume.clusterCount());         // Large value.
uint32_t CCx512 = ((512 * volume.clusterCount()) / 1048576);                          // Divide by 1MB to keep the number low for next operation.
Serial.print("CCx512: "); Serial.println(CCx512);
uint32_t bPCxCCx512_GB = ((CCx512 * volume.blocksPerCluster()) / 1024);               // Divide by 1KB to convert the MB value to GB.
Serial.print("bPCxCCx512_GB: "); Serial.println(bPCxCCx512_GB);
Serial.print("Formatted SD card size: "); Serial.print(bPCxCCx512_GB); Serial.println("GB");
Serial.println();

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”