Вы когда-нибудь хотели, чтобы датчики, разбросанные по всей квартире или дому, регулярно отправляли данные температуры и влажности на веб-сервер, и их можно будет посмотреть в любое время? Тогда этот урок ESP32 может стать для вас отправной точкой! В этом уроке ESP32 используется в качестве устройства управления, которое легко подключается к существующей сети Wi-Fi и создает веб-сервер. Когда любое подключенное устройство обращается к этому веб-серверу, ESP32 считывает температуру и относительную влажность с датчиков DHT11, DHT22 и отображает их в веб-браузере этого устройства. Вас заинтересовало, как это реализовать? Тогда давайте начнем!
Это может показаться устрашающим, но есть несколько уроков, с которыми вам следует ознакомиться, прежде чем приступать к этому уроку:
Подключить датчик DHT11, DHT22 к ESP32 довольно просто. Начните с размещения ESP32 на макетной плате.
Теперь поместите датчик на макетную плату рядом с ESP32. Подключите вывод VCC на датчике к выводу 3,3 В на ESP32, и соедините контакты GND платы и датчика. Также подключите контакт данных датчика к контакту 4 на ESP32.
Когда вы закончите, у вас должно получиться что-то похожее на изображение, показанное ниже.
Взаимодействие с датчиками DHT11, DHT22- это достаточно сложно, поскольку у них есть собственный однопроводной протокол для передачи данных. И этот протокол требует точного времени. К счастью, нам не нужно сильно об этом беспокоиться, потому что мы собираемся использовать библиотеку DHT от Adafruit, которая позаботится почти обо всем. Библиотека работает как на архитектуре Arduino, так и на ESP.
Чтобы установить библиотеку, перейдите в Скетч> Подключить библиотеку> Управлять библиотеками ... Подождите, пока диспетчер библиотек загрузит индекс библиотек и обновит список установленных библиотек.
Отфильтруйте результаты поиска, набрав «DHT». Должна быть пара записей. Ищите библиотеку датчиков DHT от Adafruit. Щелкните эту запись и выберите «Установить».
Библиотека датчиков DHT использует серверную часть поддержки Adafruit Sensor. Итак, найдите в диспетчере еще одну библиотеку «Adafruit Unified Sensor» и установите её тоже.
Как следует из заголовка, мы собираемся настроить ESP32 в режим станции (STA) и создать веб-сервер для отображения веб-страницы для любого подключенного клиента в существующей сети.
Прежде чем вы отправитесь загружать скетч, вам нужно внести одно изменение, чтобы у вас все работало. Вам необходимо изменить следующие две переменные, указав ваши сетевые учетные данные, чтобы ESP32 смог установить соединение с существующей сетью.
/* Установите здесь свои SSID и пароль */ const char* ssid = "ESP32"; // Enter SSID here const char* password = "0123456"; //Enter Password here
После чего загрузите код, а затем мы разберем его более подробно.
#include <WiFi.h> #include <WebServer.h> #include "DHT.h" // Раскомментируйте одну из строк ниже в зависимости от того, какой датчик вы используете! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 /* Установите здесь свои SSID и пароль */ const char* ssid = "ESP32"; // Enter SSID here const char* password = "password"; //Enter Password here WebServer server(80); // DHT Sensor uint8_t DHTPin = 4; // Initialize DHT sensor. DHT dht(DHTPin, DHTTYPE); float Temperature; float Humidity; void setup() { Serial.begin(115200); delay(100); pinMode(DHTPin, INPUT); dht.begin(); 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.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); } void handle_OnConnect() { Temperature = dht.readTemperature(); // Gets the values of the temperature Humidity = dht.readHumidity(); // Gets the values of the humidity server.send(200, "text/html", SendHTML(Temperature,Humidity)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); } String SendHTML(float Temperaturestat,float Humiditystat){ 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>ESP32. Информация о температуре</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;}\n"; ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<div id=\"webpage\">\n"; ptr +="<h1>ESP32. Информация о температуре в помещении:</h1>\n"; ptr +="<p>Температура: "; ptr +=(int)Temperaturestat; ptr +="°C</p>"; ptr +="<p>Влажность: "; ptr +=(int)Humiditystat; ptr +="%</p>"; ptr +="</div>\n"; ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
После загрузки скетча откройте Serial Monitor со скоростью 115200 бод, и нажмите кнопку RESET на ESP32. Если все в порядке, он выведет динамический IP-адрес, полученный от вашего маршрутизатора, и покажет сообщение о запуске HTTP-сервера.
Затем загрузите браузер и укажите ему IP-адрес, отображаемый в последовательном мониторе порта. ESP32 должен отдать веб-страницу, показывающую температуру и относительную влажность.
Скетч начинается с подключения библиотеки WiFi.h. Эта библиотека предоставляет специальные методы WiFi для ESP32, которые мы вызываем для подключения к сети. После этого мы также подключаем библиотеку WebServer.h, в которой есть несколько доступных методов, которые помогут нам настроить сервер и обрабатывать входящие HTTP-запросы, не беспокоясь о реализации на низком уровне. Наконец, мы подключаем библиотеку DHT.h.
#include <WiFi.h> #include <WebServer.h> #include "DHT.h"
Далее нам нужно определить тип используемого датчика DHT. Раскомментируйте одну из строк ниже! В моем примере я использую датчик DHT11.
// Раскомментируйте одну из строк ниже в зависимости от того, какой датчик вы используете! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
Поскольку мы настраиваем ESP32 в режиме станции (STA), он подключится к существующей сети Wi-Fi. Следовательно, вам необходимо указать ему SSID и пароль вашей сети. Что и сделали перед загрузкой кода в ESP32.
/* Установите здесь свои SSID и пароль */ const char* ssid = "ESP32"; // Enter SSID here const char* password = "password"; //Enter Password here
Затем, объявляем объект библиотеки WebServer, чтобы получить доступ к его функциям. Конструктор этого объекта принимает порт (который сервер будет слушать) в качестве параметра. Поскольку 80 - порт по умолчанию для HTTP, мы будем использовать это значение. Теперь вы можете получить доступ к серверу без необходимости указывать порт в URL-адресе.
WebServer server(80);
Затем нам нужно определить номер контакта ESP32, к которому подключен контакт Data нашего датчика, и создать объект DHT. Таким образом, мы можем получить доступ к специальным функциям, связанным с библиотекой DHT.
// DHT Sensor uint8_t DHTPin = 4; // Initialize DHT sensor. DHT dht(DHTPin, DHTTYPE);
Создаем две переменные с плавающей запятой. Для температуры и влажности.
float Temperature; float Humidity;
Мы настраиваем свой HTTP-сервер перед его запуском. Затем, мы открываем последовательное соединение для отладки и устанавливаем GPIO на INPUT. Нам также необходимо инициализировать объект DHT с помощью begin() функции.
Serial.begin(115200); delay(100); pinMode(DHTPin, INPUT); dht.begin();
Теперь нам нужно подключиться к сети Wi-Fi с помощью WiFi.begin() функции. Функция принимает в качестве параметра SSID (сетевое имя) и пароль.
Serial.println("Connecting to "); Serial.println(ssid); //connect to your local wi-fi network WiFi.begin(ssid, password);
Пока ESP32 пытается подключиться к сети, мы можем проверить статус подключения с помощью функции WiFi.status () .
Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP());
Как только ESP32 подключится к сети, скетч выведет IP-адрес в последовательный монитор порта, назначенный ESP32, за что отвечает функция WiFi.localIP.
Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP());
Чтобы обрабатывать входящие HTTP-запросы, нам нужно указать, какой код выполнять при вызове конкретного URL. Для этого мы используем метод on . Этот метод принимает два параметра. Первый - это URL-путь, а второй - имя функции, которую мы хотим выполнить при переходе по этому URL-адресу.
Приведенный ниже код указывает, что когда сервер получает HTTP-запрос по корневому пути ( / ), он запускает handle_OnConnect функцию. Обратите внимание, что указанный URL-адрес является относительным путем.
server.on("/", handle_OnConnect);
Мы не указали, что должен делать сервер, если клиент запрашивает любой 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() метод объекта сервера.
server.handleClient();
Затем, нам нужно создать функцию, которую мы прикрепили к корневому (/) URL с помощью server.on. Помните? В начале этой функции мы получаем значения температуры и влажности с датчика. Чтобы ответить на HTTP-запрос, мы используем метод send . Хотя метод может быть вызван с другим набором аргументов, его простейшая форма состоит из кода ответа HTTP.
В нашем случае, мы отправляем код 200 (один из кодов состояния HTTP), который соответствует ответу OK - ответ получен. Затем, мы указываем тип содержимого как «текст / html» и, наконец, вызываем пользовательскую функцию SendHTML (), которая создает динамическую HTML-страницу, содержащую значения температуры и влажности.
void handle_OnConnect() { Temperature = dht.readTemperature(); // Gets the values of the temperature Humidity = dht.readHumidity(); // Gets the values of the humidity server.send(200, "text/html", SendHTML(Temperature,Humidity)); }
Точно так же нам нужно создать функцию для обработки страницы ошибки 404.
void handle_NotFound(){ server.send(404, "text/plain", "Not found"); }
SendHTML() Функция отвечает за создание веб-страницы всякий раз, когда веб-сервер ESP32 получает запрос от веб-клиента. Он просто объединяет HTML-код в большую строку и возвращает server.send() функцию, которую мы обсуждали ранее. Функция принимает значения температуры и влажности в качестве параметров для динамической генерации содержимого HTML.
Первый текст, который вы всегда должны отправить <! DOCTYPE>, указывающий на то, что мы посылаем HTML код.
String SendHTML(float Temperaturestat,float Humiditystat){ 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>ESP32. Информация о температуре</title>\n";
Затем у нас есть CSS для стилизации внешнего вида веб-страницы. Мы выбираем шрифт Helvetica, определяем контент, который будет отображаться, в виде встроенного блока, и выравниваться по центру.
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
Затем следующий код устанавливает цвет, шрифт и поля вокруг тегов H1 и p.
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n"; ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n";
Далее задается заголовок веб-страницы. Вы можете изменить этот текст на любой, который подходит для вашего приложения.
ptr +="<div id=\"webpage\">\n"; ptr +="<h1>ESP32. Информация о температуре в помещении:</h1>\n";
Чтобы динамически отображать значения температуры и влажности, мы помещаем эти значения в тег абзаца «p». Эти значения преобразуются в целые числа путем приведения типа переменной (int). Для отображения символа градуса мы используем HTML-объект & deg;
ptr +="<p>Температура: "; ptr +=(int)Temperaturestat; ptr +="°C</p>"; ptr +="<p>Влажность: "; ptr +=(int)Humiditystat; ptr +="%</p>";
Программисты часто пугаются дизайна, но немного усилий может сделать вашу веб-страницу более привлекательной и профессиональной. Скриншот ниже даст вам общее представление о том, что мы собираемся делать.
Давайте применим некоторый стиль к предыдущей HTML-странице. Для начала скопируйте и вставьте код ниже, полностью заменим SendHTML() функцию. Попробуйте новый код, а затем мы его детально разберем.
#include <WiFi.h> #include <WebServer.h> #include "DHT.h" // Раскомментируйте одну из строк ниже в зависимости от того, какой датчик вы используете! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 /* Установите здесь свои SSID и пароль */ const char* ssid = "Wi-Fi"; // Enter SSID here const char* password = "password"; //Enter Password here WebServer server(80); // DHT Sensor uint8_t DHTPin = 4; // Initialize DHT sensor. DHT dht(DHTPin, DHTTYPE); float Temperature; float Humidity; void setup() { Serial.begin(115200); delay(100); pinMode(DHTPin, INPUT); dht.begin(); 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.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); } void handle_OnConnect() { Temperature = dht.readTemperature(); // Gets the values of the temperature Humidity = dht.readHumidity(); // Gets the values of the humidity server.send(200, "text/html", SendHTML(Temperature,Humidity)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); } String SendHTML(float Temperaturestat,float Humiditystat){ 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 +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n"; ptr +="<title>ESP32. Информация о температуре</title>\n"; ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n"; ptr +="body{margin-top: 50px;}\n"; ptr +="h1 {margin: 50px auto 30px;}\n"; ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n"; ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n"; ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n"; ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n"; ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n"; ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n"; ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n"; ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n"; ptr +=".data{padding: 10px;}\n"; ptr +="</style>\n"; //ptr +="<meta http-equiv=\"refresh\" content=\"2\" >\n"; ptr +="<script>\n"; ptr +="setInterval(loadDoc,200);\n"; ptr +="function loadDoc() {\n"; ptr +="var xhttp = new XMLHttpRequest();\n"; ptr +="xhttp.onreadystatechange = function() {\n"; ptr +="if (this.readyState == 4 && this.status == 200) {\n"; ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n"; ptr +="};\n"; ptr +="xhttp.open(\"GET\", \"/\", true);\n"; ptr +="xhttp.send();\n"; ptr +="}\n"; ptr +="</script>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<div id=\"webpage\">\n"; ptr +="<h1>ESP32. Информация о температуре в помещении:</h1>\n"; ptr +="<div class=\"data\">\n"; ptr +="<div class=\"side-by-side temperature-icon\">\n"; ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n"; ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n"; ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n"; ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n"; ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n"; ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n"; ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n"; ptr +="</svg>\n"; ptr +="</div>\n"; ptr +="<div class=\"side-by-side temperature-text\">Температура</div>\n"; ptr +="<div class=\"side-by-side temperature\">"; ptr +=(int)Temperaturestat; ptr +="<span class=\"superscript\">°C</span></div>\n"; ptr +="</div>\n"; ptr +="<div class=\"data\">\n"; ptr +="<div class=\"side-by-side humidity-icon\">\n"; ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n"; ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n"; ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n"; ptr +="</svg>\n"; ptr +="</div>\n"; ptr +="<div class=\"side-by-side humidity-text\">Влажность</div>\n"; ptr +="<div class=\"side-by-side humidity\">"; ptr +=(int)Humiditystat; ptr +="<span class=\"superscript\">%</span></div>\n"; ptr +="</div>\n"; ptr +="</div>\n"; ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
Мы уже знаем, что объявление <! DOCTYPE> сообщает браузеру, что мы отправляем HTML-код, а элемент области просмотра <meta> заставляет веб-страницу реагировать. Единственное дополнение - мы собираемся использовать шрифты Google . У Google есть сотни веб-шрифтов, которые бесплатны для коммерческого и личного использования.
Для нашей веб-страницы мы будем использовать Google веб-шрифт Open Sans. Шрифт Google встроен с помощью тега ссылки в <head> вашего HTML-документа. Для нашей страницы мы выбрали 300 (светлый), 400 (обычный) и 600 (жирный) шрифт. Вы можете выбрать столько, сколько хотите, но имейте в виду, что выбор неиспользуемого шрифта увеличивает время загрузки страницы. Вы также можете добавить курсив, просто добавив символ «i» в конце веса шрифта, например: «400i» будет отображать курсив.
Обратите внимание, что вы не увидите шрифт Google без активного подключения к Интернету на устройстве, на котором вы собирайтесь получить доступ к этой странице. Шрифты Google загружаются на лету.
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 +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
Затем, мы собираемся применить шрифт Open Sans для всего нашего HTML. Нам также необходимо указать sans-serif в качестве резервного шрифта, чтобы обеспечить максимальную совместимость между браузерами / операционными системами. Если браузер не поддерживает первый шрифт, он пробует следующий шрифт.
ptr +="<title>ESP32. Информация о температуре</title>\n"; ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n"; ptr +="body{margin-top: 50px;}\n"; ptr +="h1 {margin: 50px auto 30px;}\n";
Затем нам нужно применить CSS стили для значков влажности и температуры, заголовков и фактических значений. Все эти три элемента сделаны встроенными и выравнены по вертикали. Фон иконок представляет собой круг с радиусом границы 50% и имеет высоту и ширину 30 пикселей.
ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n"; ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n"; ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n"; ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n"; ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n"; ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n"; ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n"; ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n"; ptr +=".data{padding: 10px;}\n"; ptr +="</style>\n";
Далее мы выводим показание температуры с помощью значка.
Значок температуры, на самом деле, представляет собой масштабируемую векторную графику (SVG), определенную в теге <svg>. Создание SVG не требует особых навыков программирования. Вы можете использовать Google SVG Editor для создания графики для своей страницы. После значка мы собираемся показать фактическое значение температуры с датчика.
ptr +="<div id=\"webpage\">\n"; ptr +="<h1>ESP32. Информация о температуре в помещении:</h1>\n"; ptr +="<div class=\"data\">\n"; ptr +="<div class=\"side-by-side temperature-icon\">\n"; ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n"; ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n"; ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n"; ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n"; ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n"; ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n"; ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n"; ptr +="</svg>\n"; ptr +="</div>\n"; ptr +="<div class=\"side-by-side temperature-text\">Температура</div>\n"; ptr +="<div class=\"side-by-side temperature\">"; ptr +=(int)Temperaturestat; ptr +="<span class=\"superscript\">°C</span></div>\n"; ptr +="</div>\n";
Далее мы выведем показания влажности с помощью этойиконки.
Опять же, это SVG. После вывода значения влажности закроем все открытые теги, такие как body и html.
ptr +="<div class=\"data\">\n"; ptr +="<div class=\"side-by-side humidity-icon\">\n"; ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n"; ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n"; ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n"; ptr +="</svg>\n"; ptr +="</div>\n"; ptr +="<div class=\"side-by-side humidity-text\">Влажность</div>\n"; ptr +="<div class=\"side-by-side humidity\">"; ptr +=(int)Humiditystat; ptr +="<span class=\"superscript\">%</span></div>\n"; ptr +="</div>\n";
Одно из улучшений, которое можно сделать - это автоматическое обновление страницы для обновления значения датчика.
Добавив один метатег в HTML-документ, можно указать браузеру автоматически перезагружать страницу с заданным интервалом.
<meta http-equiv="refresh" content="2" >
Поместите этот код в тег <head> вашего документа, этот метатег будет заставлять браузер обновлять страницу каждые две секунды.
Обновление веб-страницы не слишком практично, если у вас тяжелая веб-страница. Лучшим методом является использованиеJavascript и Xml ( AJAX ), чтобы мы могли запрашивать данные с сервера асинхронно (в фоновом режиме) без обновления страницы.
Объект XMLHttpRequest в JavaScript обычно используется для выполнения AJAX на веб-страницах. Он выполняет тихий запрос GET на сервере и обновляет элемент на странице. AJAX - это не новая технология или другой язык, это просто существующие технологии, используемые по-новому. Помимо этого, AJAX также позволяет:
Вот сценарий AJAX, который мы будем использовать. Поместите этот скрипт непосредственно перед закрытием тега </head>.
ptr +="<script>\n"; ptr +="setInterval(loadDoc,200);\n"; ptr +="function loadDoc() {\n"; ptr +="var xhttp = new XMLHttpRequest();\n"; ptr +="xhttp.onreadystatechange = function() {\n"; ptr +="if (this.readyState == 4 && this.status == 200) {\n"; ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n"; ptr +="};\n"; ptr +="xhttp.open(\"GET\", \"/\", true);\n"; ptr +="xhttp.send();\n"; ptr +="}\n"; ptr +="</script>\n";
Скрипт начинается с тега <script>, поскольку сценарий AJAX - это не что иное, как javascript, поэтому нам нужно записать его в теге <script>. Чтобы эта функция вызывалась многократно, мы будем использовать функцию javascript setInterval () . Она принимает два параметра - функцию, которая должна выполняться, и временной интервал (в миллисекундах), определяющий, как часто следует выполнять функцию.
ptr +="<script>\n"; ptr +="setInterval(loadDoc,200);\n";
В основе этого сценария лежит loadDoc() функция. Внутри этой функции создается XMLHttpRequest() объект. Этот объект используется для запроса данных с веб-сервера.
ptr +="function loadDoc() {\n"; ptr +="var xhttp = new XMLHttpRequest();\n";
xhttp.onreadystatechange() функция вызывается каждый раз, когда readyState изменяется. Свойство readyState содержит статус XMLHttpRequest. Имеет одно из следующих значений.
Свойство status содержит статус объекта XMLHttpRequest. Имеет одно из следующих значений.
Когда значение readyState равно 4, а состояние равно 200, означает, что ответ получен. Теперь обновляем содержимое элемента с id веб-страницы (div, в котором хранятся значения температуры и влажности).
ptr +="xhttp.onreadystatechange = function() {\n"; ptr +="if (this.readyState == 4 && this.status == 200) {\n"; ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n"; ptr +="};\n";
Затем HTTP-запрос инициируется с помощью функций open () и send ().
ptr +="xhttp.open(\"GET\", \"/\", true);\n"; ptr +="xhttp.send();\n"; ptr +="}\n";
Как подключить DHT11, DHT22 датчик температуры и влажности к ESP32 и вывести полученные значения на веб-страницу рассмотрели. Сейчас посмотрим, как можно подключить датчик температуры и влажности DHT11, DHT22 к ESP8266 (NodeMCU), и что нужно изменить в коде для создания универсального скетча, который подойдет для ESP32 и ESP8266.
Если вы не работали с отладочной платой ESP8266 (NodeMCU) прочитайтеэто статью:
Что такое NodeMCU? Программируем в среде Arduino IDE.
Подключим вывод VCC на датчике к выводу 3,3 В на NodeMCU, и вывод GND на плате соседим с вводом GND датчика. Также подключите контакт Data на датчике к контакту D4 на ESP8266 (NodeMCU).
Должно получиться что-то похожее на изображение, показанное ниже.
Если вы установили DHT библиотеку для ESP32, то устанавливать библиотеку для ESP8266 (NodeMCU) не нужно, так как библиотека используется одна для работы с обеими платами.Если у вас библиотека не установлена, установите библиотеку по инструкции, которая описана выше для ESP32.
Первым делом, нам нужно изменить библиотеки для работы с ESP8266.
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h>
Затем, объявляем объект библиотеки ESP8266WebServer, чтобы получить доступ к ее функциям. Конструктор этого объекта в качестве параметра принимает номер порта (который сервер будет прослушивать).
// Web интерфейс для устройства ESP8266WebServer server(80);
GPIO у данной платы также обозначаются по-другому, поэтому нужно внести изменение, подключим датчик к D4.
uint8_t LED1pin = D4; uint8_t LED2pin = D5;
Осталось подправить в HTML странице выводимую информацию. Здесь изменим заголовок страницы, чтоб было понято, что данный пример работает на ESP8266 (NodeMCU).
ptr +="<h1>ESP8266. Информация о температуре в помещении:</h1>\n";
Скетч подключения датчика температуры и влажности DHT11, DHT22 к ESP8266 (NodeMCU) и вывод данных на веб-страницу.
Универсальный скетч подключения датчика температуры и влажности DHT11, DHT22 к ESP8266 (ESP32) и вывод данных на веб-страницу.
Чтобы не плодить десятки версий кода для ESP32 и ESP8266, код можно объединить, что позволит, используя один скетч, прошивать ESP32 и ESP8266, достаточно только выбрать нужную плату в Arduino IDE.
#ifdef ESP8266 #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #else #include <WiFi.h> #include <WebServer.h> #endif #include "DHT.h" // Uncomment one of the lines below for whatever DHT sensor type you're using! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 /*Put your SSID & Password*/ const char* ssid = "Wi-Fi"; // Enter SSID here const char* password = "password"; //Enter Password here #ifdef ESP8266 // Web интерфейс для устройства ESP8266WebServer server(80); // DHT Sensor uint8_t DHTPin = D4; #else WebServer server(80); // DHT Sensor uint8_t DHTPin = 4; #endif // Initialize DHT sensor. DHT dht(DHTPin, DHTTYPE); float Temperature; float Humidity; void setup() { Serial.begin(115200); delay(100); pinMode(DHTPin, INPUT); dht.begin(); 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.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); } void handle_OnConnect() { Temperature = dht.readTemperature(); // Gets the values of the temperature Humidity = dht.readHumidity(); // Gets the values of the humidity server.send(200, "text/html", SendHTML(Temperature,Humidity)); } void handle_NotFound(){ server.send(404, "text/plain", "Not found"); } String SendHTML(float Temperaturestat,float Humiditystat){ 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 +="<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n"; ptr +="<title>Информация о температуре</title>\n"; ptr +="<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n"; ptr +="body{margin-top: 50px;}\n"; ptr +="h1 {margin: 50px auto 30px;}\n"; ptr +=".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n"; ptr +=".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n"; ptr +=".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n"; ptr +=".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n"; ptr +=".temperature-icon{background-color: #f39c12;width: 30px;height: 30px;border-radius: 50%;line-height: 40px;}\n"; ptr +=".temperature-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n"; ptr +=".temperature{font-weight: 300;font-size: 60px;color: #f39c12;}\n"; ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n"; ptr +=".data{padding: 10px;}\n"; ptr +="</style>\n"; //ptr +="<meta http-equiv=\"refresh\" content=\"2\" >\n"; ptr +="<script>\n"; ptr +="setInterval(loadDoc,200);\n"; ptr +="function loadDoc() {\n"; ptr +="var xhttp = new XMLHttpRequest();\n"; ptr +="xhttp.onreadystatechange = function() {\n"; ptr +="if (this.readyState == 4 && this.status == 200) {\n"; ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n"; ptr +="};\n"; ptr +="xhttp.open(\"GET\", \"/\", true);\n"; ptr +="xhttp.send();\n"; ptr +="}\n"; ptr +="</script>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<div id=\"webpage\">\n"; #ifdef ESP8266 ptr +="<h1>ESP8266. Информация о температуре в помещении:</h1>\n"; #else ptr +="<h1>ESP32. Информация о температуре в помещении:</h1>\n"; #endif ptr +="<div class=\"data\">\n"; ptr +="<div class=\"side-by-side temperature-icon\">\n"; ptr +="<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n"; ptr +="width=\"9.915px\" height=\"22px\" viewBox=\"0 0 9.915 22\" enable-background=\"new 0 0 9.915 22\" xml:space=\"preserve\">\n"; ptr +="<path fill=\"#FFFFFF\" d=\"M3.498,0.53c0.377-0.331,0.877-0.501,1.374-0.527C5.697-0.04,6.522,0.421,6.924,1.142\n"; ptr +="c0.237,0.399,0.315,0.871,0.311,1.33C7.229,5.856,7.245,9.24,7.227,12.625c1.019,0.539,1.855,1.424,2.301,2.491\n"; ptr +="c0.491,1.163,0.518,2.514,0.062,3.693c-0.414,1.102-1.24,2.038-2.276,2.594c-1.056,0.583-2.331,0.743-3.501,0.463\n"; ptr +="c-1.417-0.323-2.659-1.314-3.3-2.617C0.014,18.26-0.115,17.104,0.1,16.022c0.296-1.443,1.274-2.717,2.58-3.394\n"; ptr +="c0.013-3.44,0-6.881,0.007-10.322C2.674,1.634,2.974,0.955,3.498,0.53z\"/>\n"; ptr +="</svg>\n"; ptr +="</div>\n"; ptr +="<div class=\"side-by-side temperature-text\">Температура</div>\n"; ptr +="<div class=\"side-by-side temperature\">"; ptr +=(int)Temperaturestat; ptr +="<span class=\"superscript\">°C</span></div>\n"; ptr +="</div>\n"; ptr +="<div class=\"data\">\n"; ptr +="<div class=\"side-by-side humidity-icon\">\n"; ptr +="<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n"; ptr +="<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n"; ptr +="c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n"; ptr +="</svg>\n"; ptr +="</div>\n"; ptr +="<div class=\"side-by-side humidity-text\">Влажность</div>\n"; ptr +="<div class=\"side-by-side humidity\">"; ptr +=(int)Humiditystat; ptr +="<span class=\"superscript\">%</span></div>\n"; ptr +="</div>\n"; ptr +="</div>\n"; ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
Вот такой код получается. Пояснять его не буду. Тут добавились 3 условия, а остальной код мы рассмотрели выше.
На этом урок заканчиваю. Если вам понравился урок, не забудьте нажать на сердечко в правой колонке сверху страницы, или ниже статьи, если вы читаете с телефона.
Предыдущий урок: Урок 1. Веб-сервер ESP32 (ESP8266) в среде Arduino IDE
Понравился Урок 2. Подключаем DHT11, DHT22 к ESP32, ESP8266. Показание на веб-странице? Не забудь поделиться с друзьями в соц. сетях.
А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в группу на Facebook.
Спасибо за внимание!
Технологии начинаются с простого!
Фотографии к статье
Файлы для скачивания
![]() |
Скетч DHT_esp32.ino | 3 Kb | 1376 | Скачать |
![]() |
Полный код с оформлением и AJAX DHT_esp32_full.ino | 6 Kb | 1456 | Скачать |
![]() |
Универсальный код для ESP32 end ESP8266.ino | 6 Kb | 1607 | Скачать |
А как правильно считывать данные с датчика, если у меня акселерометр GY-61 и я использую mega 2560 + esp8266?
А как реализовать возможность построения графика на основе этих показаний ?
Уже пол яндекса облазил. Где взять библиотеку WebServer.h?
Годно, самая лучшая реализация!
Уроки ESP32 и ESP8266
12 ноября , 2020
Комментариев:4
Файлов для скачивания:3
Фото:8
Понравилась статья? Нажми
Виджеты для Easy HMI
Читайте также
Мы в соц сетях
Комментарии