Passa al contenuto

Управление AC диммером через DimmerLink на Raspberry Pi

Linux не обеспечивает управление GPIO в реальном времени — прямое фазовое управление TRIAC невозможно без специализированного контроллера. DimmerLink решает задачу: Raspberry Pi отправляет только уровень яркости, DimmerLink обеспечивает точный тайминг.

TL;DR: Прямое фазовое управление TRIAC с GPIO Raspberry Pi невозможно — джиттер ОС Linux составляет 1–10 мс, тогда как для управления TRIAC требуется < 100 мкс. Используйте DimmerLink как аппаратный контроллер: RPi записывает значение яркости (0–100) по I2C на адрес 0x50, регистр 0x10. Одна строка на Python: bus.write_byte_data(0x50, 0x10, level).




Почему Raspberry Pi не может напрямую управлять TRIAC

Фазовое TRIAC диммирование включает затвор с точной задержкой после каждого перехода через ноль переменного тока (каждые 10 мс при 50 Гц). Допустимая погрешность тайминга — менее 100 мкс во избежание заметного мерцания.

Raspberry Pi работает под Linux — универсальной ОС с планировщиком задач, свопом, сетевыми драйверами и активностью GPU, конкурирующими за процессорное время. Задержка прерывания GPIO под этой ОС:

Условие Задержка прерывания GPIO
Незагруженная система 0,5–2 мс
Активная сеть / USB 2–10 мс
Дисковый ввод-вывод до 50 мс

Джиттер 2 мс при яркости 10% (окно включения 9 мс) означает вариацию яркости 22% — явно заметное мерцание. Даже с демоном pigpio (GPIO на основе DMA, лучший доступный вариант) джиттер обычно составляет 200–500 мкс — всё ещё выше требуемого порога при реальной нагрузке.

Это ограничение не специфично для Raspberry Pi. Любой Linux SBC (Orange Pi, Rock Pi, Jetson Nano, Banana Pi) имеет те же ограничения. Управление TRIAC в реальном времени на Linux требует патча RT ядра (непрактично для хобби-проектов) или делегирования тайминга выделенному микроконтроллеру.

DimmerLink — это выделенный контроллер. Он управляет детектированием перехода через ноль и включением TRIAC на Cortex-M0+ (семейство STM32), обеспечивая джиттер < 50 мкс независимо от нагрузки на ЦПУ хоста. Raspberry Pi только сообщает ему нужную яркость — никаких требований к таймингу.




Необходимое оборудование

  • Raspberry Pi 3, 4, 5 или Zero 2W (любая модель с I2C)
  • Модуль DimmerLink
  • Модуль AC диммера rbdimmer (любой номинал тока)
  • 2 × 4,7 кОм резисторы (подтяжки I2C — часто не нужны на RPi 3/4)



Шаг 1 — Переключение DimmerLink в режим I2C

DimmerLink поставляется в режиме UART по умолчанию. Переключите его в режим I2C перед подключением к Raspberry Pi.

Подключите DimmerLink к USB-UART адаптеру (TX → RX, RX → TX, GND, VCC 3,3В). На любом компьютере откройте порт на 115200 бод, 8N1, и отправьте:

text
Сырые байты: 02 5B

Ожидаемый ответ: 00 (OK). Устройство теперь запускается в режиме I2C после каждого включения. (Режим сохраняется в EEPROM.)




Шаг 2 — Подключение


Raspberry Pi → DimmerLink (I2C)

GPIO разъём Raspberry Pi DimmerLink Функция
Контакт 1 (3,3В) VCC Питание
Контакт 6 (GND) GND Земля
Контакт 3 (GPIO2 / SDA) SDA Данные I2C
Контакт 5 (GPIO3 / SCL) SCL Тактирование I2C

Подтягивающие резисторы: Raspberry Pi 3/4/5 имеет встроенные резисторы 1,8 кОм на GPIO2 и GPIO3. Обычно этого достаточно для кабелей длиной до 30 см. Для более длинных кабелей или ненадёжной связи добавьте внешние резисторы 4,7 кОм от SDA и SCL к 3,3В.


