Skip to content

LEDPixelsJSONConfig

Rob Dobson edited this page Oct 21, 2026 · 5 revisions

LEDPixels JSON Configuration

This page describes the JSON used to configure LEDPixels. The configuration is normally an entry in the Devices array of a SysType (see SysTypes), where the class is the name the application registered its LEDPixelsDevice (or subclass) under, normally LEDPixels.

The same JSON can also be passed directly to LEDPixels::setup(const RaftJsonIF&) when LEDPixels is used without the device wrapper.

Structure

{
    "class": "LEDPixels",
    "name": "LEDs",
    "brightnessPC": 100,
    "strips": [
        { LEDStripConfig },
        { LEDStripConfig }
    ],
    "segments": [
        { LEDSegmentConfig },
        { LEDSegmentConfig }
    ]
}
Setting Description Type Default
class Device class name used to find the device in the device factory. Standard device setting, not read by LEDPixels. string required
name Device name. Standard device setting. string
brightnessPC Global brightness as a percentage. Used as the brightness of any segment that doesn't set its own brightnessPC. number 100
strips Array of LED strip (hardware) configurations. At least one is required, otherwise setup fails. array required
segments Array of logical segments. Optional: if omitted, a single segment called All covering every pixel is created. array []

Applications that subclass LEDPixelsDevice may read their own extra settings from the same object.

How strips and segments relate

All strips are joined into a single pixel buffer in the order they appear in strips. A segment is a range of that buffer given by start and num.

strips:    [ strip 0: pin 18, num 6 ][ strip 1: pin 40, num 20      ]
buffer:    0  1  2  3  4  5          6  7  8 ...                   25
segments:  [st][  slots   ]          [            ring             ]
           0    1..5                  6..25
  • A segment's start is an offset into the whole buffer, not into a strip.
  • A segment should sit within one strip. One that spans strips logs a warning (segment X spans strips a..b); it still works, but it uses the colour order of the strip its first pixel is in.
  • Segments may overlap, but each segment's pattern writes its pixels independently, so overlapping segments overwrite each other.

strips

Each strip is driven by its own ESP32 RMT TX channel. The number of strips is limited by the number of RMT TX channels on the chip (for example 8 on ESP32, 4 on ESP32-S3, 2 on ESP32-C3).

Basic settings

Setting Description Type Default Example
pin GPIO pin for the strip's data line. Required: a missing or negative value makes the strip, and so the whole setup, invalid. integer required 18
num Number of pixels in the strip. Values above 2000 are clamped to 2000. integer 60 120
colorOrder (or colourOrder) Order of the colour bytes on the wire. Also sets the bytes per pixel. See Colour orders. string GRB RGB, GRBWC
bpp Bytes per pixel. Only used when colorOrder is not set. If both are set, bpp is ignored and a warning is logged. integer 3 5

Colour orders

colorOrder Bytes per pixel Wire order Typical parts
RGB 3 R, G, B Some WS2811-based strips
GRB 3 G, R, B WS2812B, SK6812 (RGB)
BGR 3 B, G, R
RGBWW 5 R, G, B, cold white, warm white WS2805
GRBWW 5 G, R, B, cold white, warm white
GRBWC 5 G, R, B, warm white, cold white

Names are case-insensitive, and an unrecognised name is treated as RGB. With a 3-byte order, the white values in RRGGBBCCWW colours and setRGBWW() calls are dropped. With a 5-byte order, plain RGB colours set both white channels to 0.

Timing settings

The defaults suit WS2812B. Times are in microseconds and are converted to RMT ticks using rmtHz, so at the default 10 MHz the resolution is 0.1 µs.

Setting Description Type Default
rmtHz RMT channel resolution in Hz. integer 10000000
T0H High time for a 0 bit (µs). Legacy name bit0_0Us. number 0.4
T0L Low time for a 0 bit (µs). Legacy name bit0_1Us. number 0.85
T1H High time for a 1 bit (µs). Legacy name bit1_0Us. number 0.8
T1L Low time for a 1 bit (µs). Legacy name bit1_1Us. number 0.45
resetUs Reset (latch) low time after each frame (µs). number 100
msbFirst Send the most significant bit of each byte first. boolean true

