Весь нужный код и сопутствующие файлы вы найдете в моём репозитории Github

Купил я Orange Pi Zero W2, поставил на него Home Assistant Supervised, но даже с радиаторами из комплекта температура поднималась выше ~60 градусов, а при подключении через HDMI температура улетала в небеса и вместо изображения можно было наблюдать "белый шум" и намертво зависшую плату.

Было решено поставить активное охлаждение в виде небольшого вентилятора, но к моему сожалению 4-pin вентиляторов таких маленьких размеров я не нашел, либо они стоили дороже самой платы, а 4 пина нужны чтобы управлять скоростью вращения вентилятора (2 на питание 1 на датчик оборотов, и четвертый, последний, как раз таки контроль оборотов).

Есть специальные вентиляторы для работы на пониженных оборотах, такие делали Noctua для Raspberry Pi, но их сейчас не найдешь (1 шт на озоне за 3к, алиэкспресс 0шт). Я же взял вентилятор за 60 руб, и чтобы управлять его скоростью можно использовать схему на транзисторе и ШИМ (далее будет подробнее).

О проекте

Весь нужный код и сопутствующие файлы вы найдете в моём репозитории Github: https://github.com/portg80/Cooling-for-orange-pi-zero-w2-and-Home-Assistant-integration

Через MQTT мы будем отображать показатели (температура, какая сейчас мощность вентилятора, вращается ли реально вентилятор или умер) получившейся системы охлаждения прямо в Home Assistant (далее иногда буду называть его "HA") и из него же сможем менять ее настройки.

Сделаем на Node-Red систему оповещения о критических ситуациях (если вентилятор помрет и перестанет крутится мы сразу об этом узнаем) уведомлением на телефон, и даже озвучим экстренное сообщение через Яндекс Алису!**

Я очень старался чтобы любой новичок разобрался. Считаю что гайд получился довольно ультимативным, затрагивает разные аспекты, есть скрины и видео кусочки многих моментов. Хорошего чтения ?

Я буду иногда расшифровывать сокращения по типу "ШИМ" вот так в скобках: "ШИМ (PWM) («мощности»)" для большей ясности новичкам.

Вот что мы получим в конце:

image
image

Это сама панель управления внутри Home Assistant (HA).

На графиках отображаются:

  • Температура процессора (CPU) (получаем через MQTT)

  • Частота ШИМ (значение от 0 до 1024, чем больше - тем быстрее крутится вентилятор, другими словами "мощность") (получаем через MQTT)

  • Скорость вращения вентилятора RPS (обороты кулера в секунду) (получаем через MQTT)

  • CPU использование, нагрузка на процессор в процентах (стандартный датчик HA)

Слайдеры меняют настройки работы системы:

  • Пороги температур:

    Первый слайдер «Temp для 100% вращения» устанавливает значение температуры процессора, при котором PWM (ШИМ), то есть «мощность» вентилятора, будет максимальной.

    Второй слайдер "Temp для 0% вращения" устанавливает ту температуру, при которой вентилятор будет работать на минимальной «мощности», а когда температура опустится ниже, то вовсе отключится

  • Пороги ШИМ (PWM) («мощности») как раз таки устанавливают минимальный и максимальный порог мощности работы вентилятора. Почему минимальный у меня = 950 PWM? Подобрал это опытным путем, ибо при меньших значениях МОЙ вентилятор за 60р просто не может стартануть.

image
image

Система предупреждения о неисправности:

image
image

Видео-демонстрация сигнализации с оповещением через алису (звук включи):

https://github.com/user-attachments/assets/526eb54d-f185-41ab-abf6-150ad8f4b349

image
image

Видео "обзор" dashboard панели:

https://github.com/user-attachments/assets/947b8b01-0ef1-4230-bbaa-66d4df62416a

Как это выглядит в жизни

image
image
image
image
image
image

Плата:

image
image

Считаю что моя идеальная пайка заслуживает того чтобы вы поставили звезду ⭐ моему репозиторию OwO. (я просто перепаивал по 10 раз, поэтому так страшно, но работает безотказно)

Принцип работы

Сразу скажу, на картинке 3 orange pi, но по факту ЭТО ОДИН И ТОТ ЖЕ модуль, просто я разбил на компоненты для наглядности.

