Главная страница » DIY проекты » DIY умный звонок с камерой на ESP32-CAM и Home Assistant
DIY умный звонок с камерой на ESP32-CAM и Home Assistant
DIY проекты

DIY умный звонок с камерой на ESP32-CAM и Home Assistant

31.03.2026 250
DIY умный звонок с камерой на ESP32-CAM и Home Assistant

Собираем умный дверной звонок на ESP32-CAM с камерой, уведомлениями и интеграцией в Home Assistant.

Привет всем, кто любит паять, программировать и автоматизировать свой дом! Сегодня мы соберём с нуля умный звонок с камерой. Это не просто кнопка, которая отправляет уведомление. Это полноценное устройство, которое покажет, кто стоит у двери, на экране вашего смартфона или планшета, а при желании — даже откроет дверь реле. Всё это на базе недорогой платы ESP32-CAM и с интеграцией в Home Assistant.

Зачем это нужно? Покупные решения вроде Ring или Nest Hello — это удобно, но дорого и часто «закрыто». Наш DIY-звонок даёт полный контроль. Мы сами решаем, куда и как отправляются данные, как выглядит интерфейс и какие сценарии запускать. Например, можно показывать видео с камеры на планшете-панели в прихожей при нажатии кнопки или автоматически делать снимок при срабатывании датчика движения (PIR), который тоже есть на ESP32-CAM.

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

  • Плата ESP32-CAM. Сердце проекта. У неё есть камера OV2640, слот для microSD, GPIO и Wi-Fi/Bluetooth. Обратите внимание: у многих версий нет встроенного USB-порта, нужен переходник.
  • USB-UART переходник (например, на базе CH340 или CP2102). Для прошивки и питания во время отладки.
  • Кнопка дверного звонка. Любая нормально-разомкнутая (NO) кнопка. Можно взять классическую уличную.
  • Реле (опционально). Если хотите управлять электромеханическим звонком или электрозамком. Подойдёт модуль на 5В, например, SRD-05VDC-SL-C.
  • Блок питания. Для постоянной работы ESP32-CAM нужен стабильный источник 5В. Подойдёт зарядка от телефона или блок питания с microUSB/Type-C разъёмом, если используете переходник с таким выходом.
  • Монтажные провода (папа-папа, папа-мама).
  • Корпус. Можно распечатать на 3D-принтере или использовать готовую влагозащищённую коробку для электроники.
  • Home Assistant. Уже установленный и работающий. Можно на Raspberry Pi, Orange Pi, виртуальной машине или в другом месте.

Подготовка среды и прошивка ESP32-CAM

Первым делом нужно запрограммировать нашу плату. Мы будем использовать Arduino IDE, так как для неё есть отличная библиотека esp32-camera и удобные примеры для работы с Home Assistant.

1. Настройка Arduino IDE

Устанавливаем Arduino IDE с официального сайта. Затем добавляем поддержку плат ESP32: 1. Откройте Файл → Настройки. 2. В поле «Дополнительные ссылки для менеджера плат» вставьте URL: https://espressif.github.io/arduino-esp32/package_esp32_index.json 3. Перейдите в Инструменты → Плата → Менеджер плат. 4. Найдите esp32 и установите последнюю версию.

2. Подключение платы и выбор параметров

Подключите ESP32-CAM к компьютеру через USB-UART переходник. Важно правильно соединить пины: * GND на ESP32-CAM -> GND на переходнике. * 5V на ESP32-CAM -> 5V (или VCC) на переходнике. * U0R (RX) на ESP32-CAM -> TX на переходнике. * U0T (TX) на ESP32-CAM -> RX на переходнике. * IO0 на ESP32-CAM -> GND (только на время прошивки!).

Да, для прошивки нужно замкнуть IO0 на GND. После прошивки — отключить этот провод, иначе плата не запустится в нормальном режиме. Это самая частая ошибка новичков.

В Arduino IDE выберите: * Плата: AI Thinker ESP32-CAM * Порт: соответствующий COM-порт (в Windows — COM3, COM4 и т.д.) * Остальные параметры можно оставить по умолчанию.

3. Установка библиотек и загрузка скетча

Нам понадобятся две библиотеки. Установите их через Скетч → Подключить библиотеку → Управлять библиотеками...: 1. esp32-camera (часто уже установлена с платами ESP32). 2. PubSubClient для связи по MQTT.

Теперь откройте пример: Файл → Примеры → esp32-camera → CameraWebServer. Этот скетч — отличная основа. Он поднимает веб-сервер для просмотра видео. Но нам нужно его модифицировать для работы с Home Assistant через MQTT.

Пишем скетч для умного звонка

Мы создадим скетч, который: 1. Подключается к Wi-Fi. 2. Подключается к MQTT-брокеру (обычно Mosquitto в Home Assistant). 3. При нажатии кнопки на GPIO отправляет MQTT-сообщение. 4. По запросу (через MQTT) делает и отправляет снимок.

Вот основа скетча. Замените значения в <> на свои.

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

// Конфигурация модели камеры (для AI-Thinker ESP32-CAM)
#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

// Настройки сети
const char* ssid = "ВАШ_SSID";
const char* password = "ВАШ_ПАРОЛЬ";
const char* mqtt_server = "IP_ВАШЕГО_HA"; // Например, 192.168.1.100

// Пины
const int buttonPin = 13; // GPIO13, куда подключена кнопка (к GND через резистор 10кОм)
const int relayPin = 12;  // GPIO12 для реле (опционально)
const int flashPin = 4;   // GPIO4 для встроенной вспышки/светодиода

// MQTT-топики
const char* mqtt_topic_button = "home/doorbell/button";
const char* mqtt_topic_image = "home/doorbell/image";
const char* mqtt_topic_cmd = "home/doorbell/cmd"; // Для команд с HA

WiFiClient espClient;
PubSubClient client(espClient);
bool buttonState = HIGH;
bool lastButtonState = HIGH;

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

void callback(char* topic, byte* payload, unsigned int length) {
  // Обработка входящих MQTT-сообщений
  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.print("Сообщение в топике [");
  Serial.print(topic);
  Serial.print("]: ");
  Serial.println(message);

  if (String(topic) == mqtt_topic_cmd) {
    if (message == "capture") {
      captureAndSendPhoto();
    }
    if (message == "flash_on") {
      digitalWrite(flashPin, HIGH);
    }
    if (message == "flash_off") {
      digitalWrite(flashPin, LOW);
    }
  }
}

void reconnectMQTT() {
  while (!client.connected()) {
    Serial.print("Попытка подключения к MQTT...");
    if (client.connect("ESP32CAM_Doorbell")) {
      Serial.println("подключено");
      client.subscribe(mqtt_topic_cmd); // Подписываемся на топик с командами
    } else {
      Serial.print("ошибка, rc=");
      Serial.print(client.state());
      Serial.println(" пробуем снова через 5 секунд");
      delay(5000);
    }
  }
}

void captureAndSendPhoto() {
  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get(); // Делаем снимок
  if (!fb) {
    Serial.println("Ошибка захвата кадра");
    return;
  }
  // Отправляем бинарные данные (картинку) в MQTT.
  // ВАЖНО: MQTT не предназначен для больших бинарных данных.
  // Для снимков низкого разрешения (например, VGA) это может сработать.
  // Лучше использовать HTTP-сервер на ESP32 или внешний хостинг.
  bool result = client.publish_P(mqtt_topic_image, fb->buf, fb->len, false);
  if (result) {
    Serial.println("Фото отправлено");
  } else {
    Serial.println("Ошибка отправки фото");
  }
  esp_camera_fb_return(fb); // Возвращаем буфер
}

void setup() {
  Serial.begin(115200);
  pinMode(buttonPin, INPUT_PULLUP); // Используем внутренний подтягивающий резистор
  pinMode(relayPin, OUTPUT);
  pinMode(flashPin, OUTPUT);
  digitalWrite(relayPin, LOW);
  digitalWrite(flashPin, LOW);

  // Инициализация камеры
  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;
  // Разрешение. Меньше разрешение -> меньше размер файла -> стабильнее MQTT.
  config.frame_size = FRAMESIZE_VGA; // VGA = 640x480
  config.jpeg_quality = 12; // 0-63, меньше число = выше качество
  config.fb_count = 1;

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

  setupWiFi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnectMQTT();
  }
  client.loop();

  // Опрос кнопки
  buttonState = digitalRead(buttonPin);
  if (buttonState == LOW && lastButtonState == HIGH) { // Кнопка нажата (подтянута к HIGH, при нажатии - LOW)
    delay(50); // Антидребезг
    if (digitalRead(buttonPin) == LOW) {
      Serial.println("Кнопка нажата!");
      client.publish(mqtt_topic_button, "pressed");
      // Можно сразу сделать снимок
      // captureAndSendPhoto();
      // Или включить реле на 1 секунду
      // digitalWrite(relayPin, HIGH);
      // delay(1000);
      // digitalWrite(relayPin, LOW);
    }
  }
  lastButtonState = buttonState;
  delay(10);
}

