Веб-сервер ESP8266 с DHT11/DHT22 – Температура и влажность с использованием Arduino IDE

В этом проекте вы создадите автономный веб-сервер на ESP8266, который отображает температуру и влажность с датчика DHT11 или DHT22 с использованием Arduino IDE. Веб-сервер, который вы создадите, доступен с любого устройства с браузером в вашей локальной сети.

Веб-сервер ESP8266 с DHT11/DHT22 — Температура и влажность с использованием Arduino IDE

В этом руководстве мы покажем, как создать два разных веб-сервера:

  • Веб-сервер #1: Асинхронный веб-сервер, который автоматически обновляет температуру и влажность без необходимости обновлять веб-страницу, с пользовательским CSS для стилизации веб-страницы.

  • Веб-сервер #2: Простой HTTP-веб-сервер, который отображает последние показания датчика при обновлении страницы в виде простого HTML.

Рекомендуемые ресурсы:

Узнайте больше о ESP8266 в нашем курсе: Home Automation using ESP8266.

Необходимые компоненты

Компоненты для проекта ESP8266 DHT веб-сервер

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

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

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

Перед тем как приступить к руководству, подключите датчик температуры и влажности DHT11 или DHT22 к ESP8266, как показано на следующей схеме.

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

В данном примере мы подключаем вывод данных DHT к GPIO5 (D1), но вы можете использовать любой другой подходящий GPIO. Прочитайте наше Руководство по GPIO ESP8266, чтобы узнать больше о GPIO ESP8266.

Если вы используете ESP-01, GPIO 2 — наиболее подходящий вывод для подключения к выводу данных DHT, как показано на следующей схеме.

Схема подключения ESP-01 с DHT11 DHT22

Установка библиотеки DHT для ESP8266

Для считывания данных с датчика DHT мы будем использовать библиотеку DHT от Adafruit. Для работы этой библиотеки также необходимо установить библиотеку Adafruit Unified Sensor. Выполните следующие шаги для установки этих библиотек.

  1. Откройте Arduino IDE и перейдите в Sketch > Include Library > Manage Libraries. Должен открыться менеджер библиотек.

  2. Введите «DHT» в поле поиска и установите библиотеку DHT от Adafruit.

Установка библиотеки Adafruit DHT
  1. После установки библиотеки DHT от Adafruit введите «Adafruit Unified Sensor» в поле поиска. Прокрутите вниз до конца, чтобы найти библиотеку, и установите её.

Установка библиотеки Adafruit Unified Sensor

После установки библиотек перезапустите Arduino IDE.


1. Асинхронный веб-сервер ESP8266

Для создания веб-сервера мы будем использовать библиотеку ESPAsyncWebServer, которая предоставляет простой способ создания асинхронного веб-сервера. Создание асинхронного веб-сервера имеет ряд преимуществ. Рекомендуем быстро ознакомиться с документацией библиотеки на странице GitHub.

Установка библиотек веб-сервера

Мы будем создавать веб-сервер с использованием следующих библиотек:

Вы можете установить эти библиотеки через менеджер библиотек Arduino IDE. Перейдите в Sketch > Include Library > Manage Libraries и найдите библиотеки по названию.

Код

Мы будем программировать ESP8266 с помощью Arduino IDE, поэтому у вас должно быть установлено дополнение ESP8266 в Arduino IDE. Если его нет, сначала следуйте этому руководству:

Откройте Arduino IDE и скопируйте следующий код.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide/
*********/

// Import required libraries
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

#define DHTPIN 5     // Digital pin connected to the DHT sensor

// Uncomment the type of sensor in use:
//#define DHTTYPE    DHT11     // DHT 11
#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);

// current temperature & humidity, updated in loop()
float t = 0.0;
float h = 0.0;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;    // will store last time DHT was updated

