Zum Inhalt springen

AC-Dimmer über MQTT mit ESP32 und ESP8266

Helligkeit einer AC-Last über MQTT steuern — Topic abonnieren, Werte 0–100 empfangen, Dimmer setzen. Funktioniert mit Home Assistant, Node-RED, AWS IoT und jedem MQTT-Broker.
26. Februar 2026 durch
AC-Dimmer über MQTT mit ESP32 und ESP8266
Administrator
| Noch keine Kommentare

Kurzfassung: Installieren Sie rbdimmerESP32 (für ESP32) oder RBDdimmer (für ESP8266) plus PubSubClient. Verbinden Sie sich mit Ihrem MQTT-Broker, abonnieren Sie ein Helligkeits-Topic und rufen Sie rbdimmer_set_level() im Callback auf. Veröffentlichen Sie den aktuellen Level als Status-Topic zurück.



Funktionsweise

text
ESP32  ──WiFi──►  MQTT-Broker  ◄──────  Home Assistant / Node-RED
  │                   │
  │  Abonnement: dimmer/level/set
  │  Veröffentlichung: dimmer/level/state
  │
  └──ISR──►  TRIAC-Gate  ──►  Last (Lampe, Heizung…)

Der ESP32 abonniert ein Befehls-Topic. Wenn HA einen Wert (0–100) veröffentlicht, wendet der Callback ihn auf den Dimmer an. Der ESP32 veröffentlicht auch seinen aktuellen Level, damit HA synchron bleibt.




Hardware

Bauteil Beispiel
MCU ESP32 (Dual-Core) oder ESP8266
Dimmer Beliebiges rbdimmer-Modul 1CH/2CH/4CH
ZC-Pin GPIO 5 (beliebiger GPIO auf ESP32)
DIM-Pin GPIO 4 (beliebiger GPIO auf ESP32)
VCC 3,3V

⚠️ Use rbdimmerESP32 on dual-core ESP32. The older RBDdimmer library has no IRAM_ATTR on its ISR — it crashes when WiFi is active. rbdimmerESP32 pins the ISR to Core 0; WiFi runs on Core 1. See: Wrong Library: RBDdimmer vs rbdimmerESP32




Erforderliche Bibliotheken

Installation über Arduino Library Manager oder PlatformIO:

Bibliothek Zweck Platine
rbdimmerESP32 AC-Dimmer-ISR-Steuerung Nur ESP32
RBDdimmer AC-Dimmer-ISR-Steuerung Arduino, ESP8266
PubSubClient MQTT-Client Alle
WiFi.h WiFi (integriert) ❌ nein
ESP8266WiFi.h WiFi (integriert) ESP8266

PlatformIO (platformio.ini):

ini
lib_deps =
  https://github.com/robotdyn-dimmer/rbdimmerESP32
  knolleary/PubSubClient @ ^2.8



Vollständiger Code — ESP32

cpp
// 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();
}



Vollständiger Code — ESP8266

Für ESP8266 tauschen Sie die Bibliothek und den WiFi-Header. Die MQTT-Logik ist identisch.

cpp
// AC-Dimmer + MQTT auf ESP8266 — vollständiger Sketch
#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-Topic-Struktur

Topic Richtung Wert Beispiel
dimmer/level/set → ESP32 0100 75
dimmer/level/state ← ESP32 0100 75

Für mehrere Dimmer verwenden Sie eindeutige Topic-Präfixe pro Gerät:

text
dimmer/kitchen/level/set
dimmer/bedroom/level/set



Home-Assistant-Konfiguration

Fügen Sie ein MQTT-light zu configuration.yaml hinzu (oder verwenden Sie MQTT Discovery):

yaml
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" — wenn Sie das Licht über HA einschalten, wird der Helligkeitswert als MQTT-Payload gesendet (z. B. 75) anstatt der Zeichenkette "ON". Die Firmware empfängt direkt eine Zahl und wendet sie auf den Dimmer an.

Nach dem Hinzufügen starten Sie HA neu. Der Dimmer erscheint als dimmbare Light-Entität mit einem Helligkeitsregler von 0–100 %.




Mehrkanal-MQTT

Für 2CH- oder 4CH-Module erstellen Sie zusätzliche Topic-Paare und Kanal-Handles. Jeder Kanal bekommt sein eigenes Subscribe/Publish-Paar:

cpp
// Zusätzlicher Kanal
rbdimmer_channel_t ch2;
const char* TOPIC_SET2   = "dimmer/ch2/level/set";
const char* TOPIC_STATE2 = "dimmer/ch2/level/state";
// In onMessage(): Topic prüfen, an richtigen Kanal weiterleiten
if (strcmp(topic, TOPIC_SET) == 0) {
    rbdimmer_set_level(dimmerCh, level);
} else if (strcmp(topic, TOPIC_SET2) == 0) {
    rbdimmer_set_level(ch2, level);
}



Verwandte Artikel



Noch Fragen?

Ask on forum.rbdimmer.com or open a GitHub Issue.

Diesen Beitrag teilen
Anmelden , um einen Kommentar zu hinterlassen