Go Down

Topic: Arduino DUE + Ethernet Shield/Sd WebServer not working (Read 3090 times) previous topic - next topic

ggorine

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 http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/SD-card-web-server/ is the following:
Code: [Select]

#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

ggorine

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!

noblepepper

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?

ggorine

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 :smiley-sweat:

Palliser

#4
Sep 23, 2013, 12:09 am Last Edit: Sep 23, 2013, 12:12 am by Palliser Reason: 1
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.

Code: [Select]
#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("<br />");      
         }
         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");
 }
}

ggorine

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 :-)

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

ggorine

#6
Sep 23, 2013, 10:47 am Last Edit: Sep 23, 2013, 10:51 am by ggorine Reason: 1
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:
Code: [Select]
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 :smiley-eek:) code:
Code: [Select]
#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();

Palliser

Hello ggorine,

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

Quote
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:

Code: [Select]
#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!

ggorine

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
                       

Palliser

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!

Palliser

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!

ggorine

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 :)

Palliser

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!

JUGmobile

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.

Go Up