I just got an Ethernet shield so i went and got a 2gb micro SD card and im just trying to get it working I've tried every example sketch but it never initializes. I made sure that the card was formatted to FAT32 but it still wont work. What could be wrong?
Show the code you are using and provide details like: what board Uno etc. , what Ethernet shield, what errors do you get?
I'am using the Duemilanove with the atmega328 and the Ethernet shield R3 the sd card is a pny 2gb micro sd formatted to FAT32. Im just using the cardinfo example sketch included with arduino 1.0 and im not getting any error's.the serial is saying
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?
/*
SD card testThis 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 examplescreated 28 Mar 2011
by Limor Fried
modified 16 Mar 2011
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()
{
Serial.begin(9600);
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) {
}
Because you are using the Ethernet shield, your code needs to be adjusted. Pin 10 is the Chip Select for the For the W5100 Ethernet chip. This is a quote from the description: "For the W5100, set digital pin 10 as a high output. " Therefore, my suggestion is to add digitalwrite low to pin 10 to make sure you are not communication with the W5100 but, rather just the SD card.
Here is the code piece written under the line I am talking about.
pinMode(10, OUTPUT);
digitalWrite(10, LOW);
I tried it didn't work so i reset it a couple of times and it worked once and said it could not find a FAT16 or FAT32 partition so i reset it again and it it still wont recognize the card. Any other ideas?
Chip select low selects a device and high deselects the device. Chip Select for the W5100 is pin 10 so to disable the W5100 you need to set pin 10 high, not low.
Put this before any access to the SD card:
pinMode(10, OUTPUT);
// deselect W5100
digitalWrite(10, HIGH);
Also it is best to format cards that are 2 GB or smaller FAT16. The SD card standard says that only SDHC card may be formatted FAT32.
I accept FAT32 on smaller cards but they don't perform as well as FAT16. It is a myth that small SD cards perform better when formatted FAT32. The smaller cluster size for FAT32 causes higher overhead due to more rewrites of the File Allocation Table.
I wrote the SdFat library and the Arduino SD.h library is a wrapper for an old version of SdFat.
cyclegadget:
Because you are using the Ethernet shield, your code needs to be adjusted. Pin 10 is the Chip Select for the For the W5100 Ethernet chip. This is a quote from the description: "For the W5100, set digital pin 10 as a high output. " Therefore, my suggestion is to add digitalwrite low to pin 10 to make sure you are not communication with the W5100 but, rather just the SD card.Here is the code piece written under the line I am talking about.
pinMode(10, OUTPUT);
digitalWrite(10, LOW);
You mean HIGH!
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
This problem doesn't seem to be well documented, it took me ages to figure out what was wrong. It's worth noting that you should set all SPI devices inactive before trying to setup the first one, this problem isn't specific to the SD card/library.
Thank you for the correction guys. The info. given about the shield threw me off.
I tried setting it high but it still wont recognize the card more than half the time and still says it cant find a FAT16 or FAT32 partition when I've tried formatting it to both. I'm starting to think it may be something with the shield
/*
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 16 Mar 2011
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()
{
Serial.begin(9600);
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
digitalWrite(10, HIGH);
// 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) {
}
change this code...
// 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;
change into
// 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;
the above code is the chip select. should be 10 for arduino. refer on the schematic. the label different a little bit. written there SS. slave select. have a try.
I don't have a problem with the shield and the SD. Here is another post that may help.
http://arduino.cc/forum/index.php/topic,86837.0.html
I have found you must:
set pins 10 and 4 to OUTPUT.
set pin 10 HIGH and pin 4 LOW, then do the SD stuff.
set pin 4 HIGH and pin 10 LOW, then do the ethernet stuff.
Did some experimenting today. After examining the ethernet/SD libraries, I found a way to let the lower level code manipulate the SS pins for both the w5100 and the SD card.
Here is the code. It has a Webserver and SD interface that inserts text into the webpage if there is an formatted SD card inserted. First pass through, it will create the file and insert some text. Next pass will insert it into the page. Note there is no mention of any SS pins after setup().
/*
A simple web server with microSD using an Arduino Wiznet Ethernet shield.
For Arduino IDE V1.0 only. Earlier IDEs require mods to this code.
created 18 Dec 2009
by David A. Mellis
modified 4 Sep 2010
by Tom Igoe
modified 14 Jan 2012
by Tim Dicus
*/
#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and network settings for your controller below.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip( 192,168,0,2 );
IPAddress gateway( 192,168,0,1 );
IPAddress dns( 1,2,3,4 );
IPAddress subnet( 255,255,255,0 );
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup()
{
Serial.begin(9600);
// Set SS pins for both w5100 and microSD
pinMode(10,OUTPUT);
digitalWrite(10,HIGH);
pinMode(4,OUTPUT);
digitalWrite(4,HIGH);
// Start microSD.
// This disables the SD SPI interface before returning
SD.begin(4);
// start the Ethernet connection and the server:
// This leaves the w5100 SPI enabled
Ethernet.begin(mac, ip, dns, subnet, gateway);
// disable w5100 SPI
digitalWrite(10,HIGH);
// now you can read/write to both w5100 and SD without manipulating the SS pins.
delay(2000);
server.begin();
Serial.println("Setup finished");
}
void loop()
{
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("Client!");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
while(client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
Serial.println("sending response");
// send a standard http response
client.println("HTTP/1.0 200 OK");
client.println("Content-Type: text/html");
client.println();
client.println("<HTML><BODY>TEST OK!
");
// insert file info from SD card
sdCheck(client);
client.println("</BODY></HTML>");
client.stop();
}
else if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
Serial.println("Client disconnected.");
}
}
void sdCheck(EthernetClient client)
{
File myFile = SD.open("testfile.txt");
if (myFile) {
Serial.println("sending testfile.txt...");
// This works, but not the best way to send.
// Best way is read a hundred characters or more, then send them in one client.write().
while (myFile.available()) {
client.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening testfile.txt");
Serial.println("creating...");
// Create file
myFile = SD.open("testfile.txt",FILE_WRITE);
if(myFile)
{
myFile.write("This is the testfile contents");
myFile.close();
Serial.println("Created testfile.txt");
}
else
{
Serial.println("Unable to create file");
}
}
}
@Tim: Have you tried this without the digitalWrite() for the SS pins? I have very similar code, without the digitalWrite() statements for the SS pins, and it works just fine. The ethernet and SD libraries seem to take care of enabling the appropriate device.
PaulS:
@Tim: Have you tried this without the digitalWrite() for the SS pins? I have very similar code, without the digitalWrite() statements for the SS pins, and it works just fine. The ethernet and SD libraries seem to take care of enabling the appropriate device.
Thanks, PaulS. I think it does take care of that, but why guess? I want both disabled before starting. I can't think of a better way to guarantee that.
Ethernet.begin() leaves the SS pin 10 enabled on return. SD.begin() leaves the SS pin 4 disabled. I verified that.
After the setup, the ethernet/SD libraries do take care of the SS pins without additional programming if both SS lines are disabled initially.
Edit: After playing with it a while, I think that the Ethernet.begin() should leave the SS pin disabled. Seems like a bit of a bug to me leaving it enabled.
I think that the Ethernet.begin() should leave the SS pin disabled. Seems like a bit of a bug to me leaving it enabled.
If it was disabled, how would a client connect to it? It seems reasonable to me that it is not disabled.
Hi Paul! Thanks for the input. I don't know how you feel, but sometimes I feel like I am talking to myself.
This is the code I use to disable the SPI interface:
// start the Ethernet connection and the server:
// This leaves the w5100 SPI enabled
Ethernet.begin(mac, ip, dns, subnet, gateway);
// disable w5100 SPI
** digitalWrite(10,HIGH);**
// now you can read/write to both w5100 and SD without manipulating the SS pins.
This leaves both SPI SS pins HIGH. Both disabled. Both w5100 and SD work fine after this. All low level read/writes after this point enable the SS, do the read/write, then disable the SS.
sometimes I feel like I am talking to myself.
That's OK, if you are paying attention. If you're ignoring yourself, too, that's bad.
I guess that we'll just have to agree to disagree on the need to disable the ethernet shield after the begin() method is called.
I don't do it in my code, and I am able to use both SPI devices at any time. You do it, and are able to use both devices. This tells me that it is not a necessary action to perform, so, being a lazy person, I don't do it. Until I see evidence that it is needed, I probably won't feel it necessary to change anything.
I'm not suggesting that you change anything, either, since what you have works for you.
My code would not access the SD card until I disable the w5100 SS. The Ethernet.begin() call leaves the SS pin 10 LOW (enabled).
If you do something with the w5100 before accessing the SD card, no problem. The low level read/write for the w5100 doesn't care how the pin was set before the read/write. It disables it when finished.
However, if you try to access the SD before the w5100, there will be no response from the SD card. I verified that also.
If you do something with the w5100 before accessing the SD card, no problem. The low level read/write for the w5100 doesn't care how the pin was set before the read/write. It disables it when finished.
However, if you try to access the SD before the w5100, there will be no response from the SD card. I verified that also.
Ah, that would explain why I don't need it. I only access the SD card after a client.connect() occurs, which then leaves the ethernet and SD pins disabled. The next attempt to use either device succeeds since each enables appropriately.
You only need to be concerned about two pins when sharing the SPI bus with between two devices. These pins are the chip select pin for each device.
If the device libraries are correctly written, you don't need to worry about SS. The SS pin need not be connected to any device in SPI master mode. Master mode is when the Arduino CPU controls slave devices like an SD or the W5100.
In the case of the Ethernet shield SD chip select is pin 4 and the W5100 chip select is pin 10 (happens to be SS on 328 Arduinos).
Before initializing the first device you must disable the other device.
If you initialize the W5100 first do this:
// set SD chip select to OUTPUT mode
pinMode(4, OUTPUT);
// disable SD card.
digitalWrite(4, HIGH);
// initialize W5100 here with chip select set to 10
// initialize SD here with chipselect set to pin 4
If you initialize the SD first:
// set W5100 chip select to OUTPUT mode
pinMode(10, OUTPUT);
// disable W5100 card.
digitalWrite(10, HIGH);
// initialize SD here with chipselect set to pin 4
// initialize W5100 here with chip select set to 10
Here are some reasons for confusion.
Chip select for one device may also be the SS pin. This is the case for 328 Arduinos and the W5100. On a Mega SS is pin 53 and not connected to the shield.
You don't need to disable the W5100 before initializing the SD on a 328 Arduino.
I wrote SdFat, the base library for SD.h. I set the SS pin to output mode and set it high. This happens to disable the W5100 on a 328 Arduino.
Sometimes you can initialize a device even if both devices are enabled. This happens because the SD library does lots of retries and bus drivers for the SD may "win" over those on the W5100.
If the above sequences fail you may have other hardware problems.
Also some pairs of libraries are incompatible. For example the old version of SdFat used in SD.h only sets SPI options in the begin call. If the second library changes SPI options the SD library may fail later.