// https://www.instructables.com/LED-Chase-Effect-Using-an-Arduino/
int potentiometerPin = A7; // Potentiometer connected to pin A7
int potValue = 0; // Variable to store potentiometer reading
int minDelay = 50; // Minimum delay (fastest speed)
int maxDelay = 400; // Maximum delay (slowest speed)
int leds[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
// https://www.arduino.cc/reference/en/language/variables/utilities/sizeof/
// sizeof(); https://forum.arduino.cc/t/how-do-you-check-the-length-of-an-array/88325/7
int total_leds = sizeof(leds) / sizeof(int); // enter the number of LEDs you want to use here
int ledDelay;
int direction = 1;
int currentLED;
unsigned long changeTime;
int effect = 0; // Effect selector (0 = Chase, 1 = Bounce, etc.)
unsigned long lastEffectChangeTime = 0; // To track when to switch effects
unsigned long effectDuration = 6000; // Effect duration in milliseconds (20 seconds)
const int buttonPin = 0; // Pin for the button
const int buttonPinAuto = 2; // Pin for the button Auto Mode
bool autoMode = true; // Track if the program is in auto mode
unsigned long buttonPressTime = 0; // Debounce timer
unsigned long buttonAutoPressTime = 0; // Debounce timer
const unsigned long debounceDelay = 200; // Debounce delay time
bool buttonPressed = false; // Track the button state
void setup() {// put your setup code here, to run once
Serial.begin(9600);// initialize serial communication at 9600 bits per second:
#ifdef debug
Serial.println("Debug Enabled");
#else
Serial.println("Debug Disabled");
#endif
for (int i = 0; i < total_leds; i++) {
pinMode(leds[i], OUTPUT); // declare LEDs as output
}
pinMode(buttonPin, INPUT_PULLUP); // Use internal pull-up resistor
pinMode(buttonPinAuto, INPUT_PULLUP); // Use internal pull-up resistor
// changeTime = millis();
}
//this function for texting only
void loop1() {
// Read the potentiometer value
potValue = analogRead(potentiometerPin);
// Map the potentiometer value to an appropriate delay range
ledDelay = map(potValue, 0, 1023, minDelay, maxDelay);
//if ((millis() - changeTime) > ledDelay) {
//ledChase(false, false); // Simple Chase
//ledChase(true, false); // Bounce Effect
//ledChase(true, true); // Knight Rider Effect
//simpleChase();
//bounce();
//knightRider();
//twoWayChase3();
//runningLights();
//randomBlink();
//cometTail();
//waveEffect();
//stackerEffect();
// fireworks();
// changeTime = millis();
//}
if (delay_without_delaying(ledDelay)) {
//knightRider();
blinkAll();
//twoWayChase3();
//ledChase(true, true);
//randomBlink();
//runningLights();
}
}
void loop() {
// Read the potentiometer value
potValue = analogRead(potentiometerPin);
// Map the potentiometer value to an appropriate delay range
ledDelay = map(potValue, 0, 1023, minDelay, maxDelay);
// Check for button press to switch to manual mode
if (digitalRead(buttonPinAuto) == LOW) { // Button pressed
if (millis() - buttonAutoPressTime > debounceDelay) { // Debounce check
autoMode = true; // Switch to manual mode
effect = 0;
buttonAutoPressTime = millis(); // Update last button press time
}
}
// Check for button press to switch to manual mode
if (digitalRead(buttonPin) == LOW) { // Button pressed
if (millis() - buttonPressTime > debounceDelay) { // Debounce check
autoMode = false; // Switch to manual mode
effect++; // Change effect immediately
if (effect > 10) { // Assuming 10 effects (0 to 10)
effect = 0;
}
Serial.print("Manual Mode ");
Serial.print("Effect changed to: "); // Print the current effect
Serial.println(effect);
buttonPressTime = millis(); // Update last button press time
}
buttonPressed = true; // Set button pressed flag
}
else {
buttonPressed = false; // Reset button pressed flag
}
// Check if it's time to change the effect automatically in auto mode
if (autoMode) {
if ((millis() - lastEffectChangeTime) > effectDuration) {
effect++;
if (effect > 10) { // Assuming 10 effects (0 to 10)
effect = 0;
}
Serial.print("Auto Mode ");
Serial.print("Effect changed to: "); // Print the current effect
Serial.println(effect);
lastEffectChangeTime = millis(); // Reset effect timer
}
}
// Call the effect based on the current effect number
if ((millis() - changeTime) > ledDelay) {
changeTime = millis();
switch (effect) {
case 0:
ledChase(false, false); // Simple Chase
break;
case 1:
ledChase(true, false); // Bounce Effect
break;
case 2:
ledChase(true, true); // Knight Rider Effect
break;
case 3:
twoWayChase3(); // Middle to sides and back
break;
case 4:
blinkAll(); // All LEDs Blink
break;
case 5:
runningLights(); // Alternating Running Lights
break;
case 6:
randomBlink(); // Random LED Blinking
break;
case 7:
cometTail(); // Comet Tail Effect
break;
case 8:
waveEffect(); // Wave Effect
break;
case 9:
stackerEffect(); // Stacking LEDs
break;
case 10:
fireworks(); // Fireworks Effect
break;
// No need for an auto mode case since it's handled above
}
}
// Check if the button is pressed to change the effect in manual mode
if (!autoMode && !buttonPressed && (millis() - buttonPressTime > debounceDelay)) {
// Change the effect when the button is released
if (digitalRead(buttonPin) == LOW) { // Button is still pressed
effect++;
if (effect >= 10) { // Assuming 10 effects (0 to 10)
effect = 0;
}
buttonPressTime = millis(); // Reset the button press timer
}
}
}
void loop3() {
// Read the potentiometer value
potValue = analogRead(potentiometerPin);
// Map the potentiometer value to an appropriate delay range
ledDelay = map(potValue, 0, 1023, minDelay, maxDelay);
// Check if it's time to change the effect
if ((millis() - lastEffectChangeTime) > effectDuration) {
effect++;
if (effect > 10) { // Assuming 5 effects (0 to 4)
effect = 0;
}
lastEffectChangeTime = millis(); // Reset effect timer
}
if ((millis() - changeTime) > ledDelay) {
changeTime = millis();
switch (effect) {
case 0:
ledChase(false, false); // Simple Chase
break;
case 1:
ledChase(true, false); // Bounce Effect
break;
case 2:
ledChase(true, true); // Knight Rider Effect
break;
case 3:
twoWayChase(); // Middle to sides and back
break;
case 4:
blinkAll(); // All LEDs Blink
break;
case 5:
runningLights(); // Alternating Running Lights
break;
case 6:
randomBlink(); // Random LED Blinking
break;
case 7:
cometTail(); // Comet Tail Effect
break;
case 8:
waveEffect(); // Wave Effect
break;
case 9:
stackerEffect(); // Stacking LEDs
break;
case 10:
fireworks(); // Fireworks Effect
break;
}
}
}
void loop2() {
// Read the potentiometer value
potValue = analogRead(potentiometerPin);
// Map the potentiometer value to an appropriate delay range
ledDelay = map(potValue, 0, 1023, minDelay, maxDelay);
// Check if it's time to change the effect
if ((millis() - lastEffectChangeTime) > effectDuration) {
effect++;
if (effect > 4) { // Assuming 5 effects (0 to 4)
effect = 0;
}
lastEffectChangeTime = millis(); // Reset effect timer
}
// Execute the current effect
if ((millis() - changeTime) > ledDelay) {
changeTime = millis();
switch (effect) {
case 0:
simpleChase();
break;
case 1:
bounce();
break;
case 2:
twoWayChase();
break;
case 3:
blinkAll();
break;
case 4:
knightRider();
break;
}
}
}
void ledChase(bool bounce, bool knightRider) {
static int direction = 1; // 1 = forward, -1 = backward
static int currentLED = 0; // Current LED index
allLedsOff(); // Turn off all LEDs
digitalWrite(leds[currentLED], HIGH); // Light up the current LED
// Update the current LED based on the direction
currentLED += direction;
// Handle bouncing logic
if (bounce || knightRider) {
if (currentLED == total_leds || currentLED < 0) {
direction = -direction; // Reverse direction
currentLED += direction; // Adjust the position back into bounds
}
} else {
// For simple chase, reset to the first LED when reaching the end
if (currentLED == total_leds) {
currentLED = 0;
}
}
// If it's the Knight Rider effect, allow the LEDs to move inward (similar to bounce)
if (knightRider && (currentLED == total_leds || currentLED < 0)) {
direction = -direction;
}
}
void simpleChase() {
allLedsOff();
currentLED += direction;
if (currentLED == -1) {
direction = 1;
}
else if (currentLED == total_leds) {
direction = -1;
}
digitalWrite(leds[currentLED], HIGH);
}
void bounce() {
allLedsOff();
digitalWrite(leds[currentLED], HIGH);
currentLED += direction;
if (currentLED == total_leds || currentLED < 0) {
direction = -direction; // Reverse direction when hitting the ends
}
}
void twoWayChase1() {
allLedsOff();
for (int i = 0; i < total_leds / 2; i++) {
digitalWrite(leds[i], HIGH);
digitalWrite(leds[total_leds - 1 - i], HIGH);
}
}
void twoWayChase2() {
allLedsOff(); // Turn all LEDs off
static int leftSide = total_leds / 2 - 1; // Start from the middle-left LED
static int rightSide = total_leds / 2; // Start from the middle-right LED
// Turn on the LEDs at leftSide and rightSide
digitalWrite(leds[leftSide], HIGH);
digitalWrite(leds[rightSide], HIGH);
// Move the chase outward
leftSide--;
rightSide++;
// Reset when the chase reaches the edges
if (leftSide < 0 && rightSide >= total_leds) {
leftSide = total_leds / 2 - 1;
rightSide = total_leds / 2;
}
}
void twoWayChase3() {
allLedsOff(); // Turn all LEDs off
static int leftSide = total_leds / 2 - 1; // Start from the middle-left LED
static int rightSide = total_leds / 2; // Start from the middle-right LED
static int direction = 1; // 1 = outward, -1 = inward
// Turn on the LEDs at leftSide and rightSide
digitalWrite(leds[leftSide], HIGH);
digitalWrite(leds[rightSide], HIGH);
// Move based on direction
leftSide -= direction;
rightSide += direction;
// Check if we reached the edges (outward movement)
if (leftSide < 0 && rightSide >= total_leds) {
direction = -1; // Reverse direction, go inward
leftSide = 0; // Start from the edges for inward movement
rightSide = total_leds - 1;
}
// Check if we reached the middle (inward movement)
if (leftSide >= total_leds / 2 - 1 && rightSide <= total_leds / 2) {
direction = 1; // Reverse direction, go outward again
leftSide = total_leds / 2 - 1; // Reset to the middle for outward movement
rightSide = total_leds / 2;
}
}
void twoWayChase() {
allLedsOff(); // Turn all LEDs off
static int leftSide = 0; // Start from the first LED on the left
static int rightSide = total_leds - 1; // Start from the last LED on the right
// Turn on the LEDs at leftSide and rightSide
digitalWrite(leds[leftSide], HIGH);
digitalWrite(leds[rightSide], HIGH);
// Move the chase inward
leftSide++;
rightSide--;
// Reset when they cross over in the middle
if (leftSide > rightSide) {
leftSide = 0;
rightSide = total_leds - 1;
}
}
void blinkAll() {
static bool state = false; // Keeps track of whether the LEDs are on or off
static unsigned long lastBlinkTime = 0; // Store the last time the LEDs toggled
int blinkInterval = ledDelay + 100; // Set a fixed blink interval (500ms = 0.5 seconds)
// Check if it's time to toggle the LEDs
if (millis() - lastBlinkTime >= blinkInterval) {
if (state) {
allLedsOff(); // Turn all LEDs off
} else {
allLedsOn();
//for (int i = 0; i < total_leds; i++) {
// digitalWrite(leds[i], HIGH); // Turn all LEDs on
//}
}
state = !state; // Toggle the state for the next call
lastBlinkTime = millis(); // Update the last blink time
}
}
void blinkAll2() {
static bool state = false; // Keeps track of whether the LEDs are on or off
if (state) {
// If state is true, turn all LEDs off
allLedsOff();
} else {
// If state is false, turn all LEDs on
allLedsOn();
}
state = !state; // Toggle the state for the next call
}
void blinkAll1() {
static bool on = false;
static bool off = false;
if (on) {
allLedsOn();
}
on = !on;
if (off) {
allLedsOff();
}
off = !off;
}
void knightRider() {
allLedsOff();
digitalWrite(leds[currentLED], HIGH);
currentLED += direction;
if (currentLED == total_leds || currentLED == -1) {
direction = -direction;
}
}
void runningLights() {
static bool alternate = false;
allLedsOff(); // Turn all LEDs off
for (int i = 0; i < total_leds; i += 2) {
if (alternate) {
digitalWrite(leds[i], HIGH); // Light up every other LED
} else {
digitalWrite(leds[i + 1], HIGH); // Invert the pattern
}
}
alternate = !alternate; // Toggle the pattern
}
void randomBlink() {
allLedsOff(); // Turn off all LEDs
//int numLedsToLight = random(1, total_leds); // Choose how many LEDs to light up
int numLedsToLight = random(1, 3); // Choose how many LEDs to light up
for (int i = 0; i < numLedsToLight; i++) {
int randomLed = random(0, total_leds); // Pick a random LED
digitalWrite(leds[randomLed], HIGH); // Turn it on
}
}
void cometTail() {
static int position = 0;
int tailLength = 4; // Number of LEDs in the tail
float fadeAmount = 0.3; // Brightness decrease per tail LED
allLedsOff(); // Turn off all LEDs
// Light up the head of the comet
digitalWrite(leds[position], HIGH);
// Create the tail by lighting previous LEDs with decreasing brightness
for (int i = 1; i < tailLength; i++) {
int tailPos = position - i;
if (tailPos >= 0) {
analogWrite(leds[tailPos], 255 - (i * fadeAmount * 255));
}
}
// Move the position forward
position++;
if (position >= total_leds) {
position = 0;
}
}
////////////////////////////////////Stacker (LEDs Filling Up)
void stackerEffect() {
static int position = 0;
//allLedsOff();
if (position < total_leds) {
digitalWrite(leds[position], HIGH); // Light up the current LED
position++;
} else {
allLedsOff(); // Reset and turn all LEDs off after it's filled
position = 0;
}
}
//////////////////////////////////// Wave (Sinusoidal Motion)
void waveEffect() {
float speed = 0.2; // Adjust this to change wave speed
float amplitude = 127; // Wave amplitude
int center = 128; // Center value for the wave
for (int i = 0; i < total_leds; i++) {
int brightness = int(sin(i * speed + millis() / 100.0) * amplitude + center);
analogWrite(leds[i], brightness); // Write brightness to each LED
}
}
///////////////////////////////////Fireworks (Exploding LEDs)
void fireworks() {
allLedsOff(); // Turn off all LEDs
// Choose a random "explosion" center
int centerLed = random(0, total_leds);
// Light the center LED
digitalWrite(leds[centerLed], HIGH);
// Light up adjacent LEDs
if (centerLed - 1 >= 0) digitalWrite(leds[centerLed - 1], HIGH);
if (centerLed + 1 < total_leds) digitalWrite(leds[centerLed + 1], HIGH);
delay(100); // Short delay for explosion effect
allLedsOff(); // Clear the LEDs for next explosion
}
//////////////////////////////////////////////////////////////////////////////////////////////
void allLedsOff() {
for (int x = 0; x < total_leds; x++) {
digitalWrite(leds[x], LOW);
}
}
void allLedsOn() {
for (int x = 0; x < total_leds; x++) {
digitalWrite(leds[x], HIGH);
}
}
boolean delay_without_delaying(unsigned long time) {
// return false if we're still "delaying", true if time ms has passed.
// this should look a lot like "blink without delay"
static unsigned long previousmillis = 0;
unsigned long currentmillis = millis();
if (currentmillis - previousmillis >= time) {
previousmillis = currentmillis;
return true;
}
return false;
}