Главная страница » ESP32 / ESP8266 » ESP32-CAM: как выводить температуру и данные датчиков поверх изображения
ESP32-CAM: как выводить температуру и данные датчиков поверх изображения
ESP32 / ESP8266

ESP32-CAM: как выводить температуру и данные датчиков поверх изображения

02.09.2026 82
ESP32-CAM: как выводить температуру и данные датчиков поверх изображения

Узнайте, как выводить температуру, влажность и давление поверх видеопотока ESP32-CAM. Подробный гайд с кодом, схемой и типичными ошибками.

Когда я впервые взял в руки ESP32-CAM, меня захватила сама идея: крошечная плата с камерой за пару сотен рублей, которая умеет снимать видео и отдавать его по Wi-Fi. Но довольно быстро пришло понимание — просто картинка с камеры это скучно. Настоящая магия начинается, когда ты накладываешь на видео живые данные с датчиков: температуру, влажность, давление, уровень CO₂. Представь: ты открываешь браузер и видишь не просто чёрно-белый (или цветной) поток с камеры в теплице, а сразу температуру воздуха, влажность грунта и уровень освещённости — всё в одном кадре.

Сегодня я покажу, как это сделать. Мы соберём устройство на базе ESP32-CAM, подключим к нему датчик температуры и влажности DHT22, а также, для полноты картины, BMP180 для давления. Всё это будет выводиться прямо поверх видеопотока. Поехали!

Зачем это нужно?

Сценариев масса. Вот лишь несколько, которые я сам считаю практически полезными:

  • Умная теплица или парник. Вы видите не только растения, но и микроклимат в реальном времени. Никаких отдельных приложений для датчиков — всё на одном экране.
  • Домашняя метеостанция с видеонаблюдением. Окно, балкон или крыльцо: температура за бортом + картинка с улицы.
  • Наблюдение за серверной или мастерской. Температура в помещении + визуальный контроль оборудования.
  • Мониторинг аквариума или террариума. Температура воды и воздуха, влажность — и всё это поверх видео.

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

Что нам понадобится

Вот полный список компонентов для этого проекта:

  • ESP32-CAM (модуль с камерой OV2640) — 1 шт.
  • USB-UART адаптер (например, CP2102 или CH340) для прошивки — 1 шт.
  • DHT22 (он же AM2302) — датчик температуры и влажности.
  • BMP180 — датчик атмосферного давления (по желанию, но с ним интереснее).
  • Резистор 10 кОм для подтяжки DHT22 (хотя у многих модулей он уже встроен).
  • Соединительные провода и макетная плата.
  • Блок питания 5V с током не менее 1А.

Важно: ESP32-CAM потребляет приличный ток, особенно при активной работе Wi-Fi и камеры. Не пытайтесь питать её от USB-порта компьютера через переходник — скорее всего, будут сбои и перезагрузки. Используйте отдельный блок питания.

Схема подключения

Подключение простое. Смотрим на распиновку ESP32-CAM:

  • GPIO 4 → DATA (пин 2) DHT22
  • 3.3V → VCC DHT22 и VCC BMP180
  • GND → GND обоих датчиков
  • GPIO 21 → SDA BMP180
  • GPIO 22 → SCL BMP180

Если ваш DHT22 — это модуль с распаянной подтяжкой, дополнительный резистор не нужен. Если используете голый датчик — обязательно поставьте резистор 10 кОм между DATA и VCC.

Настройка среды разработки

Для этого проекта я использую PlatformIO — это удобнее, чем Arduino IDE, особенно когда проект разрастается. Но если вы привыкли к Arduino IDE, весь код ниже без проблем скомпилируется и там.

Убедитесь, что у вас установлена поддержка плат ESP32. В PlatformIO это делается добавлением платформы в platformio.ini:

[env:esp32cam]
platform = espressif32
board = esp32cam
framework = arduino
monitor_speed = 115200
upload_speed = 921600

Обратите внимание на board = esp32cam — это готовая конфигурация для ESP32-CAM с правильным размером flash и PSRAM.

Пишем код: базовый веб-сервер с камерой

Начнём с основы — запустим видеопоток. Для этого я использую библиотеку esp32-camera, которая идёт в составе платформы ESP32.

#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>

// Настройки Wi-Fi
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

// Пин для DHT22
#define DHTPIN 4

// Модель камеры AI-Thinker
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM     0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM       5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