DimmerLink → Модуль AC диммера

DimmerLink Модуль диммера
VCC VCC
GND GND
Z-C Z-C
Dim DIM

Подключите модуль диммера к сети переменного тока и нагрузке согласно Руководству по аппаратному подключению.




Шаг 3 — Включение I2C на Raspberry Pi

bash
sudo raspi-config
# Interface Options → I2C → Enable → OK → Finish
sudo reboot

После перезагрузки установите i2c-tools и проверьте подключение:

bash
sudo apt install i2c-tools
i2cdetect -y 1

Ожидаемый результат — адрес 50 виден в таблице:

text
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
...
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

Если устройство не появляется, см. DimmerLink не обнаруживается.




Шаг 4 — Управление через Python (smbus2)

Установите библиотеку:

bash
pip install smbus2


Минимальный пример

python
from smbus2 import SMBus
DIMMER_ADDR = 0x50
REG_LEVEL   = 0x10  # DIM0_LEVEL — яркость 0–100%
bus = SMBus(1)  # шина I2C 1 Raspberry Pi
bus.write_byte_data(DIMMER_ADDR, REG_LEVEL, 50)  # установить 50%
bus.close()


Полный класс с обработкой ошибок

python
from smbus2 import SMBus
import time
class DimmerLink:
    ADDR = 0x50
    REG_STATUS = 0x00
    REG_LEVEL  = 0x10  # яркость 0-100%
    REG_CURVE  = 0x11  # 0=LINEAR, 1=RMS, 2=LOG
    REG_FREQ   = 0x20  # частота сети (50 или 60 Гц)
    def __init__(self, bus_number=1):
        self.bus = SMBus(bus_number)
    def is_ready(self):
        status = self.bus.read_byte_data(self.ADDR, self.REG_STATUS)
        return bool(status & 0x01)
    def set_level(self, level: int):
        """Установить яркость 0–100%."""
        level = max(0, min(100, level))
        self.bus.write_byte_data(self.ADDR, self.REG_LEVEL, level)
    def get_level(self) -> int:
        """Прочитать текущую яркость."""
        return self.bus.read_byte_data(self.ADDR, self.REG_LEVEL)
    def set_curve(self, curve: int):
        """Установить кривую диммирования: 0=LINEAR, 1=RMS, 2=LOG."""
        if curve not in (0, 1, 2):
            raise ValueError("curve must be 0, 1, or 2")
        self.bus.write_byte_data(self.ADDR, self.REG_CURVE, curve)
    def get_frequency(self) -> int:
        """Прочитать частоту сети (50 или 60 Гц)."""
        return self.bus.read_byte_data(self.ADDR, self.REG_FREQ)
    def close(self):
        self.bus.close()
if __name__ == "__main__":
    dimmer = DimmerLink()
    if dimmer.is_ready():
        print(f"Частота сети: {dimmer.get_frequency()} Гц")
        # Плавное нарастание яркости
        for level in range(0, 101, 5):
            dimmer.set_level(level)
            print(f"Яркость: {level}%")
            time.sleep(0.1)
        # Установить кривую RMS для ламп накаливания
        dimmer.set_curve(1)  # 1 = RMS
        print("Кривая: RMS (лампы накаливания)")
    else:
        print("DimmerLink не готов — проверьте подключение и режим I2C")
    dimmer.close()


Быстрое управление из командной строки (без Python)

bash
# Яркость 50%  (0x32 hex = 50 dec)
i2cset -y 1 0x50 0x10 50
# Прочитать текущую яркость
i2cget -y 1 0x50 0x10
# Прочитать частоту сети
i2cget -y 1 0x50 0x20



Шаг 5 — Интеграция с Node-RED


Использование узла команды i2cset

В простом потоке используйте exec для запуска i2cset:

text
[inject: level=50] → [function: build command] → [exec] → [debug]

Узел Function:

javascript
var level = msg.payload;  // 0-100
msg.payload = "i2cset -y 1 0x50 0x10 " + level;
return msg;


Использование node-red-contrib-i2c

Установите узел:

bash
cd ~/.node-red
npm install node-red-contrib-i2c

