Метеостанция на ESP32: BME280, OLED, WiFi-отправка
Метеостанция на ESP32 у меня на балконе висит второй год: BME280 меряет температуру, влажность и давление, OLED показывает, раз в 10 минут данные уходят на narodmon — открытый сервис графиков. Собрана за один вечер из четырёх деталей: плата ESP32, BME280, OLED 0.96" I2C и корпус от старого термометра. Скетч на 100 строк, и через неделю видны тренды: как давление падает перед дождём, как влажность растёт после полива на лоджии, как температура в солнечный день уходит на 8-10 градусов выше уличной.
Ниже — сборка метеостанции на ESP32 с нуля: выбор датчика (BME280 против BMP280 и DHT22), подключение OLED на I2C, отправка данных на narodmon, ThingSpeak или в Telegram. Код, схема, цена деталей, грабли с давлением (BMP280 без влажности, BME280 с влажностью, но дороже) и компенсация высоты по опорному давлению. Логику датчика и дисплея можно «пощупать» в симуляторе платы до пайки — компонент bmp280 на A4/A5, oled на той же шине.
Датчик: BME280, BMP280 или DHT22
BME280 (300-400 ₽) меряет три параметра: температуру, влажность и давление. BMP280 (180-250 ₽) — только температуру и давление, без влажности. DHT22 (180-250 ₽) — температуру и влажность, без давления. Для метеостанции нужен BME280 — только он закрывает все три параметра с одной I2C-шины. BMP280 берут, когда влажность не нужна (высотомер, барометр), DHT22 — когда давление не нужно (теплица, микроклимат). Подробно — в уроке про DHT22 vs BME280.
- BME280: температура ±1 °C, влажность ±3% RH, давление ±1 гПа. I2C адрес 0x76 или 0x77.
- BMP280: только температура и давление, без влажности. На 100 ₽ дешевле.
- DHT22: только температура и влажность, без давления. Один провод, без I2C.
- SHT31: выше точность (±0,3 °C, ±2% RH), но без давления. 400-500 ₽.
- DS18B20: только температура, но водонепроницаемый — для уличного термометра.
Схема: BME280 + OLED на одной шине I2C
ESP32: SDA на GPIO21, SCL на GPIO22. BME280 и OLED 0.96" SSD1306 подключаются параллельно: SDA к GPIO21, SCL к GPIO22, VCC к 3V3, GND к GND. Адрес BME280 — 0x76 (или 0x77, смотря по перемычке), OLED — 0x3C. Два устройства на одной шине — норма для I2C, до 127 устройств по протоколу. Перед пайкой сканирую I2C сканером — в уроке про сканер I2C — и проверяю адреса.
В симуляторе датчик BMP280 эмулируется: двигаете ползунок давления — readPressure и readAltitude пересчитываются. OLED-дисплей показывает текст сразу, как на живом. Подробно про OLED и Adafruit_SSD1306 — в уроке про текст на OLED; про BMP280 и пересчёт высоты — в уроке про давление в мм рт. ст..
Отправка данных: narodmon, ThingSpeak, Telegram
narodmon — открытый сервис народного мониторинга: бесплатный, без аутентификации, GET-запросом. ESP32 раз в 10 минут шлёт HTTP GET на narodmon.ru/get?ID=XX&temp=22.5&hum=45&press=752 — и данные попадают в ваш график. ThingSpeak — аналог с аналитикой и пороговыми уведомлениями: 5 минут бесплатно, дальше — бесплатно с лимитами. Telegram-бот — для личных уведомлений: HTTPS POST в чат, без графиков. Лично я совмещаю: narodmon для истории, Telegram для тревог (температура ниже -20, давление упало за 6 часов).
#include <WiFi.h>#include <HTTPClient.h> const char* SSID = "HomeNet";const char* PASS = "passw0rd";const char* NARODMON_ID = "AB1234567890CD"; void sendToNarodmon(float t, float h, float p) { WiFiClient client; HTTPClient http; String url = "http://narodmon.ru/get?ID="; url += NARODMON_ID; url += "&temp="; url += String(t, 1); url += "&hum="; url += String(h, 0); url += "&press="; url += String(p, 0); http.begin(client, url); int code = http.GET(); if (code > 0) { Serial.print("narodmon OK: "); Serial.println(code); } else { Serial.print("narodmon FAIL: "); Serial.println(code); } http.end();} void setup() { Serial.begin(115200); WiFi.begin(SSID, PASS); while (WiFi.status() != WL_CONNECTED) delay(300); Serial.println(WiFi.localIP());} void loop() { float t = 22.5, h = 45.0, p = 752.0; // читаем из BME280 sendToNarodmon(t, h, p); delay(600000); // 10 минут}Скетч отправляет раз в 10 минут — narodmon разрешает не чаще 5 минут, иначе банит. ID датчика получаете на narodmon.ru после регистрации устройства: MAC-адрес платы в любом формате. HTTP-запрос подробно разобран в уроке про HTTP-запросы на ESP32; для HTTPS (ThingSpeak API) — BearSSL с проверкой корневого сертификата.
Питание: USB-БП, PowerBank, солнечная панель
ESP32 + BME280 + OLED тянут 80-120 мА в активном режиме и 10-20 мА в light sleep. USB-БП 5V/1A (200-300 ₽) — стандарт для уличной метеостанции, запитанной от розетки. PowerBank 10000 мАч с проходным зарядом — для автономной работы 2-3 дня. Солнечная панель 5V/2W + Li-ion 18650 с TP4056 — для полностью автономной работы, 1 неделя без солнца. Грабля: ESP32 в light sleep теряет WiFi, и при пробуждении переподключается 1-3 секунды. Подробно — в уроке про энергобюджет ESP32.
Грабли метеостанции, на которые я наступал
- BME280 на солнце: нагревается до 35-40 °C, показания температуры завышены на 5-8 °C. Только в тени, с вентиляцией.
- OLED на улице: выгорает за 6-12 месяцев на солнце. Только в тени или под козырьком, или TFT-дисплей.
- Давление в мм рт. ст.: BME280 отдаёт в гПа, перевод x 0.750062 — иначе 1013 гПа превратится в 1013 мм, а не 760.
- Высота по давлению: при изменении погоды уходит на ±50 м за сутки. Для высоты нужен GPS, для давления — BME280.
- WiFi-ребуты при отправке: http.end() обязателен, иначе WiFiClient не освобождается, и через 50 отправок плата зависает.