Мой Python скрипт посылает данные в плагин MQTT, а из плагина MQTT они становятся объектами(устройствами). HA откуда их читает для графиков в панели. Так же их отслеживает моя автоматизация в плагине Node-Red, для уведомлений о поломке вентилятора.

Изменение настроек работает примерно по такому же принципу, но в обратную сторону.

image
image

Что купить?

Цены в российских рублях, актуальные на 14.11.2025

1 шт. - MF-25 (С2-23) 0.25Вт, 10 кОм, 1%, Резистор металлопленочный (5 руб)

1 шт. - CF-25 (С1-4) 0.25Вт, 1 кОм, 5%, Резистор углеродистый (3.80 руб)

1 шт. - MO-50 (С2-23) 0.5Вт, 470 Ом, 5%, Резистор металлооксидный (3.80 руб)

1 шт. - 1N4001, Диод выпрямительный 1А 50В [DO-41 / DO-204AC.] (5.70 руб)

1 шт. - IRLZ44NPBF, Транзистор, N-канал 55В 47А logic [TO-220AB] (84.50 руб)

1 шт. - Макетная плата 4х6 см (32.50 руб)

1 шт. - Флюс для пайки, паста паяльная канифольно-вазелиновая, 20 г, банка, инд. упаковка, серия "Алмаз" TDM (58.50 руб)

1 шт. - Припой трубка с канифолью, 10 г, 0,8 мм, ПОС-61, колба (100 руб)

1 шт. - EX295193RUS, Вентилятор 5В DC ExeGate EX04010S3P-5 (40x40x10 мм, Sleeve bearing (подшипник скольжения), 3pin, 5000RPM, 24dBA) (62 руб)

4 шт. используется в проекте, но брал набор из 40 - Соединительные провода «папа-мама» (40 шт. / 20 см), Шлейф из 40 проводов для прототипирования электронных устройств (200 руб)

2 шт. используется в проекте, но брал набор из 5 - JST PH 2.0мм 4pin кабель с разъемом (~150р)

ИТОГО: ~705 рублей с набором проводов и коннекторами, без них цена ~350 руб, можно сэкономить на наборах поменьше или найти поштучно.

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

Страшная принципиальная:
(если нужно будет смогу потом нарисовать в стиле ардуино схем, где видно какой контакт куда подключается если с такой схемой будут сложности)

shema_pwm
shema_pwm

Вот схема подключения с подписями каждого пина (контакта):

shema_pwm_paint
shema_pwm_paint

GND можно воткнуть в любой свободный, а PWM read и PWM control переназначить в моем скрипте (PWM control только на пин с поддержкой ШИМ, по типу PWM1 PWM2 на картинке).

Устанавливаем и настраиваем Python скрипт

Весь нужный код и сопутствующие файлы вы найдете в моём репозитории Github: https://github.com/portg80/Cooling-for-orange-pi-zero-w2-and-Home-Assistant-integration

Скрипт находится в файле pwm_fan_daemon.py, можете открыть его где вам удобно в текстовом редакторе и поменять нужные настройки.

настроим MQTT на Home Assistant

Создадим отдельного пользователя именно для mqtt.
В Home Assistant:

Настройки -> Люди -> Пользователи -> Добавить пользователя (галочка администратора НЕ нужна) -> задаем имя и пароль и нажимаем добавить

image
image

В Home Assistant:
Настройки -> Дополнения -> Магазин дополнений -> в поиске ищем "Mosquitto broker" и устанавливаем -> открываем его и вверху вкладка конфигурация есть, переходим на нее -> в категории Logins нажимаем кнопку "Добавить" -> вписываем логин и пароль пользователя созданного на предыдущем шаге

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

image
image
image
image

какие настройки нужно изменить:

Имя скрипта pwm_fan_daemon.py, в нем находится код в виде обычного текста. Открыть можно в любом текстовом редакторе

Менять нужно эти настройки (ищите через поиск по файлу названия переменных по типу MQTT_USER, TEMP_CHECK_INTERVAL и остальные, и меняем значения после равно):

...
TEMP_CHECK_INTERVAL = 8 # Время интервала сканирования температуры в секундах и отправки данных на сервер MQTT в секундах. Например тут через каждые 8 секунд.
...
# MQTT-настройки
MQTT_BROKER = "ВАШ_АДРЕС_HOME_ASSISTANT"  # тут ваш адрес Home Assistant, без порта! Например: MQTT_BROKER = "192.168.1.21"
MQTT_PORT = 1883   # это стандартный прорт MQTT. Можно поменять в настройках плагина MQTT если хотите а потом и тут, я не менял.
MQTT_USER = "ВАШ_USER_NAME_СОЗДАННОГО_ПОЛЬЗОВАТЕЛЯ" # имя пользователя для входа. Например: MQTT_USER = "mqtt-user"
MQTT_PASSWORD = "ВАШ_ПАРОЛЬ_СОЗДАННОГО_ПОЛЬЗОВАТЕЛЯ" # ваш пароль для входа в созданного пользователя. Например: MQTT_PASSWORD = "hhe7f2@HD$@#5D!fe2"
...

Читайте текст после символа решетки (#), там описано что за что отвечает. Обратите внимание, что значения в итоге должны быть в кавычках!

Например это:

 MQTT_BROKER = "ВАШ_АДРЕС_HOME_ASSISTANT"

вы измените на ваш адрес Home Assistant, у меня например это 192.168.1.33:

 MQTT_BROKER = "192.168.1.33"

Пример как искать нужные параметры в блокноте:
Чтобы открыть поиск нажимаем "ctrl+F" вводим имя настройки и переключаемся стрелочками.

image
image

После изменения сохраняем файл pwm_fan_daemon.py.

скидываем скрипт pwm_fan_daemon.py на сервер и делаем исполняемым

Дальше его нужно поместить в папку на самом сервере. Я использую для этого SSH подключение через клиент для Windows MobaExtern (очень его советую).

PS вставлять команды можно щелкнув Колесиком мыши, либо Правой кнопкой мыши (ПКМ) и выбрав в меню пункт Paste

image
image

Как создать подключение SSH смотри в видео:

https://github.com/user-attachments/assets/28122663-20dd-4611-845b-ef6d103ae84d

Дальше создадим в папке /opt папку PWM_FAN и в нее перетащим наш скрипт.

Должно получится так: /opt/PWM_FAN/pwm_fan_daemon.py

В видео показываю как это сделать:

https://github.com/user-attachments/assets/3268b96f-954e-430a-b30e-782044d7fafe

Далее в консоли переходим в эту папку и делаем файл исполняемым с помощью команд:

cd /opt/PWM_FAN/
sudo chmod +x pwm_fan_daemon.py

Устанавливаем зависимости для работы скрипта

Обновим системные пакеты и установим зависимости:

cd /root/
sudo apt update && sudo apt upgrade -y
sudo apt install -y git
sudo apt install python3-pip

Установим python библиотеку paho-mqtt для MQTT соединений:

cd /root/
sudo pip3 install --break-system-packages paho-mqtt

Теперь установим python библиотеку wiringOP (wiringPi) для поддержки управления пинами. Без нее ничего не будет работать:

cd /root/
apt-get update
apt-get install -y git
git clone https://github.com/orangepi-xunlong/wiringOP.git
cd wiringOP
sudo ./build clean
sudo ./build

После установки проверьте все ли установилось и работает этой командой:

gpio readall

Вывод должен быть примерно такой:

image
image

Теперь добавим наш скрипт в автозагрузку, чтобы при запуске сервера он автоматически включался и начинал работу

Создадим файл с помощью текстового редактора nano, для этого пишем в консоль:

sudo nano /etc/systemd/system/pwmfan.service

После команды файл сразу откроется в редакторе, вставляем туда этот код (ПКМ -> Paste):

[Unit]
Description=PWM Fan Control Service
After=multi-user.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/PWM_FAN
ExecStart=/usr/bin/python3 -u /opt/PWM_FAN/pwm_fan_daemon.py
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog

[Install]
WantedBy=multi-user.target

Выглядеть должно так:

image
image

Чтобы сохранить и выйти тут нужно нажать ctrl+X

Появится окно с подтверждением, нажимаем Y:

image
image

И появится еще одно окно с подтверждением о пути и имени файла, нажимаем Enter:

image
image

Если все норм, редактор закроется и вернет вас в терминал:

image
image

Чтобы убедится что вы сделали все правильно можете опять открыть этот файл и посмотреть сохранилось ли все в нем, и не пустой ли он:

sudo nano /etc/systemd/system/pwmfan.service

Теперь нам нужно активировать этот сервис, в консоли вводим поочередно следующие команды:

sudo systemctl daemon-reload
sudo systemctl enable pwmfan.service
sudo systemctl start pwmfan.service

Проверка статуса:

sudo systemctl status pwmfan.service
image
image

ГОТОВО - СЕРВИС ЗАПУЩЕН!

С ЭТОГО МОМЕНТА СКРИПТ УЖЕ РАБОТАЕТ, РЕГУЛИРУЕТ СКОРОСТЬ ВРАЩЕНИЯ ПО ТЕМПЕРАТУРЕ, И ОТЫСЛАЕТ ДАННЫЕ ПО MQTT НА СЕРВЕР (если сервер MQTT недоступен по каким либо причинам то не страшно, он подключится сам сразу как он станет доступен)

КОМАНДЫ ОБСЛУЖИВАНИЯ СЕРВИСА АВТОЗАГРУЗКИ:

Дальше просто список команд, который позволяет управлять уже настроенным сервисом (демоном). Просто для ознакомления.

Просмотр логов:

journalctl -u pwmfan.service -f

Перезапуск сервиса:

sudo systemctl restart pwmfan.service

Остановить сервис:

sudo systemctl stop pwmfan.service

Если нужно выключить автозапуск при загрузке:

sudo systemctl disable pwmfan.service

Включить автозапуск обратно:

sudo systemctl enable pwmfan.service

Удалить автозагрузку полностью (сам скрипт останется на диске):

sudo rm /etc/systemd/system/pwmfan.service
sudo systemctl daemon-reload

Настраиваем Home Assistant для отображения всек показателей из MQTT

Установим дополнение File editor для редактирования файла конфигурации из магазина дополнений:

image
image

Откроем веб интерфейс:

image
image
image
image

И тут нужно найти и открыть файл configuration.yaml, обратите внимание что он лежив внутри папки /homeassistant

Полный путь до него с корня будет такой: /homeassistant/configuration.yaml

image
image

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

mqtt:
  sensor:
    # -----------------------------------------------------------------------------
    # Датчик температуры CPU с Orange Pi
    # -----------------------------------------------------------------------------
    - name: "Orange Pi CPU Temp"                  # Отображаемое имя сенсора
      state_topic: "home/orangepi/fan_control/sensors/cpu_temp"  # Топик MQTT, откуда приходит температура CPU
      unit_of_measurement: "°C"                   # Единицы измерения — градусы Цельсия
      device_class: temperature                   # Тип устройства (для отображения и автоматизации)
      expire_after: 30                            # Если нет обновлений 30 секунд — считать недоступным
      availability_topic: "home/orangepi/fan_control/status"     # Топик состояния устройства (онлайн/оффлайн)
      payload_available: "online"                 # Сообщение при доступности
      payload_not_available: "offline"            # Сообщение при недоступности

    # -----------------------------------------------------------------------------
    # Датчик скорости вентилятора в оборотах в секунду (RPS)
    # -----------------------------------------------------------------------------
    - name: "Fan RPS"                             # Отображаемое имя сенсора
      state_topic: "home/orangepi/fan_control/sensors/fan_rps"   # Топик MQTT, где публикуется скорость вентилятора
      unit_of_measurement: "RPS"                  # Обороты в секунду
      expire_after: 30                            # Тайм-аут до "недоступен"
      availability_topic: "home/orangepi/fan_control/status"     # Проверка онлайн-состояния
      payload_available: "online"                 # Статус — доступен
      payload_not_available: "offline"            # Статус — недоступен

    # -----------------------------------------------------------------------------
    # Датчик текущего PWM сигнала вентилятора
    # -----------------------------------------------------------------------------
    - name: "Fan PWM"                             # Отображаемое имя сенсора
      state_topic: "home/orangepi/fan_control/pwm/current"       # Топик с текущим PWM значением
      unit_of_measurement: "PWM"                  # Единица — уровень PWM
      expire_after: 30                            # Тайм-аут до "недоступен"
      availability_topic: "home/orangepi/fan_control/status"     # Проверка состояния устройства
      payload_available: "online"                 # Сообщение, когда устройство онлайн
      payload_not_available: "offline"            # Сообщение, когда устройство оффлайн

  number:
    # -----------------------------------------------------------------------------
    # Минимальный уровень PWM вентилятора
    # -----------------------------------------------------------------------------
    - name: "Min PWM"                             # Название числа
      unique_id: "orangepi_fan_min_pwm"           # Уникальный идентификатор в HA
      command_topic: "home/orangepi/fan_control/set/pwm/min"     # Топик для установки нового минимального PWM
      state_topic: "home/orangepi/fan_control/pwm/min"           # Топик для получения текущего значения
      min: 950                                    # Минимально допустимое значение PWM
      max: 1024                                   # Максимально допустимое значение PWM
      step: 1                                     # Шаг изменения
      unit_of_measurement: "PWM"                  # Единица измерения
      retain: true                                # Сохранять последнее значение на MQTT-брокере

    # -----------------------------------------------------------------------------
    # Максимальный уровень PWM вентилятора
    # -----------------------------------------------------------------------------
    - name: "Max PWM"                             # Название числа
      unique_id: "orangepi_fan_max_pwm"           # Уникальный идентификатор в HA
      command_topic: "home/orangepi/fan_control/set/pwm/max"     # Топик для установки нового максимального PWM
      state_topic: "home/orangepi/fan_control/pwm/max"           # Топик для получения текущего значения
      min: 1000                                   # Минимально допустимое значение PWM
      max: 1024                                   # Максимально допустимое значение PWM
      step: 1                                     # Шаг изменения
      unit_of_measurement: "PWM"                  # Единица измерения
      retain: true                                # Сохранять последнее значение в брокере MQTT

    # -----------------------------------------------------------------------------
    # Температура, при которой вентилятор выключается
    # -----------------------------------------------------------------------------
    - name: "Off Temperature"                     # Название числа
      unique_id: "orangepi_fan_off_temp"          # Уникальный идентификатор
      command_topic: "home/orangepi/fan_control/set/temp/off"    # Топик для установки порога выключения
      state_topic: "home/orangepi/fan_control/temp/off"          # Топик для получения текущего значения
      min: 30                                     # Минимально допустимая температура выключения
      max: 50                                     # Максимально допустимая температура выключения
      step: 1                                     # Шаг изменения
      unit_of_measurement: "°C"                   # Единица измерения — градусы Цельсия
      retain: true                                # Сохранять последнее значение

    # -----------------------------------------------------------------------------
    # Максимальная температура, при которой вентилятор крутится на максимум
    # -----------------------------------------------------------------------------
    - name: "Max Temperature"                     # Название числа
      unique_id: "orangepi_fan_max_temp"          # Уникальный идентификатор
      command_topic: "home/orangepi/fan_control/set/temp/max"    # Топик для установки порога максимальной температуры
      state_topic: "home/orangepi/fan_control/temp/max"          # Топик для получения текущего значения
      min: 30                                     # Минимально допустимая температура
      max: 75                                     # Максимально допустимая температура
      step: 1                                     # Шаг изменения
      unit_of_measurement: "°C"                   # Единица измерения
      retain: true                                # Сохранять последнее значение

И сохраняем:

image
image

Перезапускаем конфигурацию:

image
image

Настраиваем UI панель

Создаём новую, даем имя и ок:

image
image

Открываем нашу панель и справа вверху нажимаем на "Карандаш" -> три точки -> Текстовый редактор -> и заменяем в нем всё на текст из файла (файл в скачаном архиве рядом со скриптом лежит) dashboard-UI_Lovelace.yaml -> Сохраняем и возвращаемся назад (крестик слева вверху).

В итоге у нас появится 2 подпанели, нажав на карандаш рядом с её именем (Например Home) нужно будет настроить видимость (выбрать пользователей кому эта панель будет видна, например администратору умного дома, те вам).

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

browser_VcF1Gav9sJ
browser_VcF1Gav9sJ

Если вас устраивает внешний вид первой панели то можете вторую просто удалить, мне же захотелось сделать эту панель красивее, поэтому я дополнительно установил из HACS 2 адднона:

  • Bubble Card

image
image
  • Mushroom

image
image

И 1 тему для Home Assistant:

  • Graphite Theme

    image
    image

Установить тему для панели можно здесь:

image
image

Про "сигнализацию в Node-Red для оповещения о неисправности охлаждения" выпущу вторую часть, если зайдет эта, код есть, все работает, просто нужно текст с пояснениями писать.

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

Весь нужный код и сопутствующие файлы вы найдете в моём репозитории Github: https://github.com/portg80/Cooling-for-orange-pi-zero-w2-and-Home-Assistant-integration

Комментарии (11)