// Updates DHT readings every 10 seconds
const long interval = 10000;

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP8266 DHT Server</h2>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i>
    <span class="dht-labels">Temperature</span>
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-tint" style="color:#00add6;"></i>
    <span class="dht-labels">Humidity</span>
    <span id="humidity">%HUMIDITY%</span>
    <sup class="units">%</sup>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperature").textContent = this.responseText;
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("humidity").textContent = this.responseText;
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 10000 ) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DHT values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(t);
  }
  else if(var == "HUMIDITY"){
    return String(h);
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  dht.begin();

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println(".");
  }

  // Print ESP8266 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", String(t));
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", String(h));
  });

  // Start server
  server.begin();
}

void loop(){
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you updated the DHT values
    previousMillis = currentMillis;
    // Read temperature as Celsius (the default)
    float newT = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    //float newT = dht.readTemperature(true);
    // if temperature read failed, don't change t value
    if (isnan(newT)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      t = newT;
      Serial.println(t);
    }
    // Read Humidity
    float newH = dht.readHumidity();
    // if humidity read failed, don't change h value
    if (isnan(newH)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      h = newH;
      Serial.println(h);
    }
  }
}

Просмотреть исходный код

Вставьте ваши сетевые учётные данные в следующие переменные, и код будет работать сразу.

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

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

В следующих параграфах мы объясним, как работает код. Продолжайте чтение, если хотите узнать больше, или перейдите к разделу «Демонстрация», чтобы увидеть конечный результат.

Импорт библиотек

Сначала импортируем необходимые библиотеки.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
Настройка сетевых учётных данных

Вставьте ваши сетевые учётные данные в следующие переменные, чтобы ESP8266 мог подключиться к вашей локальной сети.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Определение переменных

Определите GPIO, к которому подключен вывод данных DHT. В данном случае он подключен к GPIO5 (D1).

#define DHTPIN 5     // Digital pin connected to the DHT sensor

Затем выберите тип используемого датчика DHT. В нашем примере мы используем DHT22. Если вы используете другой тип, вам просто нужно раскомментировать свой датчик и закомментировать все остальные.

#define DHTTYPE DHT22   // DHT 22 (AM2302)

Создайте объект DHT с типом и выводом, определёнными ранее.

DHT dht(DHTPIN, DHTTYPE);

Создайте объект AsyncWebServer на порту 80.

AsyncWebServer server(80);

Создайте переменные типа float для хранения текущих значений температуры и влажности. Температура и влажность обновляются в функции loop().

float t = 0.0;
float h = 0.0;

Создайте переменные таймера, необходимые для обновления показаний температуры каждые 10 секунд.

unsigned long previousMillis = 0;    // will store last time DHT was updated

// Updates DHT readings every 10 seconds
const long interval = 10000;
Создание веб-страницы

Перейдём к веб-странице сервера.

Веб-страница ESP8266 DHT сервера с подписями элементов

Как видно на рисунке выше, веб-страница отображает один заголовок и два абзаца. Один абзац для отображения температуры, а другой — для отображения влажности. Также есть два значка для стилизации страницы.

Давайте посмотрим, как создаётся эта веб-страница.

Весь HTML-текст со стилями хранится в переменной index_html. Теперь мы рассмотрим HTML-текст и узнаем, что делает каждая часть.

Следующий тег <meta> делает вашу веб-страницу адаптивной в любом браузере.

<meta name="viewport" content="width=device-width, initial-scale=1">

Тег <link> необходим для загрузки значков с сайта fontawesome.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
Стили

Между тегами <style></style> мы добавляем CSS для стилизации веб-страницы.

<style>
 html {
   font-family: Arial;
   display: inline-block;
   margin: 0px auto;
   text-align: center;
  }
  h2 { font-size: 3.0rem; }
  p { font-size: 3.0rem; }
  .units { font-size: 1.2rem; }
  .dht-labels{
    font-size: 1.5rem;
    vertical-align:middle;
    padding-bottom: 15px;
  }
</style>

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

html {
  font-family: Arial;
  display: inline-block;
  margin: 0px auto;
  text-align: center;
}

