Arduino DUE + Ethernet Shield/Sd WebServer not working

Hi everyone,
i'm trying to get through this wonderful tutorial for making a web server with the Arduino+Ethernet Shield, but i'm experiencing some problems.
My current set up is an Arduino DUE with attached the official Ethernet Shield. The issue happens when I try, in the same sketch to access an .htm file on the SD card and send it over the ethernet.
The sketch taken from here Arduino SD Card Web Server using Ethernet Shield is the following:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 0, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

File webFile;

void setup()
{
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for debugging
    
    // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("SUCCESS - Found index.htm file.");
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                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("Connection: close");
                    client.println();
                    // send web page
                    webFile = SD.open("index.htm");        // open web page file
                    if (webFile) {
                        while(webFile.available()) {
                            client.write(webFile.read()); // send web page to client
                        }
                        webFile.close();
                    }
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

I have to point out that with my setup I'm able to run both the Ethernet/WebServer and SD/readwrite examples so the shield is working and connected well.
I assume that this is a problem of the shared SPI connection, but I don`t know how to deal with it.

Thanks in advance,
Georgi

I shall point out that the same sketch, on the Arduino UNO+Ethernet Shield works perfectly.
:~ I have no clue on what is happening there!

What version of the ide are you using? 1.5.3 had a bug in the SPI library which the Ethernet library uses. Both 1.5.2 & 1.5.4 work fine for me.

Do the sketches in the example folder work?

Hi, I'm using the last one 1.5.4 and yes, all the examples of both the SD and Ethernet folder are working well.
I've also succeeded in having something like this:

  • performing a sd.begin(), opening a file on the SD reading it and then writing on it
  • and then after closing the file doing a server.begin() and printing some HTML to client

So it looks like they work if separately used. But in my case I need to print to a client an html file on the SD.
Its a mess :sweat_smile:

Hello ggorine,

I don't see where you are matching Eth and SD pins to enable/disable them. Eth and SD modes can't work at the same time. You have to add something like this and call it from your setup:

void ethEnable()
{
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
pinMode(10, OUTPUT);
digitalWrite(10, LOW);
}

void sdEnable()
{
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
}

Here my example that works OK with Due and the Arduino SD shield. You can use it as a reference.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

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

// Matching SD in Arduino Ethernet shield: pin 4
const int chipSelect = 4;  
// Text to be read from SD card
String text1;

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
static byte arduinoMAC[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
static IPAddress ArduinoIPAddress(192,168,1,230);
EthernetServer telnetServer = EthernetServer(80);

// Matching pin to enable SD card and disable Ethernet
void ethEnable()
{
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  pinMode(10, OUTPUT);
  digitalWrite(10, LOW);
}

// Matching pin to enable Ethernet and disable SD card
void sdEnable()
{
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
}

// Initialization and reading of SD card
void sdCARD_INIT()
{
    Serial.print("\nInitializing SD card...");
    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");
  }

  // Opening 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);

  // reading a file
  if (file.open(root, "PRINT00.TXT", O_READ)) {
    Serial.println("Opened PRINT00.TXT");
  }
  else{
    Serial.println("error reading PRINT00.TXT");
    //error("file.open");
  }
Serial.println();
  
  // printing text inside the file
  int16_t c;
  while ((c = file.read()) > 0)
  {text1 = text1 + char(c);}
  Serial.println();
  Serial.println(text1);
  }

void sdCARD_IP_CONFIG()
{
//Changing the IP address for test

      ArduinoIPAddress[0] = 192;
      ArduinoIPAddress[1] = 168;
      ArduinoIPAddress[2] = 1;
      ArduinoIPAddress[3] = 101;
      
      delay(150);
       
      Serial.println(ArduinoIPAddress);
      Serial.println("\nNew IP address...Done");
}

void setup()
{
  // Open serial communications:
  Serial.begin(9600);
  // Enable SD card to read text in a file
  sdEnable();
  sdCARD_INIT();
  sdCARD_IP_CONFIG();
    
  // start the Ethernet connection and the server:
  Serial.println("starting the Ethernet connection and the server");
  ethEnable();
  Ethernet.begin(arduinoMAC, ArduinoIPAddress);
  telnetServer.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // listen for incoming clients
  EthernetClient client = telnetServer.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // 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("Connection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"5\">");
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            // The following line was originally the printing of the text "analog channel"
            // Now will be the text inside the file in SD card "canal analogico"
            client.print(text1);
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("
");       
          }
          client.println("</html>");
          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();
    Serial.println("client disconnected");
  }
}

Thank you for the code, tomorrow I'll try to run it.
A out the first enable/disable lines...I read about it in the Ethernet shield documentation, but i 've understood that the libraries do already all the necessary management of the CS pins.
I'll let you know tomorrow morning (here its 1 a.m. now) if its working.
Good night :slight_smile:

P.s. but why then the sketch works on the UNO without any additional coding???

Ok, i've tried to use also the ethEnable and sdEnable but in that way I cannot get what I want.
How you would manage for exambple this loop:

webFile = SD.open("index.htm");        // open web page file
if (webFile) {
  while(webFile.available()) {
  client.write(webFile.read()); // send web page to client
 }
   webFile.close();

As you can see here, WHILE the ethernet is enabled (the client is alive) i have to access the sd card and fetch the index.htm file. So i cannot manually enable and disable pin 10 and pin 4.

Thats my full NOT RUNNING on DUE (but working perfectly on UNO :astonished:) code:

#include <SPI.h> 
#include <Ethernet.h>
#include <SD.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0x90, 0xA2, 0xDA, 0x3D, 0xB9, 0xF1 };
IPAddress ip(137,138,63,207);
EthernetServer server(80);  // create a server at port 80

File webFile;

void setup()
{
    ethEnable();
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for debugging
    Serial.print("server is at ");
    Serial.println(Ethernet.localIP());
    
    sdEnable();
    // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("SUCCESS - Found index.htm file.");

}

void loop()
{
    EthernetServer server(80);  // create a server at port 80

    ethEnable();
    Serial.println("EthEnabled");
    EthernetClient client = server.available();  // try to get client
    long buffer;
    Serial.println("client");

    
    if (client) {  // got client?
        Serial.println("Client");
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                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("Connection: close");
                    client.println();
                   // send web page
                    sdEnable();
                    webFile = SD.open("index.htm");        // open web page file
                   if (webFile) {
                        while(webFile.available()) {
                            buffer = webFile.read();
                            ethEnable();
                            client.write(buffer); // send web page to client
                            sdEnable();
                        }
                        webFile.close();
                    }
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                }
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

void ethEnable()
{
    pinMode(4, OUTPUT);
    digitalWrite(4, HIGH);
    pinMode(10, OUTPUT);
    digitalWrite(10, LOW);
}

void sdEnable()
{
    pinMode(4, OUTPUT);
    digitalWrite(4, LOW);
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);
}

And in particular:
webFile = SD.open("index.htm"); // open web page file
if (webFile) {
while(webFile.available()) {
long buffer = webFile.read();
ethEnable();
client.write(buffer); // send web page to client
sdEnable();
}
webFile.close();

Hello ggorine,

Your code runs smoothly by moving the following two lines to the bottom of the setup():

Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients

You don't need the enable/disable functions I gave you. The explanation that I give myself is that the latest IDE updates fixed it.

Here your corrected code:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 0, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

File webFile;

void setup()
{
    Serial.begin(9600);       // for debugging
    
    // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("SUCCESS - Found index.htm file.");
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                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("Connection: close");
                    client.println();
                    // send web page
                    webFile = SD.open("index.htm");        // open web page file
                    if (webFile) {
                        while(webFile.available()) {
                            client.write(webFile.read()); // send web page to client
                        }
                        webFile.close();
                    }
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

Regards!

Dear Palliser,
thank you for trying but no, it`s not working. Let me describe what happens when I run that code:

  • SD.begin(4) and SD.exists("index.htm") (OK)
  • Ethernet.begin(mac, ip); (OK)
  • client.available() (OK) (and I can see the ETHCS pin continuously switching)
  • webFile.available() (STUCK) (the ETHCS remains high while the sd is deadly low)
  • client.write() (STUCK) (well..the code is definitely freezed)

So thats the story. No possibility to use both the SD and Ethernet dynamically. I could at the beggining of the code, load all the htm file in the Arduino and than forget about the SD, but thats really memory consuming and much less elegant than a simple
while(webFile.available()) client.write(webFile.read());

Hope to find a solution though.
Georgi

Dear Georgi,
I am sorry you still stuck with this. As I mentioned, I ran your code (corrected) in my Due and Ethernet shield using IDE1.5.2 and 1.5.3 and ran OK with both. I am going to make time today to re-install IDE1.5.3 and corroborate if the code still working. Time to time, during my tests, I use to change lines in the Arduino code. Regards!

I just tried the corrected code with a fresh IDE 1.5.3 using a crossover cable between Due and my laptop (W7 x64) and it is running OK. I am using Arduino shield model Ethernet R3. Here a snapshot.

Are you trying the corrected code? Regards!

You got it right. By loading the simple sketch without any pin enabling, it works!
Somehow with the new release 1.5.4 they've messed up with the SPI libraries instead of fixing them!

Now i'll try to reassemble all the coding i've done (I was avoiding the SD by directly printing HTML with client.print)

Thank you very much Palliser :slight_smile:

Yes. Georgi. I just tried to run the corrected code with IDE 1.5.4 and even though ping test runs OK and serial monitor shows normal, my laptop can't read the index.htm in SD.

Hello Cristian, are you aware of this? Thank you and regards!

Hi,
I'm having exactly the same problem. Any solution so far for IDE 1.5.4?
Hf, Jakob

I had a same problem , just changed the IDE to 1.5.3 and removed the enable/disable codes. working fine .
Thanks guys.

There is a 1.5.5 Beta avialable in the Nightly Builds for Windows. In the readme there are comments related to SPI.