Internet Control of LEDS with HTML buttons

Ok so I doubt this will be a hard problem to fix. I really need to set up multiple html buttons that each controls a separate pin. Like a button to control pin 4 and a different one for pin 5 and so on.
As you can see my code is below. I already have the pins enabled and everything is wired correctly I just need to make a separate button to control each pin.
( code tags added by moderator)

#include <SPI.h> 

#include <Client.h> 

#include <Ethernet.h> 

#include <Server.h> 

#include <Udp.h> 



byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address 

byte ip[] = { 192, 168, 0, 110 }; // ip in lan 

byte gateway[] = { 192, 168, 0, 1 }; 
// internet access via router 

byte subnet[] = { 255, 255, 255, 0 }; //subnet mask 

EthernetServer server(80); //server port 

int pin = 4; // LED pin
int pin2 = 5;
int pin3 = 2;
int pin4 = 3;
int pin5 = 6;
int pin6 = 7;
int pin7 = 8;


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

boolean LEDON = false; //LED status flag

void setup(){ 

//start Ethernet 

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

//Set pin 2-8 to output

pinMode(pin, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
pinMode(pin4, OUTPUT);
pinMode(pin5, OUTPUT);
pinMode(pin6, OUTPUT);
pinMode(pin7, OUTPUT);

//enable serial datada print 

Serial.begin(9600); 

} 

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; //replaces readString.append(c); 

} 

//output chars to serial port 

Serial.print(c); 

//if HTTP request has ended 

if (c == '\n') { 

//dirty skip of "GET /favicon.ico HTTP/1.1" 

if (readString.indexOf("?") <0) 

{ 

//skip everything 

} 

else 

//lets check if LED should be lighted 

if(readString.indexOf("L=1") >0)//replaces if(readString.contains("L=1")) 

{ 

//led has to be turned ON 

digitalWrite(pin, HIGH); // set the LED on
digitalWrite(pin2, HIGH);
digitalWrite(pin3, HIGH);
digitalWrite(pin4, HIGH);
digitalWrite(pin5, HIGH);
digitalWrite(pin6, HIGH);
digitalWrite(pin7, HIGH);

LEDON = true; 

}else{ 

//led has to be turned OFF 

digitalWrite(pin, LOW); // set the LED OFF 
digitalWrite(pin2, LOW);
digitalWrite(pin3, LOW);
digitalWrite(pin4, LOW);
digitalWrite(pin5, LOW);
digitalWrite(pin6, LOW);
digitalWrite(pin7, LOW);

LEDON = false; 



} 

// now output HTML data starting with standart header 

client.println("HTTP/1.1 200 OK"); 

client.println("Content-Type: text/html"); 

client.println(); 

//set background to yellow 

client.print("<body style=background-color:yellow>"); 

//send first heading 

client.println("<font color='red'><h1>Power Control Prototype</font></h1>"); 

client.println("<hr />"); 

client.println("<hr />"); 

//controlling led via checkbox 

client.println("<h1>LED control</h1>"); //address will look like http://192.168.0.110/?L=1 when submited 

if (LEDON) 

client.println("<form method=get name=LED><input type=checkbox name=L value=0>LED
<input type=submit value=submit></form>"); 

else 

client.println("<form method=get name=LED><input type=checkbox name=L value=1>LED
<input type=submit value=submit></form>");

client.println("
"); 

//printing LED status 

client.print("<font size='5'>LED status: "); 

if (LEDON) 

client.println("<font color='green' size='5'>ON"); 

else 

client.println("<font color='grey' size='5'>OFF"); 

client.println("<hr />"); 

client.println("<hr />"); 

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

//clearing string for next read 

readString=""; 

//stopping client 

client.stop(); 

} 

} 

} 

} 

}