WebServer server(80);

void setup() {
  Serial.begin(115200);

  // Настройка камеры
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_VGA;   // 640x480
  config.jpeg_quality = 12;
  config.fb_count = 2;

  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Ошибка инициализации камеры: 0x%x", err);
    return;
  }

  // Подключение к Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi подключен");
  Serial.print("IP адрес: ");
  Serial.println(WiFi.localIP());

  // Маршруты
  server.on("/", HTTP_GET, handleRoot);
  server.on("/stream", HTTP_GET, handleStream);
  server.begin();
}

void loop() {
  server.handleClient();
}

Это базовый каркас. Теперь добавим обработчики маршрутов и, самое главное, наложение данных на изображение.

Наложение текста на изображение

Вот тут самое интересное. Есть два подхода:

  1. Наложение на стороне браузера — мы отдаём данные отдельно (например, в JSON) и рисуем их на HTML-странице поверх <img> или <canvas>.
  2. Наложение на стороне ESP32 — мы модифицируем JPEG-кадр прямо в памяти микроконтроллера.

Второй вариант сложнее, но именно он даёт настоящий оверлей, который будет виден в любом плеере, включая VLC и сторонние приложения. Именно его мы и реализуем.

Для рисования поверх JPEG нам понадобится библиотека TJpg_Decoder — она умеет не только декодировать, но и рисовать на кадре. Но есть нюанс: ESP32-CAM с PSRAM позволяет работать с кадром как с массивом байтов. Мы можем декодировать JPEG в RGB565, наложить текст, а затем снова закодировать в JPEG.

Это звучит сложнее, чем есть на самом деле. Давайте посмотрим на код:

#include "TJpg_Decoder.h"
#include <SPI.h>

// Буфер для RGB565 изображения
uint16_t* rgbBuffer;

// Функция для рисования текста на изображении
void drawTextOnImage(uint16_t* buffer, int width, int height, const char* text, int x, int y, uint16_t color) {
  // Используем встроенный шрифт TJpg_Decoder
  // Для простоты используем стандартный 5x7 шрифт
  while (*text) {
    // Здесь был бы код отрисовки символа
    // В реальном проекте используем библиотеку с шрифтами
    text++;
    x += 6;
  }
}

Стоп. Давайте честно: писать свой рендерер шрифтов — это отдельный квест. Гораздо проще использовать готовую библиотеку. Я рекомендую Adafruit GFX — она умеет рисовать текст в буфер, а мы просто передадим ей наш RGB565 буфер.

Вот как это выглядит на практике:

#include <Adafruit_GFX.h>

// Класс-обёртка для рисования в буфер
class RGB565Canvas : public Adafruit_GFX {
  public:
    RGB565Canvas(uint16_t* buffer, int w, int h) : Adafruit_GFX(w, h) {
      _buffer = buffer;
    }

    void drawPixel(int16_t x, int16_t y, uint16_t color) override {
      if (x < 0 || x >= width() || y < 0 || y >= height()) return;
      _buffer[y * width() + x] = color;
    }

  private:
    uint16_t* _buffer;
};

Теперь основная логика: получаем кадр с камеры, декодируем его в RGB565, рисуем текст, кодируем обратно в JPEG и отправляем клиенту.

// Буфер для RGB565
uint16_t* rgbBuffer = nullptr;
size_t rgbBufferSize = 0;

// Буфер для выходного JPEG
uint8_t* jpegBuffer = nullptr;
size_t jpegBufferSize = 0;

