'Controlling relays through webserver with an arduino and ethernet shield but can't add more than four buttons, HTML page doesn't load

I have a software problem, I'm controlling relays through ethernet shield and arduino. I got a code from the net which works great and i can control the relays perfectly. But the problem I'm getting is when i add too many buttons on the HTML page, the HTML page just doesn't load. Only when I'm using max four buttons it works, but when i add more than four it doesn't work. I have provided the code below, please if anyone can help me add more buttons without using too much memory i would have solved my problem.

Here's the code:

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

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);



String readString = String(100); //string for fetching data from address

void setup()
{
Serial.begin(9600);

pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);

// start the Ethernet connection and the server:

Serial.println(F("Initiaizing ethernet..."));

// this uses a fixed address
Ethernet.begin(mac, ip);

// get an address with DHCP
//if (Ethernet.begin(mac) == 0)
//  Serial.println("Failed to configure Ethernet using DHCP");

// give the card a second to initialize 
delay(1000);

server.begin();

Serial.print(F("Garage Door Opener Control Ready at IP address "));
Serial.println(Ethernet.localIP());
}

 void loop()
{
// command received (one character)  '1' - activate garage door button
char cmd = 0;          // 1 - pulse button
boolean done = false;  // set to indicate that response is complete

// listen for incoming clients
EthernetClient client = server.available();
if (client) {

Serial.println(F("new client"));
readString = "";

while (client.connected()) {
  if (client.available()) {
    char c = client.read();
    Serial.write(c);
    //int i = c;
    //Serial.print("(");
    //Serial.print(i);
    //Serial.print(")");

    // store character received in receive string
    if (readString.length() < 100) {
      readString += (c);
    }

    // check for end of line
    if (c == '\n') {
        //Serial.print("Receved line: ");
        //Serial.print(readString);  

        // process line if its the "GET" request
        // a request looks like "GET /?1" or "GET /?2"
        if (readString.indexOf("GET") != -1) {
            if (readString.indexOf("?1") != -1)
               cmd = '1';
            // check for other commands here. ie turn on light, etc.
            if (readString.indexOf("?2") != -1)
               cmd = '2';  
                              if (readString.indexOf("?3") != -1)
               cmd = '3'; 
                              if (readString.indexOf("?4") != -1)
               cmd = '4'; 
                              if (readString.indexOf("?5") != -1)
               cmd = '5'; 
                              if (readString.indexOf("?6") != -1)
               cmd = '6'; 
                              if (readString.indexOf("?7") != -1)
               cmd = '7';
                             if (readString.indexOf("?8") != -1)
               cmd = '8'; 

        }              

       // if a blank line was received (just cr lf, length of 2), then its the end of the request
       if (readString.length() == 2) {
         if (cmd == '1'){
            Serial.println(F("Activate Button"));
            digitalWrite(6, HIGH);

         }
                      if (cmd == '2'){
            Serial.println(F("Activate Button"));
            digitalWrite(6, LOW);

         }
                      if (cmd == '3'){
            Serial.println(F("Activate Button"));
            digitalWrite(5, HIGH);

         }
                      if (cmd == '4'){
            Serial.println(F("Activate Button"));
            digitalWrite(5, LOW);

         }
                      if (cmd == '5'){
            Serial.println(F("Activate Button"));
            digitalWrite(7, HIGH);

         }
                      if (cmd == '6'){
            Serial.println(F("Activate Button"));
            digitalWrite(7, LOW);

         }
                      if (cmd == '7'){
            Serial.println(F("Activate Button"));
            digitalWrite(8, HIGH);

         }
                      if (cmd == '8'){
            Serial.println(F("Activate Button"));
            digitalWrite(8, LOW);

         }

         // add other commands here

         // send web page back to client 
         Serial.println(F("sending web page"));
         SendWebPage(client); 
         Serial.println(F("web page sent"));

         cmd = 0;

         // break out and disconnect. This will tell the browser the request is complete without   having to specify content-length
         break;

       }  // end of request reached

       // start line over            
       readString = "";
   }  // end of line reached
   }  // end data is available from client
   }  // end cient is connected
   // give the web browser time to receive the data
   Serial.println(F("delay before disconnect"));
   delay(100);
   // close the connection:
   client.stop();
   Serial.println(F("client disonnected")); 
   }  // end client has been created
   }

   // send web page
   void SendWebPage(EthernetClient client)
   {
   client.println(F("HTTP/1.1 200 OK")); 
   client.println(F("Content-Type: text/html")); 
   // to specify the length, wooul have to construct the entire string and then get its length
   //client.println("Content-Length: 1234"); 
  client.println(F("Connnection: close")); 
  client.println(); 

  client.println(F("<!DOCTYPE HTML>"));
  client.println(F("<html>"));
  client.println(F("<head>"));
  client.println(F("<title>Home Automation Control</title>"));

  client.println(F("<style type='text/css'>"));
  client.println(F(".label {font-size: 30px; text-align:center;}"));
  client.println(F("button {width: 160px; height: 70px; font-size: 30px; -webkit-appearance: none; background-color:#dfe3ee; }"));
  client.println(F("</style>"));

  client.println(F("<script type='text/javascript'>"));

  client.println(F("function OnButtonClicked(parm) { window.location.href=\"X?\" + parm; }"));

  client.println(F("</script>"));

  client.println(F("</head>"));

  client.println(F("<body style=\"background-color:#3b5998\">"));

  client.println(F("<div class=\"label\">"));

  client.println(F("Home Auotmation Control<br/><br/>"));

  // future idea: could read a limit switch on the garage door here and tell the user if the door is currently open or closed
  /*
  if (digitalRead(DOOR_OPEN_INPUT) == HIGH)
  client.println("Door is Open"); 
  else  
  client.println("Door is Closed"); 
  client.println("<br>");
  */

  // door open / close button
  if (digitalRead(6)==LOW)
  {
  client.println(F("<button onclick=\"OnButtonClicked('1');\">1ON</button><br/><br/>"));
  }if (digitalRead(6)==HIGH){
  client.println(F("<button onclick=\"OnButtonClicked('2');\">1Off</button><br/><br/>"));
  }   if (digitalRead(5)==LOW)
  {
  client.println(F("<button onclick=\"OnButtonClicked('3');\">2ON</button><br/><br/>"));
  }if (digitalRead(5)==HIGH){
  client.println(F("<button onclick=\"OnButtonClicked('4');\">2Off</button><br/><br/>"));
  }  if (digitalRead(7)==LOW)
  {
  client.println(F("<button onclick=\"OnButtonClicked('5');\">3ON</button><br/><br/>"));
  }if (digitalRead(7)==HIGH){
  client.println(F("<button onclick=\"OnButtonClicked('6');\">3Off</button><br/><br/>"));
  }   if (digitalRead(8)==LOW)
  { 
  client.println(F("<button onclick=\"OnButtonClicked('7');\">4ON</button><br/><br/>"));
  }if (digitalRead(8)==HIGH){

  client.println(F("<button onclick=\"OnButtonClicked('8');\">4Off</button><br/><br/>"));
  }


 // add more buttons here
 // button separator



 client.println(F("</div>"));

 client.println(F("</body>"));
 client.println(F("</html>"));

  client.println("");
 }


