Arduino webserver guide. Part 13. Graphical indicator on a web page

From a translator. This part of the tutorial explains how to connect to the Arduino server pages and use Javascript components, in this case the indicator indicator component.

This opens up truly limitless possibilities for designing web pages: thousands of ready-made Javascript components are available for you to implement various functions and design web interfaces for your projects.


This part of the tutorial looks at creating a graphical indicator on a web page to display the status of one of the Arduino analog inputs. Indicator values ​​are updated using Ajax.

The indicator itself is written in JavaScript and uses HTML5 canvas. The indicator is used as a component (no change) and is simply configured to display the value of one of the Arduino’s analog inputs. The indicator values ​​are updated every 200ms.

This video shows the operation of the Arduino server and the indicator posted on the web page.

indicator component

The “HTML Canvas Gauges” indicator component can be downloaded from

Github

. You can also check out

article

(in English) which gives details of how to use the component.

This tutorial uses the Javascript code from the Gauge.min.js file (downloaded from the link above).

Arduino sketch and web page

Sketch Arduino

Arduino sketch for this tutorial:

/*--------------------------------------------------------------
  Скетч: eth_websrv_SD_Ajax_gauge

  Описание:  Arduino сервер с SD картой, динамически отображающий на графическом индикаторе состояние аналогового входа при помощи Ajax.

  Оборудование: контроллер Arduino Uno, плата Ethernet Shield, microSD карта памяти 2 ГБ, потенциометр, подключённый на пин A2.
                
  Программное обеспечение: среда разработки Arduino IDE, microSD карта с файлом index.htm
  
  Ссылки:
    - WebServer example by David A. Mellis and modified by Tom Igoe
    - Ethernet library documentation: http://arduino.cc/en/Reference/Ethernet
    - Learning PHP, MySQL & JavaScript by Robin Nixon, O'Reilly publishers
    - SD Card library documentation: http://arduino.cc/en/Reference/SD
    - Gauge from: https://github.com/Mikhus/canv-gauge
  
  Дата создания: 27 марта 2013
  Изменения: 19 июня 2013
 
  Author:       W.A. Smith, http://startingelectronics.org
--------------------------------------------------------------*/

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 20); // IP-адрес (нужно изменить на актуальный для вашей сети)
EthernetServer server(80);

#define REQ_BUF_SZ   50
char HTTP_req[REQ_BUF_SZ] = {0}; // Хранится как null terminated string
char req_index = 0; // индекс буфера

File webFile;

void setup() {
    // отключение Ethernet
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);

    Serial.begin(115200);
    
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;
    }
    Serial.println("SUCCESS - SD card initialized.");

    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;
    }
    Serial.println("SUCCESS - Found index.htm file.");
    
    Ethernet.begin(mac, ip);
    server.begin();
}

void loop() {
    EthernetClient client = server.available();

    if (client) {
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {
                char c = client.read();  // получаем очередной байт (символ) от клиента
                // сохраняем последний элемент массива 0 (null terminate string)
                if (req_index < (REQ_BUF_SZ - 1)) {
                    HTTP_req[req_index] = c; // сохраняем символ HTTP запроса
                    req_index++;
                }

                if (c == '\n' && currentLineIsBlank) {
                    // Посылаем http заголовок
                    client.println("HTTP/1.1 200 OK");
                    // HTML или XML запрос
                    if (StrContains(HTTP_req, "ajax_inputs")) {
                        client.println("Content-Type: text/xml");
                        client.println("Connection: keep-alive");
                        client.println();
                        XML_response(client);
                    } else {
                        client.println("Content-Type: text/html");
                        client.println("Connection: keep-alive");
                        client.println();
                        webFile = SD.open("index.htm");
                        if (webFile) {
                            while(webFile.available()) {
                                client.write(webFile.read());
                            }
                            webFile.close();
                        }
                    }
                    Serial.print(HTTP_req);
                    // Обнуляем массив (буфер)
                    req_index = 0;
                    StrClear(HTTP_req, REQ_BUF_SZ);
                    break;
                }
                if (c == '\n') {
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);
        client.stop();
    } // end if (client)
}

// Посылаем XML файл
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>");
}

// Обнуление массива
void StrClear(char *str, char length) {
    for (int i = 0; i < length; i++) {
        str[i] = 0;
    }
}

// Поиск подстроки
// 1, если найдена
// 0, если не найдена
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

previous lesson

.

The sketch sends the value of analog input A2 to the browser, which is then displayed on the indicator on the web page. The status of the indicator is updated using Ajax, and the value of analog input A2 is passed as part of the XML file (from the Arduino server to the browser).

The web page hosted on the Arduino server is stored on a microSD memory card connected to the Arduino Ethernet Shield.

Webpage

The content of the web page of this example is shown below (without the code of the indicator itself).

This web page is a modified version of the page used in the previous lesson.

Translator’s note: in the screenshot above, the code of the indicator component itself is missing, only one line from it is visible (eval(function…), the rest was simply cut off by the author, which may cause confusion for the reader. In general, one can imagine that the full code is in place of this line indicator component.

Indicator

An indicator is connected to a web page by inserting its code between script tags in the page header.

The indicator is displayed in the body of the page using the HTML5 canvas tag.

Indicator update

The A2 Arduino input value is received by the browser and displayed on the web page in the same way as in the previous part of this tutorial. Also, the value of input A2 is stored in the Javascript variable data_val so that the indicator can use it.

The value in data_val is passed to the indicator using a Javascript string in the data-onready property of the canvas tag:

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

The number 200 in the above line tells the indicator to update every 200 milliseconds.

Intervals

The indicator is updated every 200ms and the frequency of Ajax requests is also set to 200ms.

The interval for Ajax requests is set in the following line of Javascript code:

setTimeout('GetArduinoInputs()', 200);

This frequency of Ajax requests can cause problems on a busy or slow network. If you have any problems with this, try changing this value to 1000 so that requests are made less frequently, once per second.

Running the sketch

Connect the potentiometer as shown in the circuit diagram in

7th part

this guide. The buttons shown in the diagram will not be used in this tutorial.

Copy the index.htm webpage (see below) to a microSD memory card and insert it into the slot on the Arduino Ethernet Shield.

Upload the above sketch to the server’s Arduino board.

Web page source code

Download the web page source code (index.htm file) here:

Arduino_web_gauge.zip (6.3 KB)

The indicator license (MIT) is included in the archive as a text file.

From the translator about the 13th part

In this part, everything is described in sufficient detail and clearly, on my own I will add only a few words about the indicator component.

In this example, the author uses a “compressed” and almost unreadable Javascript version of the indicator code, which is inserted into the body of the page as a whole piece “as is”. This approach may cause some problems in understanding for beginners – just treat this piece of code as a “black box”, for us only the mechanism for updating the data_val variable is important here, the rest is done by the “magic” of the indicator component.

Well, it should be clear that according to this (or similar) principle, many other Javascript components can be connected to a web page.

Part 1, part 2, part 3, part 4, part 5, part 6, part 7, part 8, part 9, part 10, part 11, part 12.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *