HTML/Arduino coding for single ON/OFF button

Hi,

I've just registered, so this is my first post after "lurking" around the forum for a while seeing what people have been doing in the area.

I've had a look round the forums and I can't find the solution to my particular problem. I've been interested in home automation for a while, and after exploring the options available I settled on the following:

I have also coded (with my very limited knowledge of HTML5 and CSS) a website which after a load of struggling, I've finally managed to get run successfully (and more importantly display properly with all the CSS and JS) off the Ethernet shield SD card. I chose HTML rather than an android / Ipad app as with HTML I can just log onto a website on the LAN and use either the laptop / ipad /iphone / or android phones rather than develop a platform specific interface for each.

Within one of the "control" pages (in this case "bathroom.htm") I have an "ON/OFF" button for a lightbulb, and I am wondering how I would go about coding this both from a HTML and a Arduino sketch perspective. Note here that I've seen several implementations on these forums and on the internet of separate ON and separate OFF buttons, which set the Pin to "LOW" and "HIGH" respectively, but I've not seen any HTML code I can allocate to a single button which when the button is pressed will switch the PIN from "HIGH" to "LOW" when the current state is "HIGH", but from "LOW" to "HIGH" when the current state is low.

Could somebody help me out with the following please:

  1. HTML code for the button
  2. Arduino sketch for the arduino running the standard webserver sketch (so maybe just the additional lines for void setup(), and the full lines for void loop () )

I've attached a picture of the button on my webpage to this post, and the HTML behind this currently this is as follows:

<section>
									<header>
										<h3>Lights</h3>
									</header>
									<p>Central lighting unit with extractor fan.         </p>
									<footer>
										<ul class="buttons">
										<li><a href="#" class="button special">ON / OFF</a></li>
											
										</ul>
									</footer>
								</section>

I assume that the solution will use the serial.print function, and maybe an if statement like...

if (currentState == HIGH && lastState == LOW)

....but I'm not quite sure how to tie this all together into the HTML / arduino sketch.

Please note that it would also be useful if I could expand this solution to cover a number of additional buttons (ie an expandable solution), so if I had 10 lightbulbs in the house connected through relays to 10 different pins on the Arduino, the solution would allow me to differentiate between these and map a slight variation of the standard code to each of the 10 buttons on my webpage, to switch any of these bulbs on or off independently with that button press.

Any help at all is much appreciated! XD

P.S I've found the following links which I've seen doing something similar but in both cases it's not quite what I want:

http://forum.arduino.cc/index.php?topic=72204.0

Example_button.JPG

First, in home automation, a button that turns something off is a godsend. You don't have to go there and see the light is on and turn it off; you just turn it off. Same with on. When you can see it, you know what you want to do, but if you can't, ... This is why things like garage doors are annoying. You have to know its open to send a signal to it, otherwise you wind up opening the door when you shouldn't.

However I see your point, and todays remote switches will tell you if the light is on so you can display it. I ran into this problem a few years ago and handle it in various fashions.

If you know the state of the light, just call the opposite routine:

if ( light == on)
turn it off
else
turn it on

but I bet you knew that already. There's also the tertiary statement , the xor, and a special register that can be used to flip the lights. There's a good article on this here: » Flippin’ bits » JeeLabs

If you want to change the button in your web page, perhaps you want to change the button color to yellow when it's on and black when it's off, then you name the element and use jquery to cause the browser to change the color:

First, give the button a name you can use to access its attributes.

The 'id=' above gives the button its name. The background-color gives it a color to begin with, the value holds the text for the button, etc. Now, in javascript, change the color to yellow or put it back to lightgray:

if (data.lfp=="On"){
$("#lfp").css("background-color","yellow");
}
else{
$("#lfp").css("background-color","lightgray");
}

You'll have to get the javascript libraries into the user's browser by putting:

somewhere up in the code. Using the attributes of elements is a fast and (relatively) easy way of changing the appearance right on the user's browser. I use this kind of thing a lot to change the appearance of items on a browser. The nice thing is that all the code runs on the user's browser and the arduino is left with the chore of loading the text out the ethernet port.

A warning though, HTML pages take a whole lot of text. You can run even a mega out of memory doing this, so be frugal.

Thanks, that's really helpful, but I probably should have given a little more context as to what I'm trying to achieve......

