Argggg! Arduino hangs with simple HTML code!

Hell all!
This has been driving me nuts, and I can't figure out why.

I have the Microchip based (enc28j60) ethernet shield, that now fully works, I have a simple application that toggles an LED (a website) where when you press a button, it takes you to [website]/?cmd=1 (where the submit value is command 1). It all works well with 1 button (one form), however when I try to add another form, and connect to the arduino (at ip 192.168.0.15), it just hangs with "loading..."

Here is the code that works 100%

uint16_t print_webpage(uint8_t *buf)
{
        uint16_t plen;
        plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<title>Arduino Webserver with LED control</title><center><p><h1>LED Toggle Control </h1></p> "));
         
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr>
<form METHOD=get action=\""));
        plen=es.ES_fill_tcp_data(buf,plen,baseurl);
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("\">"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> LED [PIN8] STATUS: </h2> "));
        
        if (toggleLED==1) {
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#00FF00\"> "));
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> ON! </h2> ")); 
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</font></h1>
 ") );
        }
        else {
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#FF0000\"> "));
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> OFF! </h2> ")); 
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</font></h1>
 ") );
        }
        
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=1>"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=submit value=\"TOGGLE LED!\"></form>"));

        return(plen);
  
        //return(plen);
 }

But if I add another form to this, the whole thing stops working (can't connect to the arduino).

uint16_t print_webpage(uint8_t *buf)
{
        uint16_t plen;
        plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<title>Arduino Webserver with LED control</title><center><p><h1>LED Toggle Control </h1></p> "));
         
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr>
<form METHOD=get action=\""));
        plen=es.ES_fill_tcp_data(buf,plen,baseurl);
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("\">"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> LED [PIN8] STATUS: </h2> "));
        
        if (toggleLED==1) {
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#00FF00\"> "));
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> ON! </h2> ")); 
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</font></h1>
 ") );
        }
        else {
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#FF0000\"> "));
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> OFF! </h2> ")); 
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</font></h1>
 ") );
        }
        
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=1>"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=submit value=\"TOGGLE LED!\"></form>"));

//OTHER FUNCTION

        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr>
<form METHOD=get action=\""));
        plen=es.ES_fill_tcp_data(buf,plen,baseurl);
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("\">"));    
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=2>"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=submit value=\"TOGGLE AUX!\"></form>"));


        return(plen);
  
        //return(plen);
 }

I have no idea what's going on, as it should be the browser that interprets HTML code.
Any help is greatly appreciated!
Thanks in advance!

It will definitely be necessary to see more/all of your sketch to make any diagnosis. My suspicion is that you are running out of memory and clobbering your stack. But that's just a guess.

If you search the forums for "__brkval" or "free_memory" you will find threads suggesting how to gauge at runtime when you are running out of memory.

Full code, as requested:

http://pastebin.com/sqmXQzLa (exceeds max num of characters for forum)

About the memory thing, I doubt it's that, reason being that if I type http://192.168.0.15/?cmd=1, (when the website doesn't load), the LED turns on and off (when I do it again).

EDIT:

Hyperlinks work, if I hyperlink to ?cmd=2 instead of using a button, it works! what is up with buttons though?

EDIT2: I think you are right.... Seems that hyperlinks, paired with servocontrol are too memory-intensive, seems that the poor arduino can handle only a simple LED toggle with this ethernet shield....
I think I might need to get the official arduino eth shield, as this one has a very large memory fooprint (the lib I mean).

Are you on a Mega or a Uno, or what?

#define BUFFER_SIZE 500
static uint8_t buf[BUFFER_SIZE+1];

On an Uno, this would be 1/2 your memory right there. I don't know the EthernetShield library at all. Could this buffer be 256 bytes or smaller?

I do think some code to test for your stack and heap crossing would be a good diagnostic.

How would I implement the code?
I mean if I add 'too much' to the website, it hangs. if I add too many routines it hangs...

The newest issue I've been having is it randomly chooses to work.
For example. ?cmd=2 steps the servo 10degrees, sometimes it works, other times it crashes the Uno.

I will play with the buffer tomorrow, that was the value reccomended by the shield manufacturer. I have ordered an official Arduino ethernet shield as well. This shield is not based on any reference designs at all.

You could save some RAM if you moved your HTML into PROGMEM.

