Данным уроком начну серию уроков про ESP32 и ESP8266. ESP8266 и ESP32 стали достаточно популярными среди проектов, связанных с IoT или Wi-Fi. Это экономичные модули Wi-Fi, которые можно запрограммировать для создания автономного веб-сервера. Что очень радует!
Веб-сервер - это место, где хранятся, обрабатываются и отсылаются веб-страницы веб-клиентам. Веб-клиент - это не что иное, как веб-браузер на наших ноутбуках и смартфонах. Связь между клиентом и сервером происходит с использованием специального протокола, называемого протоколом передачи гипертекста (HTTP).
В этом протоколе клиент инициирует связь, отправляя запрос на конкретную веб-страницу с помощью HTTP, а сервер отдает содержимое этой веб-страницы, или сообщение об ошибке, если не может этого сделать (например: страница не найдена, ошибка 404). Страницы, которые отдает сервер, в основном представляют собой HTML-документы.
Одна из особенностей ESP32 заключается в том, что он может не только подключаться к существующей сети Wi-Fi и действовать как веб-сервер, но также может настраивать собственную сеть, позволяя другим устройствам напрямую подключаться к ней и получать доступ к веб-страницам. Это возможно, потому что ESP32 работает в трех разных режимах: режим станции (STA), режим точки доступа (AP) и оба режима одновременно.
ESP32 (ESP8266), который подключается к существующей сети Wi-Fi (созданной вашим беспроводным маршрутизатором), называется станцией (STA).
В режиме STA ESP32 получает IP от маршрутизатора, к которому он подключен. С этим IP-адресом он может настроить веб-сервер и отдавать веб-страницы на все подключенные устройства в существующей сети Wi-Fi .
ESP32 (ESP8266), который создает свою собственную сеть Wi-Fi и действует как концентратор (как Wi-Fi маршрутизатор) для одного или нескольких устройств, называется точкой доступа (AP). В отличие от Wi-Fi роутера, у него нет интерфейса для проводной сети. Итак, такой режим работы называется Soft Access Point (soft-AP). Также максимальное количество устройств, которые могут подключиться к нему, ограничено пятью.
В режиме AP ESP32 создает новую сеть Wi-Fi и устанавливает для нее SSID (имя сети) и IP-адрес. С этим IP-адресом он может отдавать веб-страницы на все подключенные устройства в своей собственной сети.
Теперь, когда мы знаем основы работы веб-сервера, и в каких режимах ESP32 может создавать веб-сервер, пришло время подключить к ESP32 два светодиода, которыми мы планируем управлять через WiFi.
Установка, прошивка платы ESP32 в Arduino IDE (Windows, Mac OS X, Linux)
Начните с размещения ESP32 на макетной плате. Затем подключите два светодиода к цифровым GPIO 4 и 5 через ограничительный резистор 220 Ом.
Когда вы закончите, у вас получится что-то похожее на изображение, показанное ниже.
Давайте разберемся, как же происходит управлениеустройствами через веб-сервер ESP32.
Когда вводите URL-адрес в веб-браузере и нажимаете ENTER, браузер отправляет HTTP-запрос (также известный как запрос GET) на веб-сервер. Задача веб-сервера - обработать этот запрос, сделав что-нибудь. Возможно, вы уже догадались, что мы собираемся контролировать устройство, обращаясь к определенному URL-адресу. Например, предположим, что мы ввели URL-адрес типа http://192.168.1.1/ledon в браузере. Затем браузер отправляет HTTP-запрос в ESP32 для обработки этого запроса. Когда ESP32 читает этот запрос, он знает, что пользователь хочет включить светодиод. Таким образом, он включает светодиод и отдает динамическую веб-страницу в браузер, показывая состояние светодиода: ВКЛ. Не так все это и сложно!
А теперь перейдем к самому интересному!
Как следует из заголовка, этот пример демонстрирует, как превратить ESP32 в точку доступа (AP) и отдавать веб-страницы для любого подключенного клиента. Для начала подключите ESP32 к компьютеру и загрузите код, который затем разберем более подробно.
#include <WiFi.h> #include <WebServer.h> /* Установите здесь свои SSID и пароль */ const char* ssid = "ESP32"; const char* password = "01234567"; /* Настройки IP адреса */ IPAddress local_ip(192,168,2,1); IPAddress gateway(192,168,2,1); IPAddress subnet(255,255,255,0); WebServer server(80); uint8_t LED1pin = 4; bool LED1status = LOW; uint8_t LED2pin = 5; bool LED2status = LOW; void setup() { Serial.begin(115200); pinMode(LED1pin, OUTPUT); pinMode(LED2pin, OUTPUT); WiFi.softAP(ssid, password); WiFi.softAPConfig(local_ip, gateway, subnet); delay(100); server.on("/", handle_OnConnect); server.on("/led1on", handle_led1on); server.on("/led1off", handle_led1off); server.on("/led2on", handle_led2on); server.on("/led2off", handle_led2off); server.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); if(LED1status) {digitalWrite(LED1pin, HIGH);} else {digitalWrite(LED1pin, LOW);} if(LED2status) {digitalWrite(LED2pin, HIGH);} else {digitalWrite(LED2pin, LOW);} } void handle_OnConnect() { LED1status = LOW; LED2status = LOW; Serial.println("GPIO4 Status: OFF | GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,LED2status)); } void handle_led1on() { LED1status = HIGH; Serial.println("GPIO4 Status: ON"); server.send(200, "text/html", SendHTML(true,LED2status)); } void handle_led1off() { LED1status = LOW; Serial.println("GPIO4 Status: OFF"); server.send(200, "text/html", SendHTML(false,LED2status)); } void handle_led2on() { LED2status = HIGH; Serial.println("GPIO5 Status: ON"); server.send(200, "text/html", SendHTML(LED1status,true)); } void handle_led2off() { LED2status = LOW; Serial.println("GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,false)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); } String SendHTML(uint8_t led1stat,uint8_t led2stat){ String ptr = "<!DOCTYPE html> <html>\n"; ptr +="<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; ptr +="<title>Управление светодиодом</title>\n"; ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; ptr +=".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"; ptr +=".button-on {background-color: #3498db;}\n"; ptr +=".button-on:active {background-color: #2980b9;}\n"; ptr +=".button-off {background-color: #34495e;}\n"; ptr +=".button-off:active {background-color: #2c3e50;}\n"; ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<h1>ESP32 Веб сервер</h1>\n"; ptr +="<h3>Режим точка доступа WiFi (AP)</h3>\n"; if(led1stat) {ptr +="<p>Состояние LED1: ВКЛ.</p><a class=\"button button-off\" href=\"/led1off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED1: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led1on\">ВКЛ.</a>\n";} if(led2stat) {ptr +="<p>Состояние LED2: ВКЛ.</p><a class=\"button button-off\" href=\"/led2off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED2: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led2on\">ВКЛ.</a>\n";} ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
После загрузки скетча откройте Serial Monitor со скоростью 115200 бод. И нажмите кнопку RESET на ESP32. Если все в порядке, то отобразится сообщение о запуске HTTP-сервера.
Затем найдите любое устройство, которое можно подключить к сети Wi-Fi - телефон, ноутбук и т. д. И найдите сеть под названием «ESP32». Подключитесь к сети с паролем «01234567».
После подключения к сети ESP32 AP, загрузите браузер и укажите адрес 192.168.1.1. ESP32 должен открыть веб-страницу, показывающую текущее состояние светодиодов, и две кнопки для управления ими.
Если одновременно взглянуть на монитор последовательного порта, то можно увидеть состояние контактов GPIO ESP32.
Теперь нажмите кнопку, чтобы включить LED1, следя за URL-адресом. После того, как вы нажали кнопку, ESP32 получит запрос URL-адреса / led1on . Затем он включит LED1 и обновит веб-страницу с новым статусом LED.
Он также покажет состояние вывода GPIO в последовательном мониторе порта.
Вы можете протестировать кнопку LED2 и убедиться, что она работает аналогичным образом.
Теперь давайте внимательнее посмотрим на код, и увидим, как он работает, чтобы вы могли изменить его в соответствии со своими потребностями.
Скетч начинается с подключения библиотеки WiFi.h. Эта библиотека предоставляет специальные методы WiFi для ESP32, которые мы вызываем для подключения к сети. После этого мы также подключаем библиотеку WebServer.h, в которой есть несколько доступных методов, которые помогут нам настроить сервер и обрабатывать входящие HTTP-запросы, не беспокоясь о деталях реализации на низком уровне.
#include <WiFi.h> #include <WebServer.h>
Когда мы устанавливаем ESP32 в режим точки доступа (AP), он создает сеть Wi-Fi. Следовательно, нам нужно установить его SSID, пароль, IP-адрес, маску IP-подсети и IP-шлюз.
/* Установите здесь свои SSID и пароль */ const char* ssid = "ESP32"; // Enter SSID here const char* password = "0123456"; //Enter Password here /* Настройки IP адреса */ IPAddress local_ip(192,168,2,1); IPAddress gateway(192,168,2,1); IPAddress subnet(255,255,255,0);
Затем мы объявляем объект библиотеки WebServer, чтобы получить доступ к его функциям. Конструктор этого объекта принимает порт (который сервер будет слушать) в качестве параметра. Поскольку 80 - порт по умолчанию для HTTP, мы будем использовать это значение. Теперь вы можете получить доступ к серверу без необходимости указывать порт в URL-адресе.
WebServer server(80);
После чего мы объявляем выводы GPIO ESP32, к которым подключены светодиоды, и их начальное состояние.
uint8_t LED1pin = 4; bool LED1status = LOW; uint8_t LED2pin = 5; bool LED2status = LOW;
Мы настраиваем наш HTTP-сервер перед его запуском. Прежде всего, мы открываем последовательное соединение для отладки и устанавливаем для GPIO значение OUTPUT.
Serial.begin(115200); pinMode(LED1pin, OUTPUT); pinMode(LED2pin, OUTPUT);
Затем мы настраиваем программную точку доступа для создания сети Wi-Fi, проверяя SSID, пароль, IP-адрес, маску IP-подсети и IP-шлюз.
WiFi.softAP(ssid, password); WiFi.softAPConfig(local_ip, gateway, subnet); delay(100);
Чтобы обрабатывать входящие HTTP-запросы, нам нужно указать, какой код выполнять при вызове конкретного URL. Для этого мы используем метод on . Этот метод принимает два параметра. Первый - это URL-путь, а второй - имя функции, которую мы хотим выполнить при переходе по этому URL-адресу.
Например, первая строка приведенного ниже фрагмента кода указывает, что, когда сервер получает HTTP-запрос по корневому ( / ) пути, он запускает handle_OnConnect() функцию. Обратите внимание, что указанный URL-адрес является относительным путем.
Точно так же нам нужно указать еще 4 URL-адреса для обработки двух состояний 2 светодиодов.
server.on("/", handle_OnConnect); server.on("/led1on", handle_led1on); server.on("/led1off", handle_led1off); server.on("/led2on", handle_led2on); server.on("/led2off", handle_led2off);
Мы не указали, что должен делать сервер, если клиент запрашивает любой URL-адрес, отличный от указанного в server.on(). Он должен ответить HTTP-статусом 404 (Not Found) и сообщением для пользователя. Мы также помещаем в функцию и используем server.onNotFound(), чтобы сообщить, что она должна выполнить ее, когда получит запрос на URI, который не был указан в server.on.
server.onNotFound(handle_NotFound);
Теперь, чтобы запустить наш сервер, мы вызываем метод begin объекта server.
server.begin(); Serial.println("HTTP server started");
Чтобы обрабатывать входящие HTTP-запросы, нам нужно вызвать handleClient() метод объекта сервера. Также мы меняем состояние светодиода по запросу.
void loop() { server.handleClient(); if(LED1status) {digitalWrite(LED1pin, HIGH);} else {digitalWrite(LED1pin, LOW);} if(LED2status) {digitalWrite(LED2pin, HIGH);} else {digitalWrite(LED2pin, LOW);} }
Затем нам нужно создать функцию, которую мы назначили корневому (/) URL с помощью server.on. В начале этой функции мы устанавливаем состояние обоих светодиодов на LOW (исходное состояние светодиодов) и выводим состояние светодиодов в последовательный монитор. Чтобы ответить на HTTP-запрос, мы используем метод send. Хотя метод может быть вызван с другим набором аргументов, его простейшая форма состоит из кода ответа HTTP.
В нашем случае мы отправляем код 200 (один из кодов состояния HTTP), который соответствует ответу OK - ответ получен. Затем мы указываем тип содержимого как «текст / html» и, наконец, вызываем пользовательскую функцию SendHTML (), которая создает динамическую HTML-страницу, содержащую состояние светодиодов.
void handle_OnConnect() { LED1status = LOW; LED2status = LOW; Serial.println("GPIO4 Status: OFF | GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,LED2status)); }
Точно так же нам нужно создать четыре функции для обработки запросов включения / выключения светодиодов и страницы ошибки 404.
void handle_led1on() { LED1status = HIGH; Serial.println("GPIO4 Status: ON"); server.send(200, "text/html", SendHTML(true,LED2status)); } void handle_led1off() { LED1status = LOW; Serial.println("GPIO4 Status: OFF"); server.send(200, "text/html", SendHTML(false,LED2status)); } void handle_led2on() { LED2status = HIGH; Serial.println("GPIO5 Status: ON"); server.send(200, "text/html", SendHTML(LED1status,true)); } void handle_led2off() { LED2status = LOW; Serial.println("GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,false)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); }
SendHTML() Функция отвечает за создание веб-страницы всякий раз, когда веб-сервер ESP32 получает запрос от веб-клиента. Он просто объединяет HTML-код в большую строку и возвращает server.send() функцию, которую мы обсуждали ранее. Функция принимает состояние светодиодов в качестве параметров для динамической генерации содержимого HTML.
Первый текст, который вы всегда должны отправить <! DOCTYPE>, который указывает на то, что мы посылаем HTML код.
String SendHTML(uint8_t led1stat,uint8_t led2stat){ String ptr = "<!DOCTYPE html> <html>\n";
Затем элемент <meta> viewport заставляет веб-страницу загружаться в любом браузере. В то время как тег title устанавливает заголовок страницы.
ptr +="<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; ptr +="<title>Управление светодиодом</title>\n";
Затем у нас есть CSS для стилизации кнопок и внешнего вида веб-страницы. Мы выбираем шрифт Helvetica, определяем контент, который будет отображаться, в виде встроенного блока, и выравниваться по центру.
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
Затем следующий код устанавливает цвет, шрифт и поля тегов H1, H3 и p.
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
Дальше прописывая стили, которые применяются к кнопкам, указав свойства: цвет, размер, поля и т. д. Кнопки ВКЛ. и ВЫКЛ. имеют разный цвет фона, в то время как :active selector для кнопок обеспечивает эффект нажатия кнопки.
ptr +=".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"; ptr +=".button-on {background-color: #3498db;}\n"; ptr +=".button-on:active {background-color: #2980b9;}\n"; ptr +=".button-off {background-color: #34495e;}\n"; ptr +=".button-off:active {background-color: #2c3e50;}\n";
Далее задается заголовок веб-страницы. Вы можете изменить этот текст на любой, который подходит для вашего приложения.
ptr +="<h1>ESP32 Веб сервер</h1>\n"; ptr +="<h3>Режим точка доступа WiFi (AP)</h3>\n";
Чтобы динамически генерировать кнопки и статус светодиода, мы используем оператор if. Таким образом, в зависимости от состояния контактов GPIO отображается кнопка ВКЛ / ВЫКЛ.
if(led1stat) {ptr +="<p>Состояние LED1: ВКЛ.</p><a class=\"button button-off\" href=\"/led1off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED1: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led1on\">ВКЛ.</a>\n";} if(led2stat) {ptr +="<p>Состояние LED2: ВКЛ.</p><a class=\"button button-off\" href=\"/led2off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED2: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led2on\">ВКЛ.</a>\n";}
Теперь перейдем к нашему следующему примеру, который демонстрирует, как использовать ESP32 в режиме станции (STA) и выводить веб-страницы для любого подключенного клиента в сети.
Перед загрузкой кода, нужно внести некоторые изменения, чтобы все работало как нужно. Вам необходимо изменить две переменные с вашими сетевыми учетными данными, чтобы ESP32 мог установить соединение с существующей сетью.
Должен получиться вот такое код.
#include <WiFi.h> #include <WebServer.h> /* Установите здесь свои SSID и пароль */ const char* ssid = "Wi-Fi"; const char* password = "password"; WebServer server(80); uint8_t LED1pin = 4; bool LED1status = LOW; uint8_t LED2pin = 5; bool LED2status = LOW; void setup() { Serial.begin(115200); delay(100); pinMode(LED1pin, OUTPUT); pinMode(LED2pin, OUTPUT); Serial.println("Connecting to "); Serial.println(ssid); //connect to your local wi-fi network WiFi.begin(ssid, password); //check wi-fi is connected to wi-fi network while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP()); server.on("/", handle_OnConnect); server.on("/led1on", handle_led1on); server.on("/led1off", handle_led1off); server.on("/led2on", handle_led2on); server.on("/led2off", handle_led2off); server.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); if(LED1status) {digitalWrite(LED1pin, HIGH);} else {digitalWrite(LED1pin, LOW);} if(LED2status) {digitalWrite(LED2pin, HIGH);} else {digitalWrite(LED2pin, LOW);} } void handle_OnConnect() { LED1status = LOW; LED2status = LOW; Serial.println("GPIO4 Status: OFF | GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,LED2status)); } void handle_led1on() { LED1status = HIGH; Serial.println("GPIO4 Status: ON"); server.send(200, "text/html", SendHTML(true,LED2status)); } void handle_led1off() { LED1status = LOW; Serial.println("GPIO4 Status: OFF"); server.send(200, "text/html", SendHTML(false,LED2status)); } void handle_led2on() { LED2status = HIGH; Serial.println("GPIO5 Status: ON"); server.send(200, "text/html", SendHTML(LED1status,true)); } void handle_led2off() { LED2status = LOW; Serial.println("GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,false)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); } String SendHTML(uint8_t led1stat,uint8_t led2stat){ String ptr = "<!DOCTYPE html> <html>\n"; ptr +="<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; ptr +="<title>Управление светодиодом</title>\n"; ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; ptr +=".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"; ptr +=".button-on {background-color: #3498db;}\n"; ptr +=".button-on:active {background-color: #2980b9;}\n"; ptr +=".button-off {background-color: #34495e;}\n"; ptr +=".button-off:active {background-color: #2c3e50;}\n"; ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<h1>ESP32 Веб сервер</h1>\n"; ptr +="<h3>Режим станции (STA)</h3>\n"; if(led1stat) {ptr +="<p>Состояние LED1: ВКЛ.</p><a class=\"button button-off\" href=\"/led1off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED1: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led1on\">ВКЛ.</a>\n";} if(led2stat) {ptr +="<p>Состояние LED2: ВКЛ.</p><a class=\"button button-off\" href=\"/led2off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED2: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led2on\">ВКЛ.</a>\n";} ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
После загрузки скетча откройте Serial Monitor со скоростью 115200 бод. И нажмите кнопку RESET на ESP32. Если все в порядке, он выведет динамический IP-адрес, полученный от вашего маршрутизатора, и покажет сообщение о запуске HTTP-сервера.
Затем загрузите браузер и укажите ему IP-адрес, отображаемый в последовательном мониторе порта. ESP32 должен сгенерировать веб-страницу, показывающую текущее состояние светодиодов, и две кнопки для управления ими.
Если посмотреть в монитор последовательного порта, то можно увидеть состояние контактов GPIO ESP32.
Теперь нажмите кнопку, чтобы включить LED1, следя за URL-адресом. После того, как вы нажмете кнопку, ESP32 получит запрос URL-адреса / led1on . Затем он включает LED1 и обновляет веб-страницу с новым статусом LED.
Данные также выводятся о состоянии вывода GPIO в последовательный монитор порта.
Вы можете протестировать кнопку LED2 и убедиться, что она работает аналогичным образом.
Если вы сравните этот код с предыдущим кодом, единственное отличие состоит в том, что мы не устанавливаем программную точку доступа, а подключаемся к существующей сети с помощью WiFi.begin() функции.
//connect to your local wi-fi network WiFi.begin(ssid, password);
Пока ESP32 пытается подключиться к сети, мы можем проверить статус подключения с помощью WiFi.status() функции.
//check wi-fi is connected to wi-fi network while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); }
Данная функция возвращает следующие статусы:
Как только ESP32 подключен к сети, в мониторе порта вы увидите IP-адрес, который выводит функция WiFi.localIP.
Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP());
Единственная разница между режимами AP и STA заключается в том, что один создает сеть, а другой присоединяется к существующей сети. Итак, остальная часть кода для обработки HTTP-запросов и обслуживания веб-страницы в режиме STA такая же, как и в режиме AP, описанном выше, которая включает в себя:
Создание веб-сервера на ESP32 мы с вами рассмотрели. Сейчас посмотрим, что нужно изменить, чтобы данный код был применим и для ESP8266. Для этого нам нужно рассмотреть схему подключения.
Не смотря на то, что распиновка плат отличается, в примере для обеих плат будем использовать GPIO D4 и D5. Это поможет объединить код в дальнейшем.
В итоге у нас должно получиться подключение как на схеме.
Давайте рассмотрим пример использования ESP8266 (NodeMCU) в качестве HTTP сервера в режиме Wi-Fi Station (STA). Прежде чем приступить к загрузке скетча, чтобы он у вас заработал, необходимо внести некоторые изменения. Чтобы ESP8266 мог установить соединение с существующей сетью, вам необходимо изменить две следующие переменные с учетными данными вашей сети.
После чего можно загрузить код в ESP8266 (NodeMCU).
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> // Определяем переменные wifi const char* ssid = "Wi-Fi"; const char* password = "password"; // Web интерфейс для устройства ESP8266WebServer server(80); uint8_t LED1pin = D4; uint8_t LED2pin = D5; bool LED1status = LOW; bool LED2status = LOW; void setup() { Serial.begin(115200); delay(100); pinMode(LED1pin, OUTPUT); pinMode(LED2pin, OUTPUT); Serial.println("Connecting to "); Serial.println(ssid); //connect to your local wi-fi network WiFi.begin(ssid, password); //check wi-fi is connected to wi-fi network while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP()); server.on("/", handle_OnConnect); server.on("/led1on", handle_led1on); server.on("/led1off", handle_led1off); server.on("/led2on", handle_led2on); server.on("/led2off", handle_led2off); server.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); if(LED1status) {digitalWrite(LED1pin, HIGH);} else {digitalWrite(LED1pin, LOW);} if(LED2status) {digitalWrite(LED2pin, HIGH);} else {digitalWrite(LED2pin, LOW);} } void handle_OnConnect() { LED1status = LOW; LED2status = LOW; Serial.println("GPIO4 Status: OFF | GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,LED2status)); } void handle_led1on() { LED1status = HIGH; Serial.println("GPIO4 Status: ON"); server.send(200, "text/html", SendHTML(true,LED2status)); } void handle_led1off() { LED1status = LOW; Serial.println("GPIO4 Status: OFF"); server.send(200, "text/html", SendHTML(false,LED2status)); } void handle_led2on() { LED2status = HIGH; Serial.println("GPIO5 Status: ON"); server.send(200, "text/html", SendHTML(LED1status,true)); } void handle_led2off() { LED2status = LOW; Serial.println("GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,false)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); } String SendHTML(uint8_t led1stat,uint8_t led2stat){ String ptr = "<!DOCTYPE html> <html>\n"; ptr +="<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; ptr +="<title>Управление светодиодом</title>\n"; ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; ptr +=".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"; ptr +=".button-on {background-color: #3498db;}\n"; ptr +=".button-on:active {background-color: #2980b9;}\n"; ptr +=".button-off {background-color: #34495e;}\n"; ptr +=".button-off:active {background-color: #2c3e50;}\n"; ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<h1>ESP8266 Веб сервер</h1>\n"; ptr +="<h3>Режим станции (STA)</h3>\n"; if(led1stat) {ptr +="<p>Состояние LED1: ВКЛ.</p><a class=\"button button-off\" href=\"/led1off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED1: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led1on\">ВКЛ.</a>\n";} if(led2stat) {ptr +="<p>Состояние LED2: ВКЛ.</p><a class=\"button button-off\" href=\"/led2off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED2: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led2on\">ВКЛ.</a>\n";} ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
После загрузки кода в ESP8266 NodeMCU, как и в примере с ESP32, в мониторе порта увидим знакомую информацию.
В работе данного примера нет ни каких изменений в сравнении с работай ESP32.
Первым делом нам нужно изменить библиотеки для работы с ESP8266.
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h>
Затем объявляем объект библиотеки ESP8266WebServer, чтобы получить доступ к ее функциям. Конструктор этого объекта в качестве параметра принимает номер порта (который сервер будет прослушивать).
// Web интерфейс для устройства ESP8266WebServer server(80);
GPIO у данной платы также обозначаются по другому, их следует также изменить.
uint8_t LED1pin = D4; uint8_t LED2pin = D5;
Осталось подправитьв HTML странице выводимую информацию. Здесь изменим заголовок страницы. Чтобы было понято, что данный пример работает на ESP8266.
ptr +="<h1>ESP8266 Веб сервер</h1>\n"; ptr +="<h3>Режим станции (STA)</h3>\n";
Изменить код для работы ESP8266 в режиме точки доступа (AP) будет не сложно. Это будет для вас домашнее задание.
Чтобы не плодить десятки версий кода для ESP32 и ESP8266, код можно объединить, что позволит, используя один скетч и прошивать ESP32 и ESP8266, достаточно только выбрать нужную плату в Arduino IDE.
#ifdef ESP8266 #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #else #include <WiFi.h> #include <WebServer.h> #endif // Определяем переменные wifi const char* ssid = "Wi-Fi"; const char* password = "password"; #ifdef ESP8266 // Web интерфейс для устройства ESP8266WebServer server(80); uint8_t LED1pin = D4; uint8_t LED2pin = D5; #else // Web интерфейс для устройства WebServer server(80); uint8_t LED1pin = 4; uint8_t LED2pin = 5; #endif bool LED1status = LOW; bool LED2status = LOW; void setup() { Serial.begin(115200); delay(100); pinMode(LED1pin, OUTPUT); pinMode(LED2pin, OUTPUT); Serial.println("Connecting to "); Serial.println(ssid); //connect to your local wi-fi network WiFi.begin(ssid, password); //check wi-fi is connected to wi-fi network while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP()); server.on("/", handle_OnConnect); server.on("/led1on", handle_led1on); server.on("/led1off", handle_led1off); server.on("/led2on", handle_led2on); server.on("/led2off", handle_led2off); server.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); if(LED1status) {digitalWrite(LED1pin, HIGH);} else {digitalWrite(LED1pin, LOW);} if(LED2status) {digitalWrite(LED2pin, HIGH);} else {digitalWrite(LED2pin, LOW);} } void handle_OnConnect() { LED1status = LOW; LED2status = LOW; Serial.println("GPIO4 Status: OFF | GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,LED2status)); } void handle_led1on() { LED1status = HIGH; Serial.println("GPIO4 Status: ON"); server.send(200, "text/html", SendHTML(true,LED2status)); } void handle_led1off() { LED1status = LOW; Serial.println("GPIO4 Status: OFF"); server.send(200, "text/html", SendHTML(false,LED2status)); } void handle_led2on() { LED2status = HIGH; Serial.println("GPIO5 Status: ON"); server.send(200, "text/html", SendHTML(LED1status,true)); } void handle_led2off() { LED2status = LOW; Serial.println("GPIO5 Status: OFF"); server.send(200, "text/html", SendHTML(LED1status,false)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); } String SendHTML(uint8_t led1stat,uint8_t led2stat){ String ptr = "<!DOCTYPE html> <html>\n"; ptr +="<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; ptr +="<title>Управление светодиодом</title>\n"; ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; ptr +=".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"; ptr +=".button-on {background-color: #3498db;}\n"; ptr +=".button-on:active {background-color: #2980b9;}\n"; ptr +=".button-off {background-color: #34495e;}\n"; ptr +=".button-off:active {background-color: #2c3e50;}\n"; ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n"; #ifdef ESP8266 ptr +="<h1>ESP8266 Веб сервер</h1>\n"; #else ptr +="<h1>ESP32 Веб сервер</h1>\n"; #endif ptr +="<h3>Режим станции (STA)</h3>\n"; if(led1stat) {ptr +="<p>Состояние LED1: ВКЛ.</p><a class=\"button button-off\" href=\"/led1off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED1: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led1on\">ВКЛ.</a>\n";} if(led2stat) {ptr +="<p>Состояние LED2: ВКЛ.</p><a class=\"button button-off\" href=\"/led2off\">ВЫКЛ.</a>\n";} else {ptr +="<p>Состояние LED2: ВЫКЛ.</p><a class=\"button button-on\" href=\"/led2on\">ВКЛ.</a>\n";} ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
Вод такой код получается. Пояснять его не буду. Тут добавились 3 условия, а остальной код мы рассмотрели выше.
На этом урок заканчиваю. Если вам понравился Урок, не забудьте нажать на сердечко в правой колонке сверху страницы, или ниже статьи, если вы читаете с телефона.
Понравился Урок 1. Веб-сервер ESP32 (ESP8266) в среде Arduino IDE? Не забудь поделиться с друзьями в соц. сетях.
А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в группу на Facebook.
Спасибо за внимание!
Технологии начинаются с простого!
Фотографии к статье
Файлы для скачивания
![]() |
ESP32_AP.ino | 4 Kb | 2496 | Скачать |
![]() |
ESP32_STA.ino | 4 Kb | 2332 | Скачать |
![]() |
esp8266_STA.ino | 4 Kb | 2317 | Скачать |
![]() |
ESP32_and_esp8266_STA.ino | 4 Kb | 2202 | Скачать |
![]() |
ESP8266_AP.ino | 4 Kb | 2573 | Скачать |
А как ещё добавить физические кнопки?
у меня не выходит прошит модуль 12F отдельный
Пробовал Тасмоту управляя 2я кнопками с телефона, но проработал не долго стоило только сделать перезагрузку
Через ардуино не получается залить скетч ругается не подключено
все норм. а как получить платные консультации пт теме виртуино?
Статья конечно отличная. Но не хватает библиотеки WEBSERVER.H. Следуя инструкции установка и прошивка платы ESP32 библиотеки не установилось...
А у меня плата со встроенным дисплеем не хочет загораться!...
Ругается на <WebServer.h> Как называется библиотека? Их с пару десятков. Потыкал на обум - не выходит(( Подскажите пожалуйста.Ставиться вместе с ESP32. Получается что вы не настроили среду разработки. Установка, прошивка платы ESP32 в Arduino IDE (Windows, Mac OS X, Linux)
Ругается на <WebServer.h> Как называется библиотека? Их с пару десятков. Потыкал на обум - не выходит(( Подскажите пожалуйста...
Спасибо
Как сделать веб- сервер с использованием файловой системы esp?
А на 10 диодов 10 страниц делать? Так себе ваш урок.Вы о чем? в уроке используется всего 2 светодиода!
А на 10 диодов 10 страниц делать? Так себе ваш урок.
Уроки ESP32 и ESP8266
24 октября , 2020
Комментариев:11
Файлов для скачивания:5
Фото:9
Понравилась статья? Нажми
Виджеты для Easy HMI
Читайте также
Мы в соц сетях
Комментарии