Arduino Web Server Gauge Displaying Analog Value

Created on: 28 March 2013

Part 15 of the Arduino Ethernet Shield Web Server Tutorial

A gauge component is used to display the analog value from one of the Arduino's analog pins on a web page. The dial gauge is updated using Ajax.

The gauge is written in JavaScript and uses the HTML5 canvas. The gauge is used as a component (unmodified) and is simply set up to display the analog value of one of the Arduino analog pins. The value is updated every 200ms.

This video shows the gauge on the web page that is hosted by the Arduino web server.

Getting the Gauge Component

The gauge component is written by Mykhailo Stadnyk and can be downloaded from Mikhus at github. Also see a blog article on the gauge.

The JavaScript code from the file gauge.min.js (downloaded from the above github link) was used on the web page in this part of the tutorial.

Arduino Sketch and Web Page

Arduino Sketch

The Arduino sketch for this part of the tutorial is shown here.

/*--------------------------------------------------------------
  Program:      eth_websrv_SD_Ajax_gauge

  Description:  Arduino web server web page displays Arduino
                analog value on a dial gauge.
                The web page is stored on the SD card.
                Ajax is used to update the analog value on the
                web page.
  
  Hardware:     Arduino Uno and official Arduino Ethernet
                shield. Should work with other Arduinos and
                compatible Ethernet shields.
                2Gb micro SD card formatted FAT16.
                Potentiometer interfaced to A2 analog input.
                
  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
                - Gauge from:
                  https://github.com/Mikhus/canv-gauge

  Date:         27 March 2013
  Modified:     19 June 2013
 
  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   50

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

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.");
    
    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");
                    // 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();
                        // 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)
}

// send the XML file containing analog value
void XML_response(EthernetClient cl)
{
    int analog_val;
    
    cl.print("<?xml version = \"1.0\" ?>");
    cl.print("<inputs>");
    // read analog pin A2
    analog_val = analogRead(2);
    cl.print("<analog>");
    cl.print(analog_val);
    cl.print("</analog>");
    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;
}

This sketch is a slightly modified version of the sketch from the previous part of this tutorial (part 14).

The sketch sends a single analog value from Arduino pin A2 to the web browser which is then fed to the dial on the web page. The analog value is updated on the web page using Ajax and the value is sent as part of an XML file from the Arduino.

The web page hosted by the Arduino web server is stored on a micro SD card on the Arduino Ethernet shield.

Web Page

The web page for this example is shown here.

Gauge web page
The Web Page for Displaying the Gauge with Gauge Code Cut Off – click for a bigger image

The web page is a modified version of the web page used in the previous part of this tutorial.

The Gauge

The gauge is made available to the web page by inserting the gauge code between the script tags in the head of the web page HTML code.

The gauge is displayed by using the HTML5 canvas tag in the body of the HTML.

Updating the Gauge

The analog value from the Arduino is received in the same way as it was in the previous part of this tutorial and displayed at the top of the web page in the same way as the previous part of this tutorial. The analog value is also saved to the JavaScript variable data_val so that it can be used by the gauge.

The value in data_val is fed to the gauge by using the line of JavaScript in the data-onready property of the canvas tag:

setInterval( function() { Gauge.Collection.get('an_gauge_1').setValue(data_val);}, 200);

The 200 in the above line tells the gauge to update every 200ms (200 milliseconds).

Timing

The gauge updates every 200ms, and the Ajax request for an analog value is also set to 200ms.

The timing for the Ajax refresh of the analog data is done in this line of JavaScript code from the web page:

setTimeout('GetArduinoInputs()', 200);

This refresh rate may cause a problem on a busy or slow network. If there are any problems, try changing this value to 1000 to make the analog value refresh every second.

Running the Gauge Sketch

Wire up the potentiometer as shown in the circuit diagram of part 9 of this tutorial – leave the push buttons shown in the diagram off, they will not be used.

Copy the web page (index.htm) to a micro SD card and insert it into the card slot of the Arduino Ethernet shield.

Load the above sketch to the Arduino web server. The web page is available for download below.

Web Page Source Code

Download the web page source code (index.htm) for this part of the tutorial here:

Arduino_web_gauge.zip (6.3 kB)

The license for the gauge is included in the download as a text file.