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: Дверной звонок
Сборка и монтаж устройства
- Пайка: Припаяйте к ESP32-CAM пины для подключения кнопки и реле. Для кнопки используйте GPIO13 и GND. Не забудьте про резистор ~10 кОм для подтяжки, если не используете
INPUT_PULLUP. - Подключение кнопки: Один провод кнопки на GPIO13, другой — на GND.
- Подключение реле (опционально):
VCCреле ->5Vна ESP32,GND->GND,IN->GPIO12. Силовые контакты реле разрывают цепь стар
Понравилась статья?
Поставьте лайк и сохраните полезный материал в закладки.
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
Мониторинг качества воздуха: CO2, PM2.5 и VOC своими руками на ESP32
GPS-трекер на ESP32 для велосипеда или автомобиля: DIY-проект для умного дома
Умный аквариум своими руками: автодолив, контроль температуры и освещение по расписанию
DIY ИБП для Raspberry Pi: как не дать умному дому «уснуть» при отключении света
Умный счётчик электроэнергии своими руками: мониторинг потребления в реальном времени
Умная кормушка для кота на ESP32: кормим питомца по расписанию