Requesting starter code example deminstrating sd card, image, WiFi shield

I recently learned how to read and write to sd cards, and am now trying to learn how to take images from the sd card, and apply them to a server code. I found this great example, but I only have a seeed Ethernet shield V1.0 which does not come with a sd card reader/writer, I also have an offical arduino Wi-Fi shield which I am quite fond of. I looked into purchasing a Sd card reader shield but the cost was almost the same as upgrading to a newer Ethernet shield that has a sd card reader built into it. The WiFi shield already has a sd reader though, and that's what I would like to use. I found this reptile tank code which shows a great example of how to incorporate images from sd cards and use them in server form, but modifying this to work with wi-fi has proven to be.... extremely complicated... I spent many hours trying to do so.

I am curious if anyone has any examples of code that use images from sd cards (preferably using WiFi) that would be ideal for a beginner to look at and try to understand?

which shows a great example of how to incorporate images from sd cards and use them in server form, but modifying this to work with wi-fi has proven to be.... extremely complicated

Why? The code for reading the data is the same whether there is an ethernet shield, a WiFi shield, an XBee, or nothing that is going to send the data. Sending the data depends on the kind of device sending it, in terms of what precedes the .print() or .write() method. The method remains the same.

Here is a small piece of the code. You have to understand, the arthor wrote the entire code to cross back and address each possibility. You can't just put in the code what you want the gateway to be and cross out the rest. The entire code will fight you. I know it seems like it would be easy.

