Урок 2. Подключаем DHT11, DHT22 к ESP32, ESP8266. Показание на веб-странице.

Вы когда-нибудь хотели, чтобы датчики, разбросанные по всей квартире или дому, регулярно отправляли данные температуры и влажности на веб-сервер, и их можно будет посмотреть в любое время? Тогда этот урок ESP32 может стать для вас отправной точкой! В этом уроке ESP32 используется в качестве устройства управления, которое легко подключается к существующей сети Wi-Fi и создает веб-сервер. Когда любое подключенное устройство обращается к этому веб-серверу, ESP32 считывает температуру и относительную влажность с датчиков DHT11, DHT22 и отображает их в веб-браузере этого устройства. Вас заинтересовало, как это реализовать? Тогда давайте начнем!

Это может показаться устрашающим, но есть несколько уроков, с которыми вам следует ознакомиться, прежде чем приступать к этому уроку:

Схема подключения датчика DHT11, DHT22 к ESP32.

Подключить датчик DHT11, DHT22 к ESP32 довольно просто. Начните с размещения ESP32 на макетной плате.

Схема подключения датчика DHT11, DHT22 к ESP32

Теперь поместите датчик на макетную плату рядом с ESP32. Подключите вывод VCC на датчике к выводу 3,3 В на ESP32, и соедините контакты GND платы и датчика. Также подключите контакт данных датчика к контакту 4 на ESP32.

 веб-серверу, ESP32 считывает температуру и относительную влажность с датчиков DHT11, DHT22

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

Установка библиотеки датчиков DHT.

Взаимодействие с датчиками DHT11, DHT22- это достаточно сложно, поскольку у них есть собственный однопроводной протокол для передачи данных. И этот протокол требует точного времени. К счастью, нам не нужно сильно об этом беспокоиться, потому что мы собираемся использовать библиотеку DHT от Adafruit, которая позаботится почти обо всем. Библиотека работает как на архитектуре Arduino, так и на ESP.

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

Установка библиотеки датчиков DHT.

Отфильтруйте результаты поиска, набрав «DHT». Должна быть пара записей. Ищите библиотеку датчиков DHT от Adafruit. Щелкните эту запись и выберите «Установить».

библиотеку датчиков DHT от Adafruit

Библиотека датчиков DHT использует серверную часть поддержки Adafruit Sensor. Итак, найдите в диспетчере еще одну библиотеку «Adafruit Unified Sensor» и установите её тоже.

Adafruit Sensor

Создание веб-сервера ESP32 в режиме WiFi станции (STA).

Как следует из заголовка, мы собираемся настроить 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 должен отдать веб-страницу, показывающую температуру и относительную влажность.

 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;

Функция Setup ().

Мы настраиваем свой 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");

Основной цикл Loop().

Чтобы обрабатывать входящие 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");
}

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

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> вашего документа, этот метатег будет заставлять браузер обновлять страницу каждые две секунды.

Динамическая загрузка данных датчика с помощью AJAX.

Обновление веб-страницы не слишком практично, если у вас тяжелая веб-страница. Лучшим методом является использование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. Имеет одно из следующих значений.

  • 0: запрос не инициализирован
  • 1: соединение с сервером установлено
  • 2: запрос получен
  • 3: обработка запроса
  • 4: запрос завершен и готов ответ

Свойство status содержит статус объекта XMLHttpRequest. Имеет одно из следующих значений.

  • 200: «ОК»
  • 403: «Запрещено»
  • 404: «Страница не найдена»

Когда значение 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 к ESP8266 (NodeMCU). Выводим показание на веб-странице.

Как подключить DHT11, DHT22 датчик температуры и влажности к ESP32 и вывести полученные значения на веб-страницу рассмотрели. Сейчас посмотрим, как можно подключить датчик температуры и влажности DHT11, DHT22 к ESP8266 (NodeMCU), и что нужно изменить в коде для создания универсального скетча, который подойдет для ESP32 и ESP8266.

Подключаем DHT11, DHT22 к ESP8266 (NodeMCU). Выводим показание на веб-странице.

Если вы не работали с отладочной платой ESP8266 (NodeMCU) прочитайтеэто статью:

Что такое NodeMCU? Программируем в среде Arduino IDE.

Схема подключения DHT11, DHT22 к ESP8266 NodeMCU.

Подключим вывод VCC на датчике к выводу 3,3 В на NodeMCU, и вывод GND на плате соседим с вводом GND датчика. Также подключите контакт Data на датчике к контакту D4 на ESP8266 (NodeMCU).

Должно получиться что-то похожее на изображение, показанное ниже.

Схема подключения DHT11, DHT22 к ESP8266 NodeMCU.

Установка библиотеки датчиков DHT для работы с ESP8266 NodeMCU.

Если вы установили DHT библиотеку для ESP32, то устанавливать библиотеку для ESP8266 (NodeMCU) не нужно, так как библиотека используется одна для работы с обеими платами.Если у вас библиотека не установлена, установите библиотеку по инструкции, которая описана выше для ESP32.

Изменения в скетче для ESP8266 NodeMCU.

Первым делом, нам нужно изменить библиотеки для работы с 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) и вывод данных на веб-страницу.

Универсальный код для ESP32 end ESP8266.

Универсальный скетч подключения датчика температуры и влажности 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 Скетч DHT_esp32.ino3 Kb 1237 Скачать
Полный код с оформлением и AJAX DHT_esp32_full Полный код с оформлением и AJAX DHT_esp32_full.ino6 Kb 1314 Скачать
Универсальный код для ESP32 end ESP8266 Универсальный код для ESP32 end ESP8266.ino6 Kb 1429 Скачать

Комментарии

Ваше Имя*

Александр

Гость: Александр (16 января, 2023 в 21:08)

А как правильно считывать данные с датчика, если у меня акселерометр GY-61 и я использую mega 2560 + esp8266?

Владимир

Гость: Владимир (27 июля, 2022 в 11:15)

А как реализовать возможность построения графика на основе этих показаний ?

Максим

Гость: Максим (20 апреля, 2021 в 23:40)

Уже пол яндекса облазил. Где взять библиотеку WebServer.h?

Винер

Гость: Винер (28 декабря, 2020 в 16:46)

Годно, самая лучшая реализация!


Разработка проектов