ESP32 Веб-сервер – Arduino IDE
В этом проекте вы создадите автономный веб-сервер на ESP32, который управляет выходами (двумя светодиодами), используя среду программирования Arduino IDE. Веб-сервер адаптирован для мобильных устройств и доступен с любого устройства, имеющего браузер, в локальной сети. Мы покажем вам, как создать веб-сервер, и объясним работу кода шаг за шагом.
Мы рекомендуем следовать нашему последнему обновлённому руководству: Создание веб-сервера на ESP32: Полное руководство для начинающих.
Если вы хотите узнать больше о ESP32, ознакомьтесь с Руководством по началу работы с ESP32.
Обзор проекта
Прежде чем переходить непосредственно к проекту, важно описать, что будет делать наш веб-сервер, чтобы потом было проще следовать инструкциям.
Веб-сервер, который вы создадите, управляет двумя светодиодами, подключёнными к GPIO 26 и GPIO 27 платы ESP32;
Вы можете получить доступ к веб-серверу ESP32, введя IP-адрес ESP32 в браузере в локальной сети;
Нажимая кнопки на веб-сервере, вы можете мгновенно изменять состояние каждого светодиода.
Это простой пример, иллюстрирующий создание веб-сервера для управления выходами. Идея заключается в том, чтобы заменить эти светодиоды реле или любыми другими электронными компонентами, которыми вы хотите управлять.
Установка платы ESP32 в Arduino IDE
Для Arduino IDE существует дополнение, позволяющее программировать ESP32 с помощью Arduino IDE и его языка программирования. Следуйте одному из следующих руководств для подготовки вашей Arduino IDE:
Необходимые компоненты
Для этого урока вам понадобятся следующие компоненты:
Вы можете использовать ссылки выше или перейти напрямую на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!
Схема подключения
Начните со сборки схемы. Подключите два светодиода к ESP32, как показано на следующей принципиальной схеме – один светодиод подключён к GPIO 26, а другой к GPIO 27.
Примечание: Мы используем плату ESP32 DEVKIT DOIT с 36 контактами. Перед сборкой схемы убедитесь, что вы проверили распиновку вашей платы.
Код веб-сервера ESP32
Здесь мы приводим код, создающий веб-сервер ESP32. Скопируйте следующий код в Arduino IDE, но пока не загружайте его. Вам нужно внести некоторые изменения, чтобы он заработал.
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
// Load Wi-Fi library
#include <WiFi.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";
// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output26, OUTPUT);
pinMode(output27, OUTPUT);
// Set outputs to LOW
digitalWrite(output26, LOW);
digitalWrite(output27, LOW);
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// turns the GPIOs on and off
if (header.indexOf("GET /26/on") >= 0) {
Serial.println("GPIO 26 on");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("GPIO 26 off");
output26State = "off";
digitalWrite(output26, LOW);
} else if (header.indexOf("GET /27/on") >= 0) {
Serial.println("GPIO 27 on");
output27State = "on";
digitalWrite(output27, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
Serial.println("GPIO 27 off");
output27State = "off";
digitalWrite(output27, LOW);
}
// Display the HTML web page
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 to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
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>");
// Web Page Heading
client.println("<body><h1>ESP32 Web Server</h1>");
// Display current state, and ON/OFF buttons for GPIO 26
client.println("<p>GPIO 26 - State " + output26State + "</p>");
// If the output26State is off, it displays the ON button
if (output26State=="off") {
client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Display current state, and ON/OFF buttons for GPIO 27
client.println("<p>GPIO 27 - State " + output27State + "</p>");
// If the output27State is off, it displays the ON button
if (output27State=="off") {
client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
Настройка сетевых данных
Вам нужно изменить следующие строки, указав ваши сетевые данные: SSID и пароль. В коде есть комментарии, указывающие, где нужно внести изменения.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Загрузка кода
Теперь вы можете загрузить код, и веб-сервер сразу заработает. Выполните следующие шаги для загрузки кода в ESP32:
1) Подключите плату ESP32 к компьютеру;
2) В Arduino IDE выберите вашу плату в Tools > Board (в нашем случае мы используем плату ESP32 DEVKIT DOIT);
3) Выберите COM-порт в Tools > Port.
4) Нажмите кнопку Upload в Arduino IDE и подождите несколько секунд, пока код компилируется и загружается на вашу плату.
5) Дождитесь сообщения «Done uploading».
Определение IP-адреса ESP
После загрузки кода откройте монитор последовательного порта (Serial Monitor) на скорости 115200 бод.
Нажмите кнопку EN на ESP32 (сброс). ESP32 подключится к Wi-Fi и выведет IP-адрес ESP в мониторе последовательного порта. Скопируйте этот IP-адрес, так как он понадобится вам для доступа к веб-серверу ESP32.
Доступ к веб-серверу
Чтобы получить доступ к веб-серверу, откройте браузер, вставьте IP-адрес ESP32, и вы увидите следующую страницу. В нашем случае это 192.168.1.135.
Если вы посмотрите в монитор последовательного порта, вы увидите, что происходит в фоновом режиме. ESP получает HTTP-запрос от нового клиента (в данном случае вашего браузера).
Вы также можете увидеть другую информацию об HTTP-запросе.
Тестирование веб-сервера
Теперь вы можете проверить, правильно ли работает ваш веб-сервер. Нажимайте кнопки для управления светодиодами.
Одновременно вы можете наблюдать в мониторе последовательного порта, что происходит в фоновом режиме. Например, когда вы нажимаете кнопку для включения GPIO 26, ESP32 получает запрос по URL /26/on.
Когда ESP32 получает этот запрос, он включает светодиод, подключённый к GPIO 26, и обновляет его состояние на веб-странице.
Кнопка для GPIO 27 работает аналогичным образом. Проверьте, что она работает правильно.
Как работает код
В этом разделе мы подробнее рассмотрим код, чтобы понять, как он работает.
Первое, что вам нужно сделать – это подключить библиотеку WiFi.
#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 как выходы (OUTPUT) и устанавливаете их в состояние LOW.
// Initialize the output variables as outputs
pinMode(output26, OUTPUT);
pinMode(output27, OUTPUT);
// Set outputs to LOW
digitalWrite(output26, LOW);
digitalWrite(output27, LOW);
Следующие строки устанавливают Wi-Fi соединение с помощью WiFi.begin(ssid, password), ожидают успешного подключения и выводят IP-адрес ESP в мониторе последовательного порта.
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
loop()
В функции loop() мы программируем, что происходит, когда новый клиент устанавливает соединение с веб-сервером.
ESP32 постоянно прослушивает входящих клиентов с помощью следующей строки:
WiFiClient client = server.available(); // Listen for incoming clients
Когда запрос получен от клиента, мы сохраняем входящие данные. Цикл while, следующий далее, будет выполняться, пока клиент остаётся подключённым. Мы не рекомендуем изменять следующую часть кода, если вы точно не знаете, что делаете.
if (client) { // If a new client connects,
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
/ that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
Следующий раздел условий if и else проверяет, какая кнопка была нажата на вашей веб-странице, и соответственно управляет выходами. Как мы видели ранее, мы отправляем запрос на разные URL в зависимости от нажатой кнопки.
// turns the GPIOs on and off
if (header.indexOf("GET /26/on") >= 0) {
Serial.println("GPIO 26 on");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("GPIO 26 off");
output26State = "off";
digitalWrite(output26, LOW);
} else if (header.indexOf("GET /27/on") >= 0) {
Serial.println("GPIO 27 on");
output27State = "on";
digitalWrite(output27, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
Serial.println("GPIO 27 off");
output27State = "off";
digitalWrite(output27, LOW);
}
Например, если вы нажали кнопку GPIO 26 ON, 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. Мы также устанавливаем text-decoration на none, определяем размер шрифта, отступы и курсор в виде указателя.
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;}");
Мы также определяем стиль для второй кнопки со всеми свойствами ранее определённой кнопки, но с другим цветом. Это будет стиль для кнопки выключения (OFF).
client.println(".button2 {background-color: #555555;}</style></head>");
Установка заголовка веб-страницы
В следующей строке вы можете установить первый заголовок вашей веб-страницы. Здесь мы используем «ESP32 Web Server», но вы можете изменить этот текст на любой другой.
// Web Page Heading
client.println("<h1>ESP32 Web Server</h1>");
Отображение кнопок и соответствующего состояния
Затем вы пишете параграф для отображения текущего состояния GPIO 26. Как видите, мы используем переменную output26State, чтобы состояние обновлялось мгновенно при изменении этой переменной.
client.println("<p>GPIO 26 - State " + output26State + "</p>");
Затем мы отображаем кнопку ON или OFF в зависимости от текущего состояния GPIO. Если текущее состояние GPIO – выключено (off), мы показываем кнопку ON, в противном случае отображаем кнопку OFF.
if (output26State=="off") {
client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
}
Мы используем ту же процедуру для GPIO 27.
Закрытие соединения
Наконец, когда ответ заканчивается, мы очищаем переменную header и прекращаем соединение с клиентом с помощью client.stop().
// Clear the header variable
header = "";
// Close the connection
client.stop();
Подведение итогов
В этом руководстве мы показали вам, как создать веб-сервер на ESP32. Мы привели простой пример управления двумя светодиодами, но идея заключается в том, чтобы заменить эти светодиоды реле или любым другим выходом, которым вы хотите управлять. Для других проектов с ESP32 ознакомьтесь со следующими руководствами:
Источник: ESP32 Web Server – Arduino IDE