Home Articles Arduino → Switch And Web Page Button LED Control

Controlling an LED from an Arduino Web Page Button and a Push Button

Created on: 13 April 2015

How to control an LED from a web page using an Arduino Uno and Arduino ethernet shield. How to read a push button switch with an Arduino Uno and change the state of an LED, as well as show the state of the LED on a web page using an Arduino Uno and Arduino ethernet shield. This Arduino breadboard project uses an Arduino Uno and Arduino Ethernet shield with SD card as a web server. Two push button switches and two LEDs are connected to the Arduino.

The web page that the Arduino web server hosts allows one LED to be controlled by a checkbox and the other LED to be controlled by a HTML button on the web page.

(追記) (追記ここまで)

The same two LEDs are also controlled by two push button switches. When a LED is switched on or off from the web page, the state of the LED can be seen in the checkbox or in the text of the button.

The checkbox and the text in the button are also updated if the physical hardware push buttons are pressed to switch the LEDs on or off. Ajax is used on the web page so that updates on the page are free of any flicker.

The video below shows the circuit being operated from the web browser on an Android phone connected to the network via WiFi. A browser on a PC connected to the network via WiFi or cable will also work.

Arduino Uno and Ethernet Shield Circuit Diagram with LEDs and Switches

The connections of the push button switches and LEDs are shown in the circuit diagram below.

[画像:Arduino Web Server Switch and LED Connections]
Arduino Web Server Switch and LED Connections

The hardware consists of two momentary tactile push button switches and two LEDs connected to the Arduino with Ethernet Shield. The switches have pull-down resistors with values of 10kΩ each and the LEDs have current limiting resistors with values of 470Ω each.

Arduino Code and HTML Page

Download the zipped code here or copy and paste from below.

Arduino sketch and HTML page zipped: web_server_hw_button_pg_button.zip (4.8kB)

Arduino Sketch

The Arduino sketch consists of a modified version of the code from the Arduino web server tutorial part 16 on web server Ajax I/O.