RMT peripheral settings

Setting Description Type Default
memBlockSymbols RMT memory block size in symbols. RMT memory is allocated in chip-specific blocks (64 symbols on ESP32, 48 on S3/C3/C6/H2). Increasing it can reduce flicker on long strips. integer 64
transQueueDepth RMT transaction queue depth. Keep at 1: the transmit buffer is reused, so queued transactions could send corrupted data. integer 1
minChunkSize Reserved for the encoder. Read but not currently used. integer 64
blockingShow When true, show() waits for the transmission to finish before returning. boolean false
beforeDeinitMs Extra delay in ms after a blocking show completes, before power-off or peripheral stop. Only used when blockingShow is true. integer 0
stopAfterTx Release the RMT channel when idle (about 100 ms after the last transmission, or straight after a blocking show). It is set up again on the next show. Useful to save power, or to share the channel. boolean false
allowPowerDown Let the RMT channel be powered down in light sleep (its context is saved to RAM). Passed to the ESP-IDF channel config as allow_pd. boolean false

Power control settings

These settings let a GPIO switch power to the strip, for example through a MOSFET or a regulator enable pin. They only take effect when pwrPin is set.

Setting Description Type Default
pwrPin GPIO that controls power to the strip. -1 means no power control. integer -1
pwrOnLvl Level written to pwrPin to turn power on (1 = high, 0 = low). integer 1
offIfBlank Turn power off after a frame in which every pixel (apart from the first offBlankExcl1stN) is off. Any non-zero value enables it. If the key is omitted it is enabled. Set 0 to disable it. integer enabled
offBlankExcl1stN Number of pixels at the start of the strip that the offIfBlank check ignores, for pixels that are always powered. integer 0
offAfterMs Turn power off this many ms after the last transmission, whatever the pixel values. 0 disables it. Unchanged frames are not retransmitted, so a strip showing a steady colour is also turned off after this time. integer 0
pwrPinGpioHold Use gpio_hold_en() on the power pin so its level holds through light sleep. boolean false
pwrHoldIfInactive With pwrPinGpioHold, also hold the pin while power is off. Otherwise it is only held while power is on. boolean false

Power is turned on just before the first transmission that needs it, and pixel data is sent straight after. The power pin is set as an input when the driver is destroyed.

segments

Setting Description Type Default Example
name Segment name. Used (case-insensitively) to address the segment in the led API and in LEDPixels::getSegmentIdx(). string "" "ring"
start Index of the segment's first pixel in the combined pixel buffer. integer 0 6
num Number of pixels in the segment. If there is exactly one segment and num is 0 or missing, it covers all pixels. integer 0 20
brightnessPC Brightness scale for this segment (percent). Applied to every RGB, RGBWW and HSV value written through the segment, including by patterns. number top-level brightnessPC 25
pattern Name of a registered pattern to start when the device is set up. The pattern must be registered before setup() is called. string none "Status"
patternParams Parameters for the initial pattern as a query string (name=value&name=value, without a leading ?). They are converted to JSON and passed to the pattern's setup(). Include forMs=<ms> to stop the pattern after that time. string none "rateMs=1500&rgb=002040"
colorOrder (or colourOrder) Colour order for the segment. It is replaced by the colour order of the strip that contains the segment whenever the strip sets one (a warning is logged if they differ), so it rarely needs to be set. string GRB "GRB"
patternMs Read but not currently applied. To time-limit the initial pattern, use forMs in patternParams. integer 0
startupFirstPixel Read but not currently applied. string (hex) "000000"

Segments with no pattern are cleared at setup. LEDPixelsDevice also sends an all-off frame after setup, so the strip doesn't keep its power-on state.

Examples

Minimal: one strip, no segments

{
    "class": "LEDPixels",
    "name": "LEDs",
    "strips": [
        { "pin": 18, "num": 30 }
    ]
}

