Arduino Ethernet Shield - part 5

 

Arduino Web Server LED Control

Created on: 29 January 2013

Part 5 of the Arduino Ethernet Shield Web Server Tutorial

In this part of the tutorial, the Arduino and Ethernet shield serves up a web page that allows an LED to be switched on and off. The LED is connected to one of the Arduino pins – this simple circuit can be built on a breadboard.

This video shows the LED being controlled from the web page:

Arduino Web Server LED Controller Hardware

The LED is interfaced to the Arduino as shown in the circuit diagram in the Starting with Arduino tutorial. It is simply an LED and series resistor connected between Arduino pin 2 and GND.

An SD card is not used in this web server.

The hardware is shown in the image below.

Hardware for the Arduino web server LED controller
LED Web Server Hardware

How the LED is Controlled

Web Page and HTML

Web Page and HTML Code with Checkbox Unchecked

The Arduino web server serves up a page that allows the user to click a check box to switch the LED on and off. The web page is shown here:

LED Web Server Web Page
LED Web Server Web Page - Checkbox Unchecked

The HTML code that the Arduino web server sends to the web browser is shown below.

LED Web Server Web Page HTML Code
LED Web Server Web Page HTML Code - Checkbox Unchecked

Web Page and HTML Code with Checkbox Checked

After clicking the checkbox to switch the LED on, the web page and HTML code now look as follows:

LED Web Page with Checkbox Checked
LED Web Page with Checkbox Checked

Take note in the above image that the web browser added /?LED2=2 to the end of the URL field after the checkbox was clicked.

LED Web Page HTML Code with Checkbox Checked
LED Web Page HTML Code with Checkbox Checked

In the above image, the Arduino changed the HTML page that it sent to the browser so that the checkbox will be shown with a check mark in it. The change to the code is highlighted in the image and it can be seen that checked was added.

New HTML Tags

Two new HTML tags are introduced in the above HTML code, namely <form> and <input>.

HTML <form> Tag

A form tag contains form controls, such as the checkbox used in this example. In this form, method="get" in the opening form tag will result in the form being submitted using an HTTP GET request. This also results in the /?LED2=2 text being added in the URL field of the web browser.

HTML <input> Tag

A single control is added to the HTML form using the <input> tag. The input tag does not have a corresponding closing tag.

In this example, the input tag is used to create a checkbox. The following fields are included in the input tag:

  • type="checkbox" – displays this input control as a checkbox
  • name="LED2" – user defined name of the control
  • value="2" – user defined value of the control
  • onclick="submit();" – submit the form when the checkbox control is clicked
  • checked – when present the checkbox is checked, otherwise it is blank

HTTP Request and Response

When the checkbox is clicked, it will generate an HTTP GET request that sends the name and value from the checkbox to the Arduino server.

The following is an example of an HTTP request sent from the Firefox browser to the Arduino server after clicking the checkbox:

GET /?LED2=2 HTTP/1.1
Host: 10.0.0.20
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-ZA,en-GB;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://10.0.0.20/
Connection: keep-alive

When unchecking the checkbox, the following HTTP request is sent from the browser to the Arduino web server:

GET / HTTP/1.1
Host: 10.0.0.20
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-ZA,en-GB;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://10.0.0.20/?LED2=2
Connection: keep-alive

The Arduino sketch in this example reads the HTTP request header and checks for the text LED2=2 and if found, the Arduino will toggle the LED from off to on or on to off.

Both of the above requests contain the LED2=2 text although in different places. When checking the box, the text is part of the GET request line. When unchecking the box, the text is part of the Referer: header.

With this background information, we can now see how the Arduino sketch works.

LED Web Server Sketch

The Arduino sketch for the LED web server is shown below.

/*--------------------------------------------------------------
  Program:      eth_websrv_LED

  Description:  Arduino web server that serves up a web page
                allowing the user to control an LED
  
  Hardware:     - Arduino Uno and official Arduino Ethernet
                  shield. Should work with other Arduinos and
                  compatible Ethernet shields.
                - LED and resistor in series connected between
                  Arduino pin 2 and GND
                
  Software:     Developed using Arduino 1.0.3 software
                Should be compatible with Arduino 1.0 +
  
  References:   - WebServer example by David A. Mellis and 
                  modified by Tom Igoe
                - Ethernet library documentation:
                  http://arduino.cc/en/Reference/Ethernet

  Date:         11 January 2013
 
  Author:       W.A. Smith, http://startingelectronics.org
--------------------------------------------------------------*/

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

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 0, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

String HTTP_req;          // stores the HTTP request
boolean LED_status = 0;   // state of LED, off by default

void setup()
{
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for diagnostics
    pinMode(2, OUTPUT);       // LED on pin 2
}

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
                HTTP_req += c;  // save the HTTP request 1 char at a time
                // 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");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send web page
                    client.println("<!DOCTYPE html>");
                    client.println("<html>");
                    client.println("<head>");
                    client.println("<title>Arduino LED Control</title>");
                    client.println("</head>");
                    client.println("<body>");
                    client.println("<h1>LED</h1>");
                    client.println("<p>Click to switch LED on and off.</p>");
                    client.println("<form method=\"get\">");
                    ProcessCheckbox(client);
                    client.println("</form>");
                    client.println("</body>");
                    client.println("</html>");
                    Serial.print(HTTP_req);
                    HTTP_req = "";    // finished with request, empty string
                    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)
}

// switch LED and send back HTML for LED checkbox
void ProcessCheckbox(EthernetClient cl)
{
    if (HTTP_req.indexOf("LED2=2") > -1) {  // see if checkbox was clicked
        // the checkbox was clicked, toggle the LED
        if (LED_status) {
            LED_status = 0;
        }
        else {
            LED_status = 1;
        }
    }
    
    if (LED_status) {    // switch LED on
        digitalWrite(2, HIGH);
        // checkbox is checked
        cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \
        onclick=\"submit();\" checked>LED2");
    }
    else {              // switch LED off
        digitalWrite(2, LOW);
        // checkbox is unchecked
        cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \
        onclick=\"submit();\">LED2");
    }
}

Modification to Sketch

This sketch is a modified version of the eth_websrv_page sketch from the basic Arduino web server.

The sketch creates the HTML page as usual, but calls the ProcessCheckbox() function to take care of the line that draws the checkbox.

The ProcessCheckbox() function checks to see if the HTTP request contains the text LED2=2. If the HTTP request does contain this text, then the LED will be toggled (switched from on to off or from off to on) and the web page is sent again with the checkbox control also toggled to reflect the state of the LED.

Improvements

The sketch has been kept simple for learning purposes, but some improvements can be made to this sketch to make it more reliable.

The sketch currently only checks for the presence of the text LED2=2 in the HTTP request to see if the checkbox was clicked. It would be more reliable to check where the LED2=2 text is in the HTTP message to determine whether the checkbox is being checked or unchecked. This would then make it impossible for the state of the LED and the state of the checkbox to become unsynchronized.

Comentários

Postagens mais visitadas