Ethernet Shield Web Page without an SD chip.

Hey guys.

Im taking a course right now using the Arduino and were doing a project. Were essentially doing a version of tweet-a-pot but instead of tweets were using a web site designed for a smart phone. We've managed to get everything working great but were stuck using the schools old Ethernet Shield and it has no SD card reader in it.

So Ive been trying to code HTML and Javascript directly into the Arduino interface. Its a real pain in the ass. Is there not a better way to load a website onto the ethernet shield without an SD Card and read it? I would love to be able to have separate .js, .html and .css files to make our app site better.

Also trying to figure out a simple way of setting a timer for the coffee machine. So that you can set it like an alarm. Without the sd card for a php site... i have no idea how to do this :p.

Thanks for any advice or tips anyone can offer!!

Adding an SD card module is only a few USD of cost and is well justified. I have tried to program HTML into Arduino code and my rear end was also very uncomfortable while doing that. Get an SD card. You can easily modify the web pages on a PC and restart arduino to test it vs. having to change a lot of Arduino code, compile and upload. Judging from your mentioning html js and css, I would not recommend storing them in FLASH. SD card modules are the way to go. Just purchase one on ebay.

Without the sd card for a php site... i have no idea how to do this

Even with a SD card, what would you be sending? Sending files containing php code doesn't make sense. The PHP code is supposed to be executed on the server, resolving to plain html code. The Arduino can not execute PHP code.

Yeah I’m actually going over my code. Its not actually PHP but more like a fake version of it. I just had it in my head because I uses a parameters after the web adress. All im doing is following a nice example of code that I cant find the url to now. Somewhat embarrassing. If you recognize the code just let me know so I cant reference it (Ive modified it to fit my needs of course):

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    
    
    boolean currentLineIsBlank = true;
    boolean DoPage=true;
    
    while (client.connected()) {
        if (client.available()) {
               char c = client.read();
               Serial.write(c);
               if (s.length() < 7) { s.concat(c); }   // build up a short string to parse
               if(s.substring(0,3) == "GET" & DoPage){    // check for the GET from the web page
                    
                     cmd=s.substring(4,6);        // get the 2 letters in the string out and call this the CMD,  /A, or /B or /H etc, these come in after the GET
                     // Serial.println("CMD=");
                     //Serial.println(cmd);
                     
          
                     // Got a GET so, compare the received command to the specific command and then do something
                     
                     if (cmd == "/O" && DoPage) {
                                Serial.println(F(" Turn Light On")); 
                                 digitalWrite(led, LOW);     
                                //X10.sendCmd( hcE, 14, cmdOn );
                               DoPage = false;
                     }  
                     if (cmd == "/F" && DoPage) {
                                Serial.println(F("  Turn Light Off"));
                                digitalWrite(led, HIGH);  
                                //X10.sendCmd( hcE, 14, cmdDim );
                               DoPage = false;
                     }
                    
                 
               }
        
        
              // 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(F("HTTP/1.1 200 OK"));
                      client.println(F("Content-Type: text/html"));
                      client.println(F("Connnection: close"));
                      client.println();
                      client.println(F("<!DOCTYPE HTML>"));
                      client.println(F("<html>"));
                      client.println(F("<head>"));
                      client.println(F("<meta content='text/html; charset=ISO-8859-1'http-equiv='content-type'>"));
                      //Testar om hemsidan agerar som en applikation i telefonen.
                      client.println(F("<meta name='HandheldFriendly' content='True'>"));
                      client.println(F("<meta name='MobileOptimized' content='320'>"));
                      client.println(F("<meta name='viewport' content='user-scalable=no, width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0'>"));
                      client.println(F("<meta http-equiv='cleartype' content='on'>"));
                      client.println(F("<meta name = 'format-detection' content = 'telephone=no'>"));
                      client.println(F("<meta name='apple-mobile-web-app-capable' content='yes'>"));
                      client.println(F("<meta name='apple-mobile-web-app-status-bar-style' content='black'>"));
                      client.println(F("<meta name='apple-mobile-web-app-title' content=''>"));
                      
                      client.println(F("<title>Shake your coffee maker"));
                      client.println(F("</title>"));
                      client.println(F("</head>"));
                      //  load in a background .jpg for the web page.
                      client.println(F("<BODY BACKGROUND='http://www.tsmethod.com/blog/wp-content/uploads/2012/12/coffee_beans_background-wide.jpg' style='width: 481px; height: 690px;'></span>
"));
                      //  set up some HTML that has buttons with specific actions that link back to the arduino at the address of the arduino and have a specific string 
                      client.println(F("<a href='http://XX.XXX.XXX.XX/O\r'><img id='turnOn' onclick='itsOn()'  src='http://mlab1.msi.vxu.se/~cs222hq/images/coffeetime.png' /></a>  "));
                      client.println(F("<a href='http://XX.XXX.XXX.XX/F\r'><img id='turnOff' onclick='itsOff()'  src='http://mlab1.msi.vxu.se/~cs222hq/images/nocoffee.png' /></a> "));
                      client.println("</html>");
                      // Clear out the received string
                      s="";
                      break;
                }
                if (c == '\n') {
                      currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                      currentLineIsBlank = false;
                }
          }
    }
    client.stop();
    Serial.println("client disonnected");
    
  }
  
}  // end

So you see what Im doing is just parsing the last part of the url as a conditional. I wanted to have some javascript and more functional things on the web site but I’m having a very difficult time coding within the arduino interface. It would be a lot nicer to have a .html file with linked javascript and css to use. You also notice ive comment out the original authors x10 code as Im not using that module, just the ethernet shield.

