I am working on lighting up WS2812 strips in different patterns. The idea is that they show a certain pattern based on a button press. The button press increments currentPressMode, which controls a switch case. Each function in the switch case controls sets of for loops that light up a set of LEDs and move that "bar" over a certain number of LEDs, like a Larson Scanner.
I'm running into the issue of my delays are interfering with the button press, which makes sense to me. If I could just get some direction on how to replace those delays with millis() or if there is another way to break my for loops I would appreciate it. I have tried millis() from other examples in forums but can't find a setup that preserves the current functionality of the code. The delay(speedDelay) statement controls the speed of the LED sweep.
#include "FastLED.h"
#define LED_PIN 7 //define forward top controller pin
#define NUM_LEDS 144 //Total LEDs on each strip for quadrant
#define BAR_LENGTH 4 //number of LEDs for "bars"
#define DIVISION 36 //Index for front top LEDs
//change values for LED colors
#define RED_VAL 0x1F //Must be >0 to function
#define GREEN_VAL 0x1F //Must be >0 to function
#define BLUE_VAL 0xFF //Set to Blue
//delay values, only for in phase and 180 degrees
#define SWEEP_DELAY 100 //defines how long LEDs wait before sweeping again
CRGB ledsFront[NUM_LEDS];
//button constants
const int modeButton = 2;
//Button logic variables
int lastBtnMode = HIGH;
int btnMode;
int currentPressMode = 0;
int buttonMode;
int SPEED_DELAY = 50; //initialized at 50 clock ticks
//Button debounce variables
unsigned long lastDebounceTimeMode = 0;
unsigned long debounceDelay = 50;
void setup() {
Serial.begin(9600); //For debugging
//define led strips
FastLED.addLeds<WS2812, LED_PIN, GRB>(ledsFront, NUM_LEDS).setCorrection(TypicalLEDStrip);
//define button input
pinMode(modeButton, INPUT);
}
void loop() {
//initialize button debounce
buttonMode = digitalRead(modeButton);
if (buttonMode != lastBtnMode) lastDebounceTimeMode = millis();
//switch case for mode button.
switch (currentPressMode) {
//180 degrees out of phase
case 1:
setAll(0, 0, 0);
Serial.print("Displaying 180 out of phase.\n");
Pulse180(RED_VAL, GREEN_VAL, BLUE_VAL, BAR_LENGTH, SPEED_DELAY, SWEEP_DELAY);
break;
//90 degrees out of phase
case 2:
setAll(0, 0, 0);
Pulse90(RED_VAL, GREEN_VAL, BLUE_VAL, BAR_LENGTH, SPEED_DELAY, SWEEP_DELAY);
Serial.print("Displaying 90 out of phase.\n");
break;
//In phase
case 3:
setAll(0, 0, 0);
PulseInPhase(RED_VAL, GREEN_VAL, BLUE_VAL, BAR_LENGTH, SPEED_DELAY, SWEEP_DELAY);
Serial.print("Displaying in phase.\n");
break;
//Clear LEDs
default:
setAll(0, 0, 0);
//start LEDs with button press from "off"
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 1;
Serial.print(currentPressMode);
Serial.print("\n");
}
}
}
lastBtnMode = buttonMode;
break;
}
}
//Top Level function
//Front LEDs start in center, rear LEDs start on outside
void Pulse180(byte redVal, byte greenVal, byte blueVal, int barLen, int speedDelay, int sweepDelay) {
//Sweep front from center to outside, back from outside to center
int i = ((DIVISION - barLen) / 2);
for (i = ((DIVISION - barLen - 2) / 2); i >= 1; i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 2;
Serial.print(currentPressMode);
Serial.print("\n");
break;
return;
}
}
}
lastBtnMode = buttonMode;
setPixel(i, redVal, greenVal, blueVal); //Front
setPixel(DIVISION - i, redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 2;
Serial.print(currentPressMode);
Serial.print("\n");
break;
return;
}
}
}
lastBtnMode = buttonMode;
setPixel(i + j, redVal, greenVal, blueVal);
setPixel(DIVISION - i - j, redVal, greenVal, blueVal);
}
setPixel(i + barLen, 0, 0, 0);
setPixel(DIVISION - i - barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
setAll(0, 0, 0);
//Sweep front from outside to center, back from center to outside
i = ((DIVISION - barLen) / 2);
for (i = ((DIVISION - barLen - 2) / 2); i >= 0; i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 2;
Serial.print(currentPressMode);
Serial.print("\n");
break;
return;
}
}
}
lastBtnMode = buttonMode;
setPixel((((DIVISION - barLen) / 2) - i), redVal, greenVal, blueVal); //Front
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i), redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 2;
Serial.print(currentPressMode);
Serial.print("\n");
break;
return;
}
}
}
lastBtnMode = buttonMode;
setPixel((((DIVISION - barLen) / 2) - i) + j, redVal, greenVal, blueVal);
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i) - j, redVal, greenVal, blueVal);
}
setPixel((((DIVISION - barLen) / 2) - i) - barLen + (barLen - 1), 0, 0, 0);
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i) - barLen + barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
setAll(0, 0, 0);
}
//Top level function
//Front LEDs start in middle and move outside, back LEDs start outside and move inward
void Pulse90(byte redVal, byte greenVal, byte blueVal, int barLen, int speedDelay, int sweepDelay) {
int i;
//Sweep front from middle to outside, back from outside to middle
for (i = ((DIVISION - barLen - 2) / 4); i >= 1; i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}
lastBtnMode = buttonMode;
setPixel(i, redVal, greenVal, blueVal); //Front
setPixel(DIVISION - i, redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}
lastBtnMode = buttonMode;
setPixel(i + j, redVal, greenVal, blueVal);
setPixel(DIVISION - i - j, redVal, greenVal, blueVal);
}
setPixel(i + barLen, 0, 0, 0);
setPixel(DIVISION - i - barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
//delay(sweepDelay);
setAll(0, 0, 0);
//Sweep front from outside to middle, back from middle to center
for (i = ((DIVISION - barLen - 2) / 2); i >= ((DIVISION - barLen - 2) / 4); i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}
lastBtnMode = buttonMode;
setPixel((((DIVISION - barLen) / 2) - i), redVal, greenVal, blueVal); //Front
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i), redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel((((DIVISION - barLen) / 2) - i) + j, redVal, greenVal, blueVal);
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i) - j, redVal, greenVal, blueVal);
}
setPixel((((DIVISION - barLen) / 2) - i) - barLen + (barLen - 1), 0, 0, 0);
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i) - barLen + barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
//delay(sweepDelay);
setAll(0, 0, 0);
//Sweep front from middle to center, back from center to middle
for (i = ((DIVISION - barLen - 2) / 2); i >= ((DIVISION - barLen - 2) / 4); i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel(((DIVISION - barLen) / 4) + i, redVal, greenVal, blueVal); //Front
setPixel(DIVISION - ((DIVISION - barLen) / 4) - i, redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel(((DIVISION - barLen) / 4) + i + j, redVal, greenVal, blueVal);
setPixel(DIVISION - ((DIVISION - barLen) / 4) - i - j, redVal, greenVal, blueVal);
}
setPixel(((DIVISION - barLen) / 4) + i + barLen, 0, 0, 0);
setPixel(DIVISION - ((DIVISION - barLen) / 4) - i - barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
//delay(sweepDelay);
setAll(0, 0, 0);
//Sweep front from center to middle, back from middle to outside
for (i = ((DIVISION - barLen - 2) / 4); i >= 1; i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel(((DIVISION - barLen - 2) / 4) + i, redVal, greenVal, blueVal); //Front
setPixel(DIVISION - ((DIVISION - barLen - 2) / 4) - i, redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 3;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel(((DIVISION - barLen - 2) / 4) + i + j, redVal, greenVal, blueVal);
setPixel(DIVISION - ((DIVISION - barLen - 2) / 4) - i - j, redVal, greenVal, blueVal);
}
setPixel(((DIVISION - barLen - 2) / 4) + i + barLen, 0, 0, 0);
setPixel(DIVISION - ((DIVISION - barLen - 2) / 4) - i - barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
//delay(sweepDelay);
setAll(0, 0, 0);
}
//Top level function
//All LEDs start in center
void PulseInPhase(byte redVal, byte greenVal, byte blueVal, int barLen, int speedDelay, int sweepDelay) {
int i = ((DIVISION - barLen) / 2);
for (i = ((DIVISION - barLen - 2) / 2); i >= 1; i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 0;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel(i, redVal, greenVal, blueVal); //Front
setPixel(DIVISION - i, redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 0;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel(i + j, redVal, greenVal, blueVal);
setPixel(DIVISION - i - j, redVal, greenVal, blueVal);
}
setPixel(i + barLen, 0, 0, 0);
setPixel(DIVISION - i - barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
setAll(0, 0, 0);
i = ((DIVISION - barLen) / 2);
for (i = ((DIVISION - barLen - 2) / 2); i >= 0; i--) {
//Check for button press
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 0;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel((((DIVISION - barLen) / 2) - i), redVal, greenVal, blueVal); //Front
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i), redVal, greenVal, blueVal); //Front
for (int j = 1; j <= barLen; j++) {
if ((millis() - lastDebounceTimeMode) > debounceDelay) {
if (buttonMode != btnMode) {
btnMode = buttonMode;
if (btnMode == LOW) {
currentPressMode = 0;
Serial.print(currentPressMode);
Serial.print("\n");
return;
}
}
}lastBtnMode = buttonMode;
setPixel((((DIVISION - barLen) / 2) - i) + j, redVal, greenVal, blueVal);
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i) - j, redVal, greenVal, blueVal);
}
setPixel((((DIVISION - barLen) / 2) - i) + barLen - barLen, 0, 0, 0);
setPixel(DIVISION - (((DIVISION - barLen) / 2) - i) - barLen + barLen, 0, 0, 0);
FastLED.show();
delay(speedDelay);
}
setAll(0, 0, 0);
}
//set color of individual LEDs
void setPixel(int Pixel, byte red, byte green, byte blue) {
ledsFront[Pixel].r = red;
ledsFront[Pixel].g = green;
ledsFront[Pixel].b = blue;
}
//set all LEDs to specified color (used to clear LEDs)
void setAll(byte red, byte green, byte blue) {
for (int i = 0; i < NUM_LEDS; i++) {
setPixel(i, red, green, blue);
}
FastLED.show();
}
I'm attaching a dumbed down version of my code as a file since it's pretty massive. I apologize for the obnoxious amount of checking for a button press, I just posted what currently works.
For Loop With Button Forum.ino (14.7 KB)