Каталог

ESP32 Web Server

В этом проекте вы создадите автономный веб-сервер с использованием ESP32, который будет управлять выходами (двумя светодиодами) с помощью среды программирования Arduino IDE. Веб-сервер адаптирован под мобильные устройства и может быть доступен с любого устройства с браузером в локальной сети. Мы покажем вам, как создать веб-сервер и как работает код шаг за шагом.

Если вы хотите узнать больше о ESP32, прочитайте руководство для начинающих по работе с ESP32.

Обзор проекта

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

  • Веб-сервер, который вы создадите, управляет двумя светодиодами, подключенными к GPIO 26 и GPIO 27 на ESP32.
  • Вы можете получить доступ к веб-серверу ESP32, введя IP-адрес ESP32 в браузере в локальной сети.
  • Нажимая кнопки на вашем веб-сервере, вы можете мгновенно изменять состояние каждого светодиода.

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

Установка платы ESP32 в Arduino IDE

Для Arduino IDE существует дополнительный модуль, который позволяет программировать ESP32 с использованием Arduino IDE и его языка программирования. Следуйте одному из следующих руководств, чтобы подготовить Arduino IDE:

  • Инструкции для Windows – Установка платы ESP32 в Arduino IDE
  • Инструкции для Mac и Linux – Установка платы ESP32 в Arduino IDE

Необходимые детали

Для этого руководства вам понадобятся следующие компоненты:

  • Плата разработки ESP32 – прочитайте обзор и сравнение плат разработки ESP32
  • 2x светодиода 5 мм
  • 2x резистора 330 Ом
  • Макетная плата
  • Соединительные провода

Вы можете использовать приведенные выше ссылки или зайти на MakerAdvisor.com/tools, чтобы найти все необходимые детали для ваших проектов по лучшим ценам!

Схема

Начните с создания схемы. Подключите два светодиода к ESP32, как показано на следующей схеме: один светодиод подключен к GPIO 26, а другой — к GPIO 27.

Примечание: Мы используем плату ESP32 DEVKIT DOIT с 36 выводами. Перед сборкой схемы убедитесь, что вы проверили распиновку для используемой платы.

Код веб-сервера на ESP32

Здесь мы предоставляем код, который создает веб-сервер на ESP32. Скопируйте следующий код в Arduino IDE, но пока не загружайте его. Вам нужно внести некоторые изменения, чтобы он работал для вас.

// Подключаем библиотеку Wi-Fi
#include <WiFi.h>

// Замените на свои данные сети
const char* ssid = "ЗАМЕНИТЕ_НА_ВАШ_SSID";
const char* password = "ЗАМЕНИТЕ_НА_ВАШ_ПАРОЛЬ";

// Устанавливаем номер порта веб-сервера на 80
WiFiServer server(80);

// Переменная для хранения HTTP-запроса
String header;

// Вспомогательные переменные для хранения текущего состояния выходов
String output26State = "off";
String output27State = "off";

// Присваиваем выходным переменным выводы GPIO
const int output26 = 26;
const int output27 = 27;

