Error Initializing SD Card on GPS 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
Ignoramus
 
Posts: 14
Joined: Sun May 03, 2015 1:13 am

Error Initializing SD Card on GPS Shield

Post by Ignoramus »

Hi all,

I'm having difficulties reading/writing to a MicroSD on the Adafruit Ultimate GPS Logger Shield.

I currently am using an Arduino Uno with the ReadWrite sketch from Adafruit's SD library: (Code pasted below).

Code: Select all

/*
  SD card read/write
 
 This example shows how to read and write data to and from an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** UNO:  MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 4 (CS pin can be changed)
  and pin #10 (SS) must be an output
 ** Mega:  MOSI - pin 51, MISO - pin 50, CLK - pin 52, CS - pin 4 (CS pin can be changed)
  and pin #52 (SS) must be an output
 ** Leonardo: Connect to hardware SPI via the ICSP header

 
 created   Nov 2010  by David A. Mellis
 modified 9 Apr 2012  by Tom Igoe
 
 This example code is in the public domain.
 	 
 */
 
#include <SPI.h>
#include <SD.h>

File myFile;

// change this to match your SD shield or module;
//     Arduino Ethernet shield: pin 4
//     Adafruit SD shields and modules: pin 10
//     Sparkfun SD shield: pin 8
const int chipSelect = 10;

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...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(10, OUTPUT);
   
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
	// close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
    
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
    	//Serial.write(myFile.read());
        Serial.println(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop()
{
	// nothing happens after setup
}
However, when I run it I get the following error/message on the serial monitor:

Code: Select all

Initializing SD card...initialization failed!
When I run the CardInfo sketch (also pasted below for thoroughness), the output indicates no errors.

Code: Select all

/*
  SD card test 
   
 This example shows how use the utility libraries on which the'
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you're not sure whether its working or not.
 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** UNO:  MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 4 (CS pin can be changed)
  and pin #10 (SS) must be an output
 ** Mega:  MOSI - pin 51, MISO - pin 50, CLK - pin 52, CS - pin 4 (CS pin can be changed)
  and pin #52 (SS) must be an output
 ** Leonardo: Connect to hardware SPI via the ICSP header
 		Pin 4 used here for consistency with other Arduino examples

 
 created  28 Mar 2011  by Limor Fried 
 modified 9 Apr 2012   by Tom Igoe
 */
 // include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 10;    

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("\nInitializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(10, OUTPUT);


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  while (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card is inserted?");
    Serial.println("* Is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
  } 
  
  // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // 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
  volumesize *= 512;                            // SD card blocks are always 512 bytes
  Serial.print("Volume size (bytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);

  
  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);
}


void loop(void) {
  
}

Code: Select all

Initializing SD card...
Card type: SD1

Volume type is FAT12

Volume size (bytes): 62341120
Volume size (Kbytes): 60880
Volume size (Mbytes): 59

Files found on the card (name, date and size in bytes): 
I was searching for similar issues on the forum, but I didn't see any where the CardInfo could successfully read the SD card, as I am experiencing. What could be the issue, and how can I work around or address it?

Thanks!

User avatar
adafruit_support_bill
 
Posts: 88154
Joined: Sat Feb 07, 2009 10:11 am

Re: Error Initializing SD Card on GPS Shield

Post by adafruit_support_bill »

That is unusual. One thing I notice is that cardInfo is starting the SPI interface at half speed. This can be done in SD also with a bit of library tweaking as described in the link below. Timing does vary a bit between cards.

http://forum.arduino.cc/index.php?topic=108017.0

User avatar
Ignoramus
 
Posts: 14
Joined: Sun May 03, 2015 1:13 am

Re: Error Initializing SD Card on GPS Shield

Post by Ignoramus »

Thanks for the response!

The library's default SPI speed appears to be SPI_HALF_SPEED; namely, the library's unmodified begin code is:

Code: Select all

boolean SDClass::begin(uint8_t csPin, int8_t mosi, int8_t miso, int8_t sck) {
  /*

    Performs the initialisation required by the sdfatlib library.

    Return true if initialization succeeds, false otherwise.

   */
  return card.init(SPI_HALF_SPEED, csPin, mosi, miso, sck) &&
         volume.init(card) &&
         root.openRoot(volume);
}
Since the CardInfo sketch worked with SPI speed set to half, I don't believe speed is the problem. Are there any other possible causes?

User avatar
adafruit_support_bill
 
Posts: 88154
Joined: Sat Feb 07, 2009 10:11 am

Re: Error Initializing SD Card on GPS Shield

Post by adafruit_support_bill »

You can try Quarter-speed. You could also try another card. I can't think of any reason why CardInfo and the example sketch woud not work at the same speed.

User avatar
Ignoramus
 
Posts: 14
Joined: Sun May 03, 2015 1:13 am

Re: Error Initializing SD Card on GPS Shield

Post by Ignoramus »

As suggested, I tried quarter speed -- I still get the same error when running ReadWrite, but CardInfo still works (at quarter speed).

Upon further investigation, I'm finding that SD.begin is returning 0 because root.openRoot(volume) is returning zero. Both card.init(...) and volume.init(...) are returning 1.

What could be the reasons for root.openRoot(volume) failing? Is it part of the SdFat and/or SdFatUtil libraries? If so, what subdirectory are they normally located in?

Thanks!

User avatar
adafruit_support_bill
 
Posts: 88154
Joined: Sat Feb 07, 2009 10:11 am

Re: Error Initializing SD Card on GPS Shield

Post by adafruit_support_bill »

Sounds like maybe you are talking to the card fine, but there is a problem with the card format. Have you formatted the card using the SD association formatter?
https://www.sdcard.org/downloads/formatter_4/

User avatar
jboyton
 
Posts: 101
Joined: Tue Sep 16, 2014 2:52 pm

Re: Error Initializing SD Card on GPS Shield

Post by jboyton »

I could be mistaken but I believe that SD doesn't support FAT12.
SdFat, which SD was originally based upon, has an "experimental" mode for supporting FAT12.
You could get a better explanation by asking the author. He posts on forum.arduino.cc as "fat16lib".
This might be of interest: http://forum.arduino.cc/index.php?topic=315855.0


Here's an excerpt from the documentation for SdFat (emphasis added by me):
How to format SD Cards as FAT Volumes

You should use a freshly formatted SD card for best performance. FAT file systems become slower if many files have been created and deleted. This is because the directory entry for a deleted file is marked as deleted, but is not deleted. When a new file is created, these entries must be scanned before creating the file, a flaw in the FAT design. Also files can become fragmented which causes reads and writes to be slower.

A formatter sketch, SdFormatter.pde, is included in the SdFat/examples/SdFormatter directory. This sketch attempts to emulate SD Association's SDFormatter.

The best way to restore an SD card's format on a PC is to use SDFormatter which can be downloaded from:

http://www.sdcard.org/consumers/formatter/

SDFormatter aligns flash erase boundaries with file system structures which reduces write latency and file system overhead.

SDFormatter does not have an option for FAT type so it may format small cards as FAT12.

After the MBR is restored by SDFormatter you may need to reformat small cards that have been formatted FAT12 to force the volume type to be FAT16.


If you reformat the SD card with an OS utility, choose a cluster size that will result in:

4084 < CountOfClusters && CountOfClusters < 65525

The volume will then be FAT16.

If you are formatting an SD card on OS X or Linux, be sure to use the first partition. Format this partition with a cluster count in above range for FAT16. SDHC cards should be formatted FAT32 with a cluster size of 32 KB.

Microsoft operating systems support removable media formatted with a Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector in block zero.

Microsoft operating systems expect MBR formatted removable media to have only one partition. The first partition should be used.

Microsoft operating systems do not support partitioning SD flash cards. If you erase an SD card with a program like KillDisk, Most versions of Windows will format the card as a super floppy.

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: Error Initializing SD Card on GPS Shield

Post by adafruit_support_mike »

The SD Formatter doesn't know anything about filesystems.

Every SD card has a microcontroller that maps blocks of physical storage to logical blocks that are used by a filesystem. The physical storage has sections that don't work straight off the wafer, and other sections that fail as the array is used. The microcontroller tracks those issues and tries to keep a list of working physical blocks for all the logical blocks.

A low-level format tells the microcontroller to test all the physical/logical block mappings, retire any physical blocks that need it, and replace them with new working blocks.

A filesystem only knows about the logical blocks, and the low-level format doesn't know anything about the data structures or organizational scheme used in filesystems.

User avatar
jboyton
 
Posts: 101
Joined: Tue Sep 16, 2014 2:52 pm

Re: Error Initializing SD Card on GPS Shield

Post by jboyton »

adafruit_support_mike wrote:The SD Formatter doesn't know anything about filesystems.
So are you saying that Bill Greiman is wrong when he says SDFormatter will sometimes format cards as FAT12?

I just noticed that cardinfo was reporting FAT12 for the card "ignoramus" has.
I thought that might be the problem.

User avatar
Ignoramus
 
Posts: 14
Joined: Sun May 03, 2015 1:13 am

Re: Error Initializing SD Card on GPS Shield

Post by Ignoramus »

@jboyton Thanks for the link! When you say the SD doesn't support FAT12, are you referring to the SD library or the card itself? (I'm assuming the former since it makes more sense).

Also, since you've pointed out that the card's format may be the issue, I've searched and found what appears to be the solution to my problem. (Link if anybody's interested: http://forum.arduino.cc/index.php?topic ... #msg353630). Unfortunately, I don't have a microSD adapter on hand, so I'm unable to test this for the time being. I will update when I get my hands on an adapter.

@adafruit_support_mike Thanks for the response! I understand the basics of what you're saying, but I don't really see the relevance.

Overall, the impression I'm under is this:
The SdFat library(/libraries) do not work with FAT12. Small SD cards (such as mine) are default formatted as FAT12 by SDFormatter. The solution to this is to reformat the SD as FAT16, but there is no direct "option" to do so with most utilities. However, the method in the post I linked above looks promising; I will update when I'm able to test it, but I'm confident that it will work.

Thanks for the help everybody!

User avatar
jboyton
 
Posts: 101
Joined: Tue Sep 16, 2014 2:52 pm

Re: Error Initializing SD Card on GPS Shield

Post by jboyton »

I'm not sure if SD supports FAT12 or not. But since SD is based on an older version of SdFat, and SdFat will support FAT12 only if an option switch is set, it seemed like a possibility that SD won't work with it. If you look at that link I posted it's from the author of SdFat testing the FAT12 option. He's happy because the older, smaller card he's using is faster than newer, larger cards. So I suppose you could do the same thing: instead of using SD, use SdFat with that option switch set. Or figure out how to format the card as FAT16. Or maybe it's not the problem. As I said, I'm not sure. You could always ask Bill Greiman (fatlib16) yourself.

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

Return to “Arduino Shields from Adafruit”