This creates a single segment called All covering all 30 pixels, so led/All/setall/FF0000 and led/0/setall/FF0000 both work.

Status LED plus a ring on one strip

The first pixel shows system status using the built-in Status pattern, and the next twelve form a ring that runs a Chase pattern registered by the application (see the example application). indicatorSeg is an extra setting that the example application reads itself.

{
    "enable": 1,
    "class": "LEDPixels",
    "name": "LEDs",
    "indicatorSeg": "status",
    "strips": [
        { "pin": 18, "num": 13 }
    ],
    "segments": [
        {
            "name": "status",
            "start": 0,
            "num": 1,
            "brightnessPC": 25,
            "pattern": "Status"
        },
        {
            "name": "ring",
            "start": 1,
            "num": 12,
            "brightnessPC": 25,
            "pattern": "Chase",
            "patternParams": "rateMs=60&tail=4&rgb=0040FF"
        }
    ]
}

Two strips with different colour orders

An RGB status LED on one pin and a 20-pixel RGBWW (WS2805-style, warm/cold white swapped) ring on another:

{
    "class": "LEDPixels",
    "name": "LEDs",
    "strips": [
        { "pin": 13, "num": 1,  "colorOrder": "RGB" },
        { "pin": 40, "num": 20, "colorOrder": "GRBWC" }
    ],
    "segments": [
        { "name": "status", "start": 0, "num": 1,  "brightnessPC": 50, "pattern": "Status" },
        { "name": "ring",   "start": 1, "num": 20, "brightnessPC": 80 }
    ]
}

Each segment takes its colour order from its strip, so led/ring/setall/0000000080 drives only the warm white channel of the ring.

Battery-powered strip with power switching

The strip's supply is switched by GPIO 5 (active low). Power is cut whenever all pixels are off, and the pin level is held through light sleep:

{
    "class": "LEDPixels",
    "name": "LEDs",
    "brightnessPC": 40,
    "strips": [
        {
            "pin": 18,
            "num": 12,
            "pwrPin": 5,
            "pwrOnLvl": 0,
            "offIfBlank": 1,
            "pwrPinGpioHold": true,
            "stopAfterTx": true,
            "allowPowerDown": true
        }
    ],
    "segments": [
        { "name": "ring", "start": 0, "num": 12 }
    ]
}

Initial pattern with a time limit

Breathe blue for 10 seconds at startup, then turn off. This needs an application that registers a Breathe pattern, such as the example application:

"segments": [
    {
        "name": "ring",
        "start": 0,
        "num": 12,
        "pattern": "Breathe",
        "patternParams": "rateMs=2000&rgb1=000000&rgb2=0000FF&forMs=10000"
    }
]

Non-WS2812 timing

Example timing for an SK6812-style part, using the canonical key names:

"strips": [
    {
        "pin": 18,
        "num": 60,
        "rmtHz": 10000000,
        "T0H": 0.3, "T0L": 0.9,
        "T1H": 0.6, "T1L": 0.6,
        "resetUs": 80
    }
]

Building the configuration in code

LEDPixelConfig, LEDStripConfig and LEDSegmentConfig are plain classes with public members, so the configuration can be built without JSON and passed to LEDPixels::setup(LEDPixelConfig&):

LEDPixelConfig cfg;
LEDStripConfig strip;
strip.ledDataPin = 18;
strip.numPixels = 12;
strip.colourOrder = LEDPixel::GRB;
strip.colourOrderSpecified = true;
strip.bytesPerPixel = LEDPixel::getBytesPerPixel(strip.colourOrder);
cfg.stripConfigs.push_back(strip);
cfg.totalPixels = strip.numPixels;

LEDSegmentConfig seg;
seg.name = "ring";
seg.startOffset = 0;
seg.numPixels = 12;
seg.pixelBrightnessFactor = 0.5f;
cfg.segmentConfigs.push_back(seg);

_ledPixels.setup(cfg);

When building LEDStripConfig in code, the timing members are in RMT ticks (T0H_ticks and so on), not microseconds. totalPixels must equal the sum of the strips' numPixels.

Clone this wiki locally