Although modern switches will provide a status to tell you if the light is on, I'm trying to retro-fit this to a 120 year old house, which has just got traditional UK mains wiring. I'm trying to cater for the situations where I want to switch a light on or off with the arduino, but at the same time, if my mum chooses to switch the light on or off via the traditional wall switch then she can do that. In terms of the electrical wiring, the plan is just to wire the relay in as an additional switch in a 2-way or 3-way switching circuit.

This is why I want the button to be dynamic in whether it makes the pin go HIGH or LOW. You can imagine the situation where:

  1. I switch the light on with the arduino (pin set to LOW)
  2. Mum switches the light off with the wall switch (pin hasn't changed here since switching not performed with the Arduino)
  3. I want to switch the light on again, which I assume with require the button to action a HIGH this time round

In the above example, the same action (switching the light on), will require a pin to be "LOW" the first time round, but "HIGH" the second time round.

I appreciate the following could also happen, but I submit to the fact that if I get the button to switch between "HIGH" and "LOW" sequentially, then at most I would have to push the ON/OFF button twice to get the desired result:

  1. I switch the light on with the arduino (pin set to LOW)
  2. Mum switches the light off with the wall switch (pin hasn't changed here since switching not performed with the Arduino)
  3. Dad switches the light on with the wall switch (pin hasn't changed here either)
  4. I want to switch the light off again, which I assume with require the button to action a HIGH this time round??

So I guess my issue isn't so much about being able to "see" what I want to do, it's more that dependent upon whether the other manual switch(es) in the circuit have been pushed or not, I'll need the Arduino to set the pin to the opposite of whatever it last set the pin at.

Hopefully that makes it clearer what I'm trying to do? Thanks for all the help so far - eventually I might actually get this working!

I can post my existing webserver sketch when I get back this evening if that helps too :slight_smile:

If you have a two or three way switch, it becomes a different problem that I know of two approaches for.

  1. Replace all the switches involved with remote switches that control the light and then control one of the remote switches with the arduino. This is the method that is used in fully automated houses, but it costs more than I usually want to pay.

  2. Use wiring and relays that mimic another switch in the circuit. Here in the US that means a DPDT relay which will turn the light on or off regardless of the state of the manual switches. To better understand this, take a look at how to wire 2 way and three way switch arrangements, and you'll see what I mean; you're going to add a switch to the arrangement. For this kind of thing, look into DPDT latching relays. These are nice because you can send a short pulse to change the relay state and you don't have to worry about what happens when the power fails because the relay (at least some of them) will stay in the last state.

How to wire 2 and three way light setups is all over the web, so you won't have any problem finding it.

You might use some basic toggle code with the arduino so that both a web page and a local push button could toggle the same light relay connected to the arduino.

//zoomkat LED button toggle test 11-08-2012

int button = 5; //button pin, connect to ground as button
int press = 0;
boolean toggle = true;

void setup()
{
  pinMode(13, OUTPUT); //LED on pin 13
  pinMode(button, INPUT); //arduino monitor pin state
  digitalWrite(5, HIGH); //enable pullups to make pin 5 high
}

void loop()
{
  press = digitalRead(button);
  if (press == LOW)
  {
    if(toggle)
    {
      digitalWrite(13, HIGH);   // set the LED on
      toggle = !toggle;
    }
    else
    {
      digitalWrite(13, LOW);    // set the LED off
      toggle = !toggle;
    }
  }
  delay(500);  //delay for debounce
}

Thanks both, all very good ideas.

@draythomp: I particularly like the idea of the latching relay. The last thing I want is to have a powercut and then find that everything switches on straight after flicking the breaker in the fusebox back on! I've had a quick look on the net and struggling to find one that will cope with switching enough current (say 10a in the case of an immersion heater) at 230v AC. I'll keep looking though as it seems the benefits of a latching relay as opposed to a traditional relay are invaluable.

You mention a DPDT relay - I suspect a SPDT relay will work just as well; forgive my ignorance here but my understanding is that a DPDT relay will allow me to switch two circuits at the same time with one coil (in this case with one pin), but if I'm only looking to switch one appliance per relay then SPDT will do the job? In any case a PCB with 4 SPDT relays (all-in-one units so no need for additional diode) lying around which I bought specifically for this project a few weeks ago (see link below for what I have). Hopefully since I'm only looking to switch one appliance connected to one of these relays for the time being I can just use one of these until I find a latching relay which would work?

http://www.miniinthebox.com/4-channel-relay-module-with-optocoupler-5v_p903429.html?currency=GBP&litb_from=paid_adwords_shopping

@ zoomkat: In terms of the arduino sketch, I was thinking along similar lines as your sketch, but it looks like your sketch uses two pins - 1 for the relay (set to output), and one to monitor the state of the other switch/button (set to input). Extending this principle, I assume that in the case of a three-way switch (eg. a hallway, with 1) an upstairs switch, 2) a downstairs switch, and 3) an Arduino controlled relay), I would need to use three pins with two of these set to monitor the state of each of the manual switches?

