Pages: [1] 2   Go Down
Author Topic: Ethernet shield SD card initialization failed  (Read 6860 times)
0 Members and 1 Guest are viewing this topic.
California
Offline Offline
Sr. Member
****
Karma: 3
Posts: 433
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to use the microsd card slot on my ethernet shield and it is not working. I'm not even trying to run ethernet stuff yet, just SD card examples. I've tried the code in this thread and a few others with no luck. I've formatted the card several times with windows and the official SD formatting tool.

Now I am reading that the ethernet library messes with the SD library, but if I'm not even trying the ethernet library should there be any reason for the SD card to not work? Do I have a different problem in this case?
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1273
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What hardware are you using? The sd card and the Ethernet stuff run completely independently and do not affect each other on my Uno.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 617
Posts: 49463
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Do I have a different problem in this case?
Yes, no, maybe.

Some code?
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6040
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The sd card and the Ethernet stuff run completely independently and do not affect each other on my Uno.
They do not run independently on my mega2560. They are both SPI devices, and if not disabled or initialized correctly, they will cause failures in the other device.

Have you tried the ethernet part of the shield to check the SPI connection? Try this sketch. Does it show 192.168.2.2 on the serial monitor? Or does it show 0.0.0.0?
Code:
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,2,2);

void setup() {
  Serial.begin(9600);

  // disable SD card if one in the slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Serial.println("Starting w5100");
  Ethernet.begin(mac,ip);

  Serial.println(Ethernet.localIP());
}

void loop() {
}
You should be able to leave the SD card in the slot for this test. Note the SD disable in the setup.
Logged

California
Offline Offline
Sr. Member
****
Karma: 3
Posts: 433
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

But on the shield they are supposed to be independent. What I'm saying is, I can't even get the SD card to work when I completely ignore the Ethernet stuff. I have no problem with the Ethernet stuff. And I am aware that there is some conflict when using both. But I am running code as if it were just the SD card and it doesn't work.