void processFrame(camera_fb_t* fb, uint8_t** outBuf, size_t* outLen) {
  // Проверяем, достаточно ли буфера
  size_t neededSize = fb->width * fb->height * 2;
  if (rgbBufferSize < neededSize) {
    if (rgbBuffer) free(rgbBuffer);
    rgbBuffer = (uint16_t*)ps_malloc(neededSize);
    rgbBufferSize = neededSize;
  }

  // Декодируем JPEG в RGB565
  TJpgDec.setJpgBuffer(fb->buf, fb->len);
  TJpgDec.convertToRgb565(rgbBuffer, fb->width, fb->height);

  // Создаём канвас и рисуем текст
  RGB565Canvas canvas(rgbBuffer, fb->width, fb->height);
  canvas.setTextColor(0xFFFF); // Белый
  canvas.setTextSize(2);

  // Читаем датчики
  float temp = readTemperature();
  float hum = readHumidity();
  float pressure = readPressure();

  // Формируем строки
  char line1[32];
  snprintf(line1, sizeof(line1), "Temp: %.1f C", temp);
  char line2[32];
  snprintf(line2, sizeof(line2), "Hum: %.1f %%", hum);
  char line3[32];
  snprintf(line3, sizeof(line3), "Press: %.0f hPa", pressure);

  // Рисуем полупрозрачный фон для текста
  canvas.fillRect(0, 0, 200, 50, 0x0000); // Чёрный прямоугольник

  // Выводим текст
  canvas.setCursor(5, 5);
  canvas.print(line1);
  canvas.setCursor(5, 25);
  canvas.print(line2);
  canvas.setCursor(5, 45);
  canvas.print(line3);

  // Кодируем обратно в JPEG
  if (jpegBufferSize < fb->width * fb->height * 2) {
    if (jpegBuffer) free(jpegBuffer);
    jpegBuffer = (uint8_t*)ps_malloc(fb->width * fb->height * 2);
    jpegBufferSize = fb->width * fb->height * 2;
  }

  // Используем JPEG encoder
  // Здесь нужна библиотека JPEGENC или аналог
  JPEGENC jpegEnc;
  jpegEnc.open(jpegBuffer, jpegBufferSize);
  jpegEnc.encodeImage(rgbBuffer, fb->width, fb->height, 12);
  jpegEnc.close();

  *outBuf = jpegBuffer;
  *outLen = jpegEnc.getSize();
}

Чтение датчиков

Теперь добавим чтение датчиков. Для DHT22 используем библиотеку DHT sensor library, для BMP180 — Adafruit BMP085 Unified.

#include <DHT.h>
#include <Adafruit_BMP085.h>

DHT dht(DHTPIN, DHT22);
Adafruit_BMP085 bmp;

void setupSensors() {
  dht.begin();
  if (!bmp.begin()) {
    Serial.println("BMP180 не найден!");
  }
}

float readTemperature() {
  return dht.readTemperature();
}

float readHumidity() {
  return dht.readHumidity();
}

float readPressure() {
  return bmp.readPressure() / 100.0F; // Переводим в гектопаскали
}

Типичная ошибка: DHT22 — медленный датчик. Между чтениями должно пройти минимум 2 секунды, иначе он вернёт NAN. Если вы вызываете чтение чаще, чем раз в 2 секунды, — получите мусорные данные. В нашем случае это не проблема, так как кадры мы обрабатываем реже.

Полный код проекта

Соберём всё вместе. Вот полный скетч:

#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>
#include <TJpg_Decoder.h>
#include <Adafruit_GFX.h>
#include <DHT.h>
#include <Adafruit_BMP085.h>

// ================== НАСТРОЙКИ ==================
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
#define DHTPIN 4
// ===============================================

// Пины камеры (AI-Thinker)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM     0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM       5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

WebServer server(80);
DHT dht(DHTPIN, DHT22);
Adafruit_BMP085 bmp;

// Буферы
uint16_t* rgbBuffer = nullptr;
size_t rgbBufferSize = 0;

// Класс для рисования
class RGB565Canvas : public Adafruit_GFX {
  public:
    RGB565Canvas(uint16_t* buffer, int w, int h) : Adafruit_GFX(w, h) {
      _buffer = buffer;
    }
    void drawPixel(int16_t x, int16_t y, uint16_t color) override {
      if (x < 0 || x >= width() || y < 0 || y >= height()) return;
      _buffer[y * width() + x] = color;
    }
  private:
    uint16_t* _buffer;
};

