A Wave of Color, Made by Math
Build a flowing, hypnotic LED wave display using one strip of individually controllable pixels, a handful of parts, and code that turns a simple sine wave into pure eye candy.
๐ก How Does a "Wave" Made of Light Work?
The secret is addressable LEDs — special LEDs where every single one can be told its own individual color, unlike a normal LED strip that's all one color at once. Give each pixel a color based on where it sits and what time it is, and you get a wave.
๐ The one-line idea
Every pixel's color is calculated with one formula: color = f(position, time). As "time" ticks forward every frame, the same wave shape appears to slide smoothly down the whole strip.
Each pixel in the demo above is colored using a sine wave — the same smooth up-and-down curve you'd see graphed in math class — mapped onto a color wheel called HSV (Hue, Saturation, Value). Sliding the wave's phase forward each frame is what makes it look like it's flowing.
This is the "hue wheel" the wave travels around — 0° is red, and it cycles all the way back to red at 360°.
๐งฐ What You'll Need
- 1× Arduino Uno or Nano
- 1× WS2812B addressable LED strip (~90 LEDs)
- 1× 5V power supply (5V, 4A or more)
- 1× 330 ฮฉ resistor (data line protection)
- 1× 1000 ยตF capacitor, 6.3V+ (power smoothing)
- 1× 10 kฮฉ potentiometer (speed control)
- Wooden board or cardboard for a zigzag channel
- Thin diffuser material (tracing paper or frosted acrylic)
- Jumper wires, hot glue
⚡ LEDs are power-hungry
Each pixel can draw up to 60mA at full brightness — 90 pixels could theoretically pull over 5 amps! Always power the strip from a dedicated 5V supply, never straight from the Arduino's 5V pin.
๐ ️ Build It Step by Step
Cut the zigzag channel
Cut grooves into a wooden board (or fold cardboard) into 5 parallel rows, so the strip can snake back and forth to form a grid shape.
Lay the strip in the channel
Press the LED strip into the zigzag path, following the arrow markings on the strip so DIN stays at the very first pixel.
Wire power injection
Solder the 5V supply's + and – directly to the strip's power pads at the start, adding the 1000 ยตF capacitor across them.
Wire the data line
Connect Arduino pin 6 through the 330 ฮฉ resistor to the strip's DIN pad.
Tie the grounds together
Connect Arduino GND, power supply GND, and strip GND all to the same point.
Wire the potentiometer
Connect the pot's outer legs to 5V and GND, and its middle wiper leg to Arduino pin A0.
Upload the code and test
Flash the sketch below. The wave should start flowing immediately — turn the knob to change its speed.
Add the diffuser
Lay tracing paper or frosted acrylic over the top to soften each pixel into a smooth glow instead of sharp dots.
๐ป The Code
This uses the popular FastLED library, which has a handy sin8() function built exactly for effects like this.
// Kinetic LED Wave Pixel Display — Arduino + FastLED // Turns a sine wave into a flowing rainbow of light #include <FastLED.h> #define LED_PIN 6 #define NUM_LEDS 90 #define BRIGHTNESS 120 #define POT_PIN A0 CRGB leds[NUM_LEDS]; uint8_t frame = 0; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(BRIGHTNESS); } void loop() { int potValue = analogRead(POT_PIN); // 0–1023 uint8_t speed = map(potValue, 0, 1023, 1, 15); // wave speed for (int i = 0; i < NUM_LEDS; i++) { uint8_t hue = sin8((i * 12) - (frame * 4)); // position + time → color leds[i] = CHSV(hue, 255, 255); } FastLED.show(); frame += speed; delay(20); }
๐งฎ What's actually happening in that loop?
i * 12 spaces the wave out across the strip (this is the "wavelength" knob in the demo above). frame * 4 slides that pattern forward every loop (this is the "speed"). sin8() turns that number into a smooth 0–255 wave used directly as a color hue.
๐จ Make It Your Own
Three tiny code tweaks completely change the personality of the wave:
Slower, dreamier wave
Change i * 12 to i * 6 for a longer, lazier wave that stretches across more pixels at once.
Two-color wave instead of rainbow
Replace CHSV(hue, 255, 255) with a blend between two fixed colors using blend() for an ocean or sunset look.
Reverse direction
Change frame += speed to frame -= speed to make the wave flow the opposite way.
Brightness breathing
Wrap BRIGHTNESS in its own slow sin8() call so the whole strip gently pulses brighter and dimmer over time.
❓ Frequently Asked Questions
Why can't I power the strip from the Arduino's 5V pin?
The Arduino's onboard regulator can only supply a small amount of current — nowhere near enough for dozens of bright LEDs. A dedicated 5V power supply wired directly to the strip avoids dim colors, flickering, or a damaged board.
Why does the data line need a resistor?
A 300–500 ฮฉ resistor right at the strip's DIN pin protects the very first LED from voltage spikes and reduces signal reflection noise on the data line.
My colors look wrong — greens and reds are swapped!
Try changing the color order in addLeds<WS2812B, LED_PIN, GRB> to RGB or BRG — different LED chip batches wire their color channels in different orders.
Can I use a shorter or longer strip?
Yes — just change NUM_LEDS to match your strip's actual pixel count, and recheck your power supply's current rating for the new length.
Can this run on an ESP32 instead of Arduino?
Absolutely — FastLED supports ESP32 too. Just double check your chosen data pin is a valid GPIO for output on your specific board.
๐ Take It Further
Make it music-reactive
Add a small microphone module and adjust the wave's speed or brightness based on sound volume.
Add a pattern-switch button
Wire in a push button that cycles through several different wave functions each time it's pressed.
Add a second potentiometer
Use it to control brightness or hue offset independently from wave speed.
Control it wirelessly
Swap in an ESP32 and add a tiny web page so you can change wave settings from your phone.

Comments
Post a Comment