// Текущее время
unsigned long currentTime = millis();
// Предыдущее время
unsigned long previousTime = 0; 
// Определяем время ожидания в миллисекундах (например, 2000мс = 2с)
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  // Инициализируем выходные переменные как выходы
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Устанавливаем выходы в LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

  // Подключаемся к Wi-Fi сети с использованием SSID и пароля
  Serial.print("Подключение к ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Выводим локальный IP-адрес и запускаем веб-сервер
  Serial.println("");
  Serial.println("Wi-Fi подключен.");
  Serial.println("IP-адрес: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Ожидаем подключения клиентов

  if (client) {                             // Если новый клиент подключается,
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("Новый клиент.");          // выводим сообщение в серийный монитор
    String currentLine = "";                // создаем строку для хранения данных от клиента
    while (client.connected() && currentTime - previousTime <= timeoutTime) {  // продолжаем, пока клиент подключен
      currentTime = millis();
      if (client.available()) {             // если есть данные от клиента,
        char c = client.read();             // читаем байт
        Serial.write(c);                    // выводим его в серийный монитор
        header += c;
        if (c == '\n') {                    // если байт — символ новой строки
          if (currentLine.length() == 0) {
            // HTTP-заголовки всегда начинаются с кода ответа (например, HTTP/1.1 200 OK)
            // и типа содержимого, чтобы клиент знал, что придет дальше, а затем идет пустая строка:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // включает и выключает GPIO
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 включен");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 выключен");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 включен");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 выключен");
              output27State = "off";
              digitalWrite(output27, LOW);
            }
            
            // Отображаем HTML веб-страницу
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" );
            client.println("<link rel=\"icon\" href=\"data:,\">" );
            // CSS для стилизации кнопок включения/выключения
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");
            
            // Заголовок веб-страницы
            client.println("<body><h1>ESP32 Веб-сервер</h1>");
            
            // Отображение текущего состояния и кнопок включения/выключения для GPIO 26  
            client.println("<p>GPIO 26 - Состояние " + output26State + "</p>");
            if (output26State == "off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ВКЛ</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">ВЫКЛ</button></a></p>");
            } 
               
            // Отображение текущего состояния и кнопок включения/выключения для GPIO 27  
            client.println("<p>GPIO 27 - Состояние " + output27State + "</p>");
            if (output27State == "off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ВКЛ</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">ВЫКЛ</button></a></p>");
            }
            client.println("</body></html>");
            
            // Ответ HTTP заканчивается еще одной пустой строкой
            client.println();
            // Выход из цикла while
            break;
          } else {
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
      }
    }
    // Очистка переменной header
    header = "";
    // Закрытие соединения
    client.stop();
    Serial.println("Клиент отключился.");
    Serial.println("");
  }
}

Настройка сетевых данных

Вам нужно изменить следующие строки, указав свои сетевые данные: SSID и пароль. Код содержит комментарии, где нужно внести изменения.

// Замените на свои данные сети
const char* ssid = "ЗАМЕНИТЕ_НА_ВАШ_SSID";
const char* password = "ЗАМЕНИТЕ_НА_ВАШ_ПАРОЛЬ";

Загрузка кода

Теперь вы можете загрузить код, и веб-сервер начнет работать сразу же. Следуйте следующим шагам для загрузки кода на ESP32:

  1. Подключите вашу плату ESP32 к компьютеру.

  2. В Arduino IDE выберите вашу плату в меню Инструменты > Плата (в нашем случае мы используем плату ESP32 DEVKIT DOIT).

  3. Выберите COM-порт в меню Инструменты > Порт.

  4. Нажмите кнопку Загрузить в Arduino IDE и подождите несколько секунд, пока код компилируется и загружается на вашу плату.

  5. Дождитесь сообщения "Готово" после завершения загрузки.

Поиск IP-адреса ESP32

После загрузки кода откройте серийный монитор с частотой передачи 115200 бод.

Нажмите кнопку EN на ESP32 (сброс). ESP32 подключится к Wi-Fi и выведет IP-адрес на серийный монитор. Скопируйте этот IP-адрес, так как он вам понадобится для доступа к веб-серверу ESP32.

Доступ к веб-серверу

Чтобы получить доступ к веб-серверу, откройте браузер, вставьте IP-адрес ESP32, и вы увидите следующую страницу. В нашем случае это 192.168.1.135.

Тестирование веб-сервера

Теперь вы можете проверить, работает ли ваш веб-сервер правильно. Нажимайте кнопки, чтобы управлять светодиодами.

В то же время вы можете следить за серийным монитором, чтобы видеть, что происходит на заднем плане. Например, когда вы нажимаете кнопку, чтобы включить GPIO 26, ESP32 получает запрос на URL /26/on.

