SS for SD card on Ethernet shield, and FAVICON

Hi guys,

I'm just a bit confused about using the SD card on the E'net shield. I gather only one device may be used at a time, but am I right in thinking that I don't have to worry about manipulating SS for pins 10 and 4, because the libraries do the turning off and on?

Corollary question: assuming there's a SD card in the slot, and I have included the SD library in my sketch, how do I get the E'net shield to "see" the SD card? Is it a simple matter of doing an SD.begin(4)? Reason I'm asking is that I made a favicon at favicon.cc, and put it in the root of the SD card, hoping that the GET /favicon which my browser is sending would find it.

It's not finding it :~

Perhaps my "real" question should have been all along "How do I get my web server to deliver a favicon from the SD card when the browser asks ?"

TIA, as always....

Jim

The below web server code incorporates uploading image files from the SD card as well as other server control functions.

//zoomkat 1/26/13
//SD server slider test code
//open serial monitor to see what the arduino receives
//address will look like http://192.168.1.102:84/servosld.htm when submited
//for use with W5100 based ethernet shields
//put the servosld.htm, slider.js, bluev_sl.gif,
//and bluev_bg.gif on the SD card
//files at http://web.comporium.net/~shb/servoslider.htm 
// http://web.comporium.net/~shb/pix/servosld.htm
// http://web.comporium.net/~shb/pix/slider.js
// http://web.comporium.net/~shb/pix/bluev_bg.gif
// http://web.comporium.net/~shb/pix/bluev_sl.gif


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

#include <Servo.h> 
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo 
Servo myservoe, myservof, myservog;
String readString, pos;

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 
  192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 
  192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 
  255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

//////////////////////

void setup(){

  Serial.begin(9600);

  // disable w5100 while setting up SD
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  Serial.print("Starting SD..");
  if(!SD.begin(4)) Serial.println("failed");
  else Serial.println("ok");

  Ethernet.begin(mac, ip, gateway, gateway, subnet);

  //delay(2000);
  server.begin();
  Serial.println("Ready");
  
  myservoa.attach(2);  //the pin for the servoa control
  myservob.attach(3);  //the pin for the servob control
  myservoc.attach(5);  //the pin for the servoc control
  myservod.attach(6);  //the pin for the servod control 
  myservoe.attach(7);  //the pin for the servoa control
  myservof.attach(8);  //the pin for the servob control
  myservog.attach(9);  //the pin for the servoc control
  //myservoh.attach(10);  //the pin for the servod control 

}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {
          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 
        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging
         
         //select proper header for file to be sent to browser
           if(readString.indexOf("Submit") >=0) { //don't send new page
           client.println("HTTP/1.1 204 Zoomkat");
           client.println();
           client.println(); }
           
          //client.println("HTTP/1.1 200 OK"); //send new page
          if(readString.indexOf("servosld") >=0) {
          client.println("HTTP/1.1 200 OK"); //send new page          
          client.println("Content-Type: text/html");
          client.println(); }

          if(readString.indexOf("slider") >=0) {
          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: application/x-javascript");
          client.println(); }
          
          if(readString.indexOf("bluev") >=0) {
          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: image/gif");
          client.println(); }
          
          //select file to send to browser
          if(readString.indexOf("servosld") >=0) {
            File myFile = SD.open("SERVOSLD.HTM");
            if (myFile) {
              while (myFile.available()) {
                client.write(myFile.read());
              }
              myFile.close();
            }
          }

          if(readString.indexOf("slider") >=0) {
            File myFile = SD.open("slider.js");
            if (myFile) {
              while (myFile.available()) {
                client.write(myFile.read());
              }
              myFile.close();
            }
          }

          if(readString.indexOf("bluev_sl") >=0) {
            File myFile = SD.open("bluev_sl.gif");
            if (myFile) {
              while (myFile.available()) {
                client.write(myFile.read());
              }
              myFile.close();
            }
          }

          if(readString.indexOf("bluev_bg") >=0) {
            File myFile = SD.open("bluev_bg.gif");
            if (myFile) {
              while (myFile.available()) {
                client.write(myFile.read());
              }
              myFile.close();
            }
          }

          delay(1);
          //stopping client
          client.stop();

          //process GET string request from client and and position servo
          
          pos = readString.substring(8, 12); //get the first four characters         
          //Serial.println(pos);
          int n = pos.toInt();  //convert readString into a number   
          Serial.println(n); 
          Serial.println();
          
          if(readString.indexOf("?0") >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf("?1") >0) myservob.writeMicroseconds(n);
          if(readString.indexOf("?2") >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf("?3") >0) myservod.writeMicroseconds(n);
          if(readString.indexOf("?4") >0) myservoe.writeMicroseconds(n);
          if(readString.indexOf("?5") >0) myservof.writeMicroseconds(n);
          if(readString.indexOf("?6") >0) myservog.writeMicroseconds(n);
          //only seven servo pins, so back to myservoa for testing
          if(readString.indexOf("?7") >0) myservoa.writeMicroseconds(n);

          //clearing string for next read
          readString="";
          pos="";
        }
      }
    }
  } 
}

zk, you must have a huuuuuuuuuuuuuuuuuuuge stash of code, because no matter what question anybody asks, you immediately respond with a solution.

Thanks,

Jim

Here is server code that will upload any file you put on the SD card. Insure you have a file in the root directory called favicon.ico if you want the icon displayed on your web browser. http://playground.arduino.cc/Code/WebServerST The file names must be 8.3 format.

Thanks Gents...

Common to both of those sketches, is that the E'net needs to be stopped (pin 10 high) while the SD starts, but in neither is pin 10 set low again. How does the E'net start then?

