Led-switching via ethernet

Hi,

I wrote some code to let the arduino+ethernet shield send a plain website with two buttons to switch on or off an led which is placed behind a resistor on port 2. Generally, the code is based on the WebServer example. The command is posted as an extension of the url: $1 switches on, $2 switches off.
Modifying the url works like a charm to switch the led, but apparently the buttons work a kind of whacky:
To achieve the desired effect, I always have to click a button twice. When it's pressed only once, you can see it go to the associated state for blink of an eye and then immediately go back to what it was.
So, what's the error in my code?
Here it is:

#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,0,105);
boolean incoming = 0;
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
int led=2;
String ipstring="http://192.169.0.105";
int power;
void setup() {
 // Open serial communications and wait for port to open:
 Serial.begin(9600);

 // start the Ethernet connection and the server:
 Ethernet.begin(mac, ip);
 server.begin();
 Serial.print("server is at ");
 Serial.println(Ethernet.localIP());
 pinMode(led, OUTPUT);
 pinMode(7, OUTPUT);
}


void loop() {
 // listen for incoming clients
 EthernetClient client = server.available();
 if (client) {
   Serial.println("client connected");
   // an http request ends with a blank line
   boolean currentLineIsBlank = true;
   while (client.connected()) {
     if (client.available()) {
       char c = client.read();
       // 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

       //reads URL string from $ to first blank space
       if(incoming && c == ' '){
         incoming = 0;
       }
       if(c == '

Thanks in advance and greetings

){
        incoming = 1;
      }
      //Checks for the URL string $1 or $2
      if(incoming == 1){
        Serial.println(c);

if(c == '1'){
          power=HIGH;
          digitalWrite(led, power);
   //      for debugging purposes
          //            Serial.println("ON");
          //            digitalWrite(led, HIGH);
          //            delay(500);
        }
        if(c == '2'){
          power=LOW;
          digitalWrite(led, power);
   //      for debugging purposes
          //            Serial.println("OFF");
          //            digitalWrite(led, LOW);
          //            delay(500);
        }
      }
      digitalWrite(led, power);
      //Serial.write(c);
      // 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("HTTP/1.1 200 OK");
        client.println("Content-Type: text/html");
        client.println("Connnection: close");
        client.println();
        client.print("");
        client.print("");
        client.print("");
        client.print("<script type="text/javascript">");
        client.print("function btn_power_on()");
        client.print("{");
        //client.print("alert('ON!');");
        client.print("parent.location='$1'");
        client.print("}");
        client.print("function btn_power_off()");
        client.print("{");
        //client.print("alert('OFF!');");
        client.print("parent.location='$2'");
        client.print("}");
        client.print("");
        client.print("");
        client.print("");
        client.print("");
        client.print("<input type=button style="width:350px;height:200px" onClick="btn_power_on()" value='power on'>");
        client.print("
");
        client.print("
");
        client.print("
");
        client.print("
");
        client.print("
");
        client.print("<input type=button style="width:350px;height:200px" onClick="btn_power_off()" value='power off'>");
        client.print("");
        client.print("");
        client.print("");
        break;
      }
      if (c == '\n') {
        // you're starting a new line
        currentLineIsBlank = true;
      }
      else if (c != '\r') {
        // you've gotten a character on the current line
        currentLineIsBlank = false;
      }
    }
  }
  digitalWrite(led, power);
  // give the web browser time to receive the data
  delay(1);
  // close the connection:
  client.stop();
  Serial.println("client disonnected");
}
}


Thanks in advance and greetings

Some simple button test code you can compare to your code.

//zoomkat 3-17-12
//simple button GET server code to control servo and arduino pin 5
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html 
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields
//Powering a servo from the arduino usually DOES NOT WORK.
//note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605 

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

#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

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

String readString; 

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();

  myservo.write(90); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo co
  //enable serial data print 
  Serial.begin(9600); 
  Serial.println("server LED test 1.0"); // so I can keep track of what is loaded
}

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; 
          //Serial.print(c);
        } 

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

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();

          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Arduino GET test page</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          client.println("<H1>Zoomkat's simple Arduino button</H1>");
          
          // DIY buttons
          client.println("<a href=\"/?on\"\">ON</a>"); 
          client.println("<a href=\"/?off\"\">OFF</a>
"); 

          // mousedown buttons
          client.println("
<input type=\"button\" value=\"ON\" onmousedown=\"location.href ('/?on');\"/>"); 
          client.println("<input type=\"button\" value=\"OFF\" onmousedown=\"location.href ('/?off');\"/>");        
          
          // mousedown radio buttons
          client.println("

<input type=\"radio\" value=\"ON\" onmousedown=\"location.href ('/?on');\"\">ON</>"); 
          client.println("<input type=\"radio\" value=\"OFF\" onmousedown=\"location.href ('/?off');\"\">OFF</>");        
 
          client.println("</BODY>");
          client.println("</HTML>");
 
          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on") >0)//checks for on
          {
            myservo.write(40);
            digitalWrite(5, HIGH);    // set pin 5 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            myservo.write(140);
            digitalWrite(5, LOW);    // set pin 5 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
}

Hey,

thanks for your reply. The code looks quite similar to mine apart from having different kinds of buttons and reading a string instead of single characters from the url.

The effect remains the same: When I toggle the buttons, the string in the url changes as intended.
However, the led behaves the same as it did before, it still does not change the state according to the posted string ON or OFF.

I'm a bit clueless about why the action does not "reach" the led...

If you put each { on a new line, and use Tools + Auto format, I think that you will see the problem with your code. If not, post it again after making the changes.

Look at the circumstances under which you change the pin state.

However, the led behaves the same as it did before, it still does not change the state according to the posted string ON or OFF

When I try my code with IE I get single click on/off action. Perhaps your browser is set for a double click requirement to launch a link.

Perhaps your browser is set for a double click requirement to launch a link.

I tried it with the browser on my mobile phone, chrome/chromium and firefox.
Actually, there is a reaction to a button click, but it only lasts for a fraction of a second. The second click then changes the state so that it lasts.

It is notable that the url changes correctly, only the led's state is not set properly!
That may indicate that there's an error in the code

If you put each { on a new line, and use Tools + Auto format, I think that you will see the problem with your code. If not, post it again after making the changes.

I took these remarks into account, the code is posted below:

#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,0,105);
boolean incoming = 0;
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);
int led=2;
String ipstring="http://192.169.0.105";
int power=LOW;
int lastState=HIGH;
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  pinMode(led, OUTPUT);
}


void loop() 
{
  digitalWrite(led, power);
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) 
  {
    Serial.println("client connected");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        // 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

        //reads URL string from $ to first blank space
        if(incoming && c == ' ')
        { 
          incoming = 0;
        }
        if(c == '

In line 86 I changed if(c == '2') to else if(c == '2')

I discovered that the buttons' actions are just turned around: When I press the "OFF" button, the led turns on and vice versa. Just changing the buttons' labels doesn't appeal to me, I'd rather correct the code's logic.

Look at the circumstances under which you change the pin state.

The state is set depending on the character (1 or 2) in the url, but this is apparently not done correctly by the buttons.
What exactly are you pointing at?

Thanks and greetings)
        {
          incoming = 1;
        }
        //Checks for the URL string $1 or $2
        if(incoming == 1)
        {
          Serial.println(c);

if(c == '1')
          {
            power=HIGH;
            digitalWrite(led, power);
          }
          else if(c == '2')
          {
            power=LOW;
            digitalWrite(led, power);
          }
        }
        //Serial.write(c);
        // 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("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.print("");
          client.print("");
          client.print("");
          client.print("<script type="text/javascript">");
          client.print("function btn_power_on()");
          client.print("{");
          //client.print("alert('ON!');");
          client.print("parent.location='$1'");
          client.print("}");
          client.print("function btn_power_off()");
          client.print("{");
          //client.print("alert('OFF!');");
          client.print("parent.location='$2'");
          client.print("}");
          client.print("");
          client.print("");
          client.print("");
          client.print("");
          client.print("<input type=button style="width:350px;height:200px;font-size:30px" onClick="btn_power_on()" value='power on'>");
          client.print("
");
          client.print("
");
          client.print("
");
          client.print("
");
          client.print("
");
          client.print("<input type=button style="width:350px;height:200px;font-size:30px"  onClick="btn_power_off()" value='power off'>");
          client.print("");
          client.print("");
          client.print("");
          break;
        }
        if (c == '\n')
        {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r')
        {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
      if(power !=lastState)
      {
        lastState=power;
        Serial.println(power);
      }
    }

// give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}


In line 86 I changed `§_DISCOURSE_HOISTED_CODE_1_§` to `§_DISCOURSE_HOISTED_CODE_2_§`

I discovered that the buttons' actions are just turned around: When I press the "OFF" button, the led turns on and vice versa. Just changing the buttons' labels doesn't appeal to me, I'd rather correct the code's logic.

> Look at the circumstances under which you change the pin state.

The state is set depending on the character (1 or 2) in the url, but this is apparently not done correctly by the buttons. 
What exactly are you pointing at?

Thanks and greetings

Does anyone have an idea why the buttons have to be clicked two times?