Arduino Ethernet Shield - part 13

 

Arduino SD Card Ajax Web Server

Created on: 25 March 2013

Part 13 of the Arduino Ethernet Shield Web Server Tutorial

An Arduino Ethernet shield web server that hosts a web page on the SD card. The web page displays the status of a switch and uses Ajax to update the status of the switch.

In previous parts of this tutorial, an SD card hosted web page was never used to display the status of Arduino inputs – all the web pages displaying I/O were part of the Arduino sketch.

This part of the tutorial now displays an Arduino input on an SD card hosted web page.

Circuit Diagram

A switch is interfaced to pin 3 of the Arduino for this example.

Circuit Diagram of Switch Connected to Arduino Uno
Circuit Diagram of Switch Connected to Arduino Uno

Code and Web Page

The code (Arduino sketch) and web page for this part of the tutorial are basically a combination of part 4 (Arduino SD card web server) and part 8 (reading switch status automatically using Ajax) of this tutorial.

No video has been included with this tutorial as the output will look the same as part 8 of this tutorial, but with the title and heading text changed.

Web Page

The web page consisting of HTML and JavaScript (to implement Ajax) is shown below:

index.htm web page hosted on SD card
Web Page Hosted on SD Card (index.htm)

This web page is saved to the micro SD card as index.htm – it is basically the same HTML/JavaScript that was produced by the Arduino sketch in part 8 (reading switch status automatically using Ajax), but with the title and heading text changed.

Copy and paste the web page from the listing below.

<!DOCTYPE html>
<html>
    <head>
        <title>Arduino SD Card Web Page using Ajax</title>
        <script>
        function GetSwitchState()
        {
            nocache = "&nocache=" + Math.random() * 1000000;
            var request = new XMLHttpRequest();
            request.onreadystatechange = function()
            {
                if (this.readyState == 4) {
                    if (this.status == 200) {
                        if (this.responseText != null) {
                            document.getElementById("switch_txt").innerHTML = this.responseText;
                        }
                    }
                }
            }
            request.open("GET", "ajax_switch" + nocache, true);
            request.send(null);
            setTimeout('GetSwitchState()', 1000);
        }
    </script>
    </head>
    <body onload="GetSwitchState()">
        <h1>Arduino Switch State from SD Card Web Page using Ajax</h1>
        <p id="switch_txt">Switch state: Not requested...</p>
    </body>
</html>

Arduino Sketch

The Arduino sketch for this part of the tutorial is shown below. It requires the above HTML/JavaScript to be available on the micro SD card in the index.htm file.

/*--------------------------------------------------------------
  Program:      eth_websrv_SD_Ajax

  Description:  Arduino web server that serves up a web page
                that displays the status of a switch connected
                to pin 3 of the Arduino.
                The web page is stored on the SD card.
                The web page contains JavaScript code that uses
                Ajax to request the state of the switch every
                second.
  
  Hardware:     Arduino Uno and official Arduino Ethernet
                shield. Should work with other Arduinos and
                compatible Ethernet shields.
                2Gb micro SD card formatted FAT16
                Push button switch interfaced to pin 3 of the
                Arduino
                
  Software:     Developed using Arduino 1.0.5 software
                Should be compatible with Arduino 1.0 +
                SD card contains web page called index.htm
  
  References:   - WebServer example by David A. Mellis and 
                  modified by Tom Igoe
                - SD card examples by David A. Mellis and
                  Tom Igoe
                - Ethernet library documentation:
                  http://arduino.cc/en/Reference/Ethernet
                - SD Card library documentation:
                  http://arduino.cc/en/Reference/SD

  Date:         25 March 2013
  Modified:     17 June 2013
                - removed the use of the String class
 
  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   40

// 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;
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()
{
    // 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.");
    pinMode(3, INPUT);        // switch is attached to Arduino pin 3
    
    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
                // 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");
                    client.println("Content-Type: text/html");
                     client.println("Connection: keep-alive");
                    client.println();
                    // Ajax request
                    if (StrContains(HTTP_req, "ajax_switch")) {
                        // read switch state and send appropriate paragraph text
                        GetSwitchState(client);
                    }
                    else {  // web page request
                        // 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.println(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)
}

// send the state of the switch to the web browser
void GetSwitchState(EthernetClient cl)
{
    if (digitalRead(3)) {
        cl.println("Switch state: ON");
    }
    else {
        cl.println("Switch state: OFF");
    }
}

// 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;
}

How the Sketch Works

This sketch works in the same way as the sketch from part 8 (reading switch status automatically using Ajax), except that instead of sending the web page line by line from the Arduino sketch code, the web page is sent from the index.htm file on the SD card.

Because we are using Ajax, the web page (when loaded in the web browser) sends the same request for the switch status as the sketch in part 8 of this tutorial. If we were not using Ajax, then the Arduino would need to read the index.htm file from the SD card and modify the part that shows the switch status, then send back the whole web page with the modified part – depending on if the switch is on or off.

Comentários

Postagens mais visitadas