void startethernet(void){
  /*********************************************************************************************************************
                                                      DHCP or Static Network Settings
*********************************************************************************************************************/
  if (usedhcp == 1){//use DHCP
    wdt_reset();
    EthernetDHCP.begin(mac);
    wdt_reset();
    //now that we have a DHCP lease, we need to save all the lease information so the rest of the system can use it
    const byte* ipAddr = EthernetDHCP.ipAddress();
    const byte* gatewayAddr = EthernetDHCP.gatewayIpAddress();
    const byte* dnsAddr = EthernetDHCP.dnsIpAddress();
    
    //local system IP address
    localip[0] = ipAddr[0];
    localip[1] = ipAddr[1];
    localip[2] = ipAddr[2];
    localip[3] = ipAddr[3];
    
    //the subnet mask is always user define, and not determined by DHCP
    subnetmask[0] = EEPROM.read(SUBNETMASKEEPROMADDRPART1);
    subnetmask[1] = EEPROM.read(SUBNETMASKEEPROMADDRPART2);
    subnetmask[2] = EEPROM.read(SUBNETMASKEEPROMADDRPART3);
    subnetmask[3] = EEPROM.read(SUBNETMASKEEPROMADDRPART4);
    
    //the default gate way IP address 
    gateway[0] = gatewayAddr[0];
    gateway[1] = gatewayAddr[1];
    gateway[2] = gatewayAddr[2];
    gateway[3] = gatewayAddr[3];
    
    //the DNS server IP address
    dnsServerIp[0] = dnsAddr[0];
    dnsServerIp[1] = dnsAddr[1];
    dnsServerIp[2] = dnsAddr[2];
    dnsServerIp[3] = dnsAddr[3];
    Serial.println(F("A DHCP lease has been obtained."));

    Serial.print(F("System IP address is "));
    Serial.println(ip_to_str(ipAddr));
  
    Serial.print(F("Gateway address is "));
    Serial.println(ip_to_str(gatewayAddr));
  
    Serial.print(F("DNS IP address is "));
    Serial.println(ip_to_str(dnsAddr));
    
    Serial.print(F("Subnet Mask is "));
    Serial.println(ip_to_str(subnetmask));
  }else{      //do not use DHCP but use static settings defined by the user, saved in EEPROM
    localip[0] = EEPROM.read(LOCALIPADDREEPROMADDRPART1);
    localip[1] = EEPROM.read(LOCALIPADDREEPROMADDRPART2);
    localip[2] = EEPROM.read(LOCALIPADDREEPROMADDRPART3);
    localip[3] = EEPROM.read(LOCALIPADDREEPROMADDRPART4);
    subnetmask[0] = EEPROM.read(SUBNETMASKEEPROMADDRPART1);
    subnetmask[1] = EEPROM.read(SUBNETMASKEEPROMADDRPART2);
    subnetmask[2] = EEPROM.read(SUBNETMASKEEPROMADDRPART3);
    subnetmask[3] = EEPROM.read(SUBNETMASKEEPROMADDRPART4);
    gateway[0] = EEPROM.read(GATEWAYEEPROMADDRPART1);
    gateway[1] = EEPROM.read(GATEWAYEEPROMADDRPART2);
    gateway[2] = EEPROM.read(GATEWAYEEPROMADDRPART3);
    gateway[3] = EEPROM.read(GATEWAYEEPROMADDRPART4);
    dnsServerIp[0] = EEPROM.read(DNSSERVEREEPROMADDRPART1);
    dnsServerIp[1] = EEPROM.read(DNSSERVEREEPROMADDRPART2);
    dnsServerIp[2] = EEPROM.read(DNSSERVEREEPROMADDRPART3);
    dnsServerIp[3] = EEPROM.read(DNSSERVEREEPROMADDRPART4);
    
    Ethernet.begin(mac, localip, dnsServerIp, gateway, subnetmask); 
    Serial.println(F("System is using Static Ethernet Settings."));

    Serial.print(F("System IP address is "));
    Serial.println(ip_to_str(localip));
  
    Serial.print(F("Gateway address is "));
    Serial.println(ip_to_str(gateway));
  
    Serial.print(F("DNS IP address is "));
    Serial.println(ip_to_str(dnsServerIp));
    
    Serial.print(F("Subnet Mask is "));
    Serial.println(ip_to_str(subnetmask));
  }

I just want something that works, I don't want to try to reverse engineer logic if I can't see it. Otherwise if I misunderstand something, about the process then I can't trouble shoot it to find out.

That snippet of code is to get the Arduino with Ethernet shield connected to the network. It has NOTHING to do with handling client requests.

Are you looking for a server like my example ethernet code on the playground? I have a WiFi shield web server sketch, but let me warn you up front that the WiFi shield firmware has some bugs that make the server operation pretty unstable if more than one client tries to connect simultaneously. You may get corrupted or incorrect files. It also has a pretty nasty two second delay every few seconds on large file downloads.

If you are interested in it despite the firmware bugs, I'll post it for you.

Are you looking for a server like my example Ethernet code on the playground?

I haven’t even looked at any other Ethernet server examples, because my Ethernet shield doesn’t have a sd card. Does the sketch use images? I know how to make a regular server, but have no idea how to use images to make it look nice, and when you click different parts of the image it does different things.

That snippet of code is to get the Arduino with Ethernet shield connected to the network. It has NOTHING to do with handling client requests.

Correct, I just posed that to give an idea how difficult it is to modify that sketch to use with WiFi instead of Ethernet. Here is a small part of it that I think uses the images. The problem is, I can’t comprehend how it gets the images, how it places them, and how clicking on different parts of the image do different things. I need to get something working before I try modifying it.

***************************************************************************/
      case 6:  // page 7
       switch (nSubstituteIndex)
       {
         case 0:
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[30])));  //client.print("0.0.0.1");
           wdt_reset();
           break;
         case 1:
           client.print(ip_to_str(localip));
           wdt_reset();
           break;
         case 2:
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[32])));  //client.print(system_date);
           wdt_reset();
           break;
         case 3:
           client.print(hour);
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[0])));  //client.print(":");
           if (minute<10)
           {
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[1])));  //client.print("0");
           }
           client.print(minute);
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[0])));  //client.print(":");
           if (second<10)
           {
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[1])));  //client.print("0");
           }
           client.print(second);
         
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[2])));  //client.print(" ");
           switch(dayOfWeek){
           case 1:
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[3])));  //client.print("Sun");
             break;
           case 2:
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[4])));  //client.print("Mon");
             break;
           case 3:
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[5])));  //client.print("Tue");
             break;
           case 4:
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[6])));  //client.print("Wed");
             break;
           case 5:
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[7])));  //client.print("Thu");
             break;
           case 6:
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[8])));  //client.print("Fri");
             break;
           case 7:
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[9])));  //client.print("Sat");
             break;
           }
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[32])));  //client.print("  ");
           client.print(month);
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[10])));  //client.print("/");
           client.print(dayOfMonth);
           sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[11])));  //client.print("/20");
           client.println(year);
           wdt_reset();
           break;
         case 4:
           if (CSGMANUAL == 1){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }else if (CSGMANUAL == 0){
             client.print("");
           }
           wdt_reset();
           break;
         case 5:
           if (CSGMANUAL == 1){
             client.print("");
           }else if (CSGMANUAL == 0){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }
           wdt_reset();
           break;
         case 6:
           if (MSGMANUAL == 1){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }else if (MSGMANUAL == 0){
             client.print("");
           }
           wdt_reset();
           break;
         case 7:
           if (MSGMANUAL == 1){
             client.print("");
           }else if (MSGMANUAL == 0){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }
           wdt_reset();
           break;
         case 8:
           if (HSGMANUAL == 1){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }else if (HSGMANUAL == 0){
             client.print("");
           }
           wdt_reset();
           break;
         case 9:
           if (HSGMANUAL == 1){
             client.print("");
           }else if (HSGMANUAL == 0){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }
           wdt_reset();
           break;
         case 10:
           if (HEATLAMPMANUAL == 1){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }else if (HEATLAMPMANUAL == 0){
             client.print("");
           }
           wdt_reset();
           break;
         case 11:
           if (HEATLAMPMANUAL == 1){
             client.print("");
           }else if (HEATLAMPMANUAL == 0){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }
           wdt_reset();
           break;
         case 12:
           if (UVLIGHTMANUAL == 1){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }else if (UVLIGHTMANUAL == 0){
             client.print("");
           }
           wdt_reset();
           break;
         case 13:
           if (UVLIGHTMANUAL == 1){
             client.print("");
           }else if (UVLIGHTMANUAL == 0){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }
           wdt_reset();
           break;
         case 14:
           if (HUMIDIFIERMANUAL == 1){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }else if (HUMIDIFIERMANUAL == 0){
             client.print("");
           }
           wdt_reset();
           break;
         case 15:
           if (HUMIDIFIERMANUAL == 1){
             client.print("");
           }else if (HUMIDIFIERMANUAL == 0){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[12])));  //client.print("selected");
           }
           wdt_reset();
           break;
         case 16:
           if (cold_side_status == 0)
           {
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[18])));  //client.print("On");
           }else if (cold_side_status == 1){
             sendProgMemAsString(client, (char*)pgm_read_word(&(basic_table[19])));  //client.print("Off");
           }
           wdt_reset();
           break;

