Ambient Lights
Difficulty: ● ● ● ○ ○
-
Make Sure You have:
-
Did you know ?
Parts Required
No products found in parts_required metafield
How It Works ?
GENESIS
Connection Guide
Snap your modules as shown above, copy the code into the Arduino IDE and Click upload
#include <FastLED.h>
#include <Adafruit_NeoPixel.h>
#include <math.h>
/* ---------- MATRIX SETUP ---------- */
#define MATRIX_PIN 10
#define NUM_LEDS 289
#define BRIGHTNESS 40
CRGB leds[NUM_LEDS];
/* ---------- MATRIX MAPPING ---------- */
#define NUM_ROWS 21
const uint8_t rowCount[NUM_ROWS] = { 5, 9, 11, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 11, 9, 5 };
const uint8_t rowOffset[NUM_ROWS] = { 6, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 6 };
const uint16_t prefix[NUM_ROWS] PROGMEM = { 0, 5, 14, 25, 38, 53, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 236, 251, 264, 275, 284 };
#define INVALID 0xFFFF
uint16_t XY(uint8_t x, uint8_t y) {
if (y >= NUM_ROWS || x < rowOffset[y] || x >= rowOffset[y] + rowCount[y]) return INVALID;
return pgm_read_word_near(prefix + y) + (x - rowOffset[y]);
}
/* ---------- BUTTON & BUTTON LED ---------- */
#define BUTTON_PIN 14
#define BUTTON_LED_PIN 39
#define BUTTON_PIXELS 1
Adafruit_NeoPixel buttonLED(BUTTON_PIXELS, BUTTON_LED_PIN, NEO_GRB + NEO_KHZ800);
/* ---------- CENTER ---------- */
const float CENTER_X = 8.0;
const float CENTER_Y = 10.0;
/* ---------- MODE STATE ---------- */
enum Mode { AMBIENT, SWIRL, RIPPLE };
Mode currentMode = AMBIENT;
/* ---------- BUTTON STATE ---------- */
bool lastButton = HIGH;
bool buttonPressed = false;
uint32_t lastDebounceTime = 0;
const uint32_t debounceDelay = 50;
/* ---------- ANIMATION VARIABLES ---------- */
uint8_t hue = 0;
float swirlAngle = 0;
float rippleTime = 0;
/* ---------- BUTTON LED ANIMATION ---------- */
uint8_t buttonRainbowHue = 0;
uint32_t buttonLastUpdate = 0;
uint8_t buttonBrightness = 20;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
buttonLED.begin();
buttonLED.show(); // Init OFF
FastLED.addLeds<WS2812B, MATRIX_PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
Serial.begin(115200);
}
/* ---------- LOOP ---------- */
void loop() {
bool currentButton = digitalRead(BUTTON_PIN) == LOW;
// Debounce
if (currentButton != lastButton) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (currentButton && !buttonPressed) {
buttonPressed = true;
currentMode = (Mode)((currentMode + 1) % 3); // Cycle animations
// FUN COLORS on press
uint32_t funColors[] = {
buttonLED.Color(255, 105, 180), // Hot Pink
buttonLED.Color(0, 191, 255), // Deep Sky Blue
buttonLED.Color(127, 0, 255), // Purple
buttonLED.Color(255, 160, 0), // Orange
buttonLED.Color(0, 255, 180) // Aqua Green
};
uint8_t pick = random(0, 5);
buttonLED.setPixelColor(0, funColors[pick]);
buttonLED.setBrightness(255); // Full brightness
buttonLED.show();
} else if (!currentButton && buttonPressed) {
buttonPressed = false;
buttonBrightness = 20; // return to dim rainbow
}
}
lastButton = currentButton;
// Run matrix animation
switch (currentMode) {
case AMBIENT: drawAmbient(); break;
case SWIRL: drawSwirl(); break;
case RIPPLE: drawRipple(); break;
}
// Rainbow on button LED if not pressed
if (!buttonPressed && millis() - buttonLastUpdate > 30) {
buttonLastUpdate = millis();
buttonLED.setPixelColor(0, buttonLED.ColorHSV(buttonRainbowHue * 256));
buttonLED.setBrightness(buttonBrightness);
buttonLED.show();
buttonRainbowHue += 5; // Fast color change
}
FastLED.show();
delay(20);
}
/* ---------- AMBIENT FADE ---------- */
void drawAmbient() {
hue += 2; // DOUBLE SPEED
CHSV color(hue, 255, 255);
for (int y = 0; y < NUM_ROWS; y++)
for (int x = rowOffset[y]; x < rowOffset[y] + rowCount[y]; x++) {
uint16_t i = XY(x, y);
if (i != INVALID) leds[i] = color;
}
}
/* ---------- SWIRLING WINDMILL ---------- */
void drawSwirl() {
swirlAngle += 2.0; // DOUBLE SPEED
if (swirlAngle >= 360.0) swirlAngle -= 360.0;
for (int y = 0; y < NUM_ROWS; y++)
for (int x = rowOffset[y]; x < rowOffset[y] + rowCount[y]; x++) {
uint16_t i = XY(x, y);
if (i == INVALID) continue;
float dx = x - CENTER_X;
float dy = y - CENTER_Y;
float angle = atan2(dy, dx) * 180.0 / PI;
if (angle < 0) angle += 360.0;
float dist = sqrt(dx * dx + dy * dy);
float h = fmod(angle + swirlAngle + dist * 10, 360.0);
leds[i] = CHSV(h / 360.0 * 255, 255, 255);
}
}
/* ---------- RIPPLE WAVES ---------- */
void drawRipple() {
rippleTime += 0.05;
for (int y = 0; y < NUM_ROWS; y++)
for (int x = rowOffset[y]; x < rowOffset[y] + rowCount[y]; x++) {
uint16_t i = XY(x, y);
if (i == INVALID) continue;
float dx = x - CENTER_X;
float dy = y - CENTER_Y;
float dist = sqrt(dx * dx + dy * dy);
float h = fmod((dist * 30.0) - (rippleTime * 100), 360.0);
if (h < 0) h += 360.0;
leds[i] = CHSV(h / 360.0 * 255, 255, 255);
}
}