Solution 1:[1]

When You try to use more then 4 relays, i think You give values to counter "cmd" like 9 and 10 for fifth relay, 11 and 12 for next and i.e., but "cmd" must have only one symbol like a, b, c, x, 5, g ... Then it works.

Solution 2:[2]

First of all, where are you declaring your button pins as INPUTS? You only declare them as OUTPUTS, then you do digitalRead() and digitalWrite() on these pins without changing their mode. What's going on there?

"
pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
"

It seems like you are attempting to set the value of that pin (LOW or HIGH) and then you read its own voltage based on the state previuosly defined with the digitalWrite() function. Is this what you are trying to achieve?

I also believe that you might have some conflicts due to the flow of the code as it is jumping at different levels, depending on the conditions of the client. Additionally, you read the state of the pushbuttons inside of a function that also handles the client page. Try changing the algorithm to something more functions and events based which might make it programmatically more dynamic and more efficient for your Uno

I would recommend you to build the readString String from the client first, then use your (unused) done flag and trigger the subsequent processing of the received instruction, once it's complete.

Little changes:

Define states for the client:

enum {
 OFFLINE,
 ONLINE
} State;

State ClientStatus = OFFLINE;

Then, in the main loop() you check for the status of the client and execute the String read and the command processing:

void loop(){

if(client.connected()){
    ClientStatus = ONLINE;
} else{
    ClientStatus = OFFLINE;
}

//...

if(ClientStatus == ONLINE){

    if(client.available(){
        GetString();

        if (done){
            ProcessLine();
            cmd = GetCommand(readString);

            if(readString.length) == 2){
                 switch(cmd){
                     case '1':
                         Serial.println(F("Activate Button"));
                         digitalWrite(6, HIGH);
                         break;
   
                         // rest of the blocks go here

                 }

                 SendWebPage();
                 readString = ''; // clear it once you finish working with it

//...close braces adequately
}

where GetString() could be something similar to the way a String is built during a SerialEvent:

void GetString(){     
 // build your string here   
 char c = client.read();

//When you find the end of line (EOF), finish building //your string, raise the flag.
    while(readString.length() < 100){  
    readString += client.read();
    //Serial.println(readString);    // for debugging  
        if(c = '\n'){
        done = true;
        break;   
        }
    }
}

Finally, your SendWebPage() function should call another function that reads the switches debouncing them. To do so, use the `Bounce2 library. You could be experiencing some chattering on the switches which are not triggering the creation of your buttons. Basically, your door open/ door close button section should be contained inside another function. Ideally, the switches should be interrupt-based, triggering respective flags to enable/disable your buttons, but that's a limitation of the Uno (reduced number of pin interrupts)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dan
Solution 2