For instance the cardinfo sketch:
Code:
/*
  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:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
  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 <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 = 4;   

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);     // change this to 53 on a mega


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!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?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present.");
  }

  // 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) {
 
}

returns:
Quote
Initializing SD card...initialization failed. Things to check:
* is a card is inserted?
* Is your wiring correct?
* did you change the chipSelect pin to match your shield or module?

I've tried all of the example sketches for the SD card and they all fail to initialize the card.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 617
Posts: 49463
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But on the shield they are supposed to be independent.
How can they be independent when both use SPI? They use different SS pins, so you should be able to talk to each without interference from the other, but that is not the same as independent.

Quote
I've tried all of the example sketches for the SD card and they all fail to initialize the card.
Perhaps the problem is the card. Not all cards play well with all SD readers.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6040
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As PaulS said, they are never independent because they share the SPI bus. You can use either separately, but you MUST disable the other device to do so. Otherwise, you will have problems. This should be able to initialize and use the SD ok.
Code:
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
  }

  // disable w5100 SPI
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

  Serial.print("\nInitializing SD card...");
  // rest of your setup stuff
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am having the same problem.  Is there any way to debug exactly why the SD card initialization step is  failing? 

Thanks.
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1273
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What I have since found is that the SPI library will use the SS defined in the libraries even though you may be using a different SS for your device. For example, if the Ethernet is on SS pin N and the SD card uses pin M, and N is the same as the SS defined in the library, when you use the SD card (pin M) the library will also set N, in the library code. This is not what you expect or want to happen.

My way around this is that if I have one device then I will just use SS, if I have more than one device then I cannot use SS (ie it is lost to me as a valid pin) and I need to use two other pins and manage it myself. This assume that the pins are not hard wired, like on a shield.

An alternative is to hack the libraries to not use the SS pin the way it does.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

0
Offline Offline
Edison Member
*
Karma: 64
Posts: 1639
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there any way to debug exactly why the SD card initialization step is  failing?
This sketch will give more information.  The most common error code is 0X01.  This means the card does not respond to the first command to go into SPI mode.  Other error codes are defined in \arduino\libraries\SD\utility\Sd2Card.h.

Set sdCsPin and sharedCsPin for you configuration.
Code:
#include <SD.h>
#include <SPI.h>
Sd2Card card;
SdVolume vol;
SdFile root;

// Chip select pin for SD card.
const int sdCsPin = 8;

// Replace the -1 with the CS pin number of any shared SPI device.
const int sharedCsPin = -1;

void setup() {
  Serial.begin(9600);
  
  // Disable any other SPI devices
  if (sharedCsPin >= 0) {
    pinMode(sharedCsPin, OUTPUT);
    digitalWrite(sharedCsPin, HIGH);
  }
  
  // Try to initialize the SD card
  if (card.init(SPI_HALF_SPEED, sdCsPin)) {
    Serial.println("card init OK");
  } else {
    Serial.print("errorCode: ");
    Serial.println(card.errorCode(), HEX);
    Serial.print("errorData: ");
    Serial.println(card.errorData(), HEX);
    return;
  }
  
  // Try to initialize the FAT volume.
  if (vol.init(&card)) {
    Serial.println("vol init OK");
  } else {
    Serial.println("vol init failed");
    return;
  }
  
  // Try to open root.
  if (root.openRoot(&vol)) {
    Serial.println("open root OK");
  } else {
    Serial.println("open root failed");
  }
}
void loop() {}

Quote
An alternative is to hack the libraries to not use the SS pin the way it does.

If you use SS as an input, the library will no longer work.  Here is a section of the AVR datasheet for the SPI controller.
Quote
If SS is configured as an output, the pin is a general output pin which does not affect the SPI system. Typically, the pin will be driving the SS pin of the SPI Slave.

If SS is configured as an input, it must be held high to ensure Master SPI operation. If the SS pin is driven low by peripheral circuitry when the SPI is configured as a Master with the SS pin defined as an input, the SPI system interprets this as another master selecting the SPI as a slave and starting to send data to it. To avoid bus contention, the SPI system takes the following actions:

1. The MSTR bit in SPCR is cleared and the SPI system becomes a Slave. As a result of
the SPI becoming a Slave, the MOSI and SCK pins become inputs.

2. The SPIF Flag in SPSR is set, and if the SPI interrupt is enabled, and the I-bit in SREG is
set, the interrupt routine will be executed.
« Last Edit: June 04, 2014, 08:29:21 am by fat16lib » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6040
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What model Arduino are you using?

If you are using an Uno, the w5100 SPI will be disabled by accident when the SD.begin() call sets the default SPI slave select (D10) to OUTPUT and HIGH.

If you are using a Mega (SPI default SS is D53, not D10), then the w5100 SPI is left active, and this causes the SD.begin() function to fail on my Mega2560 if you do not set D10 as OUTPUT and HIGH.
Logged

0
Offline Offline
Edison Member
*
Karma: 64
Posts: 1639
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If you are using an Uno, the w5100 SPI will be disabled by accident when the SD.begin() call sets the default SPI slave select (D10) to OUTPUT and HIGH.

This is not an accident.  SS is set high to disable any device sharing SPI on 328 Arduinos and using D10 for chip select.  This was done mainly to avoid problems with the Ethernet shield on Uno and other 328 boards.  On 328 boards, D10 must be an output so setting it high avoids many problems.

In the above test sketch you should set sharedCsPin to 10 if you are using an Arduino Ethernet shield.  It won't hurt if you are using an Uno and is necessary if you use a Mega.

In general, the safest procedure is to set chip select for all SPI devices to output mode and high in setup before initializing any SPI device.


Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6040
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, fat16lib. I say it is disabled by "accident" by most Uno/Ethernet shield users because they do not intentionally do that, and because most don't realize it is being done for them. They should set that w5100 SPI SS pin OUTPUT and HIGH. I know the SPI library does that intentionally. I agree with you that all SPI SS pins should be set as OUTPUT and HIGH before initializing any SPI device.
Logged

0
Offline Offline
Edison Member
*
Karma: 64
Posts: 1639
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
They should set that w5100 SPI SS pin OUTPUT and HIGH. I know the SPI library does that intentionally

This statement points out one of the many defects in Arduino.  It is sad that users must worry about details at this level.

Why should users need to beg for help from "experts" for low level stuff like this?

The proper standards for hardware and libraries that use the SPI bus could avoid this type problem.

Hardware that uses the SPI bus should have a 50K pullup on chip select.  SD cards have this pullup and the pullup can be disabled during initialization.  Unfortunately most shields defeat this pullup with a level shifter and no pullup on the level shifter input.

Libraries should have a constructor with chip select as an argument.  The constructors could make sure all devices are disabled before setup() is called.

I am using this type constructor on new libraries and will add it to SdFat.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6040
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I agree with the hardware solution. A weak pullup on the slave select would solve most of this. There will still be the occasional user that will try to use that slave select pin for another device.

I disagree with the library/software solution. How is each device supposed to know about every SPI device connected to the bus? And even if it did, some users connect the device without adding the library include to the code.
Logged

Pages: [1] 2   Go Up
Jump to: