Color.LED (Color v0.4.0)

Copy Markdown

Colour conversion for multi-channel addressable LEDs — fixtures with one or more extra white channels alongside R, G, B.

Two channel layouts are supported:

  • RGBWColor.LED.RGBW. Three coloured LEDs plus a single white LED per pixel. The white LED's colour temperature is fixed by the chip variant. Used by e.g. WS2814 (warm, neutral and cool variants) and the SK6812-RGBW family.

  • RGBWW / RGB+CCTColor.LED.RGBWW. Three coloured LEDs plus a warm white and a cool white LED per pixel. Used by e.g. WS2805 and several SK6812 variants. The two whites can be blended to reach any CCT on the line between them.

These structs are intentionally device-referred. They do not implement Color.Behaviour (which assumes a device- independent colour space with a single from_xyz/1) because converting to an RGBW/RGBWW pixel requires the white LED's colour temperature — there is no canonical answer without that parameter. Use Color.LED.RGBW.from_srgb/2 and Color.LED.RGBWW.from_srgb/2 explicitly.

Channel semantics

All channels — r, g, b, w, ww, cw — are linear drive values in [0.0, 1.0], not sRGB-companded values. A value of 0.0 means "LED off"; 1.0 means "LED at full". The library applies sRGB companding when converting from a Color.SRGB struct, and un-compands back on the way out.

The R/G/B primaries are assumed to match the sRGB working space (close enough for all WS281x / SK681x chips; exact for chips binned to sRGB). If you need a different primary set, stage the conversion through Color.RGB (linear, any working space) and then translate the matrix yourself.

Extraction algorithm

For RGBW, given a target linear-sRGB (R, G, B) and a white LED whose spectral output corresponds to linear-sRGB (Rw, Gw, Bw) at full drive, the extraction is:

w = min(1, R/Rw, G/Gw, B/Bw)          (clamped to  0)
r = R  w·Rw
g = G  w·Gw
b = B  w·Bw

This maximises the white channel while keeping all RGB channels non-negative — more light from the (usually more efficient) white LED, less from the RGB LEDs.

For RGBWW the algorithm first picks a blend ratio between the warm and cool whites matching the target's correlated colour temperature, synthesises an effective mixed white at that blend, then runs the RGBW extraction against that mixed white. The resulting total white is split back into ww and cw by the same ratio.

Chip presets

chip_options/1 returns the default CCT options for the common chip variants:

ChipKindTypical white temperature(s)
:ws2814_wwRGBW3000 K (warm)
:ws2814_nwRGBW4500 K (neutral)
:ws2814_cwRGBW6000 K (cool)
:sk6812_wwRGBW3000 K
:sk6812_nwRGBW4500 K
:sk6812_cwRGBW6500 K
:ws2805RGBWW3000 K warm + 6500 K cool

These are typical values from datasheets and vendor pages — actual parts vary by batch and binning. Measure yours if you need calibration-grade accuracy.

Example

# Build a pixel for a WS2805 fixture from an sRGB colour
options = Color.LED.chip_options(:ws2805)
{:ok, target} = Color.new("#ffa500")                 # orange
pixel = Color.LED.RGBWW.from_srgb(target, options)
# => %Color.LED.RGBWW{r: …, g: …, b: …, ww: …, cw: …,
#                     warm_temperature: 3000,
#                     cool_temperature: 6500,
#                     alpha: nil}

# Preview what the pixel will actually emit:
{:ok, srgb_preview} = Color.LED.RGBWW.to_srgb(pixel)

Summary

Functions

Returns the recommended extraction options for a named LED chip variant.

Returns the list of supported chip presets.

Types

chip()

@type chip() ::
  :ws2814_ww
  | :ws2814_nw
  | :ws2814_cw
  | :sk6812_ww
  | :sk6812_nw
  | :sk6812_cw
  | :ws2805

Functions

chip_options(chip)

@spec chip_options(chip()) :: keyword()

Returns the recommended extraction options for a named LED chip variant.

The returned keyword list can be passed directly to Color.LED.RGBW.from_srgb/2 or Color.LED.RGBWW.from_srgb/2 — the :kind entry tells you which one.

Arguments

  • chip is a chip atom. See the chip table in the module doc.

Returns

  • A keyword list with at least :kind (:rgbw or :rgbww) and the relevant temperature(s).

Examples

iex> Color.LED.chip_options(:ws2814_ww)
[kind: :rgbw, white_temperature: 3000]

iex> Color.LED.chip_options(:ws2805)
[kind: :rgbww, warm_temperature: 3000, cool_temperature: 6500]

chips()

@spec chips() :: [chip()]

Returns the list of supported chip presets.

Examples

iex> :ws2814_nw in Color.LED.chips()
true

iex> :ws2805 in Color.LED.chips()
true