/*--------------------------------------------------------------
 Program:   web_server_hw_button_pg_button
 Description: Arduino web server that allows two LEDs to be
        controlled by a checkbox, HTML button and two
        hardware push buttons.
        The web page is stored on the micro SD card.

 Hardware:   Arduino Uno and official Arduino Ethernet
        shield. Should work with other Arduinos and
        compatible Ethernet shields.
        2Gb micro SD card formatted FAT16.
        LEDs on pins 6 and 7.
        Switches on pins 2 and 3.

 Software:   Developed using Arduino 1.6.1 software
        Should be compatible with Arduino 1.0 +
        SD card contains web page called index.htm

 References:  - Based on Ajax I/O example from Starting
         Electronics:
         http://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/SD-card-IO/

        - Switch debouncing from Arduino IDE example code
         File --> Examples --> 02.Digital --> Debounce
         http://www.arduino.cc/en/Tutorial/Debounce
 Date:     13 April 2015

 Author:    W.A. Smith, http://startingelectronics.org
--------------------------------------------------------------*/
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ  60
// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
File webFile; // the web page file on the SD card
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
boolean LED_state[2] = {0}; // stores the states of the LEDs
void setup()
{
  // disable Ethernet chip
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  
  Serial.begin(9600); // for debugging
  
  // initialize SD card
  Serial.println("Initializing SD card...");
  if (!SD.begin(4)) {
    Serial.println("ERROR - SD card initialization failed!");
    return; // init failed
  }
  Serial.println("SUCCESS - SD card initialized.");
  // check for index.htm file
  if (!SD.exists("index.htm")) {
    Serial.println("ERROR - Can't find index.htm file!");
    return; // can't find index file
  }
  Serial.println("SUCCESS - Found index.htm file.");
  // switches
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  // LEDs
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  
  Ethernet.begin(mac, ip); // initialize Ethernet device
  server.begin(); // start to listen for clients
}
void loop()
{
  EthernetClient client = server.available(); // try to get client
  if (client) { // got client?
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) { // client data available to read
        char c = client.read(); // read 1 byte (character) from client
        // limit the size of the stored received HTTP request
        // buffer first part of HTTP request in HTTP_req array (string)
        // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
        if (req_index < (REQ_BUF_SZ - 1)) {
          HTTP_req[req_index] = c;     // save HTTP request character
          req_index++;
        }
        // last line of client request is blank and ends with \n
        // respond to client only after last line received
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          // remainder of header follows below, depending on if
          // web page or XML page is requested
          // Ajax request - send XML file
          if (StrContains(HTTP_req, "ajax_inputs")) {
            // send rest of HTTP header
            client.println("Content-Type: text/xml");
            client.println("Connection: keep-alive");
            client.println();
            SetLEDs();
            // send XML file containing input states
            XML_response(client);
          }
          else { // web page request
            // send rest of HTTP header
            client.println("Content-Type: text/html");
            client.println("Connection: keep-alive");
            client.println();
            // send web page
            webFile = SD.open("index.htm"); // open web page file
            if (webFile) {
              while(webFile.available()) {
                client.write(webFile.read()); // send web page to client
              }
              webFile.close();
            }
          }
          // display received HTTP request on serial port
          Serial.print(HTTP_req);
          // reset buffer index and all buffer elements to 0
          req_index = 0;
          StrClear(HTTP_req, REQ_BUF_SZ);
          break;
        }
        // every line of text received from the client ends with \r\n
        if (c == '\n') {
          // last character on line of received text
          // starting new line with next character read
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // a text character was received from client
          currentLineIsBlank = false;
        }
      } // end if (client.available())
    } // end while (client.connected())
    delay(1); // give the web browser time to receive the data
    client.stop(); // close the connection
  } // end if (client)
  
  // read buttons and debounce
  ButtonDebounce();
}
// function reads the push button switch states, debounces and latches the LED states
// toggles the LED states on each push - release cycle
// hard coded to debounce two switches on pins 2 and 3; and two LEDs on pins 6 and 7
// function adapted from Arduino IDE built-in example:
// File --> Examples --> 02.Digital --> Debounce
void ButtonDebounce(void)
{
  static byte buttonState[2] = {LOW, LOW}; // the current reading from the input pin
  static byte lastButtonState[2] = {LOW, LOW}; // the previous reading from the input pin
  
  // the following variables are long's because the time, measured in miliseconds,
  // will quickly become a bigger number than can be stored in an int.
  static long lastDebounceTime[2] = {0}; // the last time the output pin was toggled
  long debounceDelay = 50; // the debounce time; increase if the output flickers
 
  byte reading[2];
  
  reading[0] = digitalRead(2);
  reading[1] = digitalRead(3);
  
  for (int i = 0; i < 2; i++) {
    if (reading[i] != lastButtonState[i]) {
      // reset the debouncing timer
      lastDebounceTime[i] = millis();
    }
   
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      // whatever the reading is at, it's been there for longer
      // than the debounce delay, so take it as the actual current state:
    
      // if the button state has changed:
      if (reading[i] != buttonState[i]) {
        buttonState[i] = reading[i];
     
        // only toggle the LED if the new button state is HIGH
        if (buttonState[i] == HIGH) {
          LED_state[i] = !LED_state[i];
        }
      }
    }
  } // end for() loop
  
  // set the LEDs
  digitalWrite(6, LED_state[0]);
  digitalWrite(7, LED_state[1]);
   
  // save the reading. Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState[0] = reading[0];
  lastButtonState[1] = reading[1];
}
// checks if received HTTP request is switching on/off LEDs
// also saves the state of the LEDs
void SetLEDs(void)
{
  // LED 1 (pin 6)
  if (StrContains(HTTP_req, "LED1=1")) {
    LED_state[0] = 1; // save LED state
    digitalWrite(6, HIGH);
  }
  else if (StrContains(HTTP_req, "LED1=0")) {
    LED_state[0] = 0; // save LED state
    digitalWrite(6, LOW);
  }
  // LED 2 (pin 7)
  if (StrContains(HTTP_req, "LED2=1")) {
    LED_state[1] = 1; // save LED state
    digitalWrite(7, HIGH);
  }
  else if (StrContains(HTTP_req, "LED2=0")) {
    LED_state[1] = 0; // save LED state
    digitalWrite(7, LOW);
  }
}
// send the XML file with analog values, switch status
// and LED status
void XML_response(EthernetClient cl)
{
  int analog_val; // stores value read from analog inputs
  int count; // used by 'for' loops
  int sw_arr[] = {2, 3}; // pins interfaced to switches
  
  cl.print("<?xml version = \"1.0\" ?>");
  cl.print("<inputs>");
  // checkbox LED states
  // LED1
  cl.print("<LED>");
  if (LED_state[0]) {
    cl.print("checked");
  }
  else {
    cl.print("unchecked");
  }
  cl.println("</LED>");
  // button LED states
  // LED3
  cl.print("<LED>");
  if (LED_state[1]) {
    cl.print("on");
  }
  else {
    cl.print("off");
  }
  cl.println("</LED>");
  cl.print("</inputs>");
}
// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
  for (int i = 0; i < length; i++) {
    str[i] = 0;
  }
}
// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
  char found = 0;
  char index = 0;
  char len;
  len = strlen(str);
  
  if (strlen(sfind) > len) {
    return 0;
  }
  while (index < len) {
    if (str[index] == sfind[found]) {
      found++;
      if (strlen(sfind) == found) {
        return 1;
      }
    }
    else {
      found = 0;
    }
    index++;
  }
  return 0;
}

