I’m planning a permanent AC dimmer installation in my bedroom (two dimmable ceiling lights on ESP32 with ESPHome and Home Assistant). I’ve been using the direct TRIAC approach with the ac_dimmer ESPHome platform for a few months in my workshop and it works well enough for testing.
But for a permanent install in the bedroom, I want maximum reliability — no flicker during OTA updates, no random glitches from WiFi interference.
I’ve been looking at DimmerLink as an alternative. Before I commit to one approach, I’d like to hear from people who have experience with both.
My question: Direct TRIAC via ac_dimmer vs DimmerLink via I2C — what are the real-world pros and cons of each for a Home Assistant setup?
My setup:
- ESP32 DevKit V1
- ESPHome 2024.11
- Home Assistant 2024.12
- rbdimmer 1CH 8A modules (x2)
- 230V dimmable LED ceiling lights
I’m specifically interested in:
- Reliability over months of continuous operation
- Behavior during ESP32 OTA updates
- Multi-channel support (I’ll eventually add more rooms)
- Complexity of ESPHome YAML configuration
I’ve been running the direct TRIAC approach (ac_dimmer platform) on three separate ESP32 boards for about 8 months now and I’d argue in favor of keeping it simple.
Pros of direct TRIAC:
- No extra hardware — fewer components = fewer failure points. The ESP32 handles ZC detection and TRIAC firing directly
- Full software control — you can tune the firing angle, adjust min_power, and even implement custom dimming curves without any I2C communication overhead
- Latency — direct GPIO control is effectively instantaneous. I2C adds a small communication delay (typically 1-2ms per command at 100kHz)
I measured the ZC signal with my oscilloscope on two different rbdimmer modules, and with a clean mains supply the jitter is well within acceptable range (±50µs on my bench). If your mains is reasonably clean, direct TRIAC works just fine.
The OTA concern: Yes, during an OTA update the ESP32 reboots and the lamp goes dark for 2-3 seconds. In my opinion this is acceptable if you schedule OTA updates at night or during unoccupied periods. For a bedroom light that you update once a month, is 3 seconds of darkness really a dealbreaker?
My YAML for reference:
output:
- platform: ac_dimmer
id: bedroom_dimmer
gate_pin: GPIO18
zero_cross_pin:
number: GPIO19
mode: INPUT
method: leading pulse
min_power: 20%
Been running DimmerLink on two installs for about a month now — rock solid.
The thing people underestimate about direct TRIAC is what happens in the real world, not on a bench. Your mains might be clean now but plug in a vacuum cleaner or a washing machine and watch the ZC jitter spike. DimmerLink has hardware filtering built in that handles this much better than software debouncing on the ESP.
The big win for DimmerLink in a permanent install:
- OTA is invisible — the ESP reboots, DimmerLink keeps the lamp at whatever brightness it was at. No flicker, no darkness, nothing. The lamp doesn’t even blink. This is huge for a bedroom where your partner will notice
- Hardware phase control — the DimmerLink MCU handles all timing independently. WiFi, Bluetooth, OTA, memory allocation — none of it affects the lamp
- Multi-channel — DimmerLink supports up to 4 channels on a single I2C bus. One ESP32 can control 4 separate dimmers without needing 4 ZC interrupt pins
I get the “fewer components” argument but for a permanent install you want the dimming to be bulletproof. The ESP should just be the brain sending commands, not the muscle doing real-time TRIAC timing while also running WiFi.
Tom makes a good point about the partner factor. My wife already gives me grief when the smart lights do anything unexpected. A 3-second blackout during OTA at 11pm would not go over well.
I think I’m going with DimmerLink for the bedroom. But I’ll keep the direct TRIAC setup in the workshop — it’s a dev environment and I don’t care about brief outages there.
Decision:
- Bedroom (permanent): DimmerLink via I2C
- Workshop (dev/testing): direct TRIAC via ac_dimmer
Quick question about multi-channel — if I use DimmerLink, can I control two separate light circuits from one ESP32 over the same I2C bus? I have two ceiling lights on separate switches.
Yes, DimmerLink supports up to 4 channels on a single I2C bus. Each channel has its own address or you can use a multi-channel DimmerLink board.
The way I’ve got it set up: one ESP32, one I2C bus (SDA/SCL), two DimmerLink modules with addresses 0x27 and 0x28. Each controls a separate light circuit. Works perfectly — you send brightness commands independently to each address.
Been running this exact two-channel setup for about a month in my living room. Haven’t had to touch it once.
Fair points from Tom about the real-world mains conditions. I’ll concede that my bench measurements with clean mains don’t represent every installation.
I did some additional testing — connected a 2kW induction heater on the same circuit as the dimmer. The ZC jitter jumped from ±50µs to ±300µs, which caused visible flicker at low brightness with the direct TRIAC approach. Interesting result.
That said, for my personal installations where I control the electrical environment, direct TRIAC is still my preference. But I can see why DimmerLink makes sense for a general-purpose production install where you can’t guarantee clean mains.
Here’s my updated YAML with some additional filtering I added after the induction heater test:
output:
- platform: ac_dimmer
id: workshop_dimmer
gate_pin: GPIO18
zero_cross_pin:
number: GPIO19
mode: INPUT
inverted: false
method: leading pulse
min_power: 25%
Perfect — two channels on one I2C bus is exactly what I need.
For anyone finding this thread later, here’s my planned DimmerLink ESPHome configuration for two channels:
i2c:
sda: GPIO21
scl: GPIO22
scan: true
output:
- platform: custom
type: float
lambda: |-
auto dimmer1 = new DimmerLinkOutput(0x27);
App.register_component(dimmer1);
return {dimmer1};
outputs:
id: dimmerlink_ch1
- platform: custom
type: float
lambda: |-
auto dimmer2 = new DimmerLinkOutput(0x28);
App.register_component(dimmer2);
return {dimmer2};
outputs:
id: dimmerlink_ch2
light:
- platform: monochromatic
name: 'Bedroom Main'
output: dimmerlink_ch1
gamma_correct: 1.0
zero_means_zero: true
- platform: monochromatic
name: 'Bedroom Reading'
output: dimmerlink_ch2
gamma_correct: 1.0
zero_means_zero: true
I’ll report back once it’s installed and running.
The external component approach is much cleaner — I’ll go with that. Thanks for pointing it out.
For anyone finding this later, here’s my final summary:
Direct TRIAC (ac_dimmer):
- Best for: development, testing, simple single-channel setups
- Pros: no extra hardware, direct control, simpler wiring
- Cons: lamp flickers during OTA, sensitive to mains noise, dual-core ESP32 only
DimmerLink (I2C):
- Best for: permanent installs, multi-channel, production environments
- Pros: OTA-safe, hardware ZC filtering, up to 4CH per bus, works with any MCU
- Cons: extra hardware cost, slightly more complex initial setup
I’ll update this thread once my bedroom install is complete. Thanks to everyone for the thorough discussion — this is exactly the kind of comparison I was looking for.