Настройте узел i2c out:

  • Адрес: 0x50
  • Команда: 0x10 (регистр)
  • Payload: значение яркости (0–100) из msg.payload

Ползунок UI, привязанный к диапазону 0–100, напрямую управляет диммером.




Шаг 6 — Home Assistant OS на Raspberry Pi

Если Raspberry Pi работает под Home Assistant OS (не Home Assistant на Raspberry Pi OS), доступ к аппаратному I2C из дополнений ограничен контейнерной моделью HA OS.

Рекомендуемый путь:

  1. Оставьте Raspberry Pi в качестве сервера HA.
  2. Добавьте отдельный ESP32 с DimmerLink в качестве аппаратного контроллера.
  3. Используйте дополнение ESPHome в Home Assistant для прошивки и управления ESP32.
  4. HA управляет яркостью через интеграцию ESPHome — без прямого I2C с хоста RPi.

См.: AC диммер с Home Assistant и ESPHome

Если вы используете Home Assistant supervised на Raspberry Pi OS (не HA OS), доступ I2C из Python скриптов не ограничен и подход через smbus2 работает напрямую.




Шаг 7 — Запуск как системная служба systemd

Для автоматического запуска скрипта управления диммером:

Создайте /etc/systemd/system/dimmer.service:

ini
[Unit]
Description=DimmerLink Controller
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/dimmer_control.py
Restart=on-failure
User=pi
[Install]
WantedBy=multi-user.target

Включите и запустите:

bash
sudo systemctl daemon-reload
sudo systemctl enable dimmer.service
sudo systemctl start dimmer.service



Другие Linux SBC

Тот же подход работает на любом Linux SBC с I2C:

Плата Шина I2C Команда определения Примечания
Raspberry Pi 3/4/5 /dev/i2c-1 i2cdetect -y 1 Стандарт
Raspberry Pi Zero 2W /dev/i2c-1 i2cdetect -y 1 Стандарт
Orange Pi Zero 2 /dev/i2c-3 i2cdetect -y 3 Зависит от модели
Rock Pi 4 /dev/i2c-7 i2cdetect -y 7 Зависит от модели
Banana Pi M2 /dev/i2c-1 i2cdetect -y 1 Стандарт
Jetson Nano /dev/i2c-1 i2cdetect -y 1
HA OS на RPi Недоступна Используйте ESP32 + DimmerLink

Для поиска доступных шин I2C на любой Linux плате:

bash
ls /dev/i2c-*

Для Orange Pi и Banana Pi включите I2C через armbian-config:

bash
sudo armbian-config
# System → Hardware → enable i2c

В Python передайте правильный номер шины в SMBus():

python
bus = SMBus(3)  # для /dev/i2c-3 на Orange Pi Zero 2



Типичные проблемы

Проблема Причина Решение
i2cdetect ничего не показывает по 0x50 DimmerLink в режиме UART Переключите командой 02 5B по UART
OSError: [Errno 121] Нет подтяжки / неверное подключение Проверьте SDA/SCL соединения
PermissionError: /dev/i2c-1 Пользователь не в группе i2c sudo usermod -aG i2c $USER
i2cdetect зависает Режим UART удерживает SDA Переключите DimmerLink в режим I2C
Мерцание от джиттера RPi Попытка прямого управления TRIAC Необходимо использовать DimmerLink
RPi Zero 2W медленный I2C Режим низкой скорости Уменьшите длину кабеля



Краткий чеклист

  • ☐ DimmerLink переключён в режим I2C (`02 5B` по UART)
  • ☐ I2C включён в `raspi-config` (или `armbian-config`)
  • ☐ `i2cdetect -y 1` показывает адрес `50`
  • ☐ Пользователь добавлен в группу `i2c` (`sudo usermod -aG i2c $USER`)
  • ☐ `pip install smbus2` выполнен
  • ☐ `bus.write_byte_data(0x50, 0x10, 50)` изменяет яркость лампы



  • Связанные статьи



    Остались вопросы?

    Задайте на forum.rbdimmer.com или откройте GitHub Issue.

    Condividi articolo
    Accedi per lasciare un commento