HTML Page with Embedded CSS and JavaScript

The code below must be copied to a file called index.htm and the index.htm file must be copied to a micro SD card that is to be inserted into the card slot on the Arduino shield.

The HTML code with embedded CSS and JavaScript consists of a modified version of the code from the Arduino web server tutorial part 16 on web server Ajax I/O.

<!DOCTYPE html>
<html>
 <head>
 <title>Arduino Ajax LED Button Control</title>
 <script>
 strLED1 = "";
 strLED2 = "";
 var LED2_state = 0;
 function GetArduinoIO()
 {
 nocache = "&nocache=" + Math.random() * 1000000;
 var request = new XMLHttpRequest();
 request.onreadystatechange = function()
 {
 if (this.readyState == 4) {
 if (this.status == 200) {
 if (this.responseXML != null) {
 // XML file received - contains analog values, switch values and LED states
 var count;
 // LED 1
 if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "checked") {
 document.LED_form.LED1.checked = true;
 }
 else {
 document.LED_form.LED1.checked = false;
 }
 // LED 2
 if (this.responseXML.getElementsByTagName('LED')[1].childNodes[0].nodeValue === "on") {
 document.getElementById("LED2").innerHTML = "LED 2 is ON (D7)";
 LED2_state = 1;
 }
 else {
 document.getElementById("LED2").innerHTML = "LED 2 is OFF (D7)";
 LED2_state = 0;
 }
 }
 }
 }
 }
 // send HTTP GET request with LEDs to switch on/off if any
 request.open("GET", "ajax_inputs" + strLED1 + strLED2 + nocache, true);
 request.send(null);
 setTimeout('GetArduinoIO()', 1000);
 strLED1 = "";
 strLED2 = "";
 }
 // service LEDs when checkbox checked/unchecked
 function GetCheck()
 {
 if (LED_form.LED1.checked) {
 strLED1 = "&LED1=1";
 }
 else {
 strLED1 = "&LED1=0";
 }
 }
 function GetButton1()
 {
 if (LED2_state === 1) {
 LED2_state = 0;
 strLED2 = "&LED2=0";
 }
 else {
 LED2_state = 1;
 strLED2 = "&LED2=1";
 }
 }
 </script>
 <style>
 .IO_box {
 float: left;
 margin: 0 20px 20px 0;
 border: 1px solid blue;
 padding: 0 5px 0 5px;
 width: 120px;
 }
 h1 {
 font-size: 120%;
 color: blue;
 margin: 0 0 10px 0;
 }
 h2 {
 font-size: 85%;
 color: #5734E6;
 margin: 5px 0 5px 0;
 }
 p, form, button {
 font-size: 80%;
 color: #252525;
 }
 .small_text {
 font-size: 70%;
 color: #737373;
 }
 </style>
 </head>
 <body onload="GetArduinoIO()">
 <h1>Arduino Ajax LED Button Control</h1>
 <div class="IO_box">
 <h2>LED Using Checkbox</h2>
 <form id="check_LEDs" name="LED_form">
 <input type="checkbox" name="LED1" value="0" onclick="GetCheck()" />LED 1 (D6)<br /><br />
 </form>
 </div>
 <div class="IO_box">
 <h2>LED Using Button</h2>
 <button type="button" id="LED2" onclick="GetButton1()">LED 2 is OFF (D7)</button><br /><br />
 </div>
 </body>