or add an sdcard reader component to store a lot of datas !

Thanks for your replies!
I did order an official ethernet sheield for the SD card capability.

AWOL, thanks for your suggestion.
How would I add the HTML code to the PROGMEM?
Sorry for the noobish question, however PROGMEM - Arduino Reference does not seem to help me.

I've tried:

PROGMEM uint16_t print_webpage(uint8_t *buf)
{
        uint16_t plen;
        plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<title>Arduino Webserver with LED control</title><center><p><h1>LED Toggle Control </h1></p> "));
         
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr>
<form METHOD=get action=\""));
        plen=es.ES_fill_tcp_data(buf,plen,baseurl);
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("\">"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> LED [PIN8] STATUS: </h2> "));
        
        if (toggleLED==1) {
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#00FF00\"> "));
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> ON! </h2> ")); 
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</font></h1>
 ") );
        }
        else {
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#FF0000\"> "));
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> OFF! </h2> ")); 
          plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</font></h1>
 ") );
        }
        
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=1>"));
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=submit value=\"TOGGLE LED!\"></form> <p> <a href=\"?cmd=2\">Link text</a> "));

        return(plen);
  
        //return(plen);
 }

It compiles, but same thing, I can issue the serco command (cmd=2) once, and then the uC crashes.
Worth mentioning that I can toggle the LED as many times as I want, and as fast as I want, and it works.
Thanks!

PROGMEM uint16_t print_webpage(uint8_t *buf)
{

print_webpage is a function, so it is already automatically placed in PROGMEM - no need to tell the compiler/linker.

Sorry, I just noticed that you are using PROGMEM methods for the rest of it.
Apologies.

I finally twigged that this is an ENC28J60 based ethernet interface. That Microchip unit has a fairly low level interface and the IP stack will all be in software. The uIP guys have done a great job at cramming IP into just a few hundred bytes, but I think you will find it is still pretty memory hungry for an Uno.

If you move to one of the WIZNET based boards like the Ethernet Shield, the IP stack is all in the WIZNET hardware and this frees up a good deal of space on the Arduino side.

gardner and AWOL, thanks for the suggestions. You get what you pay for, right? $11.00 lands you this shield.

So what do you think, Will I have more success driving an led and 2 servos with the official arduino shield?
This shield is just too cumbersome.
For example, if I add some client-side scripting (i.e. javascript), the arduino fails to load the webpage.
If I change the buffer from 500 to say 400, the arduino fails to load the page....
I put all the variables into prormem, still same thing, except maybe I manage to issue the servo (?cmd=2) command more than once before it crashes.
I also added delays between all commands, thinking that the uC might need to catch up, unfortunately this is not the case.

Funnier still, I wanted to add a 'keepalive' signal for myself, like a blinking LED in the void loop, and that made the arduino crash as well....

It must be a ram issue, if it's not then I don't know...

Thanks to everyone who helped out!

dRosenberg:
gardner and AWOL, thanks for the suggestions. You get what you pay for, right? $11.00 lands you this shield.

So what do you think, Will I have more success driving an led and 2 servos with the official arduino shield?
This shield is just too cumbersome.
For example, if I add some client-side scripting (i.e. javascript), the arduino fails to load the webpage.
If I change the buffer from 500 to say 400, the arduino fails to load the page....
I put all the variables into prormem, still same thing, except maybe I manage to issue the servo (?cmd=2) command more than once before it crashes.
I also added delays between all commands, thinking that the uC might need to catch up, unfortunately this is not the case.

Funnier still, I wanted to add a 'keepalive' signal for myself, like a blinking LED in the void loop, and that made the arduino crash as well....

It must be a ram issue, if it's not then I don't know...

Thanks to everyone who helped out!

The wiznet has plenty of buffer space for HTML. There's also a lot of examples around the net based on it too with Webservers working perfectly. So, you do get what you pay for.

I figured as much.
Even after trying to rewrite the library that was provided with the shield. to place all variables into progmem, it still is aweful. Something as simple as setting an output high or low works, but anything like writing to a servo (using the servo library) is a flop.

Once I recieve my ethernet shield, I will resort to storing all files on the sd card.

Below is some continous rotation servo test code I made that I use with the w5100 shield. Bottom is the html web page I use on my desktop to control the servos. Fairly simple setup for doing some testing basic testing.

//zoomkat 10-22-10
//routerbot code
//for use with IDE 0021
//open serial monitor to see what the arduino receives
//use a url like below in a browser to test
// http://192.168.1.102:84/?-1450-1550 

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

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
Server server(84); //server port

String readString, servo1, servo2; 

Servo myservo1;  // create servo object to control a servo 
Servo myservo2;
//////////////////////

void setup(){

  //start Ethernet
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();

  //enable serial data print 
  Serial.begin(9600); 
  myservo1.attach(7);
  myservo2.attach(6);
  Serial.println("bot21"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  Client 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; 
        } 

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString);

          //readString looks like "GET /?-1500-1500 HTTP/1.1"

          if (readString.length() >0) {
            Serial.println(readString);

            servo1 = readString.substring(7, 11);
            servo2 = readString.substring(12, 16);

            Serial.println(servo1);
            Serial.println(servo2);

            int n1;
            int n2;

            char carray1[6];
            servo1.toCharArray(carray1, sizeof(carray1));
            n1 = atoi(carray1); 

            char carray2[6];
            servo2.toCharArray(carray2, sizeof(carray2));
            n2 = atoi(carray2); 

            myservo1.writeMicroseconds(n1);
            myservo2.writeMicroseconds(n2);

            //myservo.write(n);
            readString="";
          } 
          ///////////////////

          //now output HTML data header
          client.println("HTTP/1.1 204 Zoomkat");
          client.println();
          client.println();
          delay(1);
          //stopping client
          client.stop();

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

        }
      }
    }
  }
}

