Problems with Arduino Mega2560 and Ethernet/SD Shield

Hello,

I am working on a project that has the requirement of both a web interface for current performance information and SD card to hold trending and historical data. I was working along and had the project working up until I attempted to add the data logging to SD Card. I found numerous examples both in the IDE, on the Web and here in the forums. I have followed what I thought was the proper code, See Below. When ever I remark out the code to init the SD Card and I/O Pins the Ethernet Web Server works with no issue, when the SD code is not remarked the web server does not function nor does the SD card, it fails to init.

#include <avr/pgmspace.h>
#include <string.h>
#include <Time.h>  
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

//SD Card Stuff
const int chipSelectSD = 4;
const int chipSelectEth = 53;

Sd2Card card;
SdVolume volume;
SdFile root;

// 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(57600);

  Serial.println("Initializing InPuts card...");  
  //Set Digital Input and Output Modes
  Serial.println("Initializing OutPuts card...");
  Serial.println("Initializing SD card...");
  pinMode(chipSelectEth,OUTPUT);

  //Temp Disable Ethernet to bring up SD
  digitalWrite(chipSelectEth,HIGH);
  //SD Init
 if (!card.init(chipSelectSD)) {
   Serial.println("card.init failed!");
 }
 
  // initialize a FAT volume
  if (!volume.init(&card)) {
    Serial.println("vol.init failed!");
  }
  
  //SD Card Info
  // 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);
  
  
  attachInterrupt(5,High_Alert,RISING);
  attachInterrupt(5,High_Alert,FALLING);
  
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
}
void loop (){
  WebSession{};
}

/*
  Web Pages
*/
void WebSession(){
 EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (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) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<head><title>Status</title><META HTTP-EQUIV=REFRESH CONTENT=5><META HTTP-EQUIV=PRAGMA CONTENT=""NO-CACHE""></head><body bgcolor=""#455ac0"">");
          client.println("<h1 align=center>System Status</h1>");
          client.print("<p>Operation Mode:&nbsp;");
          client.println("
");
          client.println("</body>");
          break;
        }
        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;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }  
}

Does anyone have some guidance on where I have steered wrong?

Thanks
Chris

I had the same problems when I tried to force the selection of the ethernet or SD card. When I stopped trying to do that, they both just worked together.

I commented out the line " digitalWrite(chipPin,HIGH); ". I am pretty sure this is what you mean by selecting each. Uploaded the updated sketch and still have the same issue :frowning:

I commented out the line " digitalWrite(chipPin,HIGH); ".

This one?

  digitalWrite(chipSelectEth,HIGH);

I don't even set the pinMode for the ethernet select pin.

  attachInterrupt(5,High_Alert,RISING);
  attachInterrupt(5,High_Alert,FALLING);

You only get one interrupt per pin. Either RISING or FALLING or CHANGE or LOW. Not one of each type.

PaulS:

I commented out the line " digitalWrite(chipPin,HIGH); ".

This one?

  digitalWrite(chipSelectEth,HIGH);

I don't even set the pinMode for the ethernet select pin.

Yes Paul, that is the line, sorry difference in variable name between posted code and actual prod code. I also commented out the line:

  pinMode(chipSelectEth,OUTPUT);

this did not help the issue either.

Thank you for the pointer on the interrupt I will address that, it also explains some funkiness I was seeing on that interrupt line.

this did not help the issue either.

My web server/logger is not running on a Mega. When I get home tonight, I'll change to using the Mega, and see if that makes any difference.

Which version of the IDE are you using (looks like 1.0) on what operating system?

Yes I am using Version 1.0 of the IDE, on Windows 7 64-Bit.

I have continued to work on another area of the project over last night, which may have some bearing on this I am not sure. Here are the details... I had been working on another tidbit of code that would be integrated into the larger project to read values from a set of MAX186 12-Bit A/D Converters using SPI. After the issues I was having with Ethernet and SD sharing the bus, I was beginning to think I would need to put a 2nd Arduino to handle the SPI Communication (Today just 2x AD Converters, but could be up to 8 more devices coming in short order), but when I merged the code together I had no issues with the Web Server, like I do when I try to enable the SD Card.

#include <avr/pgmspace.h>
#include <string.h>
#include <Time.h>  
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

//SD Card Stuff
const int chipSelectSD = 4;
const int chipSelectEth = 53;
//Other SPI Devices
const int devSPI_PH  = 6;

/*
    A/D Converter Stuff
    PH and ORP
*/

int PH_Array[64];
int PH_Counter = 0;
int intCurrentPH;
boolean brlMinPH;
boolean brlMaxPH;

const byte byteADC_CHN_0 = 0b10001111;
const byte byteADC_CHN_1 = 0b11001111;
const byte byteADC_CHN_2 = 0b10011111;
const byte byteADC_CHN_3 = 0b11011111;
const byte byteADC_CHN_4 = 0b10101111;
const byte byteADC_CHN_5 = 0b11101111;
const byte byteADC_CHN_6 = 0b10111111;
const byte byteADC_CHN_7 = 0b11111111;