Мы устанавливаем размер шрифта для заголовка (h2), абзаца (p) и единиц измерения (.units) показаний.

h2 { font-size: 3.0rem; }
p { font-size: 3.0rem; }
.units { font-size: 1.2rem; }

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

dht-labels{
  font-size: 1.5rem;
  vertical-align:middle;
  padding-bottom: 15px;
}

Все предыдущие теги должны находиться между тегами <head> и </head>. Эти теги используются для включения содержимого, которое не отображается напрямую пользователю, например, теги <meta>, <link> и стили.

Тело HTML

Внутри тегов <body></body> мы добавляем содержимое веб-страницы.

Теги <h2></h2> добавляют заголовок на веб-страницу. В данном случае это текст «ESP8266 DHT server», но вы можете добавить любой другой текст.

<h2>ESP8266 DHT Server</h2>

Далее идут два абзаца. Один для отображения температуры, другой — для отображения влажности. Абзацы ограничиваются тегами <p> и </p>. Абзац для температуры выглядит следующим образом:

<p>
  <i class="fas fa-thermometer-half" style="color:#059e8a;"</i>
  <span class="dht-labels">Temperature</span>
  <span id="temperature">%TEMPERATURE%</span>
  <sup class="units">&deg;C</sup>
</p>

А абзац для влажности — в следующем фрагменте:

<p>
  <i class="fas fa-tint" style="color:#00add6;"></i>
  <span class="dht-labels">Humidity</span>
  <span id="humidity">%HUMIDITY%</span>
  <sup class="units">%</sup>
</p>

Теги <i> отображают значки fontawesome.

Как отображать значки

Чтобы выбрать значки, перейдите на сайт Font Awesome Icons.

Сайт Font Awesome Icons

Найдите нужный значок. Например, «thermometer».

Поиск значка термометра в Font Awesome

Нажмите на нужный значок. Затем просто скопируйте предоставленный HTML-текст.

<i class="fas fa-thermometer-half">
HTML-код значка термометра Font Awesome

Чтобы выбрать цвет, вам просто нужно передать параметр style с цветом в шестнадцатеричном формате, как показано ниже:

<i class="fas fa-tint" style="color:#00add6;"></i>

Продолжим с HTML-текстом…

Следующая строка записывает слово «Temperature» на веб-страницу.

<span class="dht-labels">Temperature</span>

Текст TEMPERATURE между знаками % является заполнителем для значения температуры.

<span id="temperature">%TEMPERATURE%</span>

Это означает, что текст %TEMPERATURE% является своеобразной переменной, которая будет заменена фактическим значением температуры с датчика DHT. Заполнители в HTML-тексте должны находиться между знаками %.

Наконец, мы добавляем символ градуса.

<sup class="units">&deg;C</sup>

Теги <sup></sup> делают текст надстрочным.

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

<p>
  <i class="fas fa-tint" style="color:#00add6;"></i>
  <span class="dht-labels">Humidity</span>
  <span id="humidity">%HUMIDITY%</span>
  <sup class="units">%</sup>
</p>
Автоматическое обновление

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

Скрипты в HTML-тексте должны находиться между тегами <script></script>.

<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperature").textContent = this.responseText;
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("humidity").textContent = this.responseText;
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 10000 ) ;
</script>

Для обновления температуры в фоновом режиме у нас есть функция setInterval(), которая выполняется каждые 10 секунд.

По сути, она отправляет запрос по URL /temperature для получения последнего значения температуры.

  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

Когда значение получено, оно обновляет HTML-элемент с id «temperature».

if (this.readyState == 4 && this.status == 200) {
  document.getElementById("temperature").textContent = this.responseText;
}

Таким образом, предыдущий раздел отвечает за асинхронное обновление температуры. Тот же процесс повторяется для показаний влажности.

Важно: поскольку датчик DHT довольно медленно получает показания, если вы планируете подключать несколько клиентов к ESP8266 одновременно, мы рекомендуем увеличить интервал запросов или убрать автоматическое обновление.

Процессор