Have a look at the code I posted here (Reply #14). It should give you some clues. http://arduino.cc/forum/index.php/topic,113496.0.html

As I recall it was for a different Ethernet library, but it should be possible to adapt it.

In Reply #16, I showed how to modify it for any number of LEDs.

Awesome! I appreciate the help. I will give this a try.

My boss wants me to use buttons not URL's. Do you know how to assign a pin to a button?

If you mean a button on the webpage, then you just need to change the returned HTML to draw a button which calls the URL.

This is the HTML for a button:

e.g. This is how my other code would be modified for buttons:

void homePage(){
  //$F represents p string, $D represents word or byte, $S represents string. 
  //There are 5 leds, so 5 hyperlinks.
  bfill.emit_p(PSTR("$F"
    "<meta http-equiv='refresh' content='5'/>"
    "<title>Ethercard LED</title>" 
    "<input type=button onClick="location.href='?led=$S'" value='Turn LED$D $S'>" 
    "<input type=button onClick="location.href='?led=$S'" value='Turn LED$D $S'>" 
    "<input type=button onClick="location.href='?led=$S'" value='Turn LED$D $S'>" 
    "<input type=button onClick="location.href='?led=$S'" value='Turn LED$D $S'>" 
    "<input type=button onClick="location.href='?led=$S'" value='Turn LED$D $S'>"),
  http_OK,
  LedURL[1],(word)1,LedURL[1][1]?"ON":"OFF",
  LedURL[2],(word)2,LedURL[2][2]?"ON":"OFF",
  LedURL[3],(word)3,LedURL[3][3]?"ON":"OFF",
  LedURL[4],(word)4,LedURL[4][4]?"ON":"OFF",
  LedURL[5],(word)5,LedURL[5][5]?"ON":"OFF");
}

That makes sense. Sorry I'm still fairly new to programming. I appreciate the help and I'll give this a shot.

What is bfill.emit_p(PSTR("$F" It keeps giving me an error that says that there is an expected initializer before bfill

Ahh right yeah. Thats because it is for a different library called EtherCard, which i think is for a different ethernet sheild from the one you are using.

Edit:
I have integrated my example from the other thread into your code. Beyond it compiling, I can’t be sure it will work until you try it as I don’t have an Ethernet sheild. If it doesn’t work, let me know and I will give you some pointers as to how it can be corrected.

#include <SPI.h> 
#include <Client.h> 
#include <Ethernet.h> 
#include <Server.h> 
#include <Udp.h> 

//This is how many LEDs your webpage will control. Set the digital pin for each in this array, and the rest of the code will be
//automatically updated to match the correct number of LEDs.
byte LED[] = {4,5,2,3,6,7,8}; 


char readString[101] = {0}; //EURGH, use an array not the String library 

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address 

byte ip[] = { 192, 168, 0, 110 }; // ip in lan 

byte gateway[] = { 192, 168, 0, 1 };// internet access via router 

byte subnet[] = { 255, 255, 255, 0 }; //subnet mask 

EthernetServer server(80); //server port 

const byte numberOfLeds = sizeof(LED)/sizeof(byte);
char LedURL[numberOfLeds][numberOfLeds+1];

const char http_OK[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n\r\n";

const char http_Found[] PROGMEM =
"HTTP/1.0 302 Found\r\n"
"Location: /\r\n\r\n";

const char http_Unauthorized[] PROGMEM =
"HTTP/1.0 401 Unauthorized\r\n"
"Content-Type: text/html\r\n\r\n"
"<h1>401 Unauthorized</h1>";

const char buttonHTMLStart[] PROGMEM =
"<input type=button onClick=\"location.href='?led=";

const char buttonHTMLMid[] PROGMEM =
"'\" value='Turn LED";


void printPString(EthernetClient client,PGM_P s){
  char c;
  while ((c = pgm_read_byte(s++)) != 0){
    client.print(c);
    Serial.print(c); //For DEBUG only, remove if not needed
  }
}
void printlnPString(EthernetClient client,PGM_P s){
  printPString(client,s);
  client.println();
  Serial.println(); //For DEBUG only, remove if not needed
}

void homePage(EthernetClient client){
  printlnPString(client,http_OK);
  printlnPString(client,PSTR("<body style=background-color:yellow>")); 
  printlnPString(client,PSTR("<font color='red'><h1>Power Control Prototype</font></h1>")); 
  printlnPString(client,PSTR("<meta http-equiv='refresh' content='5'/>"));
  printlnPString(client,PSTR("<h1>LED control</h1>"));
  printlnPString(client,PSTR("<hr />"));
  printlnPString(client,PSTR("<hr />"));
  //There are 5 leds, so 5 hyperlinks.
  for (byte i = 0; i < numberOfLeds; i++){
    printPString(client,buttonHTMLStart);
    client.print(LedURL[i]);
    printPString(client,buttonHTMLMid);
    client.print((int)(i+1));
    client.println(LedURL[i][i]?" ON'>":" OFF'>");
  }
}

void setup(){
  Ethernet.begin(mac, ip, gateway, subnet); 
  Serial.begin(9600);
  for(byte i = 0; i < numberOfLeds; i++){
    pinMode(LED[i],OUTPUT); //LEDs are outputs
    digitalWrite(LED[i],LOW); //Off to begin with
    //Initialise the URL string array
    for(byte j = 0; j < numberOfLeds; j++){
      LedURL[i][j] = ((j == i)?'1':'0');
    }
    LedURL[i][numberOfLeds] = 0; //Null character
    Serial.println(LedURL[i]);
  }
}

void loop(){ 

  // Create a client connection 

  EthernetClient client = server.available(); 
  byte readStringIndex = 0;
  if (client) { 
    while (client.connected()) { 
      if (client.available()) { 
        char c = client.read(); 
        //read char by char HTTP request 
        if (readStringIndex < 100) 
        { 
          //store characters to string 
          readString[readStringIndex++] = c; 
        } 
        else { 
          printlnPString(client,http_Unauthorized);
          while(client.available()){
            client.read(); //Clear the buffer
          }
          continue; //Can't have anymore otherwise it would overflow
        }
        //output chars to serial port 
        Serial.print(c); 
        //if HTTP request has ended 
        if (c == '\n') { 
          readString[readStringIndex] = 0;
          readStringIndex = 0;
          char *data = readString; //Get the pointer to the read string.
          if (strncmp("GET /", data, 5) != 0) { //I also accidentally copied this bit in twice (though that shouldn't be an issue)
            // Unsupported HTTP request
            // 304 or 501 response would be more appropriate
          } else {
            data += 5;
            if ((data[0] == ' ') || (data[0] == 0)) { //Check if the home page, i.e. no URL
              homePage(client);
            } 
            else if (!strncmp("?led=",data,5)){ //Check if a url which changes the leds has been recieved
              data += strcspn (data,"01"); //Move to the start of the URL
              char tempURL[numberOfLeds+1] = {0};
              strncpy(tempURL, data, numberOfLeds); //Extract the recieved URL to the temporary string 
              Serial.print("temp = ");
              Serial.println(tempURL); //Just some quick logging
              for(byte i = 0; i < numberOfLeds ; i++){ //Check through each of the LEDs URLs
                if(!strcmp(tempURL,LedURL[i])){
                  //The recieved URL matches the one required to turn this LED on, so we will turn it on.
                  digitalWrite(LED[i],(tempURL[i] == '1')?HIGH:LOW); //Set the led state to match the URL.
                  //Now we need to toggle the state of this LED in all of the URLs, so that all the hyperlinks can be corrected to match this state.
                  for(byte j = 0; j < numberOfLeds ; j++){
                    if(j==i){
                      LedURL[j][i] = (tempURL[i] == '1')?'0':'1'; //Notice how we toggle the 'i'th led in each url.
                      Serial.print("led = ");
                      Serial.println(LedURL[j]); 
                      continue;
                    }
                    LedURL[j][i] = tempURL[i]; //Notice how we toggle the 'i'th led in each url.
                    Serial.print("led = ");
                    Serial.println(LedURL[j]);     
                  }
                  //The URL was found, so we don't need to check any others.
                  break; //Exit the for loop.
                }          
              }
              printlnPString(client,http_Found);
            } 
            else { //Otherwise, page isn't found
              // Page not found, do nothing.
            }
          }
        } 
      } 
    } 
  } 
}

This works almost perfectly! The only issue is that every time I click the button an LED comes on then it goes to a page with nothing but 401 Unauthorized errors. I'll post the image of the webpage and the error page.

I’ve attached the two images to this post.

Try changing this bit:

            else { //Otherwise, page isn't found
              // Page not found
              printlnPString(client,http_Unauthorized);
            }
          }
        } 
      } 
    } 
  } 
}

