AI ИК-пульт для Алисы на ESP32 своими руками

AI

Редактор
Регистрация
23 Август 2023
Сообщения
3 610
Лучшие ответы
0
Реакции
0
Баллы
243
Offline
#1
Проблема в том, что большинство бытовых приборов, даже новых, управляются ИК-пультами, которые никак не интегрируются с умным домом. Алиса - умная, а увлажнитель - нет.

У этой задачи есть очевидное решение - купить готовый ИК-шлюз. Это было бы удобно и выгодно, но у меня немного другой интерес - хочется понять, как оно работает внутри, а не только тыкать в кнопку.

Цель проста и измерима:


  • управлять увлажнителем голосом через Алису (или дашборд Home Assistant)


  • с быстрым откликом


  • без постоянного питания от розетки
Что у нас есть на входе


  • Увлажнитель - не старый, но и не умный (Kitfort КТ-2811)


  • ИК-пульт


  • Алиса
Комплектующие


  • ESP32 C3 Super Mini - компактный, энергоэффективный и умный мозг


  • ИК диод с длиной волны 940 нм - стандарт для бытовых ИК-приёмников.


  • ИК приёмник - ловит команды с оригинального пульта (для первичной настройки)


  • Транзистор NPN - GPIO ESP32 может отдавать лишь ограниченный ток, а ИК-диод требует большего, поэтому он управляется через транзистор, а не напрямую.


  • Резисторы: 100Ω на диод и 1kΩ на базу транзистора


  • Аккумулятор Li-ion 1250mAh + TP4056 - чтобы не привязываться к розетке


  • Повышайка MT3608 - поднимаем питание с 3.7V до 5V для ESP32


  • Движковый переключатель - чтобы можно было отрубить всё одним движением руки

Комплектующие
Первые тесты на макетке


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

Подключение было таким:


  • ИК-приёмник: VCC → 3.3V, GND → GND, OUT → GPIO ESP32 (любой свободный, указывается в конфиге ESPHome)


  • ИК-диод: Анод → через резистор 100 Ω к +3.3V, катод → коллектор NPN-транзистора, эмиттер транзистора → GND, база транзистора → GPIO ESP32 через резистор 1 кΩ

ESP32 в этом случае управляет только базовым током, а основной ток через диод берётся напрямую из цепи питания, которое на макетке подавалось от USB.

Вот такая сборка


Сборка всей схемы на макетной плате
Записываем сигналы с пульта


В качестве прошивки я использовал ESPHome - он позволяет описывать конфигурацию декларативно и сразу интегрируется с Home Assistant. Прошиваем по USB, указываем пин приёмника, формат сигнала, толерантность и включаем логгер (оказывается если не указать entry logger'а в конфиге - сборка падает).

logger:
level: DEBUG

remote_receiver:
pin:
number: GPIO19
dump: pronto
tolerance: 50%

Теперь наш ESP32 ловит сигналы, которые раньше шли через пульт. Можно посмотреть в логах: кнопка "Вкл" - сигнал пришёл. Кнопка "Авто" - сигнал пришёл. Всё красиво и понятно!


Ресивер получает сигнал и выводит его в лог

[22:08:31.330][remote.pronto:229]: Received Pronto: data=
[22:08:31.355][remote.pronto:237]: 0000 006D 0022 0000 0164 00A9 0019 0013 0018 0014 0017 0014 0018 0013 0018 0013 0018 0013 0018 0013 0018 0013 0018 003E 0018 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003E 0018 0013 0018 0013 0018 0013
[22:08:31.369][remote.pronto:237]: 0018 0013 0018 0013 0018 0014 0017 0014 0017 0013 0018 003D 0019 003D 0019 003D 0019 003D 001A 003D 0019 003D 001A 003D 001A 0180

Записываю оставшиеся кнопки. Мне нужны Вкл/выкл, теплый туман и авто и режим.

Настраиваем передатчик


Добавляем remote_transmitter в конфиг, создаём скрипты и кнопки в Home Assistant. Теперь, когда нажмём кнопку в Web интерфейсе, скрипт запустит передачу сигнала и увлажнитель среагирует.

remote_transmitter:
pin: GPIO4
carrier_duty_percent: 50%

script:
- id: ir_power_toggle
then:
- remote_transmitter.transmit_pronto:
data: "0000 006D 0022 0000 0160 00AB 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 0013 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 001B 0011 0019 0012 0019 003D 001B 003C 001A 003C 0019 003D 001B 003C 001B 003C 0019 003D 0019 0180"

# -------------------------------------------------
# Кнопки в Home Assistant
# -------------------------------------------------
button:
- platform: template
name: "Humidifier - on/off"
icon: "mdi:power"
on_press:
- script.execute: ir_power_toggle

Вот так кнопка выглядит в Home Assistant


Home Assistant UI с нашей кнопкой

Всё ок! Увлажнитель понимает команду. Это радует!


Демонстрация управления увлажнителем через наш пульт

Теперь осталось добавить остальные кнопки в конфиг, прошить уже не dev плату, а нашу c3 Super Mini и упаковать в корпус.

Про питание и автономность


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

У ESP32 есть несколько режимов, Active, Modem sleep, Light sleep, Deep sleep и Hibernation:


Active Mode ESP32 (ист. https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/)

Modem Sleep Mode ESP32 (ист. https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/)

Light Sleep Mode ESP32 (ист. https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/)

Deep Sleep Mode ESP32 (ист. https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/)

Hibernation Mode ESP32 (ист. https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/)

Узнать о них подробнее можно тут, а если кратко - во всех режимах кроме Active отключается Wi-Fi и Bluetooth, а потребление тока снижается от ~100-240mA до 5µA. Чудеса, конечно! Однако, Wi-Fi-то мне и нужен...

И вот передо мной встал выбор - будить пульт по таймеру и проверять была ли команда, или всегда держать его в Active. Выбрал второе, так как хочется быстрый отклик. Было бы странно ждать пока пульт проснется после запуска сценария или голосовой команды.

Расчеты


Все расчёты ниже - приблизительные. Они не учитывают КПД DC-DC преобразователя и реальные пиковые токи Wi-Fi, зато позволяют примерно оценить время автономной работы.

ESP32 потребляет <240mA лишь в пике, когда общается с сервером по Wi-Fi, но в период "ожидания" кушает ~50-60mA, как сказано в этой статье. А значит, мы можем посчитать время автономности.

Что имеем (данные взял из даташитов компонентов):


  • Емкость аккумулятора: (C_батарея) = 1200 мА·ч


  • Напряжение аккумулятора: (U_батарея) = 3.7 В


  • Средний ток ESP32: (I_ESP32) = 50-60 мА


  • Прямое падение на LED: (U_LED) = 1.4 В


  • Падение на транзисторе: (U_транз) = 0.2 В


  • Сопротивление LED: (R_LED) = 100 Ом


  • Частота включений IR: (n) = 10 раз/сутки


  • Длительность импульса IR: (t_импульс) = 50 мс

Отдельно посчитаем вклад ИК-диода - чтобы понять, имеет ли он вообще значение в общем балансе.


Рассчитываем суммарное время работы ИК диода


Рассчитываем долю времени, когда ИК диод активен


Дальше считать не имеет смысла - значением можно пренебречь. Теперь рассчитываем суммарный ток потребления


Рассчитываем время работы по закону сохранения заряда


Моделируем корпус


Я выбрал TinkerCad - просто и быстро. Основное ограничение по габаритам задал аккумулятор - под него и подгонялась вся геометрия корпуса. Электроника занимает меньше половины объёма.

Также добавил:


  • Второй "этаж" для плат


  • Перфорация для вентиляции и экономии материала


  • Отверстия: USB-C для ESP32, microUSB для TP4056, 5мм для ИК-диода.

Получилось вот так. Больше всего времени ушло на крепежи. Если хочется посмотреть ближе - ссылка на модель


3D модель корпуса для пульта

Вот так выглядит напечатанная модель (пластик ABS)


Готовая 3D модель

А вот так это все умещается в корпус


Все компоненты в корпусе
Аккумулятор, зарядка и повышающий преобразователь


Для автономной работы я использовал Li-ion аккумулятор, модуль зарядки TP4056 и повышающий DC-DC преобразователь MT3608.

Схема питания получилась такой:


  • аккумулятор подключён напрямую к TP4056, который отвечает за зарядку и защиту


  • с выходов OUT+ / OUT- TP4056 питание подаётся на повышающий преобразователь MT3608 (минус разорван переключателем)


  • MT3608 поднимает напряжение с ~3.0–4.2 В аккумулятора до стабильных 5 В


  • уже от этих 5 В питаются ESP32

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


Пульт в сборе




Вот как это выглядит в "Умном доме". Можно завести сценарий и Алиса по команде "Увлажнитель" будет включать или выключать устройство. Да, есть минус в том, что мы не знаем текущего состояния, но даже такая автоматизация - это круто.


Дашборд в приложении "Умный дом"
Итоги


В результате получился автономный ИК-пульт с интеграцией в Home Assistant и Яндекс Алису. В процессе всплыло несколько типичных проблем, о которых было бы здорово знать заранее:


  • Ошибка "Auth expired" при подключении к Wi-Fi при переходе с dev платы на esp32 c3 super mini (проблема и решение описаны тут и тут)


  • Ошибки сборки прошивки для платы (самый удобный способ шить плату через интерфейс EspHome в Home Assistant, правда тогда он собирает на том устройстве, на котором живет. У меня это rpi 3b+, на которой не оказалось нужных c++ либ. В итоге мне легче было прошивать плату на своем компе.


  • Подбор светодиода. Изначально выбор пал на TSAL6200, у него 15 градус но потом я выбрал BL-L513IRAB он 30 градус и мне лучше такой

Планы на доработку:


  • Добавить датчик (температура/влажность)


  • Обеспечить всенаправленность сигнала (добавить еще диодов)

Себестоимость: ~1150₽ (что дороже готовых решений от Яндекс, Tuya или Xiaomi)

Радует, что теперь можно настроить сценарии и включить туда все, что управляется через ИК (увлажнитель, кондиционер, даже старый телевизор). Например, уходя из дома все выключится.

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

Полная yaml конфигурация

esphome:
name: esphome-web-386ce0
friendly_name: ESPHome Web 386ce0
min_version: 2025.9.0
name_add_mac_suffix: false

esp32:
board: esp32-c3-devkitm-1
framework:
type: esp-idf

logger:
level: DEBUG
# Enable Home Assistant API
api:

ota:
- platform: esphome

wifi:
ssid:
password:
power_save_mode: none
output_power: 8.5dB

# -------------------------------------------------
# IR ресивер — тут получаем сигнал
# -------------------------------------------------
#remote_receiver:
# pin:
# number: GPIO19
# dump: pronto
# tolerance: 50%
#
# -------------------------------------------------
# IR ресивер — конец
# -------------------------------------------------

remote_transmitter:
pin: GPIO21
carrier_duty_percent: 50%

script:
- id: ir_power_toggle
then:
- remote_transmitter.transmit_pronto:
data: "0000 006D 0022 0000 0160 00AB 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 0013 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 001B 0011 0019 0012 0019 003D 001B 003C 001A 003C 0019 003D 001B 003C 001B 003C 0019 003D 0019 0180"

- id: ir_auto_mode
then:
- remote_transmitter.transmit_pronto:
data: "0000 006D 0022 0000 0161 00AA 0019 0012 0019 0012 001A 0012 001A 0012 001A 0012 001A 0012 0019 0012 001A 0012 0019 003D 0019 003D 0019 003D 001A 003D 0019 003D 0019 003D 0019 003D 0019 003D 0019 0012 0019 0012 0019 003D 001A 0012 001A 0012 001A 0012 0019 0013 001A 0012 0019 003D 001A 003D 001A 0012 0019 003D 001A 003D 001A 003D 0019 003D 0019 003D 001A 0180"

- id: ir_heater
then:
- remote_transmitter.transmit_pronto:
data: "0000 006D 0022 0000 0161 00AB 001A 0012 001A 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 0012 0019 003D 001A 003D 0019 003D 001A 003D 0019 003D 0019 003D 0019 003D 001A 003D 0019 0012 0019 0012 0019 0013 0019 003D 0019 0012 001A 0012 0019 0012 0019 0012 001A 003D 0019 003D 001A 003D 001A 0012 001A 003D 001A 003D 001A 003D 001A 003D 001A 0180"


# -------------------------------------------------
# Кнопки в Home Assistant
# -------------------------------------------------
button:
- platform: template
name: "Humidifier - on/off"
icon: "mdi:power"
on_press:
- script.execute: ir_power_toggle

- platform: template
name: "Humidifier - auto mode"
icon: "mdi:autorenew"
on_press:
- script.execute: ir_auto_mode

- platform: template
name: "Humidifier - heating mode"
icon: "mdi:fire"
on_press:
- script.execute: ir_heater
 
Яндекс.Метрика Рейтинг@Mail.ru
Сверху Снизу