Когда ESP32 получает этот запрос, он включает светодиод, подключенный к GPIO 26, и обновляет его состояние на веб-странице.

Кнопка для GPIO 27 работает аналогичным образом. Убедитесь, что все работает правильно.

Как работает код

В этом разделе мы подробно рассмотрим код, чтобы понять, как он работает.

Первое, что вам нужно сделать, это подключить библиотеку Wi-Fi.

// Подключаем библиотеку Wi-Fi
#include <WiFi.h>

Как упоминалось ранее, вам нужно вставить ваш SSID и пароль в следующие строки внутри двойных кавычек.

const char* ssid = "";
const char* password = "";

Затем установите порт веб-сервера на 80.

WiFiServer server(80);

Следующая строка создает переменную для хранения заголовка HTTP-запроса:

String header;

Далее создаем вспомогательные переменные для хранения текущего состояния ваших выходов. Если вы хотите добавить больше выходов и сохранять их состояние, вам нужно создать дополнительные переменные.

String output26State = "off";
String output27State = "off";

Также необходимо присвоить каждому из ваших выходов вывод GPIO. Здесь мы используем GPIO 26 и GPIO 27. Вы можете использовать любые другие подходящие выводы GPIO.

const int output26 = 26;
const int output27 = 27;

Функция setup()

Теперь давайте рассмотрим функцию setup(). Сначала мы запускаем серийную связь на скорости 115200 для целей отладки.

Serial.begin(115200);

Также определяем ваши выводы GPIO как выходы и устанавливаем их в LOW.

  // Инициализируем выходные переменные как выходы
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
// Устанавливаем выходы в LOW digitalWrite(output26, LOW); digitalWrite(output27, LOW);

