Addressable LEDs, explained

Beginner17 min readUpdated September 2026

How a single data wire controls hundreds of LEDs, why a strip that works on your desk misbehaves at full length, and how to power, protect and debug them.

A NeoRing has 96 LEDs on it. Every one of them can show a different colour, change a hundred times a second, and fade, chase or sparkle independently of all the others.

And they're all controlled through one data wire.

That sounds impossible at first. An ordinary LED needs its own pin to turn it on and off, and a colour LED needs three. Ninety-six colour LEDs would need 288 pins. So what's going on?

The answer is that these aren't ordinary LEDs. This article explains how addressable LEDs work, then covers the part that trips up almost everyone who scales past a handful of them: power. It builds on Electricity, explained with water and Powering your project.

A tiny computer in every LED

Look closely at an addressable LED, often called a NeoPixel or by its chip name, WS2812B, and you'll see more than just LEDs inside. There are three tiny light-emitting dies, one red, one green and one blue, and next to them a small control chip.

That chip is what makes the magic work. It listens to the data wire, remembers what colour it's been told to be, and drives its three LEDs at the right brightness. It keeps doing that on its own until it's told something different. Your microcontroller doesn't have to keep refreshing it.

The same kind of LED is on every RoboTech LED board. The NeoRing uses tiny 1 × 1 mm versions, the QuadPixel has four, and the Vector S3 has a 5 × 5 matrix of them built in.

Mixing colours

Each of the three colours has 256 brightness levels, from 0 (off) to 255 (full). Mixing them gives you 256 × 256 × 256, over 16 million colours.

Every pixel is three tiny LEDs, red, green and blue, each with 256 brightness levels. Mix them and find out how many colours you can make, and what each one costs in current.

#FF500A

255
80
10

What goes down the wire: 24 bits, green first

01010000

Green 80

11111111

Red 255

00001010

Blue 10

px.setLed(0, px.color(255, 80, 10));

Colours possible
16,777,216
256 × 256 × 256
This pixel
27.1 mA
standard LED, full brightness
60 like it
1.62 A
one metre of strip
Full white
≈60 mA
about the most one pixel draws

In code, you describe a colour with three numbers and send it to a particular LED. With the RobotechPixel library on a NeoRing or QuadPixel:

px.setLed(0, px.color(255, 80, 10));  // LED 0: a sunset orange
px.setLed(1, px.color(0, 110, 255));  // LED 1: ocean blue
px.show();                            // now send it all to the LEDs

Notice the show(). Setting colours only changes a list in your microcontroller's memory. Nothing reaches the LEDs until you call show(), which sends the whole list in one go. Why it works like that becomes clear once you see what travels down the wire.

Your eyes don't see brightness in a straight line. A value of 128 doesn't look half as bright as 255: it looks much brighter than half. That's why fades often seem to rush through the dim end and crawl through the bright end, and why effects libraries often correct for it.

One wire, many pixels

Here's how one wire controls a whole chain. The LEDs are connected in a line: the data pin feeds the first LED's DIN (data in), its DOUT (data out) feeds the second LED's DIN, and so on down the chain.

When you call show(), the microcontroller sends one long stream of bits: 24 for the first LED, 24 for the second, 24 for the third, all back to back. Then each LED follows two simple rules:

  1. Keep the first 24 bits you receive. That's your colour.
  2. Pass everything after that straight on to the next LED.

So the first LED takes its colour and forwards the rest. The second LED now sees its colour at the front of the stream, keeps it, and forwards the rest. It's a bucket brigade: every LED takes one bucket and hands the rest down the line.

Five pixels, one data wire. Choose a colour for each pixel, press Send, and watch how the message gets shared out.

micro-controllerpixel 0DINDOUTpixel 1DINDOUTpixel 2DINDOUTpixel 3DINDOUTpixel 4DINDOUT

Tap the pixels below to choose a colour for each, then press Send. Watch closely: nothing lights up until the whole message has arrived.

Colours to send (tap to change)

Speed

Pixel 0's 24 bits, as they travel down the wire

HIGHLOWGreen 000000000Red 25511111111Blue 000000000

Every bit takes 1.25 µs. A short high pulse means 0, a long one means 1. Green goes first, then red, then blue.

When the stream stops, the wire goes quiet, and that silence is a signal of its own. After at least 50 microseconds with no data, every LED latches: it switches to the colour it's been holding, all at the same instant. That's why a whole animation frame appears at once, instead of rippling down the strip.

This one design explains a lot of behaviour you'll run into:

  • Order matters. LED 0 is the one nearest the microcontroller. If your strip's colours come out backwards, you've wired the far end.
  • Data only flows one way. Strips have little arrows printed on them, pointing away from DIN. Feed the wrong end and nothing happens.
  • One dead LED breaks everything after it. If an LED stops passing data on, every LED further down the chain stops getting updates. Try the "Kill pixel 2" option in the widget above.
  • Chaining boards is the same thing. Connecting one NeoRing's DOUT to the next one's DIN just makes the chain longer, and the library works out the numbering for you. On the Vector S3, the matrix's last pixel feeds the PIX OUT pin, so external LEDs continue the chain from pixel 26.

How fast it goes

The data runs at 800,000 bits a second, so each bit takes 1.25 microseconds. There's no separate clock wire, so the timing is the message. Every bit starts with the line going high. A short high pulse means 0, a long one means 1.

Each LED needs 24 bits, which takes 30 microseconds. That means:

LEDsTime to send one frameFastest possible refresh
25 (Vector S3 matrix)0.75 msover 1,000 frames a second
96 (one NeoRing)about 3 msover 300 frames a second
300 (a 5 m strip)9 msabout 100 frames a second

In practice your animation code is the limit, not the wire. The timing has to be precise to within a fraction of a microsecond, which is why you let a library handle it.