Теперь нам нужно создать функцию processor(), которая будет заменять заполнители в нашем HTML-тексте фактическими значениями температуры и влажности.

String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(t);
  }
  else if(var == "HUMIDITY"){
    return String(h);
  }
  return String();
}

Когда запрашивается веб-страница, мы проверяем, содержит ли HTML какие-либо заполнители. Если найден заполнитель %TEMPERATURE%, мы возвращаем температуру, хранящуюся в переменной t.

if(var == "TEMPERATURE"){
  return String(t);
}

Если заполнитель — %HUMIDITY%, мы возвращаем значение влажности.

else if(var == "HUMIDITY"){
  return String(h);
}
setup()

В функции setup() инициализируем Serial Monitor для целей отладки.

Serial.begin(115200);

Инициализируем датчик DHT.

dht.begin();

Подключаемся к локальной сети и выводим IP-адрес ESP8266.

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.println("Connecting to WiFi..");
}

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

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(200, "text/plain", String(t));
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(200, "text/plain", String(h));
});

Когда мы делаем запрос по корневому URL, мы отправляем HTML-текст, хранящийся в переменной index_html (эта переменная хранится во flash-памяти — PROGMEM, поэтому нам нужно использовать функцию send_P()). Нам также нужно передать функцию processor, которая заменит все заполнители правильными значениями.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

Нам нужно добавить два дополнительных обработчика для обновления показаний температуры и влажности. Когда мы получаем запрос по URL /temperature, нам просто нужно отправить обновлённое значение температуры.

server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(200, "text/plain", String(t));
});

Тот же процесс повторяется для влажности.

server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(200, "text/plain", String(h));
});

Наконец, мы запускаем сервер.

server.begin();

В функции loop() мы получаем новые показания температуры от датчика каждые 10 секунд.

По сути, мы проверяем, пришло ли время получить новые показания датчика:

if (currentMillis - previousMillis >= interval) {

Если да, мы сохраняем новое значение температуры в переменной newT:

float newT = dht.readTemperature();

Если переменная newT содержит допустимое значение температуры, мы обновляем переменную t.

else {
  t = newT;
  Serial.println(t);
}

Тот же процесс повторяется для влажности.

// Read Humidity
float newH = dht.readHumidity();
// if humidity read failed, don't change h value
if (isnan(newH)) {
   Serial.println("Failed to read from DHT sensor!");
}
else {
  h = newH;
  Serial.println(h);
}

Вот, в общих чертах, как работает код.

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

После внесения необходимых изменений в скетч, загрузите код на ESP8266 (если вы не можете загрузить код на ESP8266, прочитайте это руководство по устранению неполадок).

Убедитесь, что выбраны правильная плата и COM-порт. Перейдите в Tools > Board и выберите модель ESP8266, которую вы используете. В нашем случае мы используем ESP8266 12-E NodeMCU Kit.

Выбор платы ESP8266 в Arduino IDE

Перейдите в Tools > Port и выберите COM-порт, к которому подключен ESP8266.

Выбор порта ESP8266 в Arduino IDE

Нажмите кнопку загрузки в Arduino IDE.

Примечание: если вы используете ESP-01, вам понадобится последовательный адаптер или FTDI программатор для загрузки кода.

IP-адрес ESP8266

После загрузки кода откройте Serial Monitor на скорости 115200 бод. Нажмите кнопку сброса ESP8266. IP-адрес ESP8266 будет напечатан в Serial Monitor, как показано на следующем рисунке.

IP-адрес ESP8266 в Serial Monitor

Демонстрация

В вашей локальной сети откройте браузер на любом устройстве и введите IP-адрес ESP8266. Должна отобразиться следующая веб-страница с последними показаниями датчика.

Демонстрация веб-сервера ESP8266 DHT11 DHT22

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


2. Простой HTTP-веб-сервер ESP8266

В этом разделе мы покажем, как создать простой HTTP-веб-сервер, который отображает температуру и влажность в виде простой HTML-страницы. Этот веб-сервер отправляет HTTP-ответ, когда ваш браузер делает запрос по IP-адресу ESP8266.

Веб-сервер ESP8266 с DHT на макетной плате

Видеодемонстрация

Сначала вы можете посмотреть видеодемонстрацию проекта веб-сервера ESP8266 ниже.

Код

Мы будем программировать ESP8266 с помощью Arduino IDE, поэтому у вас должно быть установлено дополнение ESP8266 в Arduino IDE. Если его нет, сначала следуйте этому руководству.

Откройте Arduino IDE и скопируйте следующий код.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com
*********/

// Including the ESP8266 WiFi library
#include <ESP8266WiFi.h>
#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

// Replace with your network details
const char* ssid = "YOUR_NETWORK_NAME";
const char* password = "YOUR_NETWORK_PASSWORD";

// Web Server on port 80
WiFiServer server(80);

// DHT Sensor
const int DHTPin = 5;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);

