Learn

Arduino NeoPixels: a WS2812B rainbow on an Uno

Beginner

Or see every lesson.

  • 455parts on the bench
  • 43boards running now
  • 1.00xreal time, on every board
Arduino Uno: a NeoPixel rainbowlive0.000 s 0.00x
Click to open it in the editor
Twenty WS2812Bs on pin 6 and four on pin 5, on a simulated ATmega328P. The knob on A0 sets the speed.

A NeoPixel strip is a row of tiny RGB LEDs that each have their own little chip. You send colors down one data wire, and every LED keeps its own color until you send new ones. Adafruit sells them as NeoPixels; the chip inside is the WS2812B, and cheap strips, rings and matrices all use the same one.

The circuit above is an Arduino Uno driving two strips: an arch of twenty LEDs on pin 6 and a pot of four gold LEDs on pin 5. A rainbow flows along the arch, and the knob on A0 sets how fast. It runs in your browser on the sketch below, and each strip decodes the real pulses on its data pin, so a wiring mistake goes dark here the same way it does on your desk.

What you need

  • An Arduino Uno
  • A WS2812B strip (twenty LEDs here) and a short one of four
  • Two 330 ohm resistors, one for each data line
  • A 10k potentiometer for the speed
  • A half-size breadboard and jumper wires

Wiring

Part and pinGoes toNote
Arch strip DINPin 6Through a 330 ohm resistor
Gold strip DINPin 5Through its own 330 ohm resistor
Both strips VDD (5V)5 V railUse a separate 5 V supply for a long strip
Both strips VSS (GND)GND railThe ground must be shared with the Uno
Potentiometer middle pinA0The speed knob
Potentiometer outer pins5 V and GNDEither way around

One wire, and the timing is the data

There is no clock wire. Each bit is one high pulse, and the length of the pulse is the bit: about 0.4 microseconds for a 0 and 0.8 for a 1. Every LED takes 24 bits, eight each for green, red and blue, keeps the first 24 for itself and passes the rest down the strip. When the line goes quiet for 50 microseconds, every LED shows its new color at once.

Those pulses are far too short to make with digitalWrite(). The Adafruit_NeoPixel library times them for you, so your sketch only ever deals in colors. On the Uno the bits are counted out in assembly, one clock cycle at a time.

The sketch, step by step

Each strip is one object: how many LEDs, which pin, and the color order. NEO_GRB + NEO_KHZ800 is right for almost every WS2812B. begin() sets up the pin, and setBrightness() scales every color down, which saves power and your eyes.

In loop(), the sketch reads the knob and turns it into a speed from 32 to 1024. It adds that to a starting hue, then gives each LED a hue a little further around the color wheel. ColorHSV() takes a hue from 0 to 65535 and hands back a color, and gamma32() corrects it so the fades look even to your eye. Nothing changes on the strip until show() sends the whole frame.

The loop waits 20 milliseconds, so the rainbow moves about fifty times a second. Every 200 frames it prints the speed. With the knob in the middle, the first line says "Rainbow speed 528". Turn it all the way down and it says 32.

The loop, from the rainbow example
void loop() {
  int speed = map(analogRead(A0), 0, 1023, 32, 1024);
  start += speed;
  for (int i = 0; i < ARCH; i++) {
    uint16_t hue = start + (uint32_t)i * 65536 / ARCH;
    arch.setPixelColor(i, arch.gamma32(arch.ColorHSV(hue)));
  }
  for (int i = 0; i < POT; i++) {
    int glint = random(0, 10) == 0 ? 255 : random(140, 200);
    gold.setPixelColor(i, glint, glint * 3 / 5, 0);
  }
  arch.show();
  gold.show();
  frames++;
  if (frames % 200 == 1) {
    Serial.print("Rainbow speed ");
    Serial.println(speed);
  }
  delay(20);
}

Power: the part the simulator cannot warn you about

Each WS2812B can draw about 60 milliamps at full white. Twenty of them is over an amp, more than the Uno’s 5 V pin should give. For more than a handful of LEDs, power the strip from its own 5 V supply, join its ground to the Uno’s ground, and keep the brightness down. A 1000 microfarad capacitor across the strip’s power wires, as Adafruit recommends, protects the first LED when you plug in.

Mokxi does not model the current each LED draws, so a long strip here never browns out the board. That is a real limit of the simulation, and it is why this section is here.

Try it in the editor

Make the rainbow run the other way by changing start += speed to start -= speed. Change ARCH to 60 and the count property on the strip to 60 for a longer arch. Give the pot a green shimmer by swapping the numbers in its setPixelColor() call.

Then delete the ground wire to the arch and press Run. The arch stays dark, because the data pulses have nothing to return through. Put it back and the rainbow comes back.

Common mistakes

No shared ground. A strip on its own supply still needs its GND tied to the Uno’s GND, or the data line means nothing to it.

Forgetting show(). setPixelColor() only changes a list in memory. The strip does not change until show() sends it.

The wrong color order. A WS2812B wants NEO_GRB. Use NEO_RGB and red and green come out swapped, here and on a real strip.

Wiring the wrong end. The data goes into DIN. The arrow printed on the strip points away from the input, toward DOUT.

Running a long strip from the Uno’s 5 V pin at full brightness. See the power section above.

Questions

Which pin should I use for NeoPixels on an Arduino Uno?

Any digital pin works. The library times the pulses itself, so the pin does not need PWM. This example uses pins 6 and 5, each through a 330 ohm resistor.

Can I use FastLED instead of Adafruit_NeoPixel?

Yes. Both libraries compile in Mokxi, on the AVR boards, the ESP32 family, the Pico and the Uno R4. On a board with no WS2812 driver here, such as the STM32 boards, the header says so when you build.

How many NeoPixels can an Uno drive?

The library keeps three bytes of memory for every LED, and the Uno has 2 KB of RAM, so a few hundred is the most in practice before your sketch runs out of room. Power is usually the real limit first. In Mokxi every strip in a sketch shares a fixed pool of 1024 LEDs.

Does this work on an ESP32 too?

Yes, with the same code. The ESP32 NeoPixel tutorial runs a rainbow on an ESP32-C3, and it explains how that board times the bits.

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.