Power: where most projects go wrong

Here's the part people underestimate. Every LED draws current for each of its colours, and it adds up fast.

A standard 5 mm-square strip LED draws up to about 20 mA per colour at full brightness. Full white turns on all three, so that's up to about 60 mA per LED. A typical strip has 60 LEDs per metre.

60 LEDs × 60 mA = 3.6 A per metre, at full white
5 metres        = 18 A

Eighteen amps is enough to make thin wires hot. No USB port comes close, and no microcontroller board can pass that through its pins.

The tiny LEDs on a NeoRing draw far less, around 7 mA each at full white, so a whole 96-LED board measures about 0.68 A. That's why one NeoRing runs happily from USB-C. Check the NeoRing electrical specs for the measured numbers.

Even LEDs set to black draw a little current, typically up to about 1 mA each, just to keep their control chip running. On a 300-LED strip, that's 0.3 A with every light off.

Turn the brightness down

The easiest power fix is software. Brightness scales the current for every LED at once:

px.setBrightness(150);  // about 60%: the NeoRing firmware's default

Full white is also the worst case. Most animations light only some LEDs, in colours that use one or two channels, so they draw a fraction of the maximum. But plan for the worst case anyway, because one bug or one "all white" test will find it. See Powering your project for what happens when a supply can't keep up.

On the Vector S3, the built-in matrix runs from the same 600 mA, 3.3 V regulator as the ESP32-S3, so keep its brightness modest. External LEDs on PIX OUT need their own power supply.

The far end of the strip

There's a second power problem, and it only shows up on long strips.

Remember the river from Electricity, explained with water? The copper tracks running along a strip are long, thin conductors, so every stretch of them has some resistance. As current flows along the strip, each metre takes a little of the voltage, like a river losing height as it runs downhill. The LEDs at the far end sit lower on the mountain.

That wouldn't matter much, except the three colours need different amounts of voltage. Red needs about 2 V; green and blue need about 3 V, plus some headroom for the control chip. As the voltage falls, blue and green fade first, and the far end of a "white" strip turns cream, then orange, then a murky pinkish brown.

Pick how many pixels, how bright and what colour, then choose a power supply. See whether it copes, and what happens to the far end of a long strip.

0–1 m1–2 m4.1 V

Purple arrows mark where 5 V is fed in. 60 pixels per metre.

The strip wants 7.32 A, and this supply gives 4 A. It will sag, reset your board, or shut itself off. Turn the brightness down or get a bigger supply.

120 (2.0 m)
255 / 255

What you'd pass to setBrightness()

Colour

LED type

Power supply

Feed power in at

Total current
7.32 A
36.6 W at 5 V
Supply
overloaded
rated 4 A
Lowest voltage
4.13 V
at pixel 119
Per pixel
61 mA
average

The fix is power injection: run separate, thick wires from the supply and connect 5 V and ground to the strip at more than one point. Feeding both ends helps a lot. Feeding every metre or two fixes it completely, because no pixel is ever far from a source. The data still runs through the chain in order; only the power takes a shortcut.

Whatever you do, connect all the grounds together: the supply, the strip and the microcontroller. The data signal is measured against ground, so without a shared ground the LEDs can't read it.

Protecting the first LED

Two cheap parts prevent a lot of mysterious failures. Most of these failures hit the first LED in the chain, because it's the one connected to the outside world.

A large capacitor across the power supply, at the point where power enters the strip. Something around 1,000 µF, rated for at least 6.3 V, is typical. When a big animation suddenly turns every LED on, the current jumps in an instant. Like the stretchy membrane from Electricity, explained with water, the capacitor supplies that surge while the power supply catches up, so the voltage doesn't dip.

A small resistor on the data line, placed near the first LED. Somewhere between 300 and 500 Ω is typical. It softens the sharp edges of the data signal and limits current into the first LED's data pin, which matters most on long data wires. The NeoRing's troubleshooting guide recommends one for runs longer than about 50 cm.

It's also good practice to power the LEDs before, or at the same time as, you send them data. Driving a data pin while an LED has no power can push current through it the wrong way.

3.3 V data, 5 V LEDs

Most modern microcontrollers, including the ESP32-S3, send data at 3.3 V. But standard LED strips run at 5 V, and a WS2812B powered from 5 V officially wants its data signal to reach about 3.5 V to count as a definite "high".

3.3 V is just under that line. In practice it usually works, especially with short wires. But it's working by luck rather than by design, and the symptoms when it doesn't are exactly the confusing kind: flickering, random colours, or the first LED misbehaving while the rest seem fine.

For anything beyond a quick test, use a level shifter to lift the data signal to 5 V. A single-gate buffer chip powered from 5 V does the job for a few cents. The Vector S3's own matrix doesn't have this problem, because it runs from 3.3 V, the same voltage as the data.

When it goes wrong

SymptomLikely causeWhat to check
Nothing lights at allNo power, wrong pin, or the wrong end of the stripPower and ground, the data pin in your code, the arrows on the strip. On the Vector S3, that GPIO47 is set LOW
LEDs work up to a point, then nothingA dead LED or a broken joint at that pointThe LED just before where it stops, and the solder joints either side
First LED is the wrong colour or flickersMarginal data voltage or a noisy data lineA level shifter, the series resistor, a shared ground
Colours go warm or pinkish towards the far endVoltage drop along the stripPower injection, thicker supply wires, lower brightness
Board resets when the LEDs get brightThe supply can't deliver the currentLower the brightness or use a bigger supply
Random flashes, especially on long wiresNoise on the data lineShorter data wire, the series resistor, a shared ground

Most addressable LED problems are power problems, and nearly all the rest are data signal problems at the first LED. Check those two things first, and you'll find most faults in minutes instead of hours.