От переводчика. Эта часть посвящена работе так называемого «сервера ввода/вывода» и представляет собой апофеоз всего курса — здесь даётся практический пример кода веб-сервера Arduino с подключёнными к нему «физическими» кнопками, светодиодами потенциометром и «виртуальными» кнопками и чекбоксами на веб-странице — весь этот конгломерат оборудования и технологий работает в реальном времени и обеспечивает интерактивное управление работой светодиодов и отображение актуальных данных на веб-странице.
Это всё, что может понадобиться вам для построения своих собственных микроконтроллерных приложений и интерфейсов — берите исходный код урока и модифицируйте его для своих собственных проектов.
В этой части руководства собрано всё, что мы изучали до сих пор: HTML, Javascript, CSS, HTTP, Ajax, которые используются для создания веб-страницы, хранящейся на SD карте памяти. Страница отображает состояние аналоговых и цифровых входов Arduino и одновременно позволяет управлять цифровыми выходами.
На веб-странице отображаются четыре значения аналоговых входов и состояние трех кнопок. Также страница позволяет управлять четырьмя светодиодами — двумя из них можно управлять с помощью чекбоксов (флажков), и двумя — с помощью HTML-кнопок.
Когда к веб-серверу Arduino подключено более одного компьютера (веб-браузера), то состояние выходов (светодиодов), изменённое с помощью одного компьютера, будет обновлено и на другом компьютере, то есть при установке с одного компьютера чекбокса для включения светодиода, новое состояние чекбокса также будет видно и на другом компьютере.
В следующем видео показаны два компьютера, подключенные к веб-серверу Arduino, и по мере того, как изменения производятся на странице на одном компьютере, они обновляются и на другом.
❯ Схема I/O веб-сервера
Принципиальная электрическая схема компонентов и соединений для этого урока:
Принципиальная схема: Arduino Uno, Ethernet Shield и подключенные к ним кнопки, светодиоды, резисторы и потенциометр.
В представленном выше видео схема несколько отличается, там пин A3 подключен к делителю напряжения, A4 подключен через резистор к земле (GND), а пин A5 подключен через резистор к +5V (на схеме это не показано).
❯ Обзор работы веб-сервера
После того, как браузер запросит и загрузит веб-страницу с сервера Arduino, Javascript код, находящийся на этой странице, будет периодически (каждую секунду) отправлять Ajax запрос данных к Arduino.
Веб-страница, которая размещена сервере Arduino, показана ниже:
Arduino сервер будет отвечать на каждый Ajax запрос, отправляя XML файл с данными браузеру. XML файл содержит значения четырех аналоговых входов Arduino (от A2 до A5), состояние трех кнопок (пины D2, D3 и D5) и состояние четырех светодиодов.
XML файл, отправляемый Arduino сервером веб-браузеру в ответ на Ajax запрос
Когда светодиод включается пользователем с веб-страницы путем установки чекбокса, Javascript код отправит новое состояние чекбокса (команду для включения светодиода) со следующим Ajax запросом. То же самое произойдет, если одна из HTML-кнопок используется для включения или выключения светодиода.
❯ Исходный код
Исходные коды Arduino скетча и веб-страницы достаточно велики, чтобы размещать их здесь. Поэтому вы можете загрузить эти файлы в виде архива и использовать их обычным образом (см. пояснения ниже).
Arduino скетч и веб-страница:
web_server_IO.zip (4,7 КБ)
❯ Запуск примера
Чтобы запустить этот пример, сначала скопируйте веб-страницу (файл index.htm) на microSD карту памяти. Затем вставьте эту карту в слот на Ethernet Shield. Плата Ethernet Shield должна быть подключена к контроллеру Arduino и к вашей локальной сети (см. подробности в предыдущих уроках этого руководства).
Далее подключите кнопки, резисторы, светодиоды и потенциометр согласно вышеприведённой схеме.
Затем загрузите в контроллер скетч (eth_websrv_SD_Ajax_in_out) из скачанного архива.
С помощью браузера перейдите по IP адресу, указанному в скетче, — вы должны увидеть загруженную веб-страницу на которой раз в секунду обновляются аналоговые значения и текущее состояние кнопок.
❯ Как работает этот пример
Arduino скетч и веб-страница представляют собой модифицированные версии кода из предыдущих примеров этого руководства. Для работы системы используются Ajax и XML (см. подробнее часть 12 и часть 13 руководства).
Аналоговые и цифровые входы
Аналоговые входы (аналоговые значения) и цифровые входы (состояния кнопок) запрашиваются и принимаются так же, как описано в 12-й части этого руководства, за исключением того, что здесь аналоговые значения заключены в теги analog, а состояния кнопок заключены в теги switch, — то есть здесь используются одинаковые теги для передачи однотипных значений.
Когда Javascript код на веб-странице получает XML файл от сервера Arduino, он использует один цикл for для извлечения аналоговых значений и второй цикл for для извлечения состояний кнопок.
Javascript код для извлечения аналоговых значений из XML файла:
var num_an = this.responseXML.getElementsByTagName('analog').length;
for (count = 0; count < num_an; count++) {
document.getElementsByClassName("analog")[count].innerHTML =
this.responseXML.getElementsByTagName('analog')[count].childNodes[0].nodeValue;
}
Первая строка этого кода получает количество элементов XML файла, заключенных в теги analog, и сохраняет их в переменной num_an, которая затем используется в цикле for для получения нужного количества аналоговых значений.
Следующий код в цикле for получает каждый HTML элемент span, имеющий класс analog:
document.getElementsByClassName("analog")[count].innerHTML
Фрагмент HTML кода страницы с этими элементами:
<p>A2: <span class="analog">...</span></p>
<p>A3: <span class="analog">...</span></p>
<p>A4: <span class="analog">...</span></p>
<p>A5: <span class="analog">...</span></p>
А следующая строка кода получает очередное аналоговое значение из XML файла:
this.responseXML.getElementsByTagName('analog')[count].childNodes[0].nodeValue;
Таким образом, две вышеприведенные строки Javascript кода, работающие совместно, получают каждое аналоговое значение из XML файла в том порядке, в котором они находятся в нём, и вставляют эти значения в каждый тег span в том порядке, в котором они появляются в HTML коде страницы.
Получение значений состояния кнопок работает аналогичным образом, только каждый тег span с именем класса switches получает данные из тегов switch в XML файле в том порядке, в котором они располагаются в нём.
❯ Светодиоды
Arduino отслеживает, какие светодиоды включены, а какие выключены. Эта информация отправляется обратно как часть XML файла в ответ на Ajax запрос браузера, который выполняется каждую секунду.
В скетче Arduino массив LED_state хранит состояние светодиодов («1» для включенного и «0» для выключенного):
boolean LED_state[4] = {0}; // stores the states of the LEDs
Этот массив инициализируется нулями — все светодиоды выключены. Каждый элемент массива соответствует светодиоду в порядке от LED1 до LED4, то есть LED_state[0] хранит состояние светодиода 1, LED_state[1] хранит состояние светодиода 2 и т. д.
Использование чекбоксов для управления светодиодами
Следующие строки Javascript кода показывают, как состояние LED1 извлекается из полученного XML файла и используется для обновления соответствующего чекбокса на странице.
// LED 1
if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "checked") {
document.LED_form.LED1.checked = true;
} else {
document.LED_form.LED1.checked = false;
}
В приведенном выше коде, если первое значение (например, для LED1) из XML файла в теге содержит текст checked, соответствующий чекбокс устанавливается с помощью строки:
document.LED_form.LED1.checked = true;
В противном случае чекбокс (флажок) снят.
Это гарантирует, что каждый браузер, который подключается к веб-серверу Arduino, отображает правильное состояние светодиодов, поскольку оно обновляется каждую секунду.
Когда пользователь устанавливает или снимает флажок, следующий Ajax запрос будет содержать в себе текст «LED» и информацию о его новом состоянии.
Javascript функция GetCheck() запускается всякий раз, когда изменяется состояние флажка. Если установлен флажок для LED1, то соответствующим образом изменяется значение строки для него:
strLED1 = "&LED1=1";
Если флажок не установлен, строка выглядит следующим образом:
strLED1 = "&LED1=0";
При следующем вызове функции GetArduinoIO(), который происходит каждую секунду, строка strLED1 уже не будет пустой. Эта строка теперь будет включена в GET запрос:
request.open("GET", "ajax_inputs" + strLED1 + strLED2 + strLED3 + strLED4 + nocache, true);
Все остальные LED строки будут пустыми, если чекбокс или HTML кнопка на странице не были нажаты, поэтому они не будут включены в GET запрос.
После выполнения запроса все LED строки снова становятся пустыми:
strLED1 = "";
strLED2 = "";
strLED3 = "";
strLED4 = "";
Когда Arduino получает Ajax GET запрос, функция SetLEDs() проверяет наличие в нём команды на изменение состояния светодиода, и если находит, включает или выключает соответствующий светодиод, а затем сохраняет его новое состояние в массив LED_state[].
Управление светодиодами при помощи HTML кнопок
Кнопки, управляющие светодиодами, работают так же, как и чекбоксы, за исключением того, что каждая HTML кнопка имеет собственную Javascript функцию, которая запускается при её нажатии.
Текст на кнопках обновляется, чтобы показать состояние светодиодов, которыми они управляют.
Кнопки не имеют свойства «checked», поэтому текущее состояние светодиода, ассоциированного с каждой кнопкой, сохраняется в переменной:
var LED3_state = 0;
var LED4_state = 0;
Сохранение состояния кнопки в переменной необходимо для того, чтобы при её повторном нажатии было известно, следует ли обновлять строку, отправляемую с очередным GET запросом для включения или выключения светодиода.
Когда Arduino отправляет данные о текущем состоянии светодиодов в XML файле, которыми управляют кнопки, он вставляет «on» или «off» между тегами LED вместо «checked» или «unchecked», как это делается для чекбоксов.
❯ CSS
CSS код, используемый в этом примере, помещает каждый набор входных и выходных данных в отдельные области, обрамлённые синей линией. Он также размещает эти области рядом друг с другом. Если размер окна браузера изменится по ширине, то поля справа переместятся ниже полей слева.
Работа CSS кода не будет подробно объясняться в этой части, ей будет посвящён один из следующих уроков, где мы подробно рассмотрим устройство и работу CSS.
❯ От переводчика о 14-й части
Не знаю как вам, а мне в этом уроке всё кристально ясно (что и как работает) — автор постарался всё «разжевать» и объяснить на реальных примерах кода. Если вам всё-таки что-то не понятно, то рекомендую уделить некоторое время анализу работы кода и практическим экспериментам с ним.
Сначала работа этой системы может показаться несколько «замороченной», но после некоторых усилий по её освоению, построение своих собственных серверов на Arduino вам покажется простым и невероятно увлекательным делом. К тому же крайне полезным с практической точки зрения.
Часть 1, часть 2, часть 3, часть 4, часть 5, часть 6, часть 7, часть 8, часть 9, часть 10, часть 11, часть 12, часть 13.