Следующие строки начинают подключение к Wi-Fi с помощью функции WiFi.begin(ssid, password), ожидают успешного подключения и выводят IP-адрес ESP на серийный монитор.

  // Подключаемся к Wi-Fi сети с использованием SSID и пароля
  Serial.print("Подключение к ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Выводим локальный IP-адрес и запускаем веб-сервер
  Serial.println("");
  Serial.println("Wi-Fi подключен.");
  Serial.println("IP-адрес: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

Функция loop()

В функции loop() мы программируем, что происходит, когда новый клиент устанавливает соединение с веб-сервером.

ESP32 постоянно слушает входящие подключения клиентов с помощью следующей строки:

WiFiClient client = server.available();   // Ожидаем подключения клиентов

Когда от клиента поступает запрос, мы сохраняем входящие данные. Цикл while, который следует за этим, будет выполняться, пока клиент остается подключенным. Мы не рекомендуем изменять следующую часть кода, если вы точно не знаете, что делаете.

  if (client) {                             // Если новый клиент подключается,
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("Новый клиент.");          // выводим сообщение в серийный монитор
    String currentLine = "";                // создаем строку для хранения данных от клиента
    while (client.connected() && currentTime - previousTime <= timeoutTime) {  // продолжаем, пока клиент подключен
      currentTime = millis();
      if (client.available()) {             // если есть данные от клиента,
        char c = client.read();             // читаем байт
        Serial.write(c);                    // выводим его в серийный монитор
        header += c;
        if (c == '\n') {                    // если байт — символ новой строки
          if (currentLine.length() == 0) {
            // HTTP-заголовки всегда начинаются с кода ответа (например, HTTP/1.1 200 OK)
            // и типа содержимого, чтобы клиент знал, что придет дальше, а затем идет пустая строка:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

Следующая секция if и else проверяет, какая кнопка была нажата на вашей веб-странице, и соответственно управляет выходами. Как мы уже видели ранее, запрос отправляется на разные URL-адреса в зависимости от нажатой кнопки.

// включает и выключает GPIO
if (header.indexOf("GET /26/on") >= 0) {
  Serial.println("GPIO 26 включен");
  output26State = "on";
  digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
  Serial.println("GPIO 26 выключен");
  output26State = "off";
  digitalWrite(output26, LOW);
} else if (header.indexOf("GET /27/on") >= 0) {
  Serial.println("GPIO 27 включен");
  output27State = "on";
  digitalWrite(output27, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
  Serial.println("GPIO 27 выключен");
  output27State = "off";
  digitalWrite(output27, LOW);
}

Например, если вы нажали кнопку "Включить" для GPIO 26, ESP32 получит запрос на URL /26/on (мы можем увидеть эту информацию в HTTP-заголовке на серийном мониторе). Соответственно, мы проверяем, содержит ли заголовок выражение "GET /26/on". Если содержит, мы изменяем переменную output26State на "on", и ESP32 включает светодиод.

Это работает аналогичным образом для других кнопок. Таким образом, если вы хотите добавить больше выходов, вам следует изменить эту часть кода, чтобы включить их.

Отображение HTML-страницы

Следующее, что нужно сделать, — это создать веб-страницу. ESP32 будет отправлять ответ вашему браузеру с HTML-кодом для построения веб-страницы.

Веб-страница отправляется клиенту с помощью выражения client.println(). В качестве аргумента вы должны ввести то, что хотите отправить клиенту.

Первое, что мы должны отправить, это всегда следующая строка, которая указывает, что мы отправляем HTML.

!DOCTYPE html><html

Далее следующая строка делает веб-страницу адаптивной в любом веб-браузере.

client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" );

Следующая строка используется для предотвращения запросов на favicon. — Вам не нужно беспокоиться об этой строке.

client.println("<link rel=\"icon\" href=\"data:,\">" );

Стилизация веб-страницы

Далее у нас есть CSS-текст для стилизации кнопок и внешнего вида веб-страницы. Мы выбираем шрифт Helvetica, определяем отображение содержимого как блок и выравниваем по центру.

client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");

Мы стилизуем наши кнопки с цветом #4CAF50, без границы, текстом белого цвета и с отступом: 16px 40px. Также устанавливаем текстовое оформление на "нет", задаем размер шрифта, отступы и курсор в виде указателя.

client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");

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

client.println(".button2 {background-color: #555555;}</style></head>");

Установка заголовка веб-страницы

В следующей строке вы можете установить заголовок вашей веб-страницы. Здесь у нас "ESP32 Веб-сервер", но вы можете изменить этот текст на любой другой по вашему желанию.

// Заголовок веб-страницы
client
.println("<body><h1>ESP32 Веб-сервер</h1>");

Отображение кнопок и соответствующего состояния

Затем вы пишете абзац, чтобы отобразить текущее состояние GPIO 26. Как видите, мы используем переменную output26State, чтобы состояние обновлялось мгновенно при изменении этой переменной.

client.println("<p>GPIO 26 - Состояние " + output26State + "</p>");

Затем мы отображаем кнопку включения или выключения в зависимости от текущего состояния GPIO. Если текущее состояние GPIO выключено, мы показываем кнопку "Включить", если нет, то кнопку "Выключить".

if (output26State == "off") {
  client.println("<p><a href=\"/26/on\"><button class=\"button\">ВКЛ</button></a></p>");
} else {
  client.println("<p><a href=\"/26/off\"><button class=\"button button2\">ВЫКЛ</button></a></p>");
} 

Мы используем тот же метод для GPIO 27.

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

Наконец, когда ответ завершен, мы очищаем переменную header и закрываем соединение с клиентом с помощью client.stop().

// Очистка переменной header
header = "";
// Закрытие соединения
client.stop();

Заключение

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

Комментарии
123
Прикольно
Предзаказ
Предзаказ успешно отправлен!
Имя *
Телефон *
Добавить в корзину
Название товара
100 тг
1 шт.
Перейти в корзину
Обратный звонок
Запрос успешно отправлен!
Имя *
Телефон *
Заказ в один клик
С помощью уведомлений о заказе можно не только получать актуальную информацию по заказу, но и иметь быстрый канал связи с магазином