If you are using an Uno, you are asking too much. It barely fits in an Uno without the bells and whistles.

Nope, I had to get a Mega for the extra pins.

Attached is the code I planned on putting on the playground until I found all the firmware bugs.

WifiServerPlayground.ino (16.3 KB)

Wasn't it you that fixed the firmware bugs though? I swear I thought I remember reading about your rant to get it fixed earlier back. I think that post was dated a few years ago, but as I recall you did work figuring it out.

Can you think of any bugs I should be aware of that might make it easier to understand I'm not doing anything wrong, it's just a bug in the firmware?

I tried to get it debugged, but was not successful. I have neither the time nor motive to debug the firmware on my own. I now use the ethernet shield in conjunction with high powered wifi routers. More versatility and longer range.

But despite that, the code I posted will attempt to open and upload a file named index.htm. If you want the code to display a default page, you must save a file named index.htm.

I have neither the time nor motive to debug the firmware on my own.

I understand completely, if I knew anything about firmware i'd offer to help, but i'm still learning basic arduino code. I just learned a few minutes ago there's a limit on how many f(marcos) you can use. It took me quite a while to debug that mainly because it says I have plenty of space left. "Newb"

I wonder if the built in WiFi shield on the Yun is debugged? I'm going to take a look at this code and start playing around with it. Do I need any particular images downloaded as well?