And just to confirm, apart from that one pin manipulation, the libraries seem to take care of all the E'net / SD control?

If I just want to have the favicon displayed, should that happen when I simply start the SD and have the favicon.ico in the root? Long as it's there and the SD started, should the GET favicon find it? EDIT.... sorted that part, I realised I was wrong in that assumption and that the favicon needs to be explicitly SD.open'd

Hmmm and now, mysteriously, the GET /favicon has disappeared from the debug output in the monitor, as if my browser has stopped asking for it

The SS pins D4 and D10 are handled by each library during the read/write functions.

The favicon.ico request depends on the web browser you use. As I recall, my tests showed Chrome requests it every time. IE (and Firefox?) does not.

Yep Chrome was requesting it all the time, then it stopped.... that's a bit weird.

I just installed FF but had to go out, so not tested that yet.

ST or zk, can you confirm though, as it seems to me, that for a favicon to be published by the server it does need to be SD.open'd and not just merely present?

The favicon.ico file must be SD opened and sent just like any other file. You must also send the correct Content-Type in the header.

edit: Here are the file types my sketch will send correctly. You can add more if you wish.

                // send Content-Type
                if(strcmp(fileType,"HTM") == 0) client.println(F("text/html"));
                else if(strcmp(fileType,"PHP") == 0) client.println(F("text/html"));
                else if(strcmp(fileType,"TXT") == 0) client.println(F("text/plain"));
                else if(strcmp(fileType,"CSS") == 0) client.println(F("text/css"));
                else if(strcmp(fileType,"GIF") == 0) client.println(F("image/gif"));
                else if(strcmp(fileType,"JPG") == 0) client.println(F("image/jpeg"));
                else if(strcmp(fileType,"JS") == 0) client.println(F("application/javascript"));
                else if(strcmp(fileType,"ICO") == 0) client.println(F("image/x-icon"));
                else if(strcmp(fileType,"PNG") == 0) client.println(F("image/png"));
                else if(strcmp(fileType,"PDF") == 0) client.println(F("application/pdf"));
                else if(strcmp(fileType,"ZIP") == 0) client.println(F("application/zip"));
                else client.println(F("text/plain"));

JimboZA: Yep Chrome was requesting it all the time, then it stopped.... that's a bit weird.

I just installed FF but had to go out, so not tested that yet.

ST or zk, can you confirm though, as it seems to me, that for a favicon to be published by the server it does need to be SD.open'd and not just merely present?

Browsers are quite stubborn about caching favicon.ico. I've found the most consistent way to force it to display a new one is to include a link rel="icon" tag in the head of the document specifying a new icon with a new name.

oxxo:
Browsers are quite stubborn about caching favicon.ico. I’ve found the most consistent way to force it to display a new one is to include a link rel=“icon” tag in the head of the document specifying a new icon with a new name.

Could you give me an example please oxxo? Does that mean it need not be called favicon.ico in fact?- and then one could have loads of ico’s on the SD and call them with diffferent pages? And it’s not reliant on the browser asking?

The code below comes from favicon.cc. Is this what you mean? And could favicon.ico in fact be jimboza1.ico?

<head>
<link href="/YOUR_PATH/favicon.ico" rel="icon" type="image/x-icon" />
</head>

If the name doesn’t need to be favicon in that method, what happens if there is a favicon.ico and the browser calls for it- which one wins?

Whichever file the web browser requests "wins". If you use the method oxxo uses, it should not request favicon.ico, but whatever path/file you entered in the document head.

SurferTim: Whichever file the web browser requests "wins". If you use the method oxxo uses, it should not request favicon.ico, but whatever path/file you entered in the document head.

So just need to make sure there is no favicon else it will display if the browser asks.

Thanks guys.... trying that as we speak.

JimboZA: So just need to make sure there is no favicon else it will display if the browser asks.

Yes.

I have changed my example code in the playground. It uses client.write() calls rather than client.print(). It sends the request packets much faster. MattS_UK brought that to my attention so I finally changed it after a rigorous test.
http://playground.arduino.cc/Code/WebServerST

You can see my test running online now. Just a couple very simple pages to test the uploads. All pages except the test form are from the SD. The default home page (index.htm) has a css file for the format. The waterfall page has a css file that downloads the waterfall image as a background. All should get my favicon.ico file.
http://68.99.58.119

JimboZA:

oxxo:
Browsers are quite stubborn about caching favicon.ico. I’ve found the most consistent way to force it to display a new one is to include a link rel=“icon” tag in the head of the document specifying a new icon with a new name.

Could you give me an example please oxxo? Does that mean it need not be called favicon.ico in fact?- and then one could have loads of ico’s on the SD and call them with diffferent pages? And it’s not reliant on the browser asking?

The code below comes from favicon.cc. Is this what you mean? And could favicon.ico in fact be jimboza1.ico?

<head>
> ``` > > > > If the name doesn't need to be favicon in that method, what happens if there is a favicon.ico and the browser calls for it- which one wins?

You can actually use any path, any name, jpg, png, gif, animated gif, etc. if you declare it in the head of every document. I’ve never tried it, but I see no reason why using multiple favicons for different pages, subdomains, etc. wouldn’t work.

Wikipedia has a good writeup on what each browser supports.

If you don’t do any of that, the browser checks the root for favicon.ico and will cache it. Depending on the browser you use, the favicon.ico cache doesn’t get included when you clear other local cache/history making it difficult to update and see changes.

The tag in the document head wins. So if you have a new favicon you want everyone to see right away, declare it in the document. Otherwise they might not see it for a week.