Following on from my previous post, would it not be easier to simplify things and code things so that when (and only when) the Arduino is requested (say by HTML code on a website linked to a button in my case), the Arduino monitors the pin state of the relay pin, and then toggles to the opposite of that state? That way, there would be no need to read the state of the other two pins, and one pin could be used (for the relay) regardless of how many other switches there are in the multiway switch?

I thought there might be some difficulty in "reading" the Relay pin as it it's been set to OUTPUT in void setup() which might exempt you from doing this, but I saw the following article which suggests this might be possible?

The above got me started but I didn't quite understand the format of the "bitread" line I need to use, but this cleared it up (I'm also using a Mega2560, so I'd hope this pin mapping would work):

http://forum.arduino.cc/index.php?topic=183731.0

So, for example if I wanted to read the state of pin 51, maybe I could use

Serial.read(bitRead( PORTB,2))

...which would allow me to get the status of pin51, and then write an IF to act accordingly.

Tying this all together, I was wondering whether it would be possible to write something using the following logic, extended to the use of two relays:

  1. set pinmode of pins 51 and 52 to OUTPUT (Each connected to a relay powering an appliance each).

  2. At any one point of time and upon request by HTML code, use bitread(PORTB,2) and bitread(PORTB,1) for pins 51 and 52 respectively to read their current state HIGH/LOW

  3. code within void loop() with an if/else if to say if the output of bitread is "HIGH", then switch the pin to "LOW", and vice versa. (and do the same for the other pin independently).

The only problem is.....this is my first proper sketch, so going about writing the above is beyond me. Could either of you help with the arduino code, and also the html code for the button please?

I appreciate it's difficult to talk in the abstract, so I'm going to PM each of you a link to my home automation website which is running on temporary webhosting (free!) for the time being until I figure out whether this is viable. I tried running this off the arduino SD card in the Ethernet shield, but the pages are too big to load quickly and reliably, so I'm going to base the frontend off external webhosting and focus on interfacing this into the arduino - I can worry about security and hiding the site behind passwords later on - it's only a few light switches anyway so I'm not too bothered.

If you go down to the floorplan on the index page (in the ground floor section) and click on the large room at the back, you'll see it links into a page called bathroom.htm, where I've set up a few switches as examples - the buttons link to/action nothing at the moment but this is where i plan to insert my HTML button code to interface with the arduino - I expect the code will be slightly different here dependent upon which pin I'm looking to switch?

I'll also post my basic web-server sketch when I get home, I seem to remember the mega2560 has some quirks which mean the setup part of the sketch is slightly different for a mega2560 to say something like an Uno (something to do with disabling pin 10 and pin4 because of SPI issues :slight_smile: ).

Any help at all always much appreciated XD

Take a look at this page:
https://www.cs.helsinki.fi/u/ljlukkar/wot/

You could combine the code from the two examples and get the functionality you are after.

The code listings on that page are outdated but updated versions can be found from github and are also available in the examples if you add the aWOT library.

In terms of the arduino sketch, I was thinking along similar lines as your sketch, but it looks like your sketch uses two pins - 1 for the relay (set to output), and one to monitor the state of the other switch/button (set to input). Extending this principle, I assume that in the case of a three-way switch (eg. a hallway, with 1) an upstairs switch, 2) a downstairs switch, and 3) an Arduino controlled relay), I would need to use three pins with two of these set to monitor the state of each of the manual switches?

Setting up new momentary pushbuttons to toggle a light should be fairly easy. Integrating a toggle setup into an existing three way light switch setup will probably be challenging. As to an arduino switch control setup, the toggle code could be modified to set a simple variable status flag that could be included in a web page. Any number of momentary pushbuttons could be put in parallel to actuate the toggle code. The server code probably could also check for a toggle command from a web browser GET request and actuate the toggle code when received. I suggest you start with simple proof of concept code and develop from there.

......So I spent the best part of four hours last night thinking about how I could go about putting what I want down in code.

I came up with the following as my full arduino sketch. This is the full sketch, so includes all the setup for the Ethernet shield etc in addition to the actual code I want to execute:

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

