• I






      
           

Научно-популярный образовательный ресурс для юных и начинающих радиолюбителей - Popular science educational resource for young and novice hams

Основы электричества, учебные материалы и опыт профессионалов - Basics of electricity, educational materials and professional experience

КОНКУРС
language
 
Поиск junradio

Радиодетали
ОК
Сервисы

Stock Images
Покупка - продажа
Фото и изображений


 
Выгодный обмен
электронных валют

Друзья JR



JUNIOR RADIO

 

Базовый веб-сервер Arduino

 

 

Настройка веб-сервера на Arduino - это простой процесс, охватывающий процесс его настройки и запуска. Я также расскажу о некоторых основных концепциях, таких как использование Ajax для обновления, а не для обновления страницы снова и снова.Вам нужно будет знать основы HTML, которые невероятно легко понять. Если вы никогда не с HTML, я рекомендую посетить w3schools, чтобы получить базовое введение .

Все примеры кода можно найти на Github

Если вы новичок в программировании или заинтересованы в объяснении некоторых основ, то читайте дальше, иначе вы можете пропустить этот раздел и перейти к настройке веб-сервера с разделом SD-карты или без нее.

 Инициализация

Для начала вам нужно сначала инициализировать веб-сервер, определив несколько переменных, а затем вызвав функцию.

 

 

Во-первых, вам нужно определить MAC-адрес, приведенный ниже должен работать в большинстве домашних сетей. Если вы точно знаете, что вам нужно, не стесняйтесь менять это.

byte mac[] = {

  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED

};

Во-вторых, вам нужно будет определить IP-адрес, это делается путем простого вызова IPAddressкласса с выбранным вами IP. Убедитесь, что вы обновили его до IP-адреса, который не будет конфликтовать в вашей сети.

IPAddress ip(192, 168, 1, 177);

В-третьих, вам нужно будет установить номер порта, который вы хотите, чтобы сервер слушал. По умолчанию простой HTTP работает через порт 80. Если вы измените его, вам нужно будет определить порт при переходе к веб-странице в браузере. Например, если ваш порт был 14213 , то адрес будет выглядеть так:192.168.1.177:14213

EthernetServer server(80);

Наконец, в функции настройки вам нужно будет инициализировать устройство Ethernet. После инициализации просто позвоните в server.begin(), как только это будет сделано, вы сможете прослушивать соединения и при необходимости отвечать данными.

Ethernet.begin(mac, ip);

  server.begin();

 Обнаружение нового соединения

В функции цикла нам нужно проверять наличие нового соединения каждый раз, когда оно проходит. Если обнаружено новое соединение, мы вводим логический код нашей веб-страницы.

Следующий код обнаружит, когда новый клиент пытается подключиться к серверу.

