#include <FastLED.h>
// =================================================================================================
// CONFIGURATION
// =================================================================================================
#define DATA_PIN 2 // The pin your data line is connected to
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS 60 // The number of LEDs in your strip
#define BRIGHTNESS 250 // Brightness limit (0-255)
// =================================================================================================
// >>>>> TUNABLE PARAMETERS <<<<<
// =================================================================================================
// Experiment with these values to change the look of the fireworks!
// --- TIMING & SPEED ---
#define ANIMATION_SPEED_DELAY 25 // Overall animation speed. Higher value = slower animation. (Original: 10)
#define GRAVITY -0.015 // How fast sparks fall down.
#define DRAG 0.98 // Air resistance. Lower value = sparks slow down faster.
#define SPARK_FADE_RATE 10 // How fast sparks fade. Lower value = sparks last longer. (Original: 15)
// --- QUANTITY & DENSITY ---
#define BURST_FREQUENCY 25 // How often new bursts appear. Lower value = more frequent bursts. (Original: 40)
#define SPARKS_PER_BURST_MIN 10 // Minimum number of sparks in a new burst. (Original: 5)
#define SPARKS_PER_BURST_MAX 21 // Maximum number of sparks in a new burst. (Original: 11)
// --- COLOR ---
#define HUE_ROTATION_SPEED 0.1 // How fast the colors change for new bursts.
// =================================================================================================
// =================================================================================================
// SPARK HELPER CLASS
// =================================================================================================
class Spark {
public:
bool active;
float position;
float velocity;
uint8_t hue;
uint8_t brightness;
Spark() : active(false) {}
void ignite(float start_pos, float start_vel, uint8_t start_hue) {
position = start_pos;
velocity = start_vel;
hue = start_hue;
brightness = 255;
active = true;
}
void update() {
if (!active) return;
position += velocity;
velocity += GRAVITY;
velocity *= DRAG;
if (brightness > SPARK_FADE_RATE) {
brightness -= SPARK_FADE_RATE;
} else {
brightness = 0;
active = false;
}
}
void draw(CRGB leds[]) {
if (active && position >= 0 && position < NUM_LEDS) {
leds[(int)position] += CHSV(hue, 255, brightness);
}
}
};
// =================================================================================================
// MAIN SKETCH LOGIC
// =================================================================================================
CRGB leds[NUM_LEDS];
Spark sparks[NUM_LEDS];
float currentHue = 0;
void setup() {
delay(1000);
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS)
.setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
}
void create_new_spark_burst() {
float start_pos = (float)random(0, NUM_LEDS);
int sparks_to_create = random(SPARKS_PER_BURST_MIN, SPARKS_PER_BURST_MAX);
for(int i = 0; i < sparks_to_create; i++) {
float start_vel = (float)random(-100, 100) / 100.0f;
for (int j = 0; j < NUM_LEDS; j++) {
if (!sparks[j].active) {
sparks[j].ignite(start_pos, start_vel, (uint8_t)currentHue);
break;
}
}
}
}
void loop() {
FastLED.clear();
for (int i = 0; i < NUM_LEDS; i++) {
sparks[i].update();
sparks[i].draw(leds);
}
if (random(0, BURST_FREQUENCY) == 0) {
create_new_spark_burst();
}
currentHue += HUE_ROTATION_SPEED;
if (currentHue >= 256) {
currentHue = 0;
}
FastLED.show();
delay(ANIMATION_SPEED_DELAY);
}