</html>

How the Code Works

Both the Arduino code and the HTML page were copied from part 16 of the Arduino web server tutorial and modified.

The Code was Cleaned Up

All unnecessary code for the analog inputs, extra checkboxes and buttons was removed from the HTML, JavaScript and Arduino code. The code that controls LED 2 was modified to use an HTML button.

At this stage, the two LEDs could be controlled by using a checkbox on the Arduino hosted web page for the first LED and a button on the HTML page for the second LED.

Adding the Physical Button Control Code

Nothing further had to be changed in the HTML/JavaScript for the hardware switches because the states of the LEDs was already being sent back to the web page using Ajax. Adding two physical push buttons to control the LEDs would update the stored states of the LEDs in the Arduino which would then be sent to the web page on the next Ajax request.

Switch Debouncing and Latching

Momentary push button switches do not latch. Pushing the button closes the circuit, releasing the button opens the circuit again – the contacts never stay closed, but always open when the button is released.

Buttons, switches and relays all have contact bounce. That is when the switch contacts are closed, they do not close cleanly and stay closed, but rather bounce for a small amount of time.

By bounce, we mean that they close initially, then bounce open, then closed again, then open and closed a few times before they settle. This bounce won't be perceived if the switch is used in a circuit that directly switches a light on, but will be detected by a microcontroller that is running at many megahertz.

The switches can be "debounced" using software that waits for the switch contacts to settle.

There is already some software in the Arduino IDE built-in examples that takes care of turning a momentary push button switch into a latching switch and debounces the switch contacts at the same time.

The example can be found from the Arduino IDE menu: File → Examples → 02.Digital → Debounce

When this code example is loaded to the Arduino, pushing and releasing the push button switch once, switches an LED on. Pushing and releasing the push button switch a second time switches the LED off.

In the Arduino code for this project, the Arduino IDE Debounce example code is used in the function ButtonDebounce() to debounce and latch the two push button switches and toggle the LED states.

The code is modified to handle two push buttons and two LEDs by converting the variables in the code to two-dimensional arrays and using one element of the array per push button / LED pair.

Updating the LED States on the Web Page

The array LED_state[] holds the current states of the two LEDs and is modified by the ButtonDebounce() function. This same array is also modified by the checkbox and HTML button from the web page in the SetLEDs() function.

When either a physical push button is pressed, or the checkbox or HTML button is clicked on the web page, the state of the LED is updated in the LED_state[] array.

The next time that the web page does an Ajax request, the LED states in the LED_state[] array are used to update the XML file that is sent back to the web page when the XML_response() function is called.

This updates the checkbox to either checked or unchecked and the text in the HTML button to either ON or OFF.

(追記) (追記ここまで)

AltStyle によって変換されたページ (->オリジナル) /