
От переводчика. В этой части руководства рассказывается как подключать к страницам Arduino сервера и использовать Javascript компоненты, в данном случае компонент стрелочного индикатора.
Это открывает поистине безграничные возможности для проектирования веб-страниц: вам доступны тысячи готовых Javascript компонентов для реализации различных функций и дизайна веб-интерфейсов для ваших проектов.
В этой части руководства рассматривается создание графического индикатора на веб-странице для отображения состояния одного из аналоговых входов Arduino. Значения индикатора обновляются при помощи Ajax.
Сам индикатор написан на JavaScript и использует HTML5 canvas. Индикатор используется как компонент (без изменений) и просто настраивается для отображения значения одного из аналоговых входов Arduino. Значения индикатора обновляются каждые 200 мс.
В этом видео показана работа сервера Arduino и индикатора, размещённого на веб-странице.
❯ Компонент индикатора
Компонент индикатора «HTML Canvas Gauges» можно скачать на Github. Можно также ознакомиться со статьёй (на английском) в которой даны подробности использования компонента.
В этом уроке используется Javascript код из файла Gauge.min.js (загруженный по вышеприведенной ссылке).
❯ Arduino скетч и веб-страница
Скетч Ардуино
Скетч Arduino для этого урока:
/*-------------------------------------------------------------- Скетч: 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; }
Этот скетч представляет собой немного измененную версию скетча из предыдущего урока.
Скетч отправляет значение аналогового входа A2 в браузер, которое затем отображается на индикаторе на веб-странице. Состояние индикатора обновляется с помощью Ajax, а значение аналогового входа A2 передаётся как часть XML файла (от Arduino сервера к браузеру).
Веб-страница, размещенная на сервере Arduino, хранится на microSD карте памяти, подключённой к плате Arduino Ethernet Shield.
Веб-страница
Ниже показано содержание веб-страницы этого примера (без кода самого индикатора).

Эта веб-страница — это модифицированная версия страницы, использованной в предыдущем уроке.
Примечание переводчика: на скриншоте выше отсутствует код самого компонента индикатора, видна только одна строка от него (eval(function...), остальное автор просто обрезал, что может вызвать непонимание читателя. В общем, можно представлять себе, что на месте этой строки находится полный код компонента индикатора.
Индикатор
Индикатор подключается к веб-странице путем вставки его кода между тегами script в заголовке страницы.
Индикатор отображается в теле страницы (body) с помощью HTML5 тега canvas.
Обновление индикатора
Значение входа A2 Arduino принимается браузером и отображается на веб-странице так же, как и в предыдущей части этого руководства. Также значение входа A2 сохраняется в Javascript переменной data_val, чтобы индикатор мог его использовать.
Значение в data_val передается индикатору с помощью Javascript строки в свойстве data-onready тега canvas:
setInterval( function() {Gauge.Collection.get('an_gauge_1').setValue(data_val);}, 200);
Цифра 200 в вышеприведенной строке предписывает индикатору обновляться каждые 200 миллисекунд.
Интервалы
Индикатор обновляется каждые 200 мс, и периодичность Ajax запросов также установлена на 200 мс.
Интервал для Ajax запросов задаётся в следующей строке Javascript кода:
setTimeout('GetArduinoInputs()', 200);
Такая частота следования Ajax запросов может вызвать проблемы в загруженной или медленной сети. Если у вас появятся какие-то проблемы с этим, попробуйте изменить это значение на 1000, чтобы запросы производились реже, один раз в секунду.
❯ Запуск скетча
Подключите потенциометр, как показано на принципиальной схеме в 7-й части этого руководства. Кнопки, показанные на схеме, не будут использоваться в этом уроке.
Скопируйте веб-страницу index.htm (см. ниже) на microSD карту памяти и вставьте ее в слот на плате Arduino Ethernet Shield.
Загрузите вышеприведенный скетч на плату Arduino сервера.
❯ Исходный код веб-страницы
Загрузите исходный код веб-страницы (файл index.htm) здесь:
Arduino_web_gauge.zip (6,3 КБ)
Лицензия на индикатор (MIT) включена в архив в виде текстового файла.
❯ От переводчика о 13-й части
В этой части всё описано достаточно подробно и понятно, от себя добавлю только несколько слов по поводу компонента индикатора.
В этом примере автор использует «сжатый» и практически нечитаемый вариант Javascript кода индикатора, который целым куском «как есть» вставляет в тело страницы. Такой подход может вызвать некоторые проблемы в понимании у новичков — просто относитесь к этому куску кода как к «чёрному ящику», для нас здесь важным является только механизм обновления переменной data_val, остальное делает «магия» компонента индикатора.
Ну и должно быть понятно, что по такому (или подобному) принципу можно подключить к веб-странице множество других Javascript компонентов.
Часть 1, часть 2, часть 3, часть 4, часть 5, часть 6, часть 7, часть 8, часть 9, часть 10, часть 11, часть 12.

