#include <FastLED.h>
#include <AsyncTimer.h>
// #include <DmxSimple.h>
// #define DMXPIN 3
//const int numLights = 3;
#define LED_PIN3 3
#define NUM_LEDS 14
#define LEDS_LEFT 5
#define LEDS_RIGHT 9
CRGB leds[NUM_LEDS * 3 + 1];
#define HUE_PIN A0
#define SPEED_PIN A1
#define BRIGHTNESS_PIN A2
#define SCALE_PIN A3
#define BRIGHTNESS 100
uint8_t maxBrightness = BRIGHTNESS;
uint8_t currentBrightness = maxBrightness;
float brightnessMultiplier = currentBrightness * 0.01;
uint16_t xPosition;
uint8_t starIntensity[NUM_LEDS];
uint8_t starIncreasing[NUM_LEDS];
uint8_t tailLength = 6;
uint8_t currentPulseStep = 0;
bool pulseActive = false;
// Define a palette.
DEFINE_GRADIENT_PALETTE(NorthernLightsPalette) {
0, 0, 207, 82,
62, 3, 46, 62,
143, 25, 100, 106,
192, 0, 198, 144,
255, 0, 223, 150
};
DEFINE_GRADIENT_PALETTE(WarmNorthernLightsPalette) {
0, 255, 40, 5,
62, 255, 60, 5,
143, 255, 80, 0,
180, 255, 100, 0,
200, 255, 0, 0,
255, 255, 0, 0
};
CRGBPalette16 currentPalette = CRGBPalette16(NorthernLightsPalette);
CRGBPalette16 warmPalette = CRGBPalette16(WarmNorthernLightsPalette);
enum State { STARS,
PULSE,
NOISE
};
State currentState = NOISE;
State targetState = NOISE;
uint16_t caseEffectsDuration = 10000;
bool effectStarted = false;
bool transitionInProgress = false;
AsyncTimer t;
void setup() {
Serial.begin(9600);
//DmxSimple.usePin(DMXPIN);
//DmxSimple.maxChannel(NUM_LEDS * 3);
FastLED.addLeds<WS2811, LED_PIN3, GRB>(leds, NUM_LEDS * 3);
//FastLED.setBrightness(BRIGHTNESS);
/* --- INITIALIZE POTENTIOMETERS --- */
pinMode(HUE_PIN, OUTPUT);
pinMode(SPEED_PIN, OUTPUT);
pinMode(BRIGHTNESS_PIN, OUTPUT);
pinMode(SCALE_PIN, OUTPUT);
memset(starIntensity, 0, NUM_LEDS);
memset(starIncreasing, false, NUM_LEDS);
}
void loop() {
/* --- READ POTENTIOMETERS --- */
int potValueHue = map(analogRead(HUE_PIN), 0, 1023, 0, 100);
int potValueSpeed = map(analogRead(SPEED_PIN), 0, 1023, 10, 100);
int potValueScale = map(analogRead(SCALE_PIN), 0, 1023, 1, 50);
if (currentState == NOISE && transitionInProgress == false) {
maxBrightness = map(analogRead(BRIGHTNESS_PIN), 0, 1023, 0, BRIGHTNESS);
currentBrightness = maxBrightness;
brightnessMultiplier = currentBrightness * 0.01;
}
t.handle();
if (currentState != targetState && transitionInProgress) {
EVERY_N_MILLISECONDS(40) {
//FastLED.setBrightness(currentBrightness);
currentBrightness--;
if (currentBrightness <= 0) {
currentState = targetState;
currentBrightness = 0;
}
}
}
if (currentState == targetState && transitionInProgress) {
EVERY_N_MILLISECONDS(40) {
//FastLED.setBrightness(currentBrightness);
currentBrightness++;
if (currentBrightness >= maxBrightness) {
currentBrightness = maxBrightness;
transitionInProgress = false;
}
}
}
leds[0].r = 255 * brightnessMultiplier;
FastLED.show();
}
void startPulse() {
currentPulseStep = 0;
pulseActive = true;
}
void updatePulse() {
for (int i = 1; i <= NUM_LEDS; i++) {
//leds[i] = CRGB::Black;
leds[i * 3].r = 0;
leds[i * 3 + 1].g = 0;
leds[i * 3 + 2].b = 0;
/* DmxSimple.write(i * 3 + 1, 0);
DmxSimple.write(i * 3 + 2, 0);
DmxSimple.write(i * 3 + 3, 0); */
}
int leftStart = 1;
int leftEnd = LEDS_LEFT;
int rightStart = LEDS_LEFT;
int rightEnd = NUM_LEDS;
int rightPulsePosition = rightEnd - currentPulseStep;
for (int i = 0; i < tailLength; i++) {
int pos = rightPulsePosition + i;
uint8_t brightness = maxBrightness - (i * (maxBrightness / tailLength));
if (pos >= rightStart && pos <= rightEnd) {
//leds[pos] = CRGB(0, brightness, 0);
leds[pos * 3].r = brightness * brightnessMultiplier;
leds[pos * 3].g = brightness * brightnessMultiplier;
leds[pos * 3].b = brightness * brightnessMultiplier;
/* DmxSimple.write(pos * 3 + 1, brightness);
DmxSimple.write(pos * 3 + 2, 0);
DmxSimple.write(pos * 3 + 3, 0); */
}
int mirrorStartRight = rightStart;
int mirrorEndRight = rightStart + LEDS_LEFT - 1;
if (pos >= mirrorStartRight && pos <= mirrorEndRight) {
int leftPos = leftStart + (mirrorEndRight - pos);
if (leftPos >= leftStart && leftPos <= leftEnd) {
//leds[leftPos] = CRGB(0, brightness, 0);
leds[leftPos * 3].r = brightness * brightnessMultiplier;
leds[leftPos * 3 + 1].g = brightness * brightnessMultiplier;
leds[leftPos * 3 + 2].b = brightness * brightnessMultiplier;
/* DmxSimple.write(leftPos * 3 + 1, brightness);
DmxSimple.write(leftPos * 3 + 2, 0);
DmxSimple.write(leftPos * 3 + 3, 0); */
}
}
}
currentPulseStep++;
if (rightPulsePosition + tailLength - 1 < rightStart) {
pulseActive = false;
}
}
void addNoise(int hue, int scale) {
uint8_t blendFactor = hue;
for (int i = 0; i <= NUM_LEDS; i++) {
if (i < LEDS_LEFT) {
uint8_t noise = inoise8(i * scale - xPosition, 0, i * scale - xPosition);
CRGB color1 = ColorFromPalette(currentPalette, noise);
CRGB color2 = ColorFromPalette(warmPalette, noise);
CRGB blendedColor = blend(color1, color2, blendFactor);
//leds[i] = blendedColor;
leds[i * 3 + 1].r = blendedColor.r * brightnessMultiplier;
leds[i * 3 + 2].g = blendedColor.g * brightnessMultiplier;
leds[i * 3 + 3].b = blendedColor.b * brightnessMultiplier;
/* DmxSimple.write(i * 3 + 1, blendedColor.r);
DmxSimple.write(i * 3 + 2, blendedColor.g);
DmxSimple.write(i * 3 + 3, blendedColor.b); */
} else {
uint8_t noise = inoise8(i * scale + xPosition, 0, i * scale + xPosition);
CRGB color1 = ColorFromPalette(currentPalette, noise);
CRGB color2 = ColorFromPalette(warmPalette, noise);
CRGB blendedColor = blend(color1, color2, blendFactor);
//leds[i] = blendedColor;
leds[i * 3 + 1].r = blendedColor.r * brightnessMultiplier;
leds[i * 3 + 2].g = blendedColor.g * brightnessMultiplier;
leds[i * 3 + 3].b = blendedColor.b * brightnessMultiplier;
/* DmxSimple.write(i * 3 + 1, blendedColor.r);
DmxSimple.write(i * 3 + 2, blendedColor.g);
DmxSimple.write(i * 3 + 3, blendedColor.b); */
}
}
}
void addRandomStars(int speed) {
for (int i = 1; i <= NUM_LEDS; i++) {
if (random16() < speed && starIntensity[i] == 0) {
starIntensity[i] = 1;
starIncreasing[i] = true;
}
if (starIntensity[i] > 0) {
if (starIncreasing[i]) {
if (starIntensity[i] < 245) {
starIntensity[i] += 10;
} else {
starIntensity[i] = 255;
starIncreasing[i] = false;
}
} else {
if (starIntensity[i] > 10) {
starIntensity[i] -= 10;
} else {
starIntensity[i] = 0;
//leds[i] = CRGB::Black;
leds[i * 3].r = 0;
leds[i * 3 + 1].g = 0;
leds[i * 3 + 2].b = 0;
/* DmxSimple.write(i * 3 + 1, 0);
DmxSimple.write(i * 3 + 2, 0);
DmxSimple.write(i * 3 + 3, 0); */
}
// Update the LED color
if (starIntensity[i] > 0) {
//leds[i] = CRGB(starIntensity[i], starIntensity[i], starIntensity[i]);
leds[i * 3].r = starIntensity[i] * brightnessMultiplier;
leds[i * 3 + 1].g = starIntensity[i] * brightnessMultiplier;
leds[i * 3 + 2].b = starIntensity[i] * brightnessMultiplier;
/* DmxSimple.write(i * 3 + 1, starIntensity[i]);
DmxSimple.write(i * 3 + 2, starIntensity[i]);
DmxSimple.write(i * 3 + 3, starIntensity[i]); */
}
}
}
}
}
void resetTransition() {
transitionInProgress = true;
targetState = NOISE;
}