boolean reading = false

// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ   20

// put your ethernet variables (mac, ip) here
// 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,160);						// Internally the Arduino is set to this IP.

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);						//Arduino operating on Port80 - will come in useful later for when externally accessing through port forwarding.


char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer




for (int switchpin = 11; switchpin < 53; switchpin++); 
for (int switchstate = 11; switchstate < 53; switchstate++); 


void setup()
{



Serial.begin(9600);

   // disable w5100 SPI while setting up SD
   pinMode(10,OUTPUT);
   digitalWrite(10,HIGH);

   // set up SD
   if(SD.begin(4) == 0) 
      Serial.println("SD failed");
   else
      Serial.println("SD ok");

   // set up w5100
   Ethernet.begin(mac,ip);
   // disable w5100 SPI
   digitalWrite(10,HIGH);

   // takes a second for the w5100 to get ready
   delay(2000);

   // rest of your setup
   Serial.println("Setup done");





	
   pinMode(switchpin, OUTPUT);

	

}


	


void loop(){

  // listen for incoming clients, and process qequest.
  checkForClient();


}




void checkForClient(){


EthernetClient client = server.available();

  if (client) {

    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    boolean sentHeader = false;

    while (client.connected()) {
      if (client.available()) {

        if(!sentHeader){
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          sentHeader = true;
        }

        char switchinstruction = client.read();

        if(reading && switchinstruciton == ' ') reading = false;
        if(switchinstruction == '?') reading = true; //found the ?, begin reading the info

        if(reading){
          Serial.print(switchinstruction);



	switchstate = !switchstate;

	if (Serial.available() > 0) {
    	int switchinstruction = Serial.print();


	
    switch (switchinstruction) {
    case '11':    
      digitalWrite(11, switchstate);
      break;
    case '12':    
      digitalWrite(12, switchstate);
      break;
    case '13':    
      digitalWrite(13, switchstate);
      break;
    case '14':    
      digitalWrite(14, switchstate);
      break;
    case '15':    
      digitalWrite(15, switchstate);
      break;



          }

        }

        if (switchinstruction == '\n' && currentLineIsBlank)  break;

        if (switchinstruction == '\n') {
          currentLineIsBlank = true;
        }else if (switchinstruction != '\r') {
          currentLineIsBlank = false;
        }

      }
    }

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

  } 

}

}


///...above example assumes using pins 11 to 15 for the time being only, but can continue the above line sequences so that I cover all the pins I'm using

	

{

I'm new to all of this, but the hope is that the above achieves the following:

  1. Sets up the webserver, assigns I.P 192.168.0.160 for local access, and port 80 at xxx.xxx.xxx.xxx (where this is my external IP) for remote access.
  2. Monitors/listens to(???) the serial input for an instruction (in this case the instruction will be sent via HTTP - HTML for the button on my webpage shown later below
  3. Meanwhile, the default pinstate is toggled on each loop of the code, and stores this within a variable called "switchstate"
  4. When the Arduino receives an instruction over serial, say "14", it changes the state of pin14 to whatever the stored value of "switchstate" is.

Switchstate will toggle between "HIGH" and "LOW" on each loop. If pin14 is set to HIGH, and the switchstate variable reads LOW then this will digitalWrite pin14 to LOW to match the switchstate variable. If pin14 is set to HIGH, and the switchstate variable in that particular loop reads HIGH however, then the Arduino will try to write pin14 to HIGH. Since it's already written at HIGH, I'd hope that another push of the HTML button on my webpage would force the switchstate variable to toggle back to LOW, and then when this is applied to the pin it has the desired effect.

My point is that I might need to push the same HTML button twice to achieve the desired effect, but since most of the time it's just lights in the room I am sitting in, it should be self-evident whether the first HTML button push did what I wanted, and if not, I just push it again :slight_smile:

HTML code I expect I'll need to put on the webpage behind the button as follows:

<a href="http://xxx.xxx.xxx.xxx:80/?14" class="button special">ON / OFF</a>

.....where xxx.xxx.xxx.xxx:80 is my external IP and port 80, and where an attempt is made to switch pin14.

Would anybody be kind enough to tell me if the above is viable, and if tweaks are needed let me know where I'm going wrong?

As I'm new to this, I used the knowledge gained from the following links in putting the above sketch together:

http://forum.bildr.org/viewtopic.php?t=416

Thanks again all, every day I'm getting closer to having this working. You guys are invaluable!

Regarding two and three way switching.

I had a heck of a time finding an example of a UK two way switch setup. Here is the one I found:

I'm sure there are others. If you have a two way in the room, then a SPDT relay will work fine, however, if you have a three way or higher (I've seen them go up to six), then you will need to either: 1) find the spot where the circuit begins or ends and use a SPDT, or 2) use a DPDT somewhere in the middle. Look at the middle one on this page:

The way they go to more than three way is to simply add switches like the one in the middle wherever they need them. You see this in hallways sometimes where several bedrooms have exits. That way each bedroom can turn on the hall lights.

So, it all depends on your wiring. The way you get a DPDT relay when you can only find SPDT, is to just use two of them side by side. Clever right? Notice I didn't say cheap. Heck, you can even use solid state relays that way if you want silent operation. Clever arrangement of SSRs can emulate any kind of relay you want, but you'll pay a bunch of money for the experience.

One thing you can do if you want to consider it is to use the flash memory on the arduino to save the state each time it changes, then on boot, before you do anything else, read the state from the flash and set the relay(s) accordingly. I do this with my thermostats. I save the various settings in flash, then when the power comes back on after a failure, i read the flash and set temp, mode (cooling, heating), and fan setting based on the last time they were changed. Sure this will wear the flash memory out over time, so in 2075 or so you might have to think about it a bit. That way you can get away without using latching relays. Besides, it'll be fun to do.

Regarding your ideas:

Nicely done, but you will get killed by details when you start compiling and trying this. First, you don't need to hold the current state of the switch, simply read the I/O pin to find out what it really is whenever you want. Keeping states of things like this always leads me to screwing up and not updating it somewhere, so just read the pin to see what it's doing.

Enable the ethernet board before ethernet.begin. Why are you using an SD card? If you don't need it, just leave it turned off; it'll make the code easier to understand when you're trying to debug it.

Put in some commands to try the switch out from the IDE terminal emulator. You have no idea how useful it is to be able to manipulate various controls from the command line when you're trying to make it work. Put in a lot of print statements to tell you what is going on. You'll need them when the light stays on despite the web page being decoded properly. You don't have to get fancy with it, just looking for a 't' for toggle will save you a ton of time debugging.

An interesting way to toggle the pin for a relay is to use the input from the pin as a guide for setting the pin as in:

digitalWrite( digitalRead(thePin) ^ 1);

This will toggle the pin from one state to another and you can then digitalRead(thePin) anywhere in the code to see what state it's in if you need to. However with your setup and wanting only to flip the state, you may not need to.

You don't want to get fancy with HTML on an arduino. Remember, you have to decode the incoming all by yourself with no fancy language or huge libraries to help you. When you parse the incoming, you want it to be as simple as possible. Consider something like:

href="http://xxx.xxx.xxx.xxx/14"

Then in the arduino code, just look for the 14. The ? to show arguments and & between arguments with named pairs is something for python, php, javascript, etc; not for a little arduino. If you want to get fancy with POST vs GET discussions, you'll run out of memory or patience. Just stick with a GET, and let the spot where the file goes (14 in the example above) can be whatever you want. Suppose you sent:

href="http://xxx.xxx.xxx.xxx/toggle14"

Then parse for "toggle" and grab the two numbers after it for which one. There's about a jillion ways to do this, so make it simple at first. Once you get it running, you can expand it to be as versatile as you have time for.

Thanks...hopefully almost there now....I'm certainly understanding each line of my draft sketch a lot better the more I analyse it!

I've amended to the following which is hopefully a lot simpler, and acts on some of draythomp's comments / suggestions:

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


boolean reading = false

// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ   20

// put your ethernet variables (mac, ip) here
// 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,160);						// Internally the Arduino is set to this IP.

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);						//Arduino operating on Port80 - will come in useful later for when externally accessing through port forwarding.


char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer


Serial.begin(9600);


for (int switchpin = 11; switchpin < 53; switchpin++); 
Serial.print("Pins 11 to 53 activated");




void setup()
{




 
   // set up w5100
   Ethernet.begin(mac,ip);
   Serial.println("Ethernet service started successfully");


   // rest of your setup
   Serial.println("Setup complete");


	
   pinMode(switchpin, OUTPUT);
   Serial.println("All pins set to OUTPUT initially")

	

}


	


void loop(){

  // listen for incoming clients, and process request.
  checkForClient();
  


}