// Temporary variables
static char celsiusTemp[7];
static char fahrenheitTemp[7];
static char humidityTemp[7];

// only runs once on boot
void setup() {
  // Initializing serial port for debugging purposes
  Serial.begin(115200);
  delay(10);

  dht.begin();

  // Connecting to WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Starting the web server
  server.begin();
  Serial.println("Web server running. Waiting for the ESP IP...");
  delay(10000);

  // Printing the ESP IP address
  Serial.println(WiFi.localIP());
}

// runs over and over again
void loop() {
  // Listenning for new clients
  WiFiClient client = server.available();

  if (client) {
    Serial.println("New client");
    // bolean to locate when the http request ends
    boolean blank_line = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        if (c == '\n' && blank_line) {
            // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
            float h = dht.readHumidity();
            // Read temperature as Celsius (the default)
            float t = dht.readTemperature();
            // Read temperature as Fahrenheit (isFahrenheit = true)
            float f = dht.readTemperature(true);
            // Check if any reads failed and exit early (to try again).
            if (isnan(h) || isnan(t) || isnan(f)) {
              Serial.println("Failed to read from DHT sensor!");
              strcpy(celsiusTemp,"Failed");
              strcpy(fahrenheitTemp, "Failed");
              strcpy(humidityTemp, "Failed");
            }
            else{
              // Computes temperature values in Celsius + Fahrenheit and Humidity
              float hic = dht.computeHeatIndex(t, h, false);
              dtostrf(hic, 6, 2, celsiusTemp);
              float hif = dht.computeHeatIndex(f, h);
              dtostrf(hif, 6, 2, fahrenheitTemp);
              dtostrf(h, 6, 2, humidityTemp);
              // You can delete the following Serial.print's, it's just for debugging purposes
              Serial.print("Humidity: ");
              Serial.print(h);
              Serial.print(" %\t Temperature: ");
              Serial.print(t);
              Serial.print(" *C ");
              Serial.print(f);
              Serial.print(" *F\t Heat index: ");
              Serial.print(hic);
              Serial.print(" *C ");
              Serial.print(hif);
              Serial.print(" *F");
              Serial.print("Humidity: ");
              Serial.print(h);
              Serial.print(" %\t Temperature: ");
              Serial.print(t);
              Serial.print(" *C ");
              Serial.print(f);
              Serial.print(" *F\t Heat index: ");
              Serial.print(hic);
              Serial.print(" *C ");
              Serial.print(hif);
              Serial.println(" *F");
            }
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            // your actual web page that displays temperature and humidity
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println("<head></head><body><h1>ESP8266 - Temperature and Humidity</h1><h3>Temperature in Celsius: ");
            client.println(celsiusTemp);
            client.println("*C</h3><h3>Temperature in Fahrenheit: ");
            client.println(fahrenheitTemp);
            client.println("*F</h3><h3>Humidity: ");
            client.println(humidityTemp);
            client.println("%</h3><h3>");
            client.println("</body></html>");
            break;
        }
        if (c == '\n') {
          // when starts reading a new line
          blank_line = true;
        }
        else if (c != '\r') {
          // when finds a character on the current line
          blank_line = false;
        }
      }
    }
    // closing the client connection
    delay(1);
    client.stop();
    Serial.println("Client disconnected.");
  }
}

