TL;DR: Tasmota cannot drive a phase-cut TRIAC dimmer natively. Use DimmerLink as an I2C/UART slave. On ESP32 Tasmota: write a 5-line Berry script that maps any rule trigger to an I2C register write at address 0x50. On ESP8266: use
SerialSend5with the DimmerLink binary packet format. Home Assistant discovers the device automatically via Tasmota MQTT.
Why Tasmota Cannot Drive a TRIAC Directly
Tasmota's Dimmer command controls an internal PWM output or a
SWITCH relay. It does not support phase-cut (phase-angle) TRIAC
control because that requires a hardware interrupt on every AC zero
crossing (every 10 ms at 50 Hz) with sub-millisecond firing precision.
Tasmota runs an event loop and WiFi stack on the same core. It cannot guarantee < 1 ms ISR latency under WiFi load. Connecting an rbdimmer TRIAC module directly and trying to time gate pulses from Tasmota will produce flicker or no dimming at all.
The solution: offload timing to DimmerLink. DimmerLink is a dedicated Cortex-M0+ controller that manages zero-cross detection and TRIAC firing autonomously. Tasmota only sends the target brightness level (0–100) once per user command — no timing requirements.
Hardware Required
- ESP32 or ESP8266 board flashed with Tasmota
- DimmerLink module
- rbdimmer AC dimmer module (any current rating)
- 4.7 kΩ resistors × 2 (for I2C pull-ups, if using I2C mode)
Step 1 — Switch DimmerLink to I2C Mode
DimmerLink ships in UART mode by default. For the Berry I2C approach (ESP32) you must switch it to I2C mode first.
Connect DimmerLink to any USB-UART adapter (TX → RX, RX → TX, GND → GND, VCC → 3.3V), then send the SWITCH_I2C command at 115200 baud:
Byte sequence: 02 5BIn any serial terminal (RealTerm, picocom):
- Open the port at 115200, 8N1.
- Send raw bytes:
02 5B. - Expect response
00(OK). DimmerLink now starts in I2C mode after each power-up.
After switching, disconnect from the UART adapter and wire for I2C.
If you prefer to keep DimmerLink in UART mode (simpler for ESP8266), skip this step and go directly to Step 3.
Step 2 — Wiring
I2C Connection (ESP32 — recommended)
| DimmerLink | ESP32 pin | Notes |
|---|---|---|
| VCC | 3.3V | Match MCU logic voltage |
| GND | GND | — |
| SDA (TX/SDA) | GPIO21 | Add 4.7 kΩ pull-up to 3.3V |
| SCL (RX/SCL) | GPIO22 | Add 4.7 kΩ pull-up to 3.3V |
Connect pull-up resistors from SDA and SCL to 3.3V. Without them the I2C bus will not work reliably.
3.3V ──┬──────────────┬──
4.7k 4.7k
│ │
ESP32 SDA ──── DL SDA │
ESP32 SCL ──────────── DL SCL
GND ────────────────── DL GND
3.3V ───────────────── DL VCCUART Connection (ESP8266 or ESP32)
| DimmerLink | ESP8266 | ESP32 | Notes |
|---|---|---|---|
| VCC | 3.3V | 3.3V | — |
| GND | GND | GND | — |
| RX (TX/SDA) | GPIO1 TX* | GPIO17 TX2 | DL RX ← MCU TX |
| TX (RX/SCL) | GPIO3 RX* | GPIO16 RX2 | DL TX → MCU RX |
* GPIO1/3 on ESP8266 are shared with USB. Use Serial.swap() to
remap to GPIO15/GPIO13, or use I2C instead.
// ESP8266: remap Serial to GPIO15 (TX) / GPIO13 (RX)
Serial.begin(115200);
Serial.swap(); // TX → GPIO15, RX → GPIO13DimmerLink → AC Dimmer Module
| DimmerLink | Dimmer module |
|---|---|
| VCC | VCC |
| GND | GND |
| Z-C | Z-C |
| Dim | DIM |
The dimmer module connects to mains AC and the load as described in the Hardware Connection Guide.
Step 3A — Tasmota Berry Script (ESP32, I2C mode)
Berry scripting is available on ESP32 Tasmota only. It gives full programmatic control over I2C.
Open the Tasmota web console and paste:
# File: dimmer_i2c.be — DimmerLink control via I2C
# Register 0x10 (DIM0_LEVEL): 0–100 percent
import wire
wire.begin() # initialise I2C bus once at script load
def set_dimmer(level)
var l = int(level)
if l < 0 then l = 0 end
if l > 100 then l = 100 end
wire.beginTransmission(0x50)
wire.write(0x10) # DIM0_LEVEL register
wire.write(l)
wire.endTransmission()
end
# Map Tasmota Dimmer command (0–100) to DimmerLink
tasmota.add_rule("Dimmer#State",
def(value) set_dimmer(value) end)
# Map Tasmota Power command (on/off) to full or zero
tasmota.add_rule("Power#State",
def(value)
if value == 1 then set_dimmer(100)
else set_dimmer(0) end
end)To load automatically on boot, save as autoexec.be via the Tasmota
file manager (Tools → Manage File System).
How it works:
wire.begin()is called once when the script loads to initialise the I2C bus — not on every command.wire.beginTransmission(0x50)addresses DimmerLink at the default I2C address.wire.write(0x10)selects the DIM0_LEVEL register.wire.write(l)sets brightness 0–100%.- The rule fires whenever Tasmota receives a
Dimmercommand from the console, MQTT, or Home Assistant.
Test from Tasmota Console
Dimmer 50 → set_dimmer(50) → I2C write 50 to 0x10
Dimmer 0 → set_dimmer(0) → lamp off
Power 0 → set_dimmer(0)Step 3B — Tasmota UART via SerialSend (ESP8266 and ESP32)
If Berry is not available (ESP8266) or you prefer not to write scripts,
use SerialSend5 to send raw binary packets to DimmerLink over UART.
DimmerLink UART packet format for SET brightness:
02 53 00 LEVEL
│ │ │ └── brightness 0–100 (decimal)
│ │ └────── channel index (always 00)
│ └────────── command SET (0x53)
└────────────── start byte (always 0x02)In the Tasmota console:
# Set brightness to 50% (0x32 hex = 50 decimal)
SerialSend5 02530032
# Set brightness to 75% (0x4B hex = 75 decimal)
SerialSend5 0253004B
# Turn off (0x00 = 0%)
SerialSend5 02530000
# Turn on full (0x64 hex = 100 decimal)
SerialSend5 02530064Hex conversion:
Dimmer 50→ 50 decimal → 0x32 hex → packet02 53 00 32. Use any hex calculator or the table in the DimmerLink UART docs.
Automating SerialSend with Tasmota Rules
Map Tasmota's internal Dimmer value to a SerialSend command using
Mem variables and the WebCmd hack — or write a Berry script for
clean conversion on ESP32. For ESP8266 a simpler approach is to use
fixed levels via Tasmota Rules:
Rule1
ON Dimmer#State<20 DO SerialSend5 02530000 ENDON
ON Dimmer#State>=20 DO SerialSend5 02530032 ENDONFor smooth arbitrary-level control on ESP8266, the Berry approach on ESP32 is recommended.
Step 4 — Home Assistant Integration
Once Tasmota is controlling DimmerLink, Home Assistant sees the ESP device as a standard Tasmota node via MQTT autodiscovery.
Enable MQTT autodiscovery in Tasmota:
SetOption19 1 # Enable Home Assistant MQTT discoveryHome Assistant automatically creates a light entity with brightness
control. The HA brightness slider (0–255) maps to Tasmota's Dimmer
command (0–100), which triggers the Berry rule that writes to DimmerLink.
For manual HA configuration (if autodiscovery is off):
mqtt:
light:
- name: "AC Dimmer"
command_topic: "cmnd/tasmota_dimmer/Dimmer"
brightness_command_topic: "cmnd/tasmota_dimmer/Dimmer"
brightness_scale: 100
payload_on: "100"
payload_off: "0"
state_topic: "stat/tasmota_dimmer/RESULT"
brightness_state_topic: "stat/tasmota_dimmer/RESULT"
brightness_value_template: >
{{ value_json.Dimmer | default(0) }}Common Pitfalls
| Problem | Cause | Fix |
|---|---|---|
| Berry not available on device | ESP8266 Tasmota | Use UART + SerialSend5 approach |
Dimmer command has no effect |
Rule not loaded or typo | Check tasmota.add_rule syntax; reload Berry |
| DimmerLink not responding on I2C | Wrong mode (still UART) | Send 02 5B via UART first to switch |
| I2C unreliable under WiFi | Missing pull-up resistors | Add 4.7 kΩ on SDA and SCL |
SerialSend5 sends wrong level |
Hex conversion error | 50% = 0x32, 75% = 0x4B, 100% = 0x64 |
| HA shows dimmer but level ignored | on_command_type mismatch |
Use brightness_scale: 100 in MQTT light config |
Alternative — ESPHome Instead of Tasmota
If the Tasmota Berry scripting approach feels complex, ESPHome provides a native DimmerLink integration in 5 lines of YAML and handles all I2C communication automatically.
See: ESPHome YAML for AC Dimmer and DimmerLink
Quick Checklist
Related Articles
- ESPHome alternative → ESPHome YAML for AC Dimmer and DimmerLink
- Home Assistant guide → AC Dimmer with Home Assistant and ESPHome
- DimmerLink I2C not detected → DimmerLink Not Detected: I2C vs UART Mode
- Raspberry Pi control → Raspberry Pi AC Dimmer via DimmerLink
Still have questions?
Ask on forum.rbdimmer.com or open a GitHub Issue.