Tree topper star on an Arduino Uno
A WS2812B ring behind a star cutout tops the tree: warm twinkle, a gold comet, a slow rainbow and a red and green chase, one press of a button each. The whole build, an Arduino Uno and 3 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Beginner Runs in your browser. Free, and no account needed.
Build it as the Christmas Lights Kit: the parts in numbered bags and a booklet that checks every step. Free.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Tree topper star: a ring of 16 WS2812B LEDs behind a star cutout on top of
// the tree, with four light shows. A press of the button moves to the next.
//
// LED ring 16 LEDs, DIN <- 330 ohms <- pin 6, VDD -> 5 V, VSS -> GND
// button pin 2 -> button -> GND (INPUT_PULLUP, so pressed reads LOW)
//
// show 0 warm twinkle: soft white, with LEDs brightening and fading at random
// show 1 gold comet: a bright head with a fading tail running around the ring
// show 2 rainbow: the whole color wheel turning slowly
// show 3 red and green: alternating pairs that swap places
//
// Every show is a function that draws one frame and returns. loop() calls the
// current one every FRAME_MS and checks the button in between, so a press is
// never missed, however slow the show.
//
// On the tree: a ring this size is happy on the Uno's 5 V for testing, but
// give it its own 5 V supply on the tree, with the grounds joined. Cut a star
// from card or thin plywood, line it with foil or white paper, and set the
// ring behind it so the light spreads into the points.
//
// Things to try. Press the button. Change GOLD to your own color. Add a fifth
// show by writing one more function and adding it to the switch.
#include <Adafruit_NeoPixel.h>
const int RING_PIN = 6;
const int BUTTON_PIN = 2;
const int LEDS = 16;
const int SHOWS = 4;
const unsigned long FRAME_MS = 40;
Adafruit_NeoPixel ring(LEDS, RING_PIN, NEO_GRB + NEO_KHZ800);
const uint32_t GOLD = Adafruit_NeoPixel::Color(255, 150, 20);
int show = 0;
unsigned long frame = 0;
unsigned long nextFrame = 0;
bool wasPressed = false;
unsigned long lastPress = 0;
uint8_t sparkle[LEDS];
void twinkle() {
for (int i = 0; i < LEDS; i++) {
if (sparkle[i] > 40) sparkle[i] -= 6;
if (random(0, 30) == 0) sparkle[i] = 255;
int v = sparkle[i] < 40 ? 40 : sparkle[i];
ring.setPixelColor(i, v, v * 4 / 5, v / 2); // warm white
}
}
void comet() {
int head = frame % LEDS;
ring.clear();
for (int t = 0; t < 6; t++) {
int i = (head - t + LEDS) % LEDS;
// GOLD at full for the head, and each step of the tail at half the last.
uint8_t r = (uint8_t)(GOLD >> 16) >> t;
uint8_t g = (uint8_t)(GOLD >> 8) >> t;
uint8_t b = (uint8_t)GOLD >> t;
ring.setPixelColor(i, r, g, b);
}
}
void rainbow() {
ring.rainbow((uint16_t)(frame * 256));
}
void redGreen() {
bool swap = (frame / 12) % 2;
for (int i = 0; i < LEDS; i++) {
bool red = ((i / 2) % 2 == 0) != swap;
ring.setPixelColor(i, red ? 200 : 0, red ? 0 : 160, 0);
}
}
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
ring.begin();
ring.setBrightness(160);
for (int i = 0; i < LEDS; i++) sparkle[i] = 40;
Serial.println("Star lit: show 0, warm twinkle");
}
void loop() {
unsigned long now = millis();
// One step per press: act on the moment the button goes down, and ignore
// the contacts bouncing for a moment after.
bool pressed = digitalRead(BUTTON_PIN) == LOW;
if (pressed && !wasPressed && now - lastPress > 200) {
lastPress = now;
show = (show + 1) % SHOWS;
Serial.print("Show ");
Serial.println(show);
}
wasPressed = pressed;
if (now < nextFrame) return;
nextFrame = now + FRAME_MS;
frame++;
switch (show) {
case 0: twinkle(); break;
case 1: comet(); break;
case 2: rainbow(); break;
case 3: redGreen(); break;
}
ring.show();
}
Parts list
5 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × Arduino Uno R3
- 1 × Half breadboard
- 1 × Pushbutton
- 1 × Resistor, 330 Ω
- 1 × Addressable RGB LEDs
How it is wired
5 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Arduino Uno R3 pin 6; Resistor, 330 Ω pin 1
- Arduino Uno R3 pin 2; Pushbutton pin 1a
- Arduino Uno R3 pin 5V; Addressable RGB LEDs pin VDD
- Ground: Arduino Uno R3 pin GND; Pushbutton pin 2a; Addressable RGB LEDs pin VSS
- Resistor, 330 Ω pin 2; Addressable RGB LEDs pin DIN
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.