Просмотреть исходный код

Вставьте ваши сетевые учётные данные в следующие переменные, и код будет работать сразу.

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

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

Мы подробно объяснили работу очень похожего веб-сервера в предыдущем руководстве. Ознакомьтесь со следующим руководством для подробного объяснения каждой строки кода: Создание веб-сервера ESP8266.

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

Импорт библиотек

Импортируйте библиотеки DHT для чтения данных с датчика DHT и библиотеку ESP8266WiFi для создания веб-сервера:

#include <Adafruit_Sensor.h>
#include <DHT.h>
Тип датчика DHT

Раскомментируйте одну из следующих строк для типа датчика, который вы используете. Если вы используете датчик DHT22, вам не нужно ничего менять.

//#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
#define DHTTYPE DHT22     // DHT 22  (AM2302), AM2321
Настройка сетевых учётных данных

Вставьте ваши сетевые учётные данные в следующие переменные, чтобы ESP8266 мог подключиться к вашей локальной сети.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Инициализация датчика DHT

Определите GPIO, к которому подключен вывод данных DHT. В данном случае он подключен к GPIO5 (D1).

#define DHTPIN 5     // Digital pin connected to the DHT sensor

Создайте объект DHT с типом и выводом, определёнными ранее.

DHT dht(DHTPIN, DHTTYPE);
setup()

В функции setup() инициализируем датчик DHT.

dht.begin();
loop()

В функции loop() мы проверяем, есть ли новый клиент, делающий запрос:

if (client) {
    Serial.println("New client");
    // bolean to locate when the http request ends
    boolean blank_line = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

Когда новый клиент делает запрос, мы считываем влажность, температуру в градусах Цельсия и Фаренгейта и сохраняем их в переменных h, t и f:

float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);

Наконец, мы отправляем ответ клиенту с HTML-текстом для построения страницы, а также значениями температуры и влажности:

client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head></head><body><h1>ESP8266 - Temperature and Humidity</h1><h3>Temperature in Celsius: ");
client.println(celsiusTemp);
client.println("*C</h3><h3>Temperature in Fahrenheit: ");
client.println(fahrenheitTemp);
client.println("*F</h3><h3>Humidity: ");
client.println(humidityTemp);
client.println("%</h3><h3>");
client.println("</body></html>");

Температура и влажность отправляются клиенту в следующих переменных: celsiusTemp, fahrenheitTemp и humidityTemp.

Демонстрация

После внесения необходимых изменений загрузите код на ESP8266, как описано в предыдущем разделе.

Откройте Serial Monitor Arduino IDE на скорости 115200 бод. Через несколько секунд должен появиться ваш IP-адрес. В нашем случае это 192.168.1.95.

Arduino IDE Serial Monitor с IP-адресом ESP8266

Откройте любой браузер с устройства, подключённого к тому же роутеру, что и ваш ESP. Затем введите IP-адрес и нажмите Enter!

Простой DHT веб-сервер ESP8266

Теперь вы должны увидеть последние показания температуры и влажности. Для обновления показаний вам просто нужно обновить веб-страницу.

Устранение неполадок

Если ваш датчик DHT не может получить показания, прочитайте наше Руководство по устранению неполадок DHT, чтобы помочь решить проблему.

Заключение

В этом проекте мы показали, как отображать показания датчика DHT на веб-странице. Мы предоставили два примера: простой веб-сервер и асинхронный веб-сервер с автоматическим обновлением.

Теперь вы можете легко модифицировать предоставленные примеры для отображения показаний с других датчиков. Если вам нравятся ESP8266 и IoT-проекты, ознакомьтесь с некоторыми из наших ресурсов:

Вам также могут понравиться некоторые из наших самых популярных проектов с ESP8266: