ESP32 и три в одном: измеряем температуру, влажность и давление на одной плате

Подключаем датчик к ESP32 и измеряем температуру, влажность и давление на одной плате: схема, код и проверка показаний.
Если вы, как и я, увлекаетесь созданием собственных метеостанций или просто хотите мониторить климат в доме, серверной или теплице, то эта статья для вас. Сегодня мы соберём компактную и точную систему мониторинга на базе ESP32, которая будет измерять три ключевых параметра окружающей среды одновременно. И всё это — с помощью одной единственной платы расширения! Это идеальный проект для начала работы с ESP32, который даст реальный, полезный результат уже через час.
Зачем это нужно? От идеи к реализации
Зачем городить три отдельных датчика с кучей проводов, если можно использовать одну аккуратную плату? Современные комбинированные сенсоры, такие как BME280, — это чудо миниатюризации. Они объединяют в корпусе размером с монету высокоточные датчики температуры, относительной влажности и атмосферного давления. А ESP32 с её Wi-Fi и низким энергопотреблением — идеальный мозг для такого устройства. Полученные данные можно: * Отправлять в MQTT-брокер (например, в связке с Home Assistant). * Выводить на простой веб-сервер, доступный из браузера. * Логировать на SD-карту. * Использовать для автоматизации (включить увлажнитель, если влажность упала ниже 40%).
В этом руководстве мы пройдём весь путь: от распаковки компонентов до первого запуска веб-сервера с показаниями.
Что нам понадобится
- Плата ESP32 (любая). Я использую популярный ESP32 DevKit V1. Подойдёт практически любая версия.
- Датчик BME280. Обратите внимание: есть очень похожий датчик BMP280, который измеряет только давление и температуру (без влажности). Нам нужен именно BME280. Чаще всего он продаётся в виде готового модуля с встроенными подтягивающими резисторами и стабилизатором напряжения.
- Соединительные провода (папа-папа или папа-мама, в зависимости от ваших плат).
- USB-кабель для питания и программирования ESP32.
- Компьютер с установленной Arduino IDE или PlatformIO.
Подготовка среды разработки
Если вы впервые работаете с ESP32, рекомендую сначала заглянуть в мою статью ESP32 для начинающих: первый проект за 30 минут. Там подробно описана настройка Arduino IDE.
Вкратце, основные шаги:
1. Откройте Arduino IDE.
2. Перейдите в Файл -> Настройки.
3. В поле "Дополнительные ссылки для менеджера плат" вставьте URL:
https://espressif.github.io/arduino-esp32/package_esp32_index.json
4. Перейдите в Инструменты -> Плата -> Менеджер плат.
5. Найдите esp32 и установите последнюю версию платформы от Espressif Systems.
Теперь нужно установить библиотеку для работы с датчиком BME280. Самая популярная и простая — Adafruit BME280 Library.
- Перейдите в
Скетч->Подключить библиотеку->Управлять библиотеками.... - В поиске введите
Adafruit BME280. Установите библиотеку от Adafruit. - Важно! Эта библиотека зависит от ещё двух библиотек Adafruit. При установке IDE, скорее всего, предложит их установить. Соглашайтесь. Если не предложила, найдите и установите вручную:
Adafruit Unified SensorAdafruit BusIO
Схема подключения: проще некуда
Датчик BME280 поддерживает два интерфейса связи: I2C (используется по умолчанию) и SPI. Мы будем использовать I2C — для него нужно всего 4 провода.
Подключите датчик к ESP32 согласно следующей таблице:
| BME280 (выводы) | ESP32 (GPIO) | Назначение |
|---|---|---|
| VCC / Vin | 3.3V | Питание (3.3В!) |
| GND | GND | Земля |
| SCL | GPIO 22 | Тактовый сигнал I2C |
| SDA | GPIO 21 | Данные I2C |
⚠️ Типичная ошибка: Ни в коем случае не подключайте VCC датчика к пину 5V на ESP32! Большинство модулей BME280 рассчитаны на 3.3В. Подача 5В может мгновенно вывести датчик из строя.
Схема получается до смешного простой. После подключения ваша сборка должна выглядеть примерно так:
[ESP32] --(3.3V)--> [BME280.Vin]
[ESP32] --(GND)--> [BME280.GND]
[ESP32.GPIO22] --(SCL)--> [BME280.SCL]
[ESP32.GPIO21] --(SDA)--> [BME280.SDA]
Первый скетч: проверка связи и чтение данных
Давайте убедимся, что датчик подключён правильно и отвечает. Загрузите в Arduino IDE следующий скетч.
// Подключаем необходимые библиотеки
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
// Определяем высоту над уровнем моря для корректного расчёта давления (в метрах).
// Узнать свою высоту можно, например, в Google Maps.
#define SEALEVELPRESSURE_HPA (1013.25) // Давление на уровне моря, можно уточнить по погоде
// Создаём объект датчика
Adafruit_BME280 bme;
void setup() {
// Инициализируем последовательный порт для вывода данных в монитор
Serial.begin(115200);
Serial.println(F("Тест датчика BME280"));
// Инициализируем датчик. Метод begin() вернёт true, если датчик найден.
bool status = bme.begin(0x76); // Адрес 0x76 чаще всего используется по умолчанию
// Если датчик не найден, попробуйте адрес 0x77: bme.begin(0x77);
if (!status) {
Serial.println("Ошибка! Не удалось найти датчик BME280. Проверьте схему подключения и адрес (0x76/0x77).");
while (1); // Зависаем в бесконечном цикле
}
Serial.println("Датчик BME280 инициализирован успешно!");
Serial.println();
}
void loop() {
// Читаем все показания с датчика
float temperature = bme.readTemperature(); // Температура в градусах Цельсия
float humidity = bme.readHumidity(); // Относительная влажность в %
float pressure = bme.readPressure() / 100.0F; // Давление в гектопаскалях (гПа, hPa)
float altitude = bme.readAltitude(SEALEVELPRESSURE_HPA); // Примерная высота в метрах
// Выводим данные в монитор порта
Serial.print("Температура = ");
Serial.print(temperature);
Serial.println(" °C");
Serial.print("Влажность = ");
Serial.print(humidity);
Serial.println(" %");
Serial.print("Давление = ");
Serial.print(pressure);
Serial.println(" гПа");
Serial.print("Примерная высота = ");
Serial.print(altitude);
Serial.println(" м");
Serial.println("-----------------------");
// Ждём 2 секунды перед следующим измерением
delay(2000);
}
Пояснения к коду:
* bme.begin(0x76) — пытается начать работу с датчиком по адресу I2C 0x76. Если скетч не работает и вы видите ошибку в мониторе, замените адрес на 0x77.
* bme.readPressure() / 100.0F — датчик возвращает давление в Паскалях. Делим на 100, чтобы получить более привычные гектопаскали (гПа), которые совпадают с миллибарами (мбар).
* bme.readAltitude(SEALEVELPRESSURE_HPA) — функция рассчитывает высоту на основе текущего давления и давления на уровне моря. Чем точнее вы укажете SEALEVELPRESSURE_HPA (можно взять из прогноза погоды для вашего региона), тем точнее будет расчёт.
Как прошить:
1. В Arduino IDE выберите плату ESP32 Dev Module (или вашу конкретную модель).
2. Выберите порт, на который определилась ваша ESP32.
3. Нажмите кнопку загрузки (стрелка вправо).
4. После успешной загрузки откройте Инструменты -> Монитор порта.
5. Убедитесь, что скорость (baud rate) в мониторе порта установлена в 115200.
Если всё сделано верно, вы увидите поток данных с вашего датчика каждые 2 секунды.
Создаём простой веб-сервер на ESP32
Выводить данные в монитор порта — это хорошо для отладки, но бесполезно в реальном устройстве. Давайте превратим ESP32 в мини-веб-сервер, который будет отдавать красивую страничку с показаниями по локальной сети Wi-Fi.
Для этого нам понадобится знать SSID и пароль от вашей Wi-Fi сети. Замените значения your_SSID и your_PASSWORD в скетче ниже на свои.
#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
// Настройки Wi-Fi
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
// Создаём объекты
WebServer server(80); // Веб-сервер на 80-м порту
Adafruit_BME280 bme;
#define SEALEVELPRESSURE_HPA (1013.25)
// HTML-страница, которая будет отправляться клиенту
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Метеостанция на ESP32</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 20px; background-color: #f0f0f0; }
.container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
h1 { color: #333; }
.sensor { margin: 25px 0; padding: 20px; border-radius: 10px; color: white; font-size: 1.8em; font-weight: bold; }
.temp { background: linear-gradient(135deg, #ff7e5f, #feb47b); }
.humi { background: linear-gradient(135deg, #36d1dc, #5b86e5); }
.pres { background: linear-gradient(135deg, #834d9b, #d04ed6); }
.value { font-size: 2.5em; margin: 10px 0; }
.unit { font-size: 0.7em; opacity: 0.9; }
.footer { margin-top: 30px; font-size: 0.9em; color: #777; }
</style>
</head>
<body>
<div class="container">
<h1>🌡️ Метеостанция ESP32 + BME280</h1>
<p>Данные обновляются автоматически каждые 5 секунд</p>
<div class="sensor temp">
<div>Температура</div>
<div class="value" id="temperature">--</div>
<div class="unit">градусов Цельсия</div>
</div>
<div class="sensor humi">
<div>Влажность</div>
<div class="value" id="humidity">--</div>
<div class="unit">процентов</div>
</div>
<div class="sensor pres">
<div>Давление</div>
<div class="value" id="pressure">--</div>
<div class="unit">гектопаскалей (гПа)</div>
</div>
<div class="footer">
<p>IP устройства: %IPADDRESS% | Дата сборки: %BUILD_DATE%</p>
</div>
</div>
<script>
// Функция для обновления данных через AJAX-запрос
function updateData() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.responseText);
document.getElementById("temperature").innerHTML = data.temp.toFixed(1);
document.getElementById("humidity").innerHTML = data.hum.toFixed(1);
document.getElementById("pressure").innerHTML = data.pres.toFixed(0);
}
};
xhr.open("GET", "/data", true); // Запрашиваем данные с эндпоинта /data
xhr.send();
}
// Обновляем данные сразу после загрузки страницы и каждые 5 секунд
updateData();
setInterval(updateData, 5000);
</script>
</body>
</html>
)rawliteral";
// Переменные для хранения последних прочитанных значений
float temp, hum, pres;
void handleRoot() {
// Динамически заменяем плейсхолдеры в HTML на реальные значения
String html = String(index_html);
html.replace("%IPADDRESS%", WiFi.localIP().toString());
html.replace("%BUILD_DATE%", String(__DATE__) + " " + String(__TIME__));
server.send(200, "text/html", html);
}
void handleData() {
// Формируем JSON-ответ с актуальными данными с датчика
String json = "{";
json += ""temp":" + String(temp) + ",";
json += ""hum":" + String(hum) + ",";
json += ""pres":" + String(pres);
json += "}";
server.send(200, "application/json", json);
}
void handleNotFound() {
server.send(404, "text/plain", "404: Not Found");
}
void setup() {
Serial.begin(115200);
// Инициализация датчика
if (!bme.begin(0x76)) { // Попробуйте 0x77, если не работает
Serial.println("Датчик BME280 не найден!");
while (1);
}
// Подключение к Wi-Fi
WiFi.begin(ssid, password);
Serial.print("Подключение к Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Подключено! IP-адрес: ");
Serial.println(WiFi.localIP());
// Настройка маршрутов веб-сервера
server.on("/", handleRoot); // Главная страница
server.on("/data", handleData); // JSON-данные для AJAX
server.onNotFound(handleNotFound); // Обработка несуществующих страниц
// Запуск сервера
server.begin();
Serial.println("HTTP-сервер запущен.");
}
void loop() {
// Обслуживаем клиентские запросы
server.handleClient();
// Периодически обновляем данные с датчика (раз в 2 секунды)
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate > 2000) {
lastUpdate = millis();
temp = bme.readTemperature();
hum = bme.readHumidity();
pres = bme.readPressure() / 100.0F;
// Также выводим в Serial для отладки
Serial.printf("Обновление: %.1f C, %.1f %%, %.0f гПаn", temp, hum, pres);
}
}
Что делает этот скетч:
1. Подключается к вашей Wi-Fi сети.
2. Запускает веб-сервер на стандартном 80-м порту.
3. По адресу / (например, http://192.168.1.100/) отдаёт красивую HTML-страницу.
4. По адресу /data отдаёт актуальные показания датчика в формате JSON.
5. Страница использует jаvascript (AJAX) для автоматического обновления данных каждые 5 секунд без перезагрузки.
Проверка результата
- Загрузите скетч в ESP32, предварительно подставив свои данные Wi-Fi.
- Откройте Монитор порта (скорость 115200). Вы должны увидеть процесс подключения к Wi-Fi, а затем IP-адрес, который получила ваша плата. Запишите этот адрес.
Подключение к Wi-Fi..... Подключено! IP-адрес: 192.168.1.100 HTTP-сервер запущен. - Откройте любой браузер на устройстве, подключённом к той же локальной сети (компьютер, смартфон).
- Введите в адресную строку IP-адрес вашей ESP32 (например,
http://192.168.1.100). - Готово! Вы должны увидеть стильную страницу с текущими температурой, влажностью и давлением, которые будут плавно обновляться.
Возможные проблемы и их решение: * "Датчик BME280 не найден!" в мониторе порта: Проверьте
Понравилась статья?
Поставьте лайк и сохраните полезный материал в закладки.
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
Что можно сделать на LILYGO T-Dongle S3: 10 практических проектов
ESP32 и MQTT: Подключаем датчик к Home Assistant за вечер
ESPHome: прошиваем ESP32 без единой строки кода. Визуальный путь к умному устройству
ESP: как Espressif переписала правила DIY-электроники
ESP32 Marauder: что это такое, как выбрать плату и где скачать прошивку
ESP32 Web Server: Управляем реле через браузер