Sd2Card card;
SdVolume volume;
SdFile root;



// 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(57600);

  Serial.println("Initializing InPuts card...");  
  //Set Digital Input and Output Modes
  Serial.println("Initializing OutPuts card...");
  Serial.println("Initializing SD card...");
  //pinMode(chipSelectEth,OUTPUT);
  
  Serial.println("Initializing SPI AD Converters...");
  pinMode(devSPI_PH,OUTPUT);
  pinMode(devSPI_ORP,OUTPUT);
  digitalWrite(devSPI_PH,HIGH);
  digitalWrite(devSPI_ORP,HIGH); 
  
  //Temp Disable Ethernet to bring up SD
  //digitalWrite(chipSelectEth,HIGH);
  //SD Init
 if (!card.init(chipSelectSD)) {
   Serial.println("card.init failed!");
 }
 
  // initialize a FAT volume
  if (!volume.init(&card)) {
    Serial.println("vol.init failed!");
  }
  
  //SD Card Info
  // 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);
  
  
  attachInterrupt(5,High_Alert,CHANGE);
  
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
}
void loop (){
  intCurrentPH = ReadPH(); 
  WebSession{};
 
}

/*
  Web Pages
*/
void WebSession(){
 EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (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) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<head><title>Status</title><META HTTP-EQUIV=REFRESH CONTENT=5><META HTTP-EQUIV=PRAGMA CONTENT=""NO-CACHE""></head><body bgcolor=""#455ac0"">");
          client.println("<h1 align=center>System Status</h1>");
          client.print("<p>Operation Mode:&nbsp;");
          client.println("
");
          client.println("</body>");
          break;
        }
        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;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }  
}

/*
    Water Chemistry
      PH and ORP    
*/

int ReadPH(){
  int intTemp = 0;
  long intAvg = 0;

  intTemp = ReadADC_2Bytes(byteADC_CHN_0,devSPI_PH);
  PH_Array[PH_Counter] = intTemp;
  PH_Counter ++;
  if (PH_Counter == 64){
    PH_Counter = 0;
  }
  for (int l = 0; l < 64; l++){
    intAvg = intAvg + PH_Array[l];
  }
  intAvg = intAvg/64;
  float fltReturn;
  fltReturn = map(intAvg,0,4096,0,9);
  return(fltReturn);
}

int ReadADC_2Bytes(byte thisValue, int intSPI_CS) {
  word result;   // result to return
  byte hByte;
  byte lByte;
  int tempBit;
  
  // take the chip select low to select the device:
  digitalWrite(intSPI_CS, LOW);
  // send the device the register you want to read:
  SPI.transfer(thisValue);
  // send a value of 0 to read the First byte returned:
  hByte = SPI.transfer(0x00);
  // send a value of 0 to read the Second byte returned:
  lByte = SPI.transfer(0x00);
  // take the chip select high to de-select:
  digitalWrite(intSPI_CS, HIGH);
  //read bits from adc
 for (int i = 3; i < 15; i++){
   if (i >= 8){
     tempBit = bitRead(hByte,(i-8));
     bitWrite(result,(i-3),tempBit);
   } else if (i <= 7){
     tempBit = bitRead(lByte,i);
     bitWrite(result,(i-3),tempBit);
   } else {
     Serial.println("Error in ReadBytes() to many bytes");
   } 
 }
 return(result);
}

In the above code, if I comment out the section in void setup (){}:

  //Temp Disable Ethernet to bring up SD
  //digitalWrite(chipSelectEth,HIGH);
  //SD Init
 if (!card.init(chipSelectSD)) {
   Serial.println("card.init failed!");
 }
 
  // initialize a FAT volume
  if (!volume.init(&card)) {
    Serial.println("vol.init failed!");
  }
  
  //SD Card Info
  // 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);

The WebServer will serve up the page properly, otherwise it just sits on the loading screen.

hi. hello. may i know what is the function of #include <Time.h> ?

is it can put a time stamp on the serial monitor? with all, regards

hi. hello. may i know what is the function of #include <Time.h> ?

is it can put a time stamp on the serial monitor? with all, regards

There is some omitted code from below for the sake of brevity and that is where the Time functions of the arduino are used.

To answer your question, yes you can use the library Time.h for displaying time over the serial connection, I use that in the project as part of a near real time data stream to the serial port for advanced monitoring and debugging. There are example sketches in v1.0 of the IDE on how to do this.

I don't have a problem with the Mega and the shield. Here is the explanation:
http://arduino.cc/forum/index.php/topic,86837.0.html

Edit: This is based on using the newer type ethernet shields. Those would be the models with the ICSP connector on the bottom of the shield. Otherwise, without the connector, there will be some pin jumping required.