EthernetClient client = server.available();

  if (client) {

    while (client.connected()) {

        if (client.available()) {

Как только будет определено, что клиент доступен, мы переходим к выводу HTML с веб-сервера Arduino.

 Возврат заголовка ответа HTML

Чтобы браузер правильно отображал веб-страницу, нам сначала нужно ответить заголовком ответа HTML. В этом не должно быть ничего сложного, приведенного ниже примера более чем достаточно, чтобы все работало правильно.

Если вам нужна дополнительная информация о полях заголовков, то эта невероятно удобная вики-страница все довольно хорошо объясняет.

client.println("HTTP/1.1 200 OK");

client.println("Content-Type: text/html");

client.println("Connection: close");

client.println();

 Вывод HTML

Вывод HTML может быть выполнен просто путем вызова client.println()или client.print()с помощью текста / HTML, переданного в качестве параметра. Это просто, но, как вы можете видеть в примерах ниже на этой странице, это действительно раздувает код.

Ниже приведен базовый пример вывода некоторого HTML.

 

client.println("<!DOCTYPE HTML>");

client.println("<html>");

client.print("<h1>Analogue Values</h1>");

Другой вариант - хранить файлы HTML на SD-карте, к которой вы можете получить доступ и загрузить с нее. Затем вы можете выполнять запросы AJAX для обновления элементов на веб-странице, чтобы они отображали правильные данные.

Вы также можете сделать это, чтобы заставить Arduino выполнять такие действия, как включение и выключение светодиода.

 Закрытие соединения

После того, как вы закончите обработку веб-страницы, вам следует отложить на короткое время, чтобы гарантировать, что клиент получит данные. Через секунду или около того просто закройте соединение с клиентом.

delay(1);

    client.stop();

 Веб-сервер Arduino без SD-карты

Если вы не используете SD-карту, то настроить и запустить веб-сервер невероятно просто.

Важно отметить, что если у вас вставлена ​​SD-карта, но она не используется, это может вызвать проблемы с взаимодействием скетча с Arduino. Чтобы этого не произошло, добавьте следующие две строки в функцию настройки.

pinMode(4, OUTPUT);

digitalWrite(4, HIGH);

Как только они будут добавлены, вы можете снова добавить SD-карту в устройство.

Чтобы быстро запустить и запустить веб-сервер Arduino, просто откройте скетч, скопируйте и вставьте приведенный ниже код. Его также можно найти на странице Github вместе с полным кодом для всех примеров в этом руководстве.

#include <SPI.h>

#include <Ethernet.h>

byte mac[] = {

  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED

};

IPAddress ip(192, 168, 1, 177);

EthernetServer server(80);

void setup() {

  Serial.begin(9600);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

  }

  Ethernet.begin(mac, ip);

  server.begin();

  Serial.print("server is at ");

  Serial.println(Ethernet.localIP());

}

 

void loop() {

  // listen for incoming clients

  EthernetClient client = server.available();

  if (client) {

    Serial.println("new client");

    // an http request ends with a blank line

    boolean currentLineIsBlank = true;

    while (client.connected()) {

      if (client.available()) {

        char c = client.read();

        Serial.write(c);

        if (c == '\n' && currentLineIsBlank) {

          client.println("HTTP/1.1 200 OK");

          client.println("Content-Type: text/html");

          client.println("Connection: close");

          client.println("Refresh: 5");

          client.println();

          client.println("<!DOCTYPE HTML>");

          client.println("<html>");

          client.print("<h1>Analogue Values</h1>");

          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {

            int sensorReading = analogRead(analogChannel);

            client.print("analog input ");

            client.print(analogChannel);

            client.print(" is ");

            client.print(sensorReading);

            client.println("<br />");

          }

          client.println("</html>");

          break;

        }

        if (c == '\n') {

          currentLineIsBlank = true;

        } else if (c != '\r') {

          currentLineIsBlank = false;

        }

      }

    }

    delay(1);

    // close the connection:

    client.stop();

    Serial.println("client disconnected");

  }

}

После того, как вы загрузили этот код в Arduino, у вас должен быть запущен и работает очень простой веб-сервер.

Он будет обновляться каждые 5 секунд, обновляя значения аналоговых выводов Arduino (это будут просто случайные значения, если к ним не подключено фактическое устройство или датчик).

Вы также можете отслеживать последовательный монитор для любых строк отладки, которые расположены по всему коду.

 

 

Веб-сервер Arduino с SD-картой

Если вы решите пойти по маршруту SD-карты для веб-сервера Arduino, тогда HTML-файлы необходимо будет создать на вашем компьютере, а затем скопировать на SD-карту, прежде чем она будет вставлена ​​в Arduino.

Плюс к загрузке веб-страницы с SD-карты заключается в том, что у вас могут быть более сложные / тяжелые страницы без необходимости писать сотни строк client.write . Это также помогает предотвратить любые ситуации с нехваткой памяти, которые обычно возникают, когда у вас слишком много кода, запущенного на Arduino.

 Инициализация SD-карты

Прежде чем вы сможете получить доступ к SD-карте, вам нужно будет импортировать SD-пакет и инициализировать его в функции настройки. Проверка в функции настройки покажет, может ли он получить доступ к карте, иначе вызовет ошибку в последовательном мониторе.

Serial.println("Checking SD card is accessible...");

  if (!SD.begin(4)) {

    Serial.println("ERROR - SD card initialization failed!");

    return;    // init failed

  }

  Serial.println("SUCCESS - SD card initialized.");

 Загрузка файла

Когда вы будете готовы загрузить файл, просто используйте, sd.open(filename)чтобы открыть файл. Используйте оператор if, чтобы убедиться, что файл существует, а затем прокрутите содержимое файла до конца.

webPage = SD.open("index.htm"); // open web page file

if (webPage) {

    while (webPage.available()) {

    client.write(webPage.read()); // send web page to client

}

webPage.close();

Ниже приведен пример веб-страницы, которая загружается через SD-карту с помощью Ajax (поясняется ниже), обновляющего элементы на странице.

 

 

Выполнение действий через веб-страницу (AJAX)

Может быть, в какой-то момент вы захотите управлять устройством или датчиком через веб-страницу. В этом разделе я рассмотрю выполнение запросов и обновлений с помощью AJAX. Это означает, что вы не будете видеть загрузку страницы снова и снова, но при необходимости она все равно будет обновляться.

AJAX или асинхронный JavaScript и XML слишком сложны, чтобы полностью описать их в этом руководстве, но я рассмотрю основы их использования на Arduino. У вас должна быть возможность настроить примеры в соответствии со своими потребностями без особых проблем.

 Пример AJAX

AJAX работает, отправляя запрос на сервер, затем сервер проверяет,  существует ли в заголовке строка ajaxrefresh  или ledstatus (для этого примера). Если это так, он сгенерирует соответствующие данные и вернет их.

Затем JavaScript находит соответствующий элемент HTML с правильным идентификатором, а затем заменяет innerHTML ответом на запрос AJAX.

В приведенном ниже примере отправляется запрос на веб-сервер, работающий на Arduino, с переменной GET ajaxrefresh . Если сервер возвращает данные, он заменит innerHTML элемента с идентификатором analogue_data .

Этот сценарий запускается каждые 5 секунд, но его можно настроить в соответствии с вашими потребностями.

<script>window.setInterval(function(){

  nocache = "&nocache=" + Math.random() * 10;

  var request = new XMLHttpRequest();

  request.onreadystatechange = function() {

    if (this.readyState == 4) {

      if (this.status == 200) {

        if (this.responseText != null) {

          document.getElementById("analoge_data").innerHTML = this.responseText;

        }

      }

    }

  }

  request.open("GET", "ajaxrefresh" + nocache, true);

  request.send(null);

  }, 5000);

</script>

 Функции Arduino Ajax

Две указанные ниже функции вызываются всякий раз, когда на сервер поступает соответствующий запрос AJAX. Они очень просты: первый считывает аналоговые выводы и возвращает соответствующие данные.

Вторая функция включает или выключает КРАСНЫЙ светодиод в зависимости от его текущего состояния. Он также вернет состояние светодиода, чтобы AJAX мог обновить значение на веб-странице.

void ajaxRequest(EthernetClient client)

{

  for (int analogChannel = 0; analogChannel < 6; analogChannel++) {

    int sensorReading = analogRead(analogChannel);

    client.print("analog input ");

    client.print(analogChannel);

    client.print(" is ");

    client.print(sensorReading);

    client.println("<br />");

  }

}

 

void ledChangeStatus(EthernetClient client)

{

  int state = digitalRead(RED);

  Serial.println(state);

  if (state == 1) {

    digitalWrite(RED, LOW);

    client.print("OFF");

  }

  else {

    digitalWrite(RED, HIGH);

    client.print("ON");

  }

}

 AJAX с HTML, созданный Arduino

В приведенном ниже примере весь HTML и JavaScript полностью сгенерирован Arduino. JavaScript отправляет запросы AJAX на сервер Arduino, который обновляет страницу в зависимости от результатов, которые он предоставляет.

Одна проблема, которую я заметил, сгенерировав весь код на Arduino, заключается в том, что он начал заканчивать место и выдавать предупреждения о стабильности. Это может быть проблемой, если вы хотите, чтобы на странице было множество датчиков и опций. Возможно, вы захотите сохранить HTML на SD-карте и вместо этого получить его оттуда.

void loop() {

  EthernetClient client = server.available();

  if (client) {

    Serial.println("new client");

    boolean currentLineIsBlank = true;

    while (client.connected()) {

      if (client.available()) {

        char c = client.read();

        if( HTTP_req.length() < 120)

           HTTP_req += c; // save the HTTP request 1 char at a time

           Serial.write(c);

           if (c == '\n' && currentLineIsBlank)

           {

            // send a standard http response header

            client.println("HTTP/1.1 200 OK");

            client.println("Content-Type: text/html");

            client.println("Connection: close");

            client.println();

            Serial.println(HTTP_req);

            if (HTTP_req.indexOf("ajaxrefresh") >= 0 ) {

            // read switch state and analog input

            ajaxRequest(client);

            break;

          }

          else if (HTTP_req.indexOf("ledstatus") >= 0 ) {

            // read switch state and analog input

            ledChangeStatus(client);

            break;

          }

          else {

            client.println("<!DOCTYPE HTML>");

            client.println("<html lang=\"en\">");

            client.println("<script>window.setInterval(function(){");

            client.println("nocache = \"&nocache=\" + Math.random() * 10;");

            client.println("var request = new XMLHttpRequest();");

            client.println("request.onreadystatechange = function() {");

            client.println("if (this.readyState == 4) {");

            client.println("if (this.status == 200) {");

            client.println("if (this.responseText != null) {");

            client.println("document.getElementById(\"analoge_data\").innerHTML = this.responseText;");

            client.println("}}}}");

            client.println("request.open(\"GET\", \"ajaxrefresh\" + nocache, true);");

            client.println("request.send(null);");

            client.println("}, 5000);");

            client.println("function changeLEDStatus() {");

            client.println("nocache = \"&nocache=\" + Math.random() * 10;");

            client.println("var request = new XMLHttpRequest();");

            client.println("request.onreadystatechange = function() {");

            client.println("if (this.readyState == 4) {");

            client.println("if (this.status == 200) {");

            client.println("if (this.responseText != null) {");

            client.println("document.getElementById(\"led_status\").innerHTML = this.responseText;");

            client.println("}}}}");

            client.println("request.open(\"GET\", \"?ledstatus=1\" + nocache, true);");

            client.println("request.send(null);");

            client.println("}");

            client.println("</script></head>");

            // output the value of each analog input pin

            client.print("<h1>Analogue Values</h1>");

            client.println("<div id=\"analoge_data\">Arduino analog input values loading.....</div>");

            client.println("<h1>Arduino LED Status</h1>");

            client.println("<div><span id=\"led_status\">");

            if(digitalRead(RED) == 1)

             client.println("On");

            else

              client.println("Off");

            client.println("</span> | <button onclick=\"changeLEDStatus()\">Change Status</button> </div>");

            client.println("</html>");

            break;

          }

        }

        if (c == '\n') {

          // you're starting a new line

          currentLineIsBlank = true;

        } else if (c != '\r') {

          // you've gotten a character on the current line

          currentLineIsBlank = false;

        }

      }

    }

    delay(1);

    client.stop();

    HTTP_req = "";

    Serial.println("client disconnected");

  }

}

 AJAX с файлами HTML на SD-карте

Как вы можете видеть ниже, результат намного чище, если просто сохранить HTML в файле на SD-карте. Это должно помочь вашему скрипту в основном обрабатывать код, особенно если вы делаете все через AJAX и загружаете HTML с SD-карты.

Имейте в виду, что это всего лишь часть цикла кода, если вы хотите, чтобы полная версия находилась на странице Github .

void loop()

{

  EthernetClient client = server.available();

  if (client) {

    Serial.println("new client");

    boolean currentLineIsBlank = true;

    while (client.connected()) {

      if (client.available()) {

        char c = client.read();

        if ( HTTP_req.length() < 80)

          HTTP_req += c;

        if (c == '\n' && currentLineIsBlank) {

          client.println("HTTP/1.1 200 OK");

          client.println("Content-Type: text/html");

          client.println("Connection: close");

          client.println();

          if (HTTP_req.indexOf("ajaxrefresh") >= 0 ) {

            ajaxRequest(client);

            break;

          }

          else if (HTTP_req.indexOf("ledstatus") >= 0 ) {

            ledChangeStatus(client);

            break;

          }

          else {

            webPage = SD.open("index.htm");

            if (webPage) {

              while (webPage.available()) {

                client.write(webPage.read());

              }

              webPage.close();

            }

            break;

          }

          if (c == '\n') {

            currentLineIsBlank = true;

          } else if (c != '\r') {

            currentLineIsBlank = false;

          }

        }

      }

    }

    delay(1);

    client.stop();

    HTTP_req = "";

    Serial.println("client disconnected");

  }

}

 Исправление проблем

Я не могу получить доступ к своей веб-странице: дважды проверьте IP-адрес и убедитесь, что он не конфликтует с другим устройством в сети. Также попробуйте пропинговать IP-адрес и посмотреть, получите ли вы ответ. Моя SD-карта говорит, что она недоступна: удерживайте кнопку выключения, затем вставьте SD-карту, я обнаружил, что это обычно решает проблему. CSS: вы можете включать CSS на свои веб-страницы, вы можете сделать это встроенным или расположенным в заголовке между тегами стиля. Это то, о чем вы, возможно, захотите прочитать больше, если вы не очень много работали с CSS. В этом нет необходимости, если вы не хотите, чтобы ваши страницы выглядели хорошо.

 Дальнейшие реализации

Есть гораздо больше способов использования веб-сервера, которые увеличивают функциональность вашей схемы. Я быстро перечислю несколько проектов, в которых вы, возможно, захотите реализовать веб-интерфейс. Вентилятор / контроль температуры - следите за серверной, теплицей или чем-то подобным, где важны тепло и воздушный поток. Вы можете добавить элементы управления для включения и выключения обогревателей и вентиляторов. Счетчик - используйте датчик движения для обнаружения движения и подсчета при каждом срабатывании датчика. Эту же логику можно применить практически к любому датчику. Я надеюсь, что это руководство по веб-серверу Arduino помогло вам создать веб-сайт, на котором вы можете просматривать данные и взаимодействовать с ними. 

 




Необходимо добавить материалы...
Результат опроса Результаты Все опросы нашего сайта Архив опросов
Всего голосовало: 373



          

Радио для всех© 2024