Важные замечания по коду: * MQTT и фото: Прямая отправка JPEG по MQTT — не лучшая практика из-за ограничений на размер сообщения. Для проекта звонка, где нужно 1-2 фото, это может сработать. Для видеопотока лучше использовать HTTP-стриминг или RTSP, но это сложнее и требует больше ресурсов. * Безопасность: В коде нет логина/пароля MQTT для простоты. В реальном проекте обязательно добавьте client.connect("ESP32CAM_Doorbell", "mqtt_user", "mqtt_pass");. * Потребление памяти: Выберите небольшое разрешение (FRAMESIZE_VGA или SVGA), иначе плата может не хватить памяти для создания кадра.

Загрузите этот скетч на плату, не забыв про замыкание IO0 на GND. После успешной загрузки отключите этот провод и нажмите кнопку RST на плате.

Настройка Home Assistant

Теперь научим Home Assistant реагировать на нажатие нашей кнопки и показывать фото.

1. Настройка MQTT

Убедитесь, что в Home Assistant установлен и настроен MQTT-брокер (например, Mosquitto add-on). В файле configuration.yaml должна быть примерно такая строка:

mqtt:
  broker: 127.0.0.1 # Если брокер на этой же машине
  username: !secret mqtt_username
  password: !secret mqtt_password

2. Добавление устройства (кнопки) через MQTT Discovery

Home Assistant может автоматически добавить устройство, если ESP32 отправит специальное сообщение. Добавьте в setup() скетча после подключения к MQTT:

// Автообнаружение для кнопки
String discovery_topic = "homeassistant/binary_sensor/doorbell_button/config";
String discovery_message = "{"name":"Doorbell Button", "device_class":"occupancy", "state_topic":"home/doorbell/button", "payload_on":"pressed", "off_delay":5}";
client.publish(discovery_topic.c_str(), discovery_message.c_str(), true);

Это создаст в HA бинарный датчик, который будет в состоянии «включено» 5 секунд после нажатия.

3. Создаём автоматизацию и интерфейс

Теперь создадим автоматизацию, которая при нажатии кнопки: 1. Отправляет команду ESP32 сделать снимок. 2. Сохраняет этот снимок в файл. 3. Показывает уведомление с фото.

Создайте новый файл automations.yaml или добавьте в существующий:

- alias: "Doorbell Ring - Capture and Notify"
  trigger:
    platform: mqtt
    topic: "home/doorbell/button"
    payload: "pressed"
  action:
    # 1. Отправляем команду на захват фото
    - service: mqtt.publish
      dаta:
        topic: "home/doorbell/cmd"
        payload: "capture"
    # 2. Ждём немного
    - delay: "00:00:02"
    # 3. Создаём уведомление с последним фото (способ ниже)

Для работы с фото нужен более сложный подход. Лучше всего настроить в ESP32 не отправку фото по MQTT, а поднятие простого HTTP-сервера, который отдаёт последний снимок. Тогда в HA можно использовать камеру generic или mjpeg.

Упрощённый вариант через MQTT (для теста): Создайте сенсор-шаблон, который будет хранить ссылку на последнее фото (если вы сохраняете его на диск через другой скрипт, слушающий MQTT home/doorbell/image).

# В configuration.yaml
template:
  - sensor:
      - name: "Last Doorbell Image"
        state: "{{ states('sensor.doorbell_image_path') }}"

4. Создаём Lovelace-карточку

На вкладке Lovelace добавьте карточку, которая покажет состояние кнопки и последний снимок.

type: picture-entity
entity: binary_sensor.doorbell_button
camera_image: camera.doorbell_camera # Если настроили камеру
title: Дверной звонок

Сборка и монтаж устройства

  1. Пайка: Припаяйте к ESP32-CAM пины для подключения кнопки и реле. Для кнопки используйте GPIO13 и GND. Не забудьте про резистор ~10 кОм для подтяжки, если не используете INPUT_PULLUP.
  2. Подключение кнопки: Один провод кнопки на GPIO13, другой — на GND.
  3. Подключение реле (опционально): VCC реле -> 5V на ESP32, GND -> GND, IN -> GPIO12. Силовые контакты реле разрывают цепь стар

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

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

Комментарии (0)
Добавить комментарий
Ваш комментарий
Кликните на изображение чтобы обновить код, если он неразборчив

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