#include <Adafruit_NeoPixel.h>
#define PIN A3
#define NUM_LEDS 60
#define MAX_SPARKS 12
Adafruit_NeoPixel strip(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
struct Spark {
float pos; // Sub-pixel position
float velocity; // Speed/Direction
float brightness; // Current intensity (0.0 to 1.0)
float decay; // How fast it dies
bool active = false;
};
Spark sparks[MAX_SPARKS];
void setup() {
strip.begin();
strip.show();
}
void createSpark() {
for (int i = 0; i < MAX_SPARKS; i++) {
if (!sparks[i].active) {
sparks[i].pos = random(0, NUM_LEDS * 100) / 100.0;
sparks[i].velocity = (random(-50, 50) / 1000.0); // Micro-movement
sparks[i].brightness = 1.0;
sparks[i].decay = random(5, 15) / 100.0; // Fast decay
sparks[i].active = true;
break;
}
}
}
void loop() {
if (random(0, 10) > 7) createSpark();
strip.clear();
for (int i = 0; i < MAX_SPARKS; i++) {
if (sparks[i].active) {
sparks[i].pos += sparks[i].velocity;
sparks[i].brightness -= sparks[i].decay;
if (sparks[i].brightness <= 0) {
sparks[i].active = false;
continue;
}
float p = sparks[i].pos;
int led1 = (int)p;
int led2 = led1 + 1;
float weight2 = p - led1;
float weight1 = 1.0 - weight2;
// --- ENHANCED BRIGHTNESS MATH ---
float b = sparks[i].brightness;
// Red stays high longest
uint8_t r = 255 * pow(b, 0.5);
// Green drops off to create orange/red tones
uint8_t g = 255 * pow(b, 1.5);
// Blue only exists at the very peak (White-hot core)
uint8_t bl = 255 * pow(b, 3.5);
if (led1 >= 0 && led1 < NUM_LEDS) addBuffer(led1, r * weight1, g * weight1, bl * weight1);
if (led2 >= 0 && led2 < NUM_LEDS) addBuffer(led2, r * weight2, g * weight2, bl * weight2);
}
}
strip.show();
delay(8); // Slightly faster refresh for "sharper" movement
}
void addBuffer(int i, uint8_t r, uint8_t g, uint8_t b) {
uint32_t oldColor = strip.getPixelColor(i);
uint8_t oldR = (oldColor >> 16) & 0xFF;
uint8_t oldG = (oldColor >> 8) & 0xFF;
uint8_t oldB = oldColor & 0xFF;
// Saturated addition: ensures overlapping sparks create "White" hot-spots
int newR = qadd8(oldR, r);
int newG = qadd8(oldG, g);
int newB = qadd8(oldB, b);
strip.setPixelColor(i, newR, newG, newB);
}
// Helper for saturated addition (caps at 255)
uint8_t qadd8(uint8_t a, uint8_t b) {
int res = a + b;
return (res > 255) ? 255 : (uint8_t)res;
}