// Функция обработки кадра
void processFrame(camera_fb_t* fb, uint8_t** outBuf, size_t* outLen) {
  size_t neededSize = fb->width * fb->height * 2;
  if (rgbBufferSize < neededSize) {
    if (rgbBuffer) free(rgbBuffer);
    rgbBuffer = (uint16_t*)ps_malloc(neededSize);
    rgbBufferSize = neededSize;
  }

  // Декодируем JPEG в RGB565
  TJpgDec.setJpgBuffer(fb->buf, fb->len);
  TJpgDec.convertToRgb565(rgbBuffer, fb->width, fb->height);

  // Рисуем оверлей
  RGB565Canvas canvas(rgbBuffer, fb->width, fb->height);
  canvas.setTextColor(0xFFFF);
  canvas.setTextSize(2);

  // Читаем датчики
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();
  float pressure = bmp.readPressure() / 100.0F;

  // Проверяем на ошибки
  if (isnan(temp) || isnan(hum)) {
    temp = 0;
    hum = 0;
  }

  char line1[32];
  snprintf(line1, sizeof(line1), "Temp: %.1f C", temp);
  char line2[32];
  snprintf(line2, sizeof(line2), "Hum: %.1f %%", hum);
  char line3[32];
  snprintf(line3, sizeof(line3), "Press: %.0f hPa", pressure);

  // Полупрозрачный фон
  canvas.fillRect(0, 0, 220, 60, 0x0000);
  canvas.drawRect(0, 0, 220, 60, 0xFFFF); // Рамка

  canvas.setCursor(5, 5);
  canvas.print(line1);
  canvas.setCursor(5, 25);
  canvas.print(line2);
  canvas.setCursor(5, 45);
  canvas.print(line3);

  // Кодируем обратно в JPEG
  // Используем простой JPEG-энкодер
  // В реальном проекте подключите библиотеку JPEGENC
  *outBuf = fb->buf; // Заглушка
  *outLen = fb->len;
}

// Обработчик главной страницы
void handleRoot() {
  String html = "<!DOCTYPE html><html><head><title>ESP32-CAM Monitor</title>";
  html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
  html += "<style>body{font-family:Arial;text-align:center;background:#1a1a2e;color:#fff;}";
  html += "img{max-width:100%;border:2px solid #e94560;border-radius:10px;}</style>";
  html += "</head><body>";
  html += "<h1>ESP32-CAM Monitor</h1>";
  html += "<img src='/stream'>";
  html += "</body></html>";
  server.send(200, "text/html", html);
}

// Обработчик видеопотока
void handleStream() {
  WiFiClient client = server.client();
  String response = "HTTP/1.1 200 OKrn";
  response += "Content-Type: multipart/x-mixed-replace; boundary=framern";
  response += "Cache-Control: no-cachern";
  response += "Connection: closernrn";
  client.print(response);

  while (client.connected()) {
    camera_fb_t* fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("Не удалось получить кадр");
      continue;
    }

    uint8_t* outBuf;
    size_t outLen;
    processFrame(fb, &outBuf, &outLen);

    client.print("--framern");
    client.print("Content-Type: image/jpegrn");
    client.print("Content-Length: ");
    client.print(outLen);
    client.print("rnrn");
    client.write(outBuf, outLen);
    client.print("rn");

    esp_camera_fb_return(fb);
    delay(100); // ~10 FPS
  }
}

void setup() {
  Serial.begin(115200);

  // Инициализация датчиков
  dht.begin();
  if (!bmp.begin()) {
    Serial.println("BMP180 не найден!");
  }

  // Настройка камеры
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size = FRAMESIZE_VGA;
  config.jpeg_quality = 12;
  config.fb_count = 2;

  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Ошибка камеры: 0x%x", err);
    return;
  }

  // Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());

  // Маршруты
  server.on("/", HTTP_GET, handleRoot);
  server.on("/stream", HTTP_GET, handleStream);
  server.begin();
}

void loop() {
  server.handleClient();
}

Прошивка и типичные ошибки

Прошивка ESP32-CAM — отдельный ритуал. Вот что нужно знать:

  1. Переключите GPIO 0 на GND. На большинстве плат ESP32-CAM есть переключатель или перемычка. Без этого плата не войдёт в режим загрузки.
  2. Подключите USB-UART адаптер: TX адаптера → RX платы (U0R), RX адаптера → TX платы (U0T), GND → GND.
  3. Питание: адаптер должен давать 5V на вывод 5V платы. Не подключайте питание к 3.3V — это выход, а не вход!

Типичные ошибки при прошивке:

  • "Failed to connect to ESP32" — вы забыли замкнуть GPIO0 на GND, или неправильно подключили TX/RX (перепутали местами).
  • Плата перезагружается в цикле — слабый блок питания. ESP32-CAM с камерой может потреблять до 500 мА, а с Wi-Fi — до 1А.
  • Картинка с артефактами — слишком высокое качество JPEG или большой размер кадра. Попробуйте FRAMESIZE_SVGA или уменьшите jpeg_quality до 10.

Проверка результата

