Rangoli lights on an Arduino Uno
A 16x16 WS2812B panel draws glowing rangoli patterns for Diwali, each symmetric eight ways from the center, with colors flowing outward and a button for the next design. 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.
Intermediate Runs in your browser. Free, and no account needed.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Rangoli lights: a 16x16 panel of LEDs that draws glowing rangoli patterns,
// each one symmetric eight ways from the middle, slowly turning through the
// colors. A button moves to the next design.
//
// panel 256 WS2812B LEDs, a 16x16 matrix, DIN <- 330 ohms <- pin 6
// button pin 2 -> button -> GND (INPUT_PULLUP)
//
// At Diwali, families draw rangoli at the door: patterns of colored powder,
// rice or flower petals, often in rings of petals around a center. Most
// rangoli are symmetric, so the same shape repeats as you turn around the
// middle. That is easy to build in code: measure each LED's distance from the
// center across and down, and fold so that only the two distances matter and
// not their order. Any color worked out from them is the same in all eight
// mirror places.
//
// There are three designs: rings, a diamond lotus, and an eight-petal flower.
// Each colors an LED by a shape number plus a slowly growing offset, so the
// colors flow outward from the middle.
//
// The panel needs 768 bytes for its colors, more than a third of the Uno's
// memory. At full white 256 LEDs could draw 15 A, so the brightness is kept
// low and a real panel wants its own 5 V supply.
//
// Things to try. Press the button. Invent a fourth design in shape().
#include <Adafruit_NeoPixel.h>
const int SIZE = 16;
const int BUTTON_PIN = 2;
const int DESIGNS = 3;
Adafruit_NeoPixel panel(SIZE * SIZE, 6, NEO_GRB + NEO_KHZ800);
int design = 0;
uint16_t offset = 0;
const char *NAMES[DESIGNS] = {"rings", "diamond lotus", "eight petals"};
// A number for the LED at a, b: the two folded distances from the center,
// 1, 3, 5 ... 15 each, with a >= b.
uint16_t shape(int a, int b) {
switch (design) {
case 0: return (a * a + b * b) * 40; // rings
case 1: return (a + b) * 600 + (a - b) * 200; // diamond lotus
default: return (a - b) * 900 + (a * b) % 16 * 300; // eight petals
}
}
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
panel.begin();
panel.setBrightness(40);
Serial.println("Rangoli lights: design 0, rings");
}
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) {
design = (design + 1) % DESIGNS;
Serial.print("Design ");
Serial.print(design);
Serial.print(", ");
Serial.println(NAMES[design]);
while (digitalRead(BUTTON_PIN) == LOW) delay(10);
}
for (int y = 0; y < SIZE; y++) {
for (int x = 0; x < SIZE; x++) {
int dx = abs(2 * x - (SIZE - 1));
int dy = abs(2 * y - (SIZE - 1));
int a = dx > dy ? dx : dy;
int b = dx > dy ? dy : dx;
uint16_t hue = shape(a, b) - offset;
panel.setPixelColor(y * SIZE + x, panel.ColorHSV(hue, 255, 255));
}
}
panel.show();
offset += 400;
delay(30);
}
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.