#include <FastLED.h>
#define LED_PIN_1 6 // Pin for the first LED strip (purple)
#define LED_PIN_2 5 // Pin for the second LED strip (dark blue)
#define NUM_LEDS 60 // Number of LEDs in the first strip
#define BRIGHTNESS 255 // Set brightness (0-255)
#define MAX_BRIGHTNESS 1.0 // Maximum brightness (values between 0 and 1)
#define MIN_BRIGHTNESS 0.4 // 10% of the maximum brightness (values between 0 and 1)
#define SPEED 20 // Speed of the chase (lower is faster, in milliseconds)
#define FADE_AMOUNT 0 // Fade amount for the tail effect
#define WAVE_SPEED 20 // Speed of the wave
#define WAVE_LENGTH 20 // Length of the wave (in terms of how many LEDs it affects)
#define WAVE_OFFSET 4 // Speed at which the wave moves
#define TRANSITION_TIME 2000 // Duration of the transition between chase and wave (in milliseconds)
CRGB leds1[NUM_LEDS]; // Array for the first strip's LEDs
CRGB leds2[NUM_LEDS]; // Array to track the second strip's LEDs
float ledBrightness[NUM_LEDS]; // Array to track the brightness of each LED
int purple[] = {120, 0, 255}; // Purple color (RGB)
int blue[] = {50, 50, 255}; // Dark blue color (RGB)
unsigned long previousMillis = 0; // Stores the last time LEDs were updated
int position1 = 0; // Tracks the current position in the strip
const int buttonPin = 2; // Pin where the button is connected
int buttonState = 0; // Variable to store the state of the button
bool isActive = false; // Defines if the strip should be running
unsigned long lastRelease = 0;
bool isChasing = true; // Track whether we are in chasing mode
float chaseFinalBrightness[NUM_LEDS]; // Array to hold the final brightness from the chase
unsigned long transitionStart = 0; // Time when the transition to wave started
bool transitioning = false; // Indicates if we are in the transition phase
void setup() {
// Initialize the first strip (purple on pin 6)
FastLED.addLeds<WS2812, LED_PIN_1, GRB>(leds1, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
// Initialize the second strip (dark blue on pin 5)
FastLED.addLeds<WS2812, LED_PIN_2, GRB>(leds2, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(buttonPin, INPUT_PULLUP); // Set the button pin as input with internal pull-up resistor
// Initialize brightness for each LED to the minimum brightness
for (int i = 0; i < NUM_LEDS; i++) {
ledBrightness[i] = MIN_BRIGHTNESS;
chaseFinalBrightness[i] = MIN_BRIGHTNESS;
}
Serial.begin(115200);
}
void loop() {
unsigned long currentMillis = millis(); // Get the current time
// Read the state of the button
int newValue = digitalRead(buttonPin);
// Check for a button release (LOW to HIGH transition)
if (newValue == LOW && buttonState == HIGH) {
// Debounce logic (ignore if pressed too quickly)
if (currentMillis - lastRelease > 200) {
isActive = !isActive; // Toggle isActive state
lastRelease = currentMillis; // Record the time of the last button press/release
position1 = NUM_LEDS - 1;
isChasing = true; // Start with the chasing effect
FastLED.clear();
FastLED.show();
// Reset all LEDs' brightness to minimum at the start of the chase
for (int i = 0; i < NUM_LEDS; i++) {
ledBrightness[i] = MIN_BRIGHTNESS;
chaseFinalBrightness[i] = MIN_BRIGHTNESS;
}
}
}
buttonState = newValue; // Store the current button state
if (isActive) {
// Check if enough time has passed to update the LEDs
if (currentMillis - previousMillis >= SPEED) {
previousMillis = currentMillis; // Save the last time you updated the LEDs
if (isChasing && position1 >= 0) {
// Light up the current position LED
leds1[position1] = CRGB(
purple[0] * ledBrightness[position1],
purple[1] * ledBrightness[position1],
purple[2] * ledBrightness[position1]
);
leds2[position1] = CRGB(
blue[0] * ledBrightness[position1],
blue[1] * ledBrightness[position1],
blue[2] * ledBrightness[position1]
);
// Now, for all previously lit LEDs, increase their brightness by 1%
for (int i = position1; i < NUM_LEDS; i++) {
if (ledBrightness[i] < MAX_BRIGHTNESS) {
ledBrightness[i] += 0.01; // Increase brightness by 1%
if (ledBrightness[i] > MAX_BRIGHTNESS) {
ledBrightness[i] = MAX_BRIGHTNESS; // Cap the brightness
}
// Apply the updated brightness
leds1[i] = CRGB(
purple[0] * ledBrightness[i],
purple[1] * ledBrightness[i],
purple[2] * ledBrightness[i]
);
leds2[i] = CRGB(
blue[0] * ledBrightness[i],
blue[1] * ledBrightness[i],
blue[2] * ledBrightness[i]
);
}
// Store final brightness for wave effect transition
chaseFinalBrightness[i] = ledBrightness[i];
}
fadeToBlackBy(leds1, NUM_LEDS, FADE_AMOUNT); // Fade the tail (optional)
fadeToBlackBy(leds2, NUM_LEDS, FADE_AMOUNT); // Fade the tail (optional)
position1--; // Move to the next position
FastLED.show();
// If the chasing effect is done, start the transition
if (position1 < 0) {
isChasing = false; // End chase mode
transitioning = true; // Start transition to wave
transitionStart = currentMillis; // Record the start time of the transition
}
} else if (transitioning) {
// Calculate the transition progress (0.0 to 1.0)
float transitionProgress = (float)(currentMillis - transitionStart) / TRANSITION_TIME;
if (transitionProgress >= 1.0) {
transitioning = false; // End transition
transitionProgress = 1.0; // Cap the progress
}
// During transition, blend the chase state into the wave state
uint8_t time = currentMillis / WAVE_SPEED;
for (int i = 0; i < NUM_LEDS; i++) {
// Calculate the wave brightness for this LED based on a sine wave
uint8_t waveValue = sin8(time + (i * WAVE_OFFSET)); // Value between 0 and 255
// Interpolate between chaseFinalBrightness and the sine wave
float blendedBrightness = chaseFinalBrightness[i] * (1.0 - transitionProgress) +
(map(waveValue, 0, 255, MIN_BRIGHTNESS * 255, MAX_BRIGHTNESS * 255) / 255.0) * transitionProgress;
// Apply the blended brightness
leds1[i] = CRGB(
purple[0] * blendedBrightness,
purple[1] * blendedBrightness,
purple[2] * blendedBrightness
);
leds2[i] = CRGB(
blue[0] * blendedBrightness,
blue[1] * blendedBrightness,
blue[2] * blendedBrightness
);
}
FastLED.show();
} else {
// Normal wave effect after transition is complete
uint8_t time = currentMillis / WAVE_SPEED;
for (int i = 0; i < NUM_LEDS; i++) {
// Calculate the brightness of each LED based on a sine wave
uint8_t waveValue = sin8(time + (i * WAVE_OFFSET)); // Value between 0 and 255
leds1[i] = CRGB(
map(waveValue, 0, 255, purple[0] * MIN_BRIGHTNESS, purple[0] * MAX_BRIGHTNESS),
map(waveValue, 0, 255, purple[1] * MIN_BRIGHTNESS, purple[1] * MAX_BRIGHTNESS),
map(waveValue, 0, 255, purple[2] * MIN_BRIGHTNESS, purple[2] * MAX_BRIGHTNESS)
);
leds2[i] = CRGB(
map(waveValue, 0, 255, blue[0] * MIN_BRIGHTNESS, blue[0] * MAX_BRIGHTNESS),
map(waveValue, 0, 255, blue[1] * MIN_BRIGHTNESS, blue[1] * MAX_BRIGHTNESS),
map(waveValue, 0, 255, blue[2] * MIN_BRIGHTNESS, blue[2] * MAX_BRIGHTNESS)
);
}
FastLED.show();
}
}
} else {
// Turn off LEDs if not active
FastLED.clear();
FastLED.show();
}
}