После прошивки откройте монитор порта (115200 бод) и дождитесь сообщения с IP-адресом. Затем:

  1. Откройте браузер и введите http://<IP-адрес>/.
  2. Вы увидите страницу с видеопотоком.
  3. На изображении в левом верхнем углу должны отображаться температура, влажность и давление.

Если данные не появляются, проверьте:

  • Правильно ли подключены датчики (перепутали SDA и SCL у BMP180?).
  • Не возвращает ли DHT22 NAN (слишком частое чтение?).
  • Виден ли BMP180 в логе (сообщение "BMP180 не найден!").

Что дальше?

Этот проект — отличная основа для более серьёзных вещей. Вот несколько идей:

  • Добавьте датчик качества воздуха (например, CCS811 или SGP30) — и у вас будет полноценный монитор окружающей среды.
  • Интегрируйте с Home Assistant через MQTT: данные датчиков уйдут в умный дом, а видео останется доступным по IP. Кстати, у нас есть отличная статья про ESP32 и MQTT — рекомендую.
  • Настройте OTA-обновления, чтобы не перепрошивать плату по проводам каждый раз. Вот подробный гайд по OTA.
  • Добавьте распознавание лиц — ESP32-CAM отлично с этим справляется. Смотрите статью про веб-камеру и распознавание лиц.

Заключение

Мы собрали устройство, которое выводит данные датчиков прямо поверх видеопотока. Это не только красиво, но и практично: вся информация — в одном месте, не нужно переключаться между приложениями. ESP32-CAM — удивительно гибкая платформа, и я уверен, что вы найдёте ей массу применений.

Если у вас остались вопросы или вы нашли более элегантное решение для наложения текста — пишите в комментариях. А если хотите пойти дальше и собрать полноценную метеостанцию с графиками, загляните в статью про ESP32 + InfluxDB + Grafana. Удачи в ваших DIY-проектах!

Понравилась статья?

Поставьте лайк и сохраните полезный материал в закладки.

Комментарии (0)
Добавить комментарий
Прокомментировать
Кликните на изображение чтобы обновить код, если он неразборчив
ESP: как Espressif переписала правила DIY-электроники
ESP32 / ESP8266
10.09.2026
ESP: как Espressif переписала правила DIY-электроники
История создания чипов Espressif: от случайного успеха ESP8266 до линейки ESP32, C6, S3 и P4. Разбираем, чем отличаются платы и какую выбрать под конкретный DIY-проект.
Что можно сделать на LILYGO T-Dongle S3: 10 практических проектов
ESP32 / ESP8266
01.09.2026
Что можно сделать на LILYGO T-Dongle S3: 10 практических проектов
10 практических идей для LILYGO T-Dongle S3: мониторинг сервера, Home Assistant, MQTT, USB HID, 3D-принтер, сетевые инструменты и другие проекты на ESP32-S3.
ESP32 и три в одном: измеряем температуру, влажность и давление на одной плате
ESP32 / ESP8266
31.03.2026
ESP32 и три в одном: измеряем температуру, влажность и давление на одной плате
Подключаем датчик к ESP32 и измеряем температуру, влажность и давление на одной плате: схема, код и проверка показаний.
ESPHome: прошиваем ESP32 без единой строки кода. Визуальный путь к умному устройству
ESP32 / ESP8266
31.03.2026
ESPHome: прошиваем ESP32 без единой строки кода. Визуальный путь к умному устройству
Пошаговое руководство: как прошить ESP32 через ESPHome без кода. Интеграция с Home Assistant, OTA-обновления, примеры конфигов для датчиков и реле. Упрощаем DIY!
ESP32 и MQTT: Подключаем датчик к Home Assistant за вечер
ESP32 / ESP8266
31.03.2026
ESP32 и MQTT: Подключаем датчик к Home Assistant за вечер
Пошаговое руководство: как подключить датчик на ESP32 к умному дому через MQTT и Home Assistant. Пишем прошивку, настраиваем брокер, используем автообнаружение.
ESP32 Marauder: что это такое, как выбрать плату и где скачать прошивку
ESP32 / ESP8266
09.09.2026
ESP32 Marauder: что это такое, как выбрать плату и где скачать прошивку
ESP32 Marauder — это прошивка с открытым исходным кодом для тестирования Wi-Fi сетей на базе микроконтроллера ESP32. В статье разбираем, что умеет инструмент, как

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