Коротко: Установите
rbdimmerESP32(для ESP32) илиRBDdimmer(для ESP8266) плюсPubSubClient. Подключитесь к MQTT-брокеру, подпишитесь на топик яркости и вызовитеrbdimmer_set_level()в колбэке. Публикуйте обратно текущий уровень как топик состояния.
Как это работает
ESP32 ──WiFi──► MQTT-брокер ◄────── Home Assistant / Node-RED
│ │
│ подписка: dimmer/level/set
│ публикация: dimmer/level/state
│
└──ISR──► затвор TRIAC ──► Нагрузка (лампа, нагреватель…)ESP32 подписывается на командный топик. Когда HA публикует значение (0–100), колбэк применяет его к диммеру. ESP32 также публикует текущий уровень, чтобы HA оставался синхронизированным.
Оборудование
| Компонент | Пример |
|---|---|
| MCU | ESP32 (двухъядерный) или ESP8266 |
| Диммер | Любой модуль rbdimmer 1CH/2CH/4CH |
| Пин ZC | GPIO 5 (любой GPIO на ESP32) |
| Пин DIM | GPIO 4 (любой GPIO на ESP32) |
| VCC | 3,3 В |
⚠️ Use
rbdimmerESP32on dual-core ESP32. The olderRBDdimmerlibrary has noIRAM_ATTRon its ISR — it crashes when WiFi is active.rbdimmerESP32pins the ISR to Core 0; WiFi runs on Core 1. See: Wrong Library: RBDdimmer vs rbdimmerESP32
Необходимые библиотеки
Установите через Arduino Library Manager или PlatformIO:
| Библиотека | Назначение | Плата |
|---|---|---|
rbdimmerESP32 |
Управление ISR AC-диммера | Только ESP32 |
RBDdimmer |
Управление ISR AC-диммера | Arduino, ESP8266 |
PubSubClient |
MQTT-клиент | Любая |
WiFi.h |
WiFi (встроенная) | ❌ нет |
ESP8266WiFi.h |
WiFi (встроенная) | ESP8266 |
PlatformIO (platformio.ini):
lib_deps =
https://github.com/robotdyn-dimmer/rbdimmerESP32
knolleary/PubSubClient @ ^2.8Полный код — ESP32
// AC Dimmer + MQTT on ESP32 (dual-core)
// Library: rbdimmerESP32 + PubSubClient
// IMPORTANT: use rbdimmerESP32, NOT RBDdimmer, on ESP32
#include <WiFi.h>
#include <PubSubClient.h>
#include "rbdimmerESP32.h"
// ── Configuration ─────────────────────────────────────────────
const char* WIFI_SSID = "YourSSID";
const char* WIFI_PASS = "YourPassword";
const char* MQTT_SERVER = "192.168.1.100"; // broker IP
const int MQTT_PORT = 1883;
const char* DEVICE_ID = "dimmer_esp32_01"; // unique per device
// MQTT topics
const char* TOPIC_SET = "dimmer/level/set"; // receive command
const char* TOPIC_STATE = "dimmer/level/state"; // publish state
// Dimmer pins
#define ZC_PIN 5
#define DIM_PIN 4
// ── Globals ───────────────────────────────────────────────────
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
rbdimmer_channel_t dimmerCh;
int currentLevel = 0;
// ── MQTT callback ─────────────────────────────────────────────
void onMessage(char* topic, byte* payload, unsigned int length) {
char buf[8];
int len = min((int)length, 7);
memcpy(buf, payload, len);
buf[len] = '\0';
int level = atoi(buf);
level = constrain(level, 0, 100);
rbdimmer_set_level(dimmerCh, level);
currentLevel = level;
// Publish confirmed state
char stateStr[8];
itoa(level, stateStr, 10);
mqtt.publish(TOPIC_STATE, stateStr, true); // retained
}
// ── MQTT reconnect ────────────────────────────────────────────
void mqttReconnect() {
while (!mqtt.connected()) {
Serial.print("Connecting to MQTT…");
if (mqtt.connect(DEVICE_ID)) {
Serial.println(" connected.");
mqtt.subscribe(TOPIC_SET);
// Republish retained state on reconnect
char stateStr[8];
itoa(currentLevel, stateStr, 10);
mqtt.publish(TOPIC_STATE, stateStr, true);
} else {
Serial.print(" failed, rc=");
Serial.println(mqtt.state());
delay(5000);
}
}
}
// ── Setup ─────────────────────────────────────────────────────
void setup() {
Serial.begin(115200);
// Connect WiFi
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print(".");
}
Serial.println("\nWiFi connected: " + WiFi.localIP().toString());
// Init dimmer
rbdimmer_init();
rbdimmer_register_zero_cross(ZC_PIN, RBDIMMER_PHASE_DEFAULT);
rbdimmer_config_t cfg = {
.gpio_pin = DIM_PIN,
.phase = RBDIMMER_PHASE_DEFAULT,
.initial_level = 0,
.curve_type = RBDIMMER_CURVE_RMS
};
rbdimmer_create_channel(&cfg, &dimmerCh);
// Setup MQTT
mqtt.setServer(MQTT_SERVER, MQTT_PORT);
mqtt.setCallback(onMessage);
}
// ── Loop ──────────────────────────────────────────────────────
void loop() {
if (!mqtt.connected()) mqttReconnect();
mqtt.loop();
}Полный код — ESP8266
Для ESP8266 замените библиотеку и заголовок WiFi. Логика MQTT идентична.
// AC-диммер + MQTT на ESP8266 — полный скетч
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <RBDdimmer.h>
const char* WIFI_SSID = "YourSSID";
const char* WIFI_PASS = "YourPassword";
const char* MQTT_SERVER = "192.168.1.100";
const int MQTT_PORT = 1883;
const char* DEVICE_ID = "dimmer_esp8266_01";
const char* TOPIC_SET = "dimmer/level/set";
const char* TOPIC_STATE = "dimmer/level/state";
#define ZC_PIN 5 // D1 (NodeMCU)
#define DIM_PIN 4 // D2
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
dimmerLamp dimmer(DIM_PIN, ZC_PIN);
int currentLevel = 0;
void onMessage(char* topic, byte* payload, unsigned int length) {
char buf[8];
int len = min((int)length, 7);
memcpy(buf, payload, len);
buf[len] = '\0';
int level = constrain(atoi(buf), 0, 100);
dimmer.setPower(level);
currentLevel = level;
char stateStr[8];
itoa(level, stateStr, 10);
mqtt.publish(TOPIC_STATE, stateStr, true);
}
void mqttReconnect() {
while (!mqtt.connected()) {
if (mqtt.connect(DEVICE_ID)) {
mqtt.subscribe(TOPIC_SET);
} else {
delay(5000);
}
}
}
void setup() {
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
dimmer.begin(NORMAL_MODE, ON);
dimmer.setPower(0);
mqtt.setServer(MQTT_SERVER, MQTT_PORT);
mqtt.setCallback(onMessage);
}
void loop() {
if (!mqtt.connected()) mqttReconnect();
mqtt.loop();
}Структура MQTT-топиков
| Топик | Направление | Значение | Пример |
|---|---|---|---|
dimmer/level/set |
→ ESP32 | 0–100 |
75 |
dimmer/level/state |
← ESP32 | 0–100 |
75 |
Для нескольких диммеров используйте уникальные префиксы топиков для каждого устройства:
dimmer/kitchen/level/set
dimmer/bedroom/level/setКонфигурация Home Assistant
Добавьте MQTT light в configuration.yaml (или используйте MQTT Discovery):
mqtt:
light:
- name: "Living Room Dimmer"
unique_id: "dimmer_esp32_01"
command_topic: "dimmer/level/set"
state_topic: "dimmer/level/state"
brightness_command_topic: "dimmer/level/set"
brightness_state_topic: "dimmer/level/state"
brightness_scale: 100
on_command_type: "brightness"
retain: true
optimistic: false
on_command_type: "brightness"— при включении света из HA отправляется значение яркости в качестве MQTT-payload (например,75) вместо строки"ON". Прошивка получает число напрямую и применяет его к диммеру.
После добавления перезапустите HA. Диммер появится как сущность диммируемого света с ползунком яркости 0–100 %.
Многоканальный MQTT
Для модулей 2CH или 4CH создайте дополнительные пары топиков и дескрипторов каналов. Каждый канал получает свою пару подписки/публикации:
// Дополнительный канал
rbdimmer_channel_t ch2;
const char* TOPIC_SET2 = "dimmer/ch2/level/set";
const char* TOPIC_STATE2 = "dimmer/ch2/level/state";
// В onMessage(): проверяем топик, направляем на нужный канал
if (strcmp(topic, TOPIC_SET) == 0) {
rbdimmer_set_level(dimmerCh, level);
} else if (strcmp(topic, TOPIC_SET2) == 0) {
rbdimmer_set_level(ch2, level);
}Связанные статьи
- Wrong library on ESP32 → RBDdimmer vs rbdimmerESP32
- ESP32 crashes with WiFi → IRAM_ATTR Causes and Fix
- Single-core ESP32 → ESP32-S2/C3/H2 Doesn't Work
- ESPHome instead of MQTT → ESPHome YAML for AC Dimmer
- Which dimmer module → Complete Buyer's Guide
Остались вопросы?
Ask on forum.rbdimmer.com or open a GitHub Issue.