copy, paste in notepad, and save as test.htm on the desktop. OK the windows warnings generated when opened by double clicking to open.

<HTML>
<HEAD>
<H3>Zoomkat's Routerbot
 Web Control Page</H3>
<TITLE>Zoomkat's Routerbot Control Page</TITLE>
</HEAD>
<BODY>

Foward-*Stop*-Reverse



<a href="http://192.168.1.102:84/?-1000-2000" target="inlineframe">F-F</a>|
<a href="http://192.168.1.102:84/?-1450-1550" target="inlineframe">S-F</a>|
<a href="http://192.168.1.102:84/?-1500-1500" target="inlineframe">*-Stop-*</a>|
<a href="http://192.168.1.102:84/?-1550-1450" target="inlineframe">S-R</a>|
<a href="http://192.168.1.102:84/?-2000-1000" target="inlineframe">F-R</a>|




Turn-L-*Stop*-Turn-R


<a href="http://192.168.1.102:84/?-1000-1000" target="inlineframe">F-L</a>|
<a href="http://192.168.1.102:84/?-1450-1450" target="inlineframe">S-L</a>|
<a href="http://192.168.1.102:84/?-1500-1500" target="inlineframe">*-Stop-*</a>|
<a href="http://192.168.1.102:84/?-1550-1550" target="inlineframe">S-R</a>|
<a href="http://192.168.1.102:84/?-2000-2000" target="inlineframe">F-R</a>|


<IFRAME name=inlineframe 
src="res://D:\WINDOWS\System32\shdoclc.dll/dnserror.htm" width=1 
height=1> this will hold the html answer of the moves
</IFRAME>

</body>
</html>

I shall give it a try once my Ethernet shield is in (the W5100 one).
The biggest advantage for me is that it is a smaller and highly optimized library, and the ability to run webpages off of the sd card.

I have just had an idea. Could it be back-EMF?
I can't recall, but I think that something along those lines I had, with a servo caused back-emf and caused the arduino to reset.
Does the arduino have any sort of protection against back-emf?
Or what if I use a diode?
Still, if it was back-emf, and the arduino reset, wouldn't it work after the reset (I mean load the page again)?

Motor noise can cause all sorts of havoc, yes. If you disconnect the servo and just look at the behaviour of the HTTP server and debugging output on serial, you should be able to tell if motor noise is causing trouble. Is that feasible?

The motor current supplies should be isolated from the Arduino power supply -- extra decoupling caps, a blocking diode and a series inductor. If you search the forums for "motor noise" you will find lots of good stuff.

I have two servos controlled by my arduino and don't have the issues you describe. I hope you are NOT trying to power the servos from your arduino.