void checkForClient(){


EthernetClient client = server.available();
Serial.println("Server now activated and available");


  if (client) {

    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    boolean sentHeader = false;

    while (client.connected()) {
      if (client.available()) {

        if(!sentHeader){
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          sentHeader = true;

	  Serial.println("HTML test response header successfully sent");



        }

        char switchinstruction = client.read();

        if(reading && switchinstruction == ' ') reading = false;
        if(switchinstruction == '?') reading = true; //found the ?, begin reading the info

        if(reading){
          	Serial.println("Instruction received over HTTP......");
		Serial.print("toggle pin ");
		Serial.print(switchinstruction);


	if (Serial.available() > 0) {
    	int switchinstruction = Serial.print();


	
    switch (switchinstruction) {
    case '11':    
      digitalWrite(digitalRead(11)^1);
      Serial.println("Pin 11 successfully toggled")
      break;
    case '12':    
      digitalWrite(digitalRead(12)^1);
      Serial.println("Pin 12 successfully toggled")
      break;
    case '13':    
      digitalWrite(digitalRead(13)^1);
      Serial.println("Pin 13 successfully toggled")
      break;
    case '14':    
      digitalWrite(digitalRead(14)^1);
      Serial.println("Pin 14 successfully toggled")
      break;
    case '15':    
      digitalWrite(digitalRead(15)^1);
      Serial.println("Pin 15 successfully toggled")
      break;



          }

        }

        if (switchinstruction == '\n' && currentLineIsBlank)  break;

        if (switchinstruction == '\n') {
          currentLineIsBlank = true;
        }else if (switchinstruction != '\r') {
          currentLineIsBlank = false;
        }

      }
    }

    delay(1); // give the web browser time to receive the data
    client.stop(); // close the connection:
    Serial.println("HTTP request received and completed - Stopped listening for HTTP requests").

  } 

}

}


///...above example assumes using pins 11 to 15 for the time being only, but can continue the above line sequences so that I cover all the pins I'm using

	

{

Points to note:

  1. I've changed things around, but I'm not sure I'm enabling the ethernet board before I ethernet.begin as draythomp suggested?

  2. I've removed the SD card stuff, as it's true I'm not using this (neither do I plan to - my website was initially run off this and then I realised it's way too slow and unreliable to read a weighty / GUI heavy website such as mine)

  3. I'm not sure if there are any commands in to "switch out from the IDE terminal emulator"? I'm quite used to messing around with Raspberry Pi's and SSH'ing into these with Putty - I assume you are suggesting the same here but sending the "?14" instruction over Putty? If so, can I not just log into the Arduino at the appropriate IP/port with Putty and then type this instruction into the command line to activate the switch? In that case, I'm not sure if I need to include anything more in the sketch to facilitate this?

  4. I've put in as many Serial.print and Serial.println statements as possible - as draythomp has suggested if (I mean when) something breaks this will hopefully allow me to debug easier by seeing which line of code it is which has errored.

  5. I've got rid of trying to store the previous/existing pin state in a variable called "pinstate) - instead I'm using the digitalWrite(digitalRead(14)^1) action instead which hopefully I'm implemented correctly and will do a better job. Note I've also removed any references to the "pinstate" which I was using in my previous draft sketch but no longer need.

  6. I've kept the ? in the arduino code as the point at which the arduino knows to start reading the instruction, and therefore kept my proposed HTML button coding.....

<a href="http://xxx.xxx.xxx.xxx:80/?14" class="button special">ON / OFF</a>

....the same too. I've not done this as I want to start using PHP or Python (both still alien languages to me), but rather because if I later want to switch two pins at the same time, I'm guessing retaining the ? would also allow me to use a "&" as follows to achieve this (switching pin 14 and pin15 at the same time):

<a href="http://xxx.xxx.xxx.xxx:80/?14&15" class="button special">ON / OFF</a>

So...........overall, is this likely to work if I upload the sketch to the arduino / button code to the website? Any more suggestions / corrections of my errors much appreciated.

I'll try this as soon as I get home from work tomorrow!

I'll try this as soon as I get home from work tomorrow!

I suggest you try compiling your code before posting.

  1. I'm not sure if there are any commands in to "switch out from the IDE terminal emulator"? I'm quite used to messing around with Raspberry Pi's and SSH'ing into these with Putty - I assume you are suggesting the same here but sending the "?14" instruction over Putty? If so, can I not just log into the Arduino at the appropriate IP/port with Putty and then type this instruction into the command line to activate the switch? In that case, I'm not sure if I need to include anything more in the sketch to facilitate this?

