От переводчика. Примеры руководства становятся всё более и более практичными — на этом уроке автор «скрестил» Arduino веб-сервер с SD картой памяти и динамическое отображение состояния кнопки (входов/выходов) на веб-странице.
В результате получился ещё более приближенный к жизни (практическому применению) пример кода, который, при некоторой доработке, можно использовать в своих проектах.
Исходные данные для этого урока: Arduino веб-сервер с платой Ethernet Shield и microSD картой памяти, на которой размещается веб-страница. На этой веб-странице с помощью Ajax динамически отображается состояние кнопки, подключённой к Arduino.
В предыдущих частях этого руководства веб-страница, размещенная на SD карте, никогда не использовалась для отображения состояния входов Arduino — все веб-страницы, отображающие ввод/вывод, были частью скетча Arduino.
В этом уроке веб-страница, отображающая состояние кнопки, размещается на SD карте памяти.
❯ Принципиальная электрическая схема
В этом примере кнопка подключается к контакту D3 Arduino по следующей схеме:
❯ Код и веб-страница
Код (скетч Arduino) и веб-страница этого урока представляют собой комбинацию 2-й части («Веб-сервер с SD картой») и 7-й части («Отображение DI и AI входов при помощи AJAX») из этого руководства.
Видео не было включено в этот урок, так как будет выглядеть так же, как в 7-й части, только с измененным текстом заголовка веб-страницы.
Веб-страница
Веб-страница, состоящая из HTML и JavaScript кода (для реализации Ajax), показана ниже:
Веб-страница, размещающаяся на SD карте памяти (файл index.htm)
Эта страница сохраняется на microSD карту в виде файла index.htm — это в основном тот же HTML/JavaScript код, который создавался (генерировался) Arduino скетчем в 7-й части («Отображение DI и AI входов при помощи AJAX»), но с измененным текстом заголовка.
Скопируйте нижеприведённый код и вставьте в файл index.htm.
<!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 скетч показан ниже. Для работы системы требуется, чтобы указанный выше HTML/JavaScript код был доступен на microSD карте в виде файла index.htm.
/*-------------------------------------------------------------- Скетч: eth_websrv_SD_Ajax Описание: Arduino веб-сервер с SD картой, динамически (раз в секунду) отображающий текущее состояние кнопки на веб-странице при помощи Ajax. Оборудование: контроллер Arduino Uno, плата Ethernet Shield, microSD карта памяти 2 ГБ, кнопка, подключённая на пин D3 Arduino Программное обеспечение: среда разработки 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 Дата создания: 25 марта 2013 Изменения: 17 июня 2013 Автор: 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); File webFile; // Буфер для HTTP запросов #define REQ_BUF_SZ 40 char HTTP_req[REQ_BUF_SZ] = {0}; // Хранится как null terminated string char req_index = 0; // индекс буфера 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."); pinMode(3, INPUT); // Кнопка на D3 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"); client.println("Content-Type: text/html"); client.println("Connection: keep-alive"); client.println(); // Ajax запрос if (StrContains(HTTP_req, "ajax_switch")) { // получаем состояние кнопки и посылаем соответствующий текст GetSwitchState(client); } else { // запрос веб-страницы // посылаем страницу webFile = SD.open("index.htm"); if (webFile) { while(webFile.available()) { client.write(webFile.read()); } webFile.close(); } } // дублируем HTTP запрос в Serial Serial.println(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) } // Посылаем состояние кнопки браузеру void GetSwitchState(EthernetClient cl) { if (digitalRead(3)) { cl.println("Switch state: ON"); } else { cl.println("Switch state: OFF"); } } // Обнуляем массив (буфер) 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; }
Как работает скетч
Этот скетч работает так же, как и скетч из 7-й части этого руководства, за исключением того, что вместо отправки веб-страницы построчно из кода скетча Arduino, веб-страница посылается браузеру из файла index.htm на SD карте.
Поскольку мы используем Ajax, веб-страница (при загрузке в веб-браузере) отправляет тот же запрос текущего состояния кнопки, что и код в 7-й части. Если бы мы не использовали Ajax, то Arduino нужно было бы прочитать файл index.htm с SD карты и изменить часть, показывающую текущее состояние кнопки, а затем отправить обратно всю изменённую веб-страницу. Использование Ajax делает это процесс более простым и эффективным.
❯ От переводчика о 11-й части
На этом уроке автор постоянно ссылается на 7-ю (и 2-ю) части в этого руководства, поэтому рекомендуется (если вы ещё не знакомы с ними) обязательно с ними ознакомиться и хорошо понять принципы работы системы, изложенные в предыдущих частях — тогда материал этой статьи станет для вас простым и понятным.
И вообще, для лучшего понимания рекомендуется проходить все уроки последовательно и проводить практические эксперименты с кодом из этих статей.
Часть 1, часть 2, часть 3, часть 4, часть 5, часть 6, часть 7, часть 8, часть 9, часть 10.
ссылка на оригинал статьи https://habr.com/ru/articles/733744/
Добавить комментарий