Skip to main content

LED Strips

Wiring WS2812 and SK6812 addressable LED strips to an ESP32 for panel backlighting and multi-colour annunciators, and dividing one strip into independent LED Ranges.

Addressable LEDs

An addressable LED strip puts a tiny controller chip inside every LED. The ESP32 sends a stream of colour bytes down one data wire ; each LED keeps the first three bytes it sees and passes the rest on. Hundreds of individually coloured LEDs therefore cost a single GPIO pin — ideal for panel backlighting, where a classic LED-per-pin design runs out of pins fast.

ChipColoursByte orderNotes
WS2812 / WS2812BRGBGRBThe common strip; 60 LEDs per metre is typical
SK6812 (RGB)RGBGRBWS2812-compatible clone, same protocol
Single pixels / ringsRGBVaries (RGB, BRG…)Same protocol; check the byte order if red and green swap

Power budget

Each LED draws up to ~60 mA at full white (20 mA per colour). Sixty LEDs at full white draw about 3.6 A — far more than the ESP32's 5 V pin or a USB port can supply. Size the power supply for the brightness you actually use, and cap the brightness so the strip can never exceed it.

LEDsFull whiteAt 25 % brightness cap
100.6 A0.15 A
603.6 A0.9 A
1509 A2.25 A
Wiring
GPIO 18 GND 74AHCT125 3.3 V → 5 V 330 Ω 5 V PSU 1000 µF WS2812B strip (DIN end) DIN +5V GND LED 0 · 1 · 2 · 3 …

Feed the strip from a separate 5 V supply and connect its GND to the ESP32's GND — the data signal needs a common reference. Wire into the DIN end; the arrows printed on the strip point away from it.

Strip padConnect toColour
DINGPIO (via level shifter and 300–500 Ω series resistor)Orange
+5V5 V power supply (not the ESP32's 5 V pin)Red
GNDPower supply GND and ESP32 GNDBlack

Protecting the strip

  • 300–500 Ω resistor in series with DIN, close to the strip, damps ringing and protects the first LED.
  • 1000 µF capacitor (6.3 V or higher) across +5V and GND at the strip absorbs the inrush when it powers up.
  • Power injection: the strip's thin copper drops voltage along its length, so the far end turns brown or pink at full white. Feed +5V and GND again every 50–100 LEDs — never the data line.
  • Connect GND before +5V, and never hot-plug the data wire while the strip is powered.
Arduino Code — Basic Fill

The FastLED library generates the timing-critical signal with the ESP32's RMT peripheral. Set the byte order to match your chip and cap the brightness before the first show() .

// WS2812B strip with FastLED — Library Manager → "FastLED"
#include <FastLED.h>

const int DATA_PIN = 18;
const int NUM_LEDS = 30;
CRGB leds[NUM_LEDS];

void setup() {
    FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);  // GRB is the WS2812B byte order
    FastLED.setBrightness(64);                                 // cap: 64/255 keeps current low
    FastLED.setMaxPowerInVoltsAndMilliamps(5, 2000);           // never draw more than 2 A
}

void loop() {
    fill_solid(leds, NUM_LEDS, CRGB(255, 160, 60));   // warm panel backlight
    FastLED.show();
    delay(1000);
}
LED Ranges — One Strip, Many Lights
DIN → Backlight ledOffset 0 · count 6 Gear 7 · 1 Master caution · 8 · 1 0 11

A panel rarely wants a whole strip to show one thing. The same strip usually carries the backlight and a few annunciators. An LED Range is a contiguous run of LEDs on the strip, lit as one: it starts at an offset counted from the DIN end (the first LED is 0) and covers a count of LEDs.

Range settingMeaning
OffsetFirst LED of the run, counted from the data-in end (0–299)
CountHow many LEDs the run covers
Base colour The colour at full level ( #rrggbb ) — the tint of the lens or backlight it sits behind; white if not set

A range is driven with one of two kinds of value:

ValueEffectExample
Level 0–255Brightness of the base colour; 0 is darkPanel backlight following the panel-brightness knob
Colour #rrggbbReplaces the base colourGear light: off, red in transit, green when down

The sketch below implements the same idea by hand:

// Three independent "ranges" on one strip
#include <FastLED.h>

const int DATA_PIN = 18;
const int NUM_LEDS = 12;
CRGB leds[NUM_LEDS];

// A run of LEDs lit as one: first LED (from DIN) and how many
struct Range { int offset; int count; CRGB base; };
Range backlight = { 0, 6, CRGB(255, 160, 60) };
Range gearLight = { 7, 1, CRGB::Green };

void setLevel(const Range& r, uint8_t level) {        // 0–255 of the range's base colour
    CRGB c = r.base;
    c.nscale8_video(level);
    for (int i = 0; i < r.count; i++) leds[r.offset + i] = c;
}

void setColour(const Range& r, CRGB colour) {         // a colour that replaces the base
    for (int i = 0; i < r.count; i++) leds[r.offset + i] = colour;
}

void setup() {
    FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
}

void loop() {
    setLevel(backlight, 128);              // panel brightness knob at 50 %
    setColour(gearLight, CRGB::Red);       // gear in transit
    FastLED.show();
    delay(500);
    setColour(gearLight, CRGB::Green);     // down and locked
    FastLED.show();
    delay(500);
}

On a CockpitConnect controller you don't write this. Add an LED Strip to the controller in the Flow Builder with its data pin, length (up to 300 LEDs), byte order (GRB by default) and a brightness cap that protects your power supply. Then add an LED Range node per light, with its offset, count and base colour, and bind it to a dataref: a map to 0–255 dims a backlight, a lookup to colours drives a multi-state light. The controller renders the bytes and applies the cap last.

Cockpit Applications
ApplicationRange setupNotes
Panel backlightingOne long range, warm-white base colourLevel follows the panel-brightness dataref
Landing gear lightsOne LED per gear legColour value: off, red in transit, green down and locked
Annunciator panelOne short range per legendAmber or red base colour; level 0 or 255
Glareshield flood lightStrip under the glareshield lipLevel follows the flood-light knob
Master caution / warningOne or two LEDs behind a lensFlash with a blink pattern in the base colour