To be:

            else { //Otherwise, page isn't found
              // Page not found
              //printlnPString(client,http_Unauthorized); //Commented out this line as it may not be needed.
            }
          }
        } 
      } 
    } 
  } 
}

Still getting the same error...I'm trying to troubleshoot it here too but I'm not much into programming lol Still really new to it.

It might be the other one then.

        if (c == '\n') { 
          readString[readStringIndex] = 0;
          readStringIndex = 0;
          char *data = readString; //Get the pointer to the read string.
          if (strncmp("GET /", data, 5) != 0) {
            // Unsupported HTTP request
            // 304 or 501 response would be more appropriate
            //printlnPString(client,http_Unauthorized); //Comment out this line
          } else {

Awesome!!! That fixed that part! Now everytime I click a button I have to refresh the page to click another one though.

It should refresh automatically after 5 seconds, as instructed by the HTML for the home page. You could try increasing the speed of the refresh.

...
void homePage(EthernetClient client){
  printlnPString(client,http_OK);
  printlnPString(client,PSTR("<body style=background-color:yellow>")); 
  printlnPString(client,PSTR("<font color='red'><h1>Power Control Prototype</font></h1>")); 
  printlnPString(client,PSTR("<meta http-equiv='refresh' content='5'/>")); //This line means refresh after 5 seconds. Change the number to change the time
  printlnPString(client,PSTR("<h1>LED control</h1>"));
...

Thank you so much! You were incredibly helpful and patient. Thank you!

This was incredibly helpful. Thank you so much.