#include <Adafruit_NeoPixel.h>
#define LED_PIN 2
#define LED_COUNT 60
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// --- FORWARD DECLARATIONS for the new functions ---
void runnerFillAndEmpty_Forward(uint32_t color, int wait);
void runnerFillAndEmpty_Reverse(uint32_t color, int wait);
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'
strip.setBrightness(160);
randomSeed(analogRead(0));
}
void loop() {
// This speed is used ONLY for the original effects. It remains unchanged.
int wipeSpeed = 23;
// This speed is used ONLY for the new runner effects.
int runnerSpeed = 2;
int holdTime = 300;
int pauseBetweenColors = 500;
uint32_t colorPalette[] = {
strip.Color(204, 0, 0), // Red
strip.Color(255, 215, 0), // Gold
strip.Color(255, 20, 147) // Deep Pink
};
int numColors = 3;
uint32_t black = strip.Color(0, 0, 0);
for (int i = 0; i < numColors; i++) {
uint32_t currentColor = colorPalette[i];
// --- Calling the ORIGINAL effects with the original wipeSpeed ---
fillAndEmpty_ForwardToReverse(currentColor, wipeSpeed);
delay(holdTime);
fillAndEmpty_ReverseToForward(currentColor, wipeSpeed);
delay(holdTime);
colorWipe(currentColor, wipeSpeed);
delay(holdTime);
colorWipe(black, wipeSpeed);
colorWipeReverse(currentColor, wipeSpeed);
delay(holdTime);
colorWipeReverse(black, wipeSpeed);
wipeToCenter(currentColor, wipeSpeed);
delay(holdTime);
wipeToCenter(black, wipeSpeed);
wipeFromCenter(currentColor, wipeSpeed);
delay(holdTime);
wipeFromCenter(black, wipeSpeed);
fillInward_EmptyOutward(currentColor, wipeSpeed);
delay(holdTime);
fillOutward_EmptyInward(currentColor, wipeSpeed);
delay(holdTime);
// --- Calling the NEW effects with the new runnerSpeed ---
runnerFillAndEmpty_Forward(currentColor, runnerSpeed);
delay(holdTime);
runnerFillAndEmpty_Reverse(currentColor, runnerSpeed);
delay(holdTime);
// --- Calling an ORIGINAL effect with its original wipeSpeed ---
wipeRandom(currentColor, wipeSpeed);
delay(holdTime);
wipeRandom(black, 60);
delay(pauseBetweenColors);
}
}
// =================================================================
// NEW RUNNER EFFECT FUNCTIONS
// =================================================================
/**
* @brief Fills the strip from end-to-start, then empties it by "reeling in"
* each pixel towards the start of the strip.
* @param color The color of the effect.
* @param wait The delay between each step of the runner pixel.
*/
void runnerFillAndEmpty_Forward(uint32_t color, int wait) {
uint32_t black = strip.Color(0, 0, 0);
// --- Part 1: Fill ---
for (int destination = strip.numPixels() - 1; destination >= 0; destination--) {
for (int runnerPos = 0; runnerPos <= destination; runnerPos++) {
strip.setPixelColor(runnerPos, color);
if (runnerPos > 0) {
strip.setPixelColor(runnerPos - 1, black);
}
strip.show();
delay(wait);
}
}
delay(200);
// --- Part 2: Empty ("Reel-In" Logic) ---
for (int pixelToClear = 1; pixelToClear < strip.numPixels(); pixelToClear++) {
for (int runnerPos = pixelToClear; runnerPos >= 0; runnerPos--) {
strip.setPixelColor(runnerPos, color);
if (runnerPos < pixelToClear) {
strip.setPixelColor(runnerPos + 1, black);
}
strip.show();
delay(wait);
}
strip.setPixelColor(0, color);
strip.setPixelColor(pixelToClear, black);
strip.show();
}
strip.setPixelColor(0, black);
strip.show();
}
/**
* @brief Fills the strip from start-to-end, then empties it by "reeling in"
* each pixel towards the end of the strip.
* @param color The color of the effect.
* @param wait The delay between each step of the runner pixel.
*/
void runnerFillAndEmpty_Reverse(uint32_t color, int wait) {
uint32_t black = strip.Color(0, 0, 0);
int lastPixel = strip.numPixels() - 1;
// --- Part 1: Fill ---
for (int destination = 0; destination < strip.numPixels(); destination++) {
for (int runnerPos = lastPixel; runnerPos >= destination; runnerPos--) {
strip.setPixelColor(runnerPos, color);
if (runnerPos < lastPixel) {
strip.setPixelColor(runnerPos + 1, black);
}
strip.show();
delay(wait);
}
}
delay(200);
// --- Part 2: Empty ("Reel-In" Logic) ---
for (int pixelToClear = lastPixel - 1; pixelToClear >= 0; pixelToClear--) {
for (int runnerPos = pixelToClear; runnerPos <= lastPixel; runnerPos++) {
strip.setPixelColor(runnerPos, color);
if (runnerPos > pixelToClear) {
strip.setPixelColor(runnerPos - 1, black);
}
strip.show();
delay(wait);
}
strip.setPixelColor(lastPixel, color);
strip.setPixelColor(pixelToClear, black);
strip.show();
}
strip.setPixelColor(lastPixel, black);
strip.show();
}
// =================================================================
// ORIGINAL EFFECT FUNCTIONS (Unchanged)
// =================================================================
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, color);
strip.show();
delay(wait);
}
}
void colorWipeReverse(uint32_t color, int wait) {
for(int i=strip.numPixels()-1; i>=0; i--) {
strip.setPixelColor(i, color);
strip.show();
delay(wait);
}
}
void wipeToCenter(uint32_t color, int wait) {
for(int i=0; i < strip.numPixels()/2; i++) {
int oppositePixel = strip.numPixels() - 1 - i;
strip.setPixelColor(i, color);
strip.setPixelColor(oppositePixel, color);
strip.show();
delay(wait);
}
if (strip.numPixels() % 2 != 0) {
strip.setPixelColor(strip.numPixels()/2, color);
strip.show();
}
}
void wipeFromCenter(uint32_t color, int wait) {
int center = strip.numPixels() / 2;
for(int i = 0; i <= center; i++) {
if (center + i < strip.numPixels()) {
strip.setPixelColor(center + i, color);
}
if (center - i >= 0) {
strip.setPixelColor(center - i, color);
}
strip.show();
delay(wait);
}
}
void wipeRandom(uint32_t color, int wait) {
int pixelOrder[strip.numPixels()];
for (int i = 0; i < strip.numPixels(); i++) {
pixelOrder[i] = i;
}
for (int i = strip.numPixels() - 1; i > 0; i--) {
int j = random(i + 1);
int temp = pixelOrder[i];
pixelOrder[i] = pixelOrder[j];
pixelOrder[j] = temp;
}
for (int i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(pixelOrder[i], color);
strip.show();
delay(wait);
}
}
void fillAndEmpty_ForwardToReverse(uint32_t color, int wait) {
colorWipe(color, wait);
colorWipeReverse(strip.Color(0, 0, 0), wait);
}
void fillAndEmpty_ReverseToForward(uint32_t color, int wait) {
colorWipeReverse(color, wait);
colorWipe(strip.Color(0, 0, 0), wait);
}
void fillInward_EmptyOutward(uint32_t color, int wait) {
wipeToCenter(color, wait);
wipeFromCenter(strip.Color(0, 0, 0), wait);
}
void fillOutward_EmptyInward(uint32_t color, int wait) {
wipeFromCenter(color, wait);
wipeToCenter(strip.Color(0, 0, 0), wait);
}