ChimeraFX Light Platform
The ChimeraFX Light Platform (cfx_light) is a custom ESPHome light component specifically designed to be the ultimate companion for ChimeraFX.
Hardware & Driver Architecture
cfx_light is an asynchronous DMA driver built directly on native ESP-IDF peripherals. Here is what that means in practice:
- Framework-agnostic RMT backend. Whether you compile with ESP-IDF or Arduino,
cfx_lightdrives the ESP32's RMT (Remote Control) peripheral directly via IDF drivers — fire-and-forget DMA transmissions regardless of your framework choice. - 1-wire NRZ strips (WS2812X, SK6812, WS2811) are driven via RMT at a hardware-locked 800 kHz. Timing is generated by a custom engine to guarantee 1:1 color accuracy and zero-flicker output.
- 2-wire SPI strips (APA102, SK9822) are driven via the SPI Master peripheral at configurable speeds (typically 10–20 MHz+), bypassing the NRZ physical bottleneck entirely. The bottleneck shifts to CPU math — see Performance & Troubleshooting for details.
- Chipset-aware defaults.
cfx_lightselects the correct byte order, RGBW protocol width, and RMT symbol allocation automatically based on your declaredchipset.
If your strip uses standard 800 kbps NRZ timing but is not on the supported list, WS2812X is a reliable drop-in. For unlisted SPI strips, try APA102.
Node limits for V1.41: A ChimeraFX node must be either RMT-only or SPI-only. Mixed RMT + SPI
cfx_lightentries are rejected at compile time because sustained SPI transfers can disturb RMT timing on tested ESP32 Classic hardware. ESP32 Classic supports up to 4 RMT outputs or 2 SPI outputs per node; ESP32-S3 supports up to 2 RMT outputs or 2 SPI outputs; ESP32-C3 supports either 1 experimental RMT output or 1 experimental SPI output. Eachcfx_lightcan define up to 4 segments.
Tested LED Limits
The limits below are based on physical testing for ChimeraFX V1.41 using the Energy effect at default values, chosen because it is one of the heavier calculation loads in the library. Treat the recommended range as the target for smooth real-world installations, the tested range as validated on the current rig, and the stress range as useful engineering data rather than a deployment target. When validating your own rig, use LedFPS as the visible strip-refresh metric; RenderFPS only measures effect calculation speed.
| Platform | Transport | Recommended smooth limit | Tested stable limit | Stress result |
|---|---|---|---|---|
| ESP32 Classic | RMT / 1-wire NRZ | 360 LEDs per GPIO for ~60 LedFPS |
600 LEDs per GPIO for 30+ LedFPS |
1100 LEDs per GPIO on 4 outputs runs, but visible refresh drops to roughly 16-18 LedFPS |
| ESP32 Classic | SPI / APA102-SK9822 | Up to 2000 LEDs per SPI output | 2x2000 LEDs, smooth on the test rig | Pending larger stress test |
| ESP32-C3 | RMT / 1-wire NRZ | Experimental: 360 LEDs on 1 output at ~60 LedFPS |
600 LEDs on 1 output for 30+ LedFPS |
Pending larger stress test |
| ESP32-C3 | SPI / APA102-SK9822 | Up to 2000 LEDs on 1 SPI output | 2000 virtual LEDs at ~60 LedFPS |
Pending larger stress test |
| ESP32-S3 | RMT / 1-wire NRZ | 2 RMT outputs max. Constrained by 192-symbol limit. | 2x600 SK6812/RGBW at roughly ~40 LedFPS |
Pending larger stress test |
| ESP32-S3 | SPI / APA102-SK9822 | Up to 2000 LEDs per SPI output | Pending long-strip physical retest | Pending larger stress test |
For 60 LED/m strips, the tested ESP32 Classic RMT guidance translates to about 24 meters total at ~60 LedFPS with 4x360 LEDs, or about 40 meters total at 30+ LedFPS with 4x600 LEDs.
ESP32-C3 RMT is intentionally marked experimental. After C3-specific RMT tuning plus Energy optimization, one RMT output can run the reference Energy effect cleanly at the limits above. Two 600-LED RMT outputs still overload the C3 RMT path and are not part of the V1.41 recommended configuration.
ESP32-S3 RMT Limitation: V1.41 is heavily constrained by the S3’s smaller RMT symbol pool (just 192 symbols, managed in 48-symbol blocks, compared to the Classic's 512 symbols). Only the first RMT output utilizes the GDMA lane, providing the best timing margin. While the hardware can theoretically support more, additional outputs fall back to non-DMA transmission, which leads to flickering or artifacts at high LED counts. Testing showed 2 RMT outputs are release-grade. 3 or 4 RMT outputs are not realistically possible on ESP32-S3 for production deployments. A high-performance parallel LED driver is currently in development to address this hardware constraint in a future release.
For the timing details behind these numbers, see Performance & Troubleshooting.
Why use cfx_light?
- Auto-injection (
all_effects): The biggest feature! By default,cfx_lightwill automatically parse and inject all ChimeraFX effects into your device at compile time. No more!includemacros, and no more bloated YAML files with hundreds of lines of effect blocks. You can disable this feature by settingall_effects: false. - Chipset-Aware Intelligence: Native understanding of the strip's timing requirements.
- Optimized RMT Symbols Allocation: ESPHome's standard RMT driver occasionally struggles with symbol buffering on different chips (like S3 vs Classic).
cfx_lighttries automatically setting the optimal RMT memory boundaries for your exact silicon, eliminating the "flickering" or "data corruption" issues associated with large LED strips. Can be manually overridden withrmt_symbols. - Automatic RGBW Handling: If you select
SK6812, it automatically configures the 4-byte protocol andGRBWformatting without requiring manual overrides (although you can still override them if you have a weird LED strip variant).
CFX Light Configuration
# Example config for 1-wire NRZ strips (WS2812X, SK6812, WS2811):
light:
- platform: cfx_light
name: "LED Strip RMT"
id: led_strip_rmt
pin: GPIO16
num_leds: 120
chipset: WS2812X
# RMT strip with one extra physical sacrificial pixel near the controller:
light:
- platform: cfx_light
name: "LED Strip With Sacrificial Pixel"
id: led_strip_signal
pin: GPIO16
num_leds: 60 # Visible LEDs only; physical strip has 61 LEDs
chipset: WS2812X
sacrificial_pixel: true # First physical LED stays off and boosts signal
# Example config for 2-wire SPI strips (APA102, SK9822):
light:
- platform: cfx_light
name: "LED Strip SPI"
id: led_strip_spi
data_pin: GPIO23 # Data pin required for SPI strips
clock_pin: GPIO18 # Clock pin required for SPI strips
spi_speed: 10MHz # SPI speed for SPI strips
num_leds: 120
chipset: SK9822
Required Parameters
For 1-wire NRZ chipsets:
- name (string): The name of the light in Home Assistant.
- id (ID): The ID of the light component.
- pin (Pin): The GPIO pin the data line of your LED strip is connected to.
- chipset (string): The type of LED strip you are using.
- num_leds (int): The number of visible, controllable LEDs in your strip. If
sacrificial_pixelis enabled, do not include the sacrificial LED in this count.
For 2-wire SPI chipsets:
- name (string): The name of the light in Home Assistant.
- id (ID): The ID of the light component.
- data_pin (Pin): The GPIO pin the data line of your LED strip is connected to.
- clock_pin (Pin): The GPIO pin the clock line of your LED strip is connected to.
- chipset (string): The type of LED strip you are using.
- num_leds (int): The total number of LEDs in your strip.
Supported Chipsets
cfx_light supports both 1-wire (NRZ) and 2-wire (SPI) chipsets. It utilizes native hardware peripherals (RMT and SPI Master) to generate precise timings:
- 1-wire NRZ: WS2812, WS2812B, WS2813, WS2815, SK6812 (RGBW), WS2811.
- 2-wire SPI: APA102, SK9822 (beta driver).
Chipset Identification and Configuration
To use a specific chipset, use the chipset variable in your YAML:
| Parameter | Chipset Option | Description |
|---|---|---|
| chipset | WS2812X |
Standard 3-pin RGB timing (Default) |
SK6812 |
4-byte RGBW timing (GRBW order) | |
WS2811 |
Optimized timing for WS2811 data rates | |
APA102 |
2-wire SPI timing (beta driver) | |
SK9822 |
2-wire SPI timing (beta driver) |
Optional Parameters
- all_effects (boolean, default:
true): When set totrue, the component will instantly register all effects. Set tofalseto manually register just the effects and custom presets you want to use. - rgb_order (string): The byte order of the colors. If omitted,
cfx_lightsets the standard default based on yourchipset(e.g.,WS2812Xdefaults toGRB). Options:RGB,RBG,GRB,GBR,BGR,BRG. - is_rgbw (boolean): Explicitly declare the strip as 4-byte RGBW. If your chipset is
SK6812, this is automaticallytrue. - is_wrgb (boolean, default:
false): Sets the white byte position to the front of the data packet rather than the end. Required for some rare SK6812 variant clones. - rmt_symbols (int, default:
0): The number of RMT symbols to allocate. If left at0,cfx_lightwill dynamically allocate the maximum safe bounds based on your specific ESP32 processor variant. - sacrificial_pixel (boolean, default:
false): RMT-only option for long data-line runs. When enabled,cfx_lighttransmits one extra black pixel before logical LED0. Place this extra physical LED close to the controller; it stays off, boosts the signal, and is not counted innum_ledsor segment indexes. - spi_speed (Frequency, Optional): The SPI clock speed for
APA102andSK9822strips. If omitted,cfx_lightuses a sensible default. - default_transition_length (Time, default:
0s): The standard ESPHome transition duration for solid-color mode and for eligible ChimeraFX effect powerOFF -> ON -> OFFtransitions. Architectural effects and the signature effectsEnergyandChaos Theoryintentionally ignore this setting so their authored intros/outros stay untouched. - set_intro (int, Optional): Force a global Intro Animation for eligible effects. Architectural effects,
Energy, andChaos Theorykeep their authored intros. - set_outro (int, Optional): Force a global Outro Animation for eligible effects. Architectural effects,
Energy, andChaos Theorykeep their authored outros. - set_inout_dur (Time, Optional): Sets the duration for both global intros and outros.
- set_brightness (percentage, Optional): Applies a brightness default every time the light turns on, using the same
0-100%style as ESPHome light brightness values. - set_color (list[int], Optional): Applies a color default every time the light turns on as
[r, g, b]or[r, g, b, w]using0-100channel percentages (wrequires a white-channel strip). This also affects single-tone effects that derive their color from the current light state. It does not force palette-driven multicolor effects to a single color. - controls (boolean, default:
true): Automatically generate the ChimeraFX control entities for this light. - ctrl_exclude (list[int], Optional): Exclude specific auto-generated control groups by ID. See Controls for the control ID list.
- segments (list, Optional): Define logical sub-zones of the strip as independent light entities, up to 4 per
cfx_light. See the next chapter Segments for more details.
Segments (Multi-Zone Control)
ChimeraFX supports dividing a single physical LED strip into up to 4 independent logical segments. Each segment is exposed to Home Assistant as a separate light entity, allowing you to run different effects on different parts of the same strip simultaneously.
Segment Configuration
Segments are defined under the segments key in your cfx_light configuration.
light:
- platform: cfx_light
name: "Main TV Strip"
id: tv_strip
pin: GPIO16
num_leds: 120
chipset: WS2812X
segments:
- id: "tv_left"
name: "TV Left Side"
start: 0
stop: 40
- id: "tv_top"
name: "TV Top"
start: 40
stop: 80
mirror: true
- id: "tv_right"
name: "TV Right Side"
start: 80
stop: 120
Segment Parameters
- id (ID, Required): A unique ESPHome
idfor the segment light entity. - name (string, Optional): The name of the light entity in Home Assistant. If omitted, the
idis used. - start (int, Required): The starting pixel index (inclusive).
- stop (int, Required): The stopping pixel index (exclusive).
- mirror (boolean, default:
false): If true, calculations are reversed for this segment (useful for symmetrical setups). - set_intro (int, Optional): Override the global intro mode for this segment on eligible effects. Architectural effects,
Energy, andChaos Theorykeep their authored intros. - set_outro (int, Optional): Override the global outro mode for this segment on eligible effects. Architectural effects,
Energy, andChaos Theorykeep their authored outros. - set_inout_dur (Time, Optional): Override the global intro/outro duration for this specific segment.
- set_brightness (percentage, Optional): Applies a brightness default every time the segment turns on, using the same
0-100%style as ESPHome light brightness values. - set_color (list[int], Optional): Defines the default color applied when the segment turns on. Accepts
[r, g, b]or[r, g, b, w]values (wherewrequires a white-channel strip) using0-100channel percentages. This setting affects solid-color mode and single-tone effects. Values can be validated via the light logs.
Master vs. Segment Behavior
When segments are defined:
-
The "Master" light entity (e.g., "Main TV Strip") acts as a global power and brightness control. It does not have its own effects. Turning off the Master turns off all segments.
-
Each segment light entity (e.g., "TV Left Side") has the full suite of ChimeraFX effects injected into it (unless
all_effects: falseis set on the main/master light). -
Each light segment operates on its own dedicated runner instance. This ensures that every single parameter is completely independent, allowing users to configure each segment exactly as they want.
Overriding and Customizing Effects
While all_effects: true loads all available effects automatically, you may still want to set hardcoded defaults (such as making the Aurora effect default to the Forest palette on boot). How you do this depends on whether you want to replace the original effect or create a new variation:
- To override an effect: Manually define an
addressable_cfxeffect with the exact same name. Your manual override will seamlessly replace the auto-injected version. - To create multiple versions: If you want to keep the default effect but add custom variations, simply define the effect and give it a different name (e.g.,
name: "Aurora Fast"). This adds your customized preset as a completely new, separate effect.
light:
- platform: cfx_light
name: "Living Room Light"
id: led_strip
pin: GPIO16
num_leds: 300
chipset: WS2812X
# We want ALL effects, but we want to customize 'Aurora'
effects:
- addressable_cfx:
name: "Aurora" # Override the default Aurora effect
effect_id: 38
set_palette: 2 # Force 'Forest'
set_speed: 50 # Make it faster (dfault is 24)
- addressable_cfx:
name: "Aurora Fast"
effect_id: 38
set_palette: 2 # Force 'Forest'
set_speed: 200 # Make it even faster