I wasn't clear enough. In the terminal, in the IDE (which is what you use to compile it), you can type something in and send it to the board through the serial port. This is where you want to put commands to make things happen.

So, put it together, compile it, fix the compile errors, and shove it out to a board and start trying things. Then a whole lot of what folk have suggested will make more sense to you.

Oh,, and don't even think this is like a raspberry pi, this little guy has a lot of I/O possibilities that you just can't get on the Pi. The Pi's a nice board, I have several, but the arduino is a really great little controller for lots of jobs around my house.

Last tweaks now I think - I managed to get rid of all compile errors except the following

FINAL_SKETCH.ino: In function 'void checkForClient()':
FINAL_SKETCH:94: error: 'switchpin14' was not declared in this scope
FINAL_SKETCH:99: error: 'switchpin15' was not declared in this scope
FINAL_SKETCH:104: error: 'switchpin16' was not declared in this scope

My final sketch is as follows:

#include <Ethernet.h>
#include <SPI.h>
boolean reading = false;

// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ   20
////////////////////////////////////////////////////////////////////////
//CONFIGURE
////////////////////////////////////////////////////////////////////////
  byte ip[] = { 192, 168, 0, 160 };   //ip address to assign the arduino
  

  // if need to change the MAC address (Very Rare)
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

  EthernetServer server = EthernetServer(80); //port 80
////////////////////////////////////////////////////////////////////////

char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer



void setup(){

  Serial.begin(9600);

  //Pins 10,11,12 & 13 are used by the ethernet shield

int switchpin14 = 14;
int switchpin15 = 15;
int switchpin16 = 16;
Serial.print("Pins 14 to 53 activated");
Serial.println("All pins set to OUTPUT initially");

  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);


Ethernet.begin(mac, ip);
server.begin();
Serial.println("Ethernet service started successfully");
  
// rest of your setup
Serial.println("Setup complete");
  
  
}

void loop(){

  // listen for incoming clients, and process qequest.
  checkForClient();

}

void checkForClient(){

  EthernetClient client = server.available();
  Serial.println("Server now activated and available");
  
  if (client) {

    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    boolean sentHeader = false;

    while (client.connected()) {
      if (client.available()) {

        if(!sentHeader){
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          sentHeader = true;
          
          Serial.println("HTML test response header successfully sent");
          
        }

        char switchinstruction = client.read();

        if(reading && switchinstruction == ' ') reading = false;
        if(switchinstruction == '?') reading = true; //found the ?, begin reading the info

        if(reading){
          Serial.print(switchinstruction);

           switch (switchinstruction) {
            case '14':
              //toggle pin 14
              digitalWrite(digitalRead(switchpin14)^1);
              Serial.println("Pin 14 successfully toggled");
              break;
            case '15':
              //toggle pin 15
              digitalWrite(digitalRead(switchpin15)^1);
              Serial.println("Pin 15 successfully toggled");
              break;
            case '16':
              //toggle pin 16
              digitalWrite(digitalRead(switchpin16)^1);
              Serial.println("Pin 16 successfully toggled");
              break;

          }

        }

        if (switchinstruction == '\n' && currentLineIsBlank)  break;

        if (switchinstruction == '\n') {
          currentLineIsBlank = true;
        }else if (switchinstruction != '\r') {
          currentLineIsBlank = false;
        }

      }
    }

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

  } 

}

