// for https://forum.arduino.cc/t/statemachine-compiling-but-not-working/1126324
#include <FastLED.h>
#include <Arduino.h>
#define NUM_LEDS 60
#define LED_PIN 3
#define BUTT_PIN 5
#define BRIGHTNESS 255
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define UPDATES_PER_SECOND 60
CRGBPalette16 currentPalette(CRGB::Black);
CRGBPalette16 targetPalette(PartyColors_p);
void changeEffect();
void setup() {
delay(3000); // power-up safety delay
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
FastLED.setMaxPowerInVoltsAndMilliamps( 5, 5000);
Serial.begin(9600);
pinMode(BUTT_PIN, INPUT_PULLUP); // need to add this line to fix some of https://forum.arduino.cc/t/statemachine-compiling-but-not-working/1126324/15?u=davex
}
void loop() {
//fadeAnimationWrapper();
//cylon();
//sparkles();
changeEffect();
}
void changeEffect() {
enum class effectState : uint8_t {
sparkles,
fadeAnimationWrapper,
cylon,
};
static effectState currEffect = effectState::sparkles;
static effectState prevEffect = effectState::sparkles;
static int buttonState = LOW;
static int prevButtonState = LOW;
static auto activeEffectFunction = sparkles;
buttonState = digitalRead(BUTT_PIN);
if (buttonState != prevButtonState) {
if (buttonState == LOW) { // change to LOW if you use INPUT_PULLUP
Serial.println("Button Pressed!");
switch (currEffect) {
case effectState::sparkles:
activeEffectFunction = fadeAnimationWrapper;
currEffect = effectState::fadeAnimationWrapper;
Serial.println("Fade Running!!");
break;
case effectState::fadeAnimationWrapper:
activeEffectFunction = cylon;
currEffect = effectState::cylon;
Serial.println("Cylon Running!!");
break;
case effectState::cylon:
activeEffectFunction = sparkles;
currEffect = effectState::sparkles;
Serial.println("Sparkles Running!!");
break;
}
prevEffect = currEffect;
}
prevButtonState = buttonState;
}
activeEffectFunction(); // cede control to the chosen animation
}
// END OF TAB 1 - MAIN CODE
// START OF TAB 2 - CYLON EFFECT
#include <FastLED.h>
#define CLOCK_PIN 13
void fadeall() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i].nscale8(250);
}
}
void cylon() { // blocking -- Look into sinelon https://forum.arduino.cc/t/convert-a-full-sketch-into-a-single-animation/1217414/15?u=davex
static uint8_t hue = 0;
Serial.print("x");
// First slide the led in one direction
for (int i = 0; i < NUM_LEDS; i++) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(10);
}
// Now go in the other direction.
for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(10);
}
}
// END OF TAB 2 - CYLON EFFECT
// START OF TAB 3 - FADE ANIMATION EFFECT
void fadeAnimationWrapper() {
Serial.print('F');
fadeAnimation(random(256), random(256), random(256));
}
void fadeAnimation(int red, int green, int blue) {
float r, g, b;
uint32_t startTime = millis();
uint32_t totalTime = 1000; // total time for fade in and out, in milliseconds
// Define array of durations for fade in and fade out
uint32_t fadeInDurations[] = {600, 800, 1000, 1200, 1600, 2000, 2500};
uint32_t fadeOutDurations[] = {600, 800, 1000, 1200, 1600, 2000, 2500};
int numFadeInDurations = sizeof(fadeInDurations) / sizeof(fadeInDurations[0]);
int numFadeOutDurations = sizeof(fadeOutDurations) / sizeof(fadeOutDurations[0]);
// Randomly select duration for fade in and fade out
uint32_t fadeInTime = fadeInDurations[random(numFadeInDurations)];
uint32_t fadeOutTime = fadeOutDurations[random(numFadeOutDurations)];
// FADE IN
while (millis() - startTime <= fadeInTime) {
float progress = (float)(millis() - startTime) / (float)fadeInTime;
r = progress * red;
g = progress * green;
b = progress * blue;
fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
FastLED.show();
}
// FADE OUT
startTime = millis(); // reset start time for fade out
while (millis() - startTime <= fadeOutTime) {
float progress = 1.0 - ((float)(millis() - startTime) / (float)fadeOutTime);
r = progress * red;
g = progress * green;
b = progress * blue;
fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
FastLED.show();
}
}
// END OF TAB 3 - FADE ANIMATION EFECT
// START OF TAB 4 - SPARKLES EFFECT
void sparkles()
{
Serial.print('s');
ChangePalettePeriodically();
uint8_t maxChanges = random(48); // values 0-48 (Max colors at play)
nblendPaletteTowardPalette( currentPalette, targetPalette, maxChanges);
static uint8_t startIndex = 0;
startIndex = startIndex + 1; /* motion speed */
FillLEDsFromPaletteColors( startIndex);
FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
}
void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
uint8_t brightness = 255;
for ( int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette( currentPalette, colorIndex + sin8(i * 16), brightness);
colorIndex += 3;
}
}
void ChangePalettePeriodically()
{
static uint8_t last = -1;
uint8_t secondHand = (millis() / 1000) % 60;
if(secondHand == last ) return;
last = secondHand;
switch (secondHand) {
case 0:
targetPalette = RainbowColors_p;
Serial.print("sparkleRainbow");
break;
case 10:
targetPalette = CRGBPalette16( CHSV(HUE_GREEN, 255, 255), CHSV(HUE_PURPLE, 255, 255), CRGB::Black, CRGB::Black, CHSV(HUE_PURPLE, 255, 255), CHSV(HUE_GREEN, 255, 255), CRGB::Black, CRGB::Black, CHSV(HUE_PURPLE, 255, 255), CHSV(HUE_GREEN, 255, 255), CRGB::Black, CRGB::Black, CHSV(HUE_PURPLE, 255, 255), CHSV(HUE_GREEN, 255, 255), CRGB::Black, CRGB::Black );
Serial.print("sparkleGPK");
break;
case 20:
targetPalette = CRGBPalette16( CRGB::Black, CRGB::Black, CRGB::Black, CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, CRGB::White );
Serial.print("sparkleBW");
break;
case 30:
targetPalette = LavaColors_p;
Serial.print("sparkleLava");
break;
case 40:
targetPalette = CloudColors_p;
Serial.print("sparkleCloud");
break;
case 50:
targetPalette = PartyColors_p;
Serial.print("sparkleParty");
break;
}
}