I have the Arduino ethernet shield R3 that supposedly works with the Mega 2560 R3. I HAVE a Mega 2560 R3.
I've created test code to prove I can read/write to the SD shield. I can only read the micro sd card type/capacity (SdVolume), Any attempts to do a SD.exists, or open a file for writing or reading yield nothing. No errors, it just doesn't work.
I've made sure my file names are 8.3. I'm using a 2GB SD card formatted FAT (also tried SDHC 4GB formatted FAT). I'm at a loss. For one, I can't understand why SPI is working to read the SD card type/size, but nothing else.
Also, I'm new to Arduino and admittedly have only a rudimentary idea of what is going on. It's safe to assume I'm doing something stupid with object assignments, constructors, etc. Help...
Here's my test harness. LogInit() works up until it calls LogWriteLog(). That's where the File object begins and fails.
#include "SD.h"
const int chipSelect = 4;
Sd2Card card;
SdVolume volume;
SdFile root;
String CurrentFile = "";
File DataFile;
void LogInit()
{
pinMode(53, OUTPUT);
// see if the card is present and can be initialized:
//SPI_HALF_SPEED, SPI_QUARTER_SPEED, SPI_FULL_SPEED
if (!card.init(SPI_HALF_SPEED,chipSelect)) {
LogDumpLn("SD Card failed");
// don't do anything more:
delay (1000);
return;
}
LogDumpLn("SD Card Initialized");
// print the type of card
LogDump("Card type: ");
switch(card.type()) {
case SD_CARD_TYPE_SD1:
LogDumpLn("SD1");
break;
case SD_CARD_TYPE_SD2:
LogDumpLn("SD2");
break;
case SD_CARD_TYPE_SDHC:
LogDumpLn("SDHC");
break;
default:
LogDumpLn("Unknown");
}
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
if (!volume.init(card)) {
LogDumpLn("SD VOL READ FAIL");
delay (4000);
return;
}
// print the type and size of the first FAT-type volume
uint32_t volumesize;
LogDump("Vol type FAT");
LCDPrint(volume.fatType(), DEC);
LCDCRLF();
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
volumesize /= 1024;
LogDump("Size (Mbytes): ");
volumesize /= 1024;
LogDumpLn(volumesize);
LogWriteLog("AquaLog.txt",LogTimeStamp());
//LogReadLog("SensLog.txt");
delay(4000);
}
String LogTimeStamp()
{
String text = "";
text += "TS:";
text += TimeReadSmall();
return text;
}
void LogWriteLog(String file, String text)
{
LogOpenFile(file);
//DataFile.println(text);
if (DataFile)
{
DataFile.println(text);
LogDumpLn("Log Written");
}
DataFile.close();
//LogFileFlush();
}
void LogReadLog(String file)
{
LogOpenFile(file);
while (DataFile.available()) {
//LogDumpChar(DataFile.read());
}
}
void LogOpenFile(String file)
{
if (CurrentFile != file)
{
if (file == "AquaLog.txt") {LogDumpLn("AquaLog.txt opened"); DataFile = SD.open("AquaLog.txt", FILE_WRITE);}
if (file == "ErrorLog.txt") {LogDumpLn("ErrorLog.txt opened"); DataFile = SD.open("ErrorLog.txt", FILE_WRITE);}
if (file == "NetLog.txt") {LogDumpLn("NetLog.txt opened"); DataFile = SD.open("NetLog.txt", FILE_WRITE);}
if (file == "SensLog.txt") {LogDumpLn("SensLog.txt opened"); DataFile = SD.open("SensLog.txt", FILE_WRITE);}
CurrentFile = file;
}
}
void LogFileFlush()
{
DataFile.flush();
LogDumpLn("Flushing data file");
}
//redirect or do nothing. For debugging.
void LogDump(String text)
{
LCDPrint(text);
}
void LogDump(int val, int format)
{
LCDPrint(val,format);
}
void LogDumpLn(String text)
{
LCDPrint(text);
LCDCRLF();
}
void LogDumpLn(int val)
{
LCDPrint(val);
LCDCRLF();
}
Where is the setup() and loop() functions? You should post all your code. The w5100 and SD must be initialized correctly or they will cause fails in the other device. If you are testing the SD, then disable the w5100 during your test. Use something like this:
void setup() {
Serial.begin(9600);
// disable w5100 SPI
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
// rest of your setup
}
Setup() and Loop() are in the main ino file. I'm trying to keep some separation of concerns. I added your pin 10 output high code to my LogInit() routine and tested it. Still no go.
Considering the Ethernet port works fine and the SD card volume data is read fine, I'm convinced it's a hardware malfunction on the shield. So I ordered a 10$ Chinese shield to test. I'll laugh if the cheap one works where the expensive Arduino shield doesn't.
Considering the Ethernet port works fine and the SD card volume data is read fine, I'm convinced it's a hardware malfunction on the shield.
I'm able to read and write to the SD card while clients connect to the Arduino-as-server. So, unless you've fried the SD reader/write part of the card, it's more likely a software issue.
That's what I'm saying. It's fried. There is no software/hardware permutation I haven't tried at this point. I'm hoping someone can look at my code and say "Dope! You forgot {insert x here}"
OR, maybe shed light on WHY the volume info can be read but files can't be read or written. How are those two actions fundamentally different? I would think I'm talking to the micro SD card for both operations using the same pins and protocol. Another option is my SD libraries are confused. Can someone upload their SD library sub-directory from a code base that has been SD card tested?
I am the author of SdFat but I do not maintain the Arduino SD library or the version of SdFat used by the Arduino company.
SD.h is a wrapper for a very old version of SdFat and user code should not use the SD object in the same sketch as these objects.
Sd2Card card;
SdVolume volume;
SdFile root;
They are also defined in the class for SD:
class SDClass {
private:
// These are required for initialisation and use of sdfatlib
Sd2Card card;
SdVolume volume;
SdFile root;
// my quick&dirty iterator, should be replaced
SdFile getParentDir(const char *filepath, int *indx);
public:
// This needs to be called to set up the connection to the SD card
// before other methods are used.
boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN);
// Open the specified file/directory with the supplied mode (e.g. read or
// write, etc). Returns a File object for interacting with the file.
// Note that currently only one file can be open at a time.
File open(const char *filename, uint8_t mode = FILE_READ);
// Methods to determine if the requested file path exists.
boolean exists(char *filepath);
// Create the requested directory heirarchy--if intermediate directories
// do not exist they will be created.
boolean mkdir(char *filepath);
// Delete the file.
boolean remove(char *filepath);
boolean rmdir(char *filepath);
private:
// This is used to determine the mode used to open a file
// it's here because it's the easiest place to pass the
// information through the directory walking function. But
// it's probably not the best place for it.
// It shouldn't be set directly--it is set via the parameters to `open`.
int fileOpenMode;
friend class File;
friend boolean callback_openPath(SdFile&, char *, boolean, void *);
};
The CardInfo example works because it does not use the SD object.
You must insert this code when you use the Ethernet shield on a Mega. It must be inserted before the SD.begin call.
The pin 10,high thing has no relevance. It works either way. You DID answer my plea for help though. I wasn't using SD.begin(chipSelect). I was using card.init thinking it was sharing the same base objects. Like you said, they are not the same. So, you saved me! Thanks!
The pin 10,high thing has no relevance. It works either way.
This is luck. When you have multiple SPI devices there can be interference when you initialize the libraries. You should disable devices that have not been initialized before accessing the first device.
I get loads of mail about this issue. If the Ethernet controller is not disabled, some SD cards may work and some may not.
For reliability disable the Ethernet controller if you initialize the SD first. It happens to be done on Uno by the SD libraries but not on the Mega. So do this:
// Disable Ethernet by setting chip select high.
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
// initialize SD here
If you initialize the Ethernet first do this:
// Disable SD by setting chip select high.
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
// initialize Ethernet here
There are dozens of posts in this forum about this issue.