Could someone help me get rid of this last error please (it's the same error I believe for each of pin14/15/ and 16).

The error doesn't make sense to me as I've definitely declared all the switchpin names in the void setup() part of the scope, as follows (and made sure I've checked for silly obvious mistakes like spelling things wrong):

int switchpin14 = 14;
int switchpin15 = 15;
int switchpin16 = 16;
Serial.print("Pins 14 to 53 activated");
Serial.println("All pins set to OUTPUT initially");

  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);

You defined them inside the routine setup(), but used them outside that routine. Variables defined inside a routine only exists inside it. If you want to use them in other places, move the definition outside all routines.

Take a look at 'c++ scope of variables'. It's useful, but can drive you a bit nuts sometimes.

Thanks to everyone on this forum - I finally got this working....almost perfectly!

After battling with variations of the sketch I posted previously and not being able to get it work, I ended up poaching the code from another sketch I found on another website http://forum.bildr.org/viewtopic.php?f=29&t=416, and modifying slightly to get the following:

#include <Ethernet.h>
#include <SPI.h>
boolean reading = false;

////////////////////////////////////////////////////////////////////////
//CONFIGURE
////////////////////////////////////////////////////////////////////////
  byte ip[] = { 192, 168, 0, 160 };   //ip address to assign the arduino
  byte gateway[] = { 192, 168, 0, 1 }; //ip address of the gatewa or router

  //Rarly need to change this
  byte subnet[] = { 255, 255, 255, 0 };

  // if need to change the MAC address (Very Rare)
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

  EthernetServer server = EthernetServer(80); //port 80
////////////////////////////////////////////////////////////////////////

void setup(){
  //Pins 10,11,12 & 13 are used by the ethernet shield

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

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

void loop(){

  // listen for incoming clients, and process qequest.
  checkForClient();

}

void checkForClient(){

  EthernetClient client = server.available();

  if (client) {

    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    boolean sentHeader = false;

    while (client.connected()) {
      if (client.available()) {

        if(!sentHeader){
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          sentHeader = true;
        }

        char c = client.read();

        if(reading && c == ' ') reading = false;
        if(c == '?') reading = true; //found the ?, begin reading the info

        if(reading){
          Serial.print(c);

           switch (c) {
            case '2':
              //add code here to trigger on 2
              triggerPin(2, client);
              break;
            case '3':
            //add code here to trigger on 3
              triggerPin(3, client);
              break;
            case '4':
            //add code here to trigger on 4
              triggerPin(4, client);
              break;
            case '5':
            //add code here to trigger on 5
              triggerPin(5, client);
              break;
            case '6':
            //add code here to trigger on 6
              triggerPin(6, client);
              break;
            case '7':
            //add code here to trigger on 7
              triggerPin(7, client);
              break;
            case '8':
            //add code here to trigger on 8
              triggerPin(8, client);
              break;
            case '9':
            //add code here to trigger on 9
              triggerPin(9, client);
              break;
          }

        }

        if (c == '\n' && currentLineIsBlank)  break;

        if (c == '\n') {
          currentLineIsBlank = true;
        }else if (c != '\r') {
          currentLineIsBlank = false;
        }

      }
    }

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

  } 

}

void triggerPin(int pin, EthernetClient client){
//blink a pin - Client needed just for HTML output purposes.  
  client.print("Toggling pin ");
  client.println(pin);
  client.print("
");

  
  digitalWrite(pin, !digitalRead(pin));  // toggle state

}

This works fine as long as I use any of pins 2 to 9. If I even try to put a break case in for anything higher (I tried 15 as I know 10 to 14 are blocked out by the Ethernet shield) the sketch won't even compile.

Any idea how I can extend this to operate pins with two digits?

From my limited understanding of the code, it looks like the Arduino is only monitoring for the first character after the "?", and then acts on this. I can also tell this is the case as if I issue the command http://192.168.0.160/?23 it toggles pins 2 and 3, rather than pin 23?

I'm really sorry about the endless questions - I guess one upside of me struggling so much with this (and it being my first sketch) is that I'm certainly learning a lot, and quickly!

indergod:
Any idea how I can extend this to operate pins with two digits?

It's OK, I got it all sorted this evening - forgot that there are 128 ASCII characters, not only 9!

Thanks to everyone who helped me along. Special thanks to zoomkat and draythomp :slight_smile:

forgot that there are 128 ASCII characters, not only 9!

You can have many multi character identifiers like below using conditional "if" statements;

          ///////////////////// control arduino pin
          if(readString.indexOf("on1") >0)//checks for on1 in captured readString
          {
            digitalWrite(4, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(4, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

A bit late to this discussion, but I had designed a solution for this which I think is different to those discussed so far.
Problem: existing light controlled by two or more switches
need to add remote control.

i) remove mains power from the existing light switches and supply 5V instead and move the lead from the light to an Arduino input.
ii) check input for change in state either Low to High or High to Low (as the exiting light switches are switched)
iii) which each change in state toggle the relay powering the light. So any flick of any existing switch will change the light.
iv) via remote connection have button to also toggle the relay. (Display the current state on the button when you connect)

Finally save the current state of the relay in EEPROM each time so that after loss of power the light comes back in the same state as before the power failure

Instead of HTML I would use pfodApp (www.pfod.com.au) for control from an Android mobile. There is a pfodDesigner that builds the menu for you and writes the Arduino code.
But that would not suit if you must have a computer web page control.