Don't know about the Yun.

I recommend a favicon.ico image so you get the icon. Besides that, it recognizes gif, jpg, and png image types. If you refer to an image on a page on the SD, you must have that image file on the SD.

You can use a css file also if you want to use formatting in a cascaded style sheet.

Well, you know more than me about the F() macro. I am not aware there is a limit. What is the limit?

Well, you know more than me about the F() macro. I am not aware there is a limit. What is the limit?

I don't know, I didn't exactly write the code to keep count.

This is the error message using the 1.0.6 IDE

This report would have more information with "Show verbose output during compilation" enabled in File > Preferences. Arduino: 1.0.6 (Windows NT (unknown)), Board: "Arduino Mega 2560 or Mega ADK" c:/users/admin/desktop/arduino-1.0.6-windows/arduino-1.0.6/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o: In function __vector_default': (.vectors+0xc0): relocation truncated to fit: R_AVR_13_PCREL against symbol__vector_48' defined in .text section in c:/users/admin/desktop/arduino-1.0.6-windows/arduino-1.0.6/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o

now the interesting thing about this is, if you take out one F(macro); or one complete if{} statement that doesn't use serial.print(); but does use a string that eventually is printed later in the code, everything works fine. If you take one F(macro away, and try to add another F(macro) anywhere else in the page it will come up again

Surprisingly the same sketch works on the 1.5.8 (but you have to load the SPI extra library. Here is a readout of the stats.

Sketch uses 56,976 bytes (22%) of program storage space. Maximum is 253,952 bytes. Global variables use 4,852 bytes (59%) of dynamic memory, leaving 3,340 bytes for local variables. Maximum is 8,192 bytes.

another interesting little thing i've learned is if you use a wifi shield, and an uno. If you use too many serial.prints(); without the F(macro); it will say you need to upgrade the firmware (even though the firmware is already upgraded). I never tried to figure out why that was. I found a fix F(macro) and was happy with it.

You can use a css file also if you want to use formatting in a cascaded style sheet.

I'm familiar now with .csv files .txt files, and ad4. The files used in the other Reptile tank sketch are.PNG format. I don't even know what a cascaded style sheet is, but I will look into it tomorrow. I am quite interested in figuring out how to make it so that you can click different parts of the image to do different things, and that automatically writes to the image like it does in the reptile sketch.

Have you tried combining the F() macro statements to determine if it is a number or a size that causes the failure?

// change something like this
  client.println(F("Host: www.mydomain.com"));
  client.println(F("Connection: close));

// to this
  client.println(F("Host: www.mydomain.com\r\nConnection: close"));

I never use the F() macro on client print because I noticed everything doesn't print. It's like serial.print if you do things to fast but the results are half the page doesn't show up. I figured it took extra time to pull from the F() macro, and so that was the reason adding the F() macro to client print resulted in everything not printing. I know I could probably increase the baud rate, but I'd rather find a better fix and reserve that option for later if I need it.

I was curious about your suggestion so I added the F() macro to client print just to try, so I could figure out why it was happening. The results truly have me baffled.

Upon commenting out one F() macro Serial.print line in the sd section the error went away, as I knew it would. I then added two F() macros to client print and loaded the sketch, no errors.

I then added another F() marco to serial print (that wasn't in the sd section) still everything worked with no error. The last thing I tried was I then uncommitted the same line I previously commented to get the error to go away. Surprisingly, no error.

I then closed out the sketch without saving and re-opened it. Again there was the error. I commented out a F() marco, error went away, I then uncommitted the same line I just commented and error came back. Without commenting it again, I went to client print and put in an extra F() macro. The error went away.