Judging from your mentioning html js and css, I would not recommend storing them in FLASH. SD card modules are the way to go. Just purchase one on ebay.

Unfortunately the project deadline is this friday. We only had a week to do this and I didn’t realize until now that most people use SD for these types of projects. I dont have the time or money to order a new one (I live in Sweden) so Im either just going to have to settle for a super simple website or find a work around.

OK, you CAN store long strings in PROGMEM so you don't have to do separate client.print, since you can't get an SD card module. But I don't see any dynamic content on your web page such as javascript etc. Does this mean your web page can be served "as is", like read from SD card and write to client?

#include <avr/pgmspace.h>
PROGMEM prog_char HTTP_header_00[]="HTTP/1.1 200 OK\r\n(rest of HTTP header)\r\n\r\n";
PROGMEM prog_char page_00[]="\r\n\r\n(rest of web page)\r\n\r\n";
char Ram_buffer[101];
Then use strncpy_P(Ram_buffer,page_00,100); to copy a chunk of the HTTP header (100 in example) or the page to an SRAM buffer and then use client.write(Ram_buffer,100) to send to client. Use strlen_P(page_00) to figure out the total length.

Well theres no javascript as of now because every attempt we made to include some sort of functionality didin’t work. For example:

client.println(F("<a href='http://XX.XXX.XXX.XX/O\r'><img id='turnOn' onclick='itsOn()'  src='http://mlab1.msi.vxu.se/~cs222hq/images/coffeetime.png' /></a>  "));
client.println(F("<a href='http://XX.XXX.XXX.XX/F\r'><img id='turnOff' onclick='itsOff()'  src='http://mlab1.msi.vxu.se/~cs222hq/images/nocoffee.png' /></a> "));

It would be nice to include some javascript to change the images to show whether the user has activated the coffee machine. However my onclick() functions never worked. You can see I still have the onclick in the img tags that i never deleted. Also I almost always have a separate css file when im developing for web sites, i guess its more of a OCD need…

Unfortunately as well We’ve only been using the Arduino for about 4 weeks so a lot of that code is a bit beyond me. Ill have to look into PROGMEM and prog_char etc… But no Id rather have a “not served as is” web site if I can. If I cant well just have to make do with a simple site.

OK. I was kind of wondering why there are two functions with the images but actual javascript about these functions. Unfortunately every web server sample code I have seen so far has the same idea: fragment an HTML page so that Arduino can print out say “coffee machine is ON”. My approach is entirely different. I start with a static web page like yours. I then give ID to everything that I would need to update. Say I would do:

Coffee machine is <span id="coffee_machine"></span>

Then later in the html I do:

<script src="js1.js"></script>

Then Arduino will server the static page when asked. Secondly, when the web browser starts asking for js1.js, Arduino will generate:

client.print("document.getElementByID('coffee_machine').innerHTML=');
client.print(coffee_machine?"ON":"OFF");
client.println("'");

Actual result:

document.getElementByID('coffee_machine').innerHTML='ON'

Or OFF is the state is off.

I hope this is clear enough for you.

I would say the ‘onclick never worked’ part may be because you don’t cancel the action and thus the href gets loaded. You need to add ‘;return false’ following the onclick functions itsOn() and itsOff() to cancel (prevent) the href from being loaded when you click on the link.

As to the primary questions, those seem to have been adequately answered already by others.

Cheezogrammer:
Well theres no javascript as of now because every attempt we made to include some sort of functionality didin’t work. For example:

client.println(F("<a href='http://XX.XXX.XXX.XX/O\r'><img id='turnOn' onclick='itsOn()'  src='http://mlab1.msi.vxu.se/~cs222hq/images/coffeetime.png' /></a>  "));

client.println(F(" "));




It would be nice to include some javascript to change the images to show whether the user has activated the coffee machine. However my onclick() functions never worked. You can see I still have the onclick in the img tags that i never deleted. Also I almost always have a separate css file when im developing for web sites, i guess its more of a OCD need...

Unfortunately as well We've only been using the Arduino for about 4 weeks so a lot of that code is a bit beyond me. Ill have to look into PROGMEM and prog_char etc... But no Id rather have a "not served as is" web site if I can. If I cant well just have to make do with a simple site.

So thanks for all your help guys. I still dont really understand with what you mean by:

Then later in the html I do:

Code:

<script src="js1.js"></script>

Where does js1.js exist? as a separate file? on the Arduino?

Either way, I found a simple solution by just printing in the javascript carefully. I just gave myself a lot of white space to see what I was doing. If you guys see a better way Id love to know, but I think theres a lot more learning I need to do as well :D.

Heres the final code: ( Need to clean up a bit of redundancy though )

… ok so I couldn’t get it to fit into this post so I just attached the file.

CoffePotSketch.ino (9.64 KB)

Your static webpage:

<html>
<header>
<script>
//Do your scripts here
</script>
</header>
<body>
Here goes the web page
The coffee pot is: <span id="coffee_pot"></span>
<script src="js1.js"></script>
</body>
</html>

The js1.js is NOT stored on arduino so if the client asks for it, arduino needs to generate it besides the HTTP response header.

On request, arduino will print the HTTP header for js1.js, then it will print document.getElementById("coffee_pot").innerHTML="ON" if the pot is on or it will print document.getElementById("coffee_pot").innerHTML="OFF" otherwise. This is the dynamic part that goes with the static web page.

You can always put all the files and html on an existing server and have the GET/POST commands contained in the html go to an arduino/Ethernet shield at some other location.