// This sketch is for controlling the WS2812B LED strips.
// Power requirements:
// ~900 mA for the 5V pin on the Arduino.
// Each LED at full brighness draw 60 mA:
// ~ 15 LEDs at max brightness are able to be powered (255) (25 cm max length).
// ~ 30 LEDs at half brightness (127) (50 cm length).
// ~ 60 LEDs at quarter brightness (64) (1 m length).
// If needed, may have to just get a new 5V power supply (maybe 2A?)
#include <FastLED.h>
// Pin which LED Data line is connected to on Arduino
#define LED_PIN 5
// Total number of LEDs on the strip
#define NUM_LEDS 30
// Set max brightness
#define MAX_BRIGHTNESS 127.0
// Potentiometer/button input pins
// ARDUINO ONLY (FOLLOWING 4 DEFINITIONS):
/*
#define POT_PIN A0
#define BUTTON_PALETTE_STATE_PIN 4
#define BUTTON_LED_STATE_PIN 2
#define MAX_READING 1023.0
*/
// ESP32 ONLY (FOLLOWING 4 DEFINITIONS):
#define POT_PIN 39
#define BUTTON_PALETTE_STATE_PIN 19
#define BUTTON_LED_STATE_PIN 25
#define MAX_READING 4095.0
// Number of different LED states and palettes
#define NUM_STATES 5
#define NUM_PALETTES 11
// Max brightness for LEDs (0-255), scalar for use in the pot reading
#define scalar MAX_BRIGHTNESS / 1023.0
// Type CRGB: Represents color in RGB Space. (Red, Green, Blue)
// All values are from 0-255.
// Array of LEDs
CRGB leds[NUM_LEDS];
// GRADIENT DEFINITIONS.
DEFINE_GRADIENT_PALETTE(rainbow_gp) {
0, 255, 0, 0, // black at index 0
42, 255, 255, 0, // red at index 128
85, 0,255,0, // bright yellow at index 200
127, 0,255,255, // white at index 255
170, 0,0,255, // white at index 255
213,255,0,255,
255, 255, 0, 0
};
DEFINE_GRADIENT_PALETTE(heatmap_gp) {
0, 0, 0, 0, // black at index 0
64, 255, 0, 0, // red at index 128
128, 255, 255, 0, // bright yellow at index 200
192, 255, 255, 255, // white at index 255
255, 0, 0, 0
};
DEFINE_GRADIENT_PALETTE(purple_gp) {
0, 3, 0, 30,
63, 115, 3, 192,
127, 236, 56, 188,
191, 253, 239, 249,
255, 3, 0, 30
};
DEFINE_GRADIENT_PALETTE(ocean_gp) {
0, 55, 59, 68,
127, 66, 134, 244,
255, 55, 59, 68
};
DEFINE_GRADIENT_PALETTE(terminal_gp) {
0, 0, 0, 0,
127, 15, 155, 15,
255, 0, 0, 0
};
DEFINE_GRADIENT_PALETTE(celestial_gp) {
0, 195, 55, 100,
127, 29, 38, 113,
255, 195, 55, 100
};
DEFINE_GRADIENT_PALETTE(netflix_gp) {
0, 142, 14, 0,
127, 31, 28, 24,
255, 142, 14, 0
};
DEFINE_GRADIENT_PALETTE(predawn_gp) {
0, 255, 161, 127,
127, 0, 34, 62,
255, 255, 161, 127
};
DEFINE_GRADIENT_PALETTE(moon_gp) {
0, 53, 99,145,
3, 54,100,147,
9, 57,103,149,
14, 59,105,151,
20, 64,108,151,
26, 66,111,153,
31, 68,114,155,
37, 72,115,156,
43, 74,118,156,
48, 78,121,158,
54, 82,124,158,
59, 84,127,160,
65, 88,130,160,
71, 91,133,162,
76, 94,136,162,
82, 97,138,164,
88, 100,141,164,
93, 104,144,166,
99, 107,147,166,
104, 112,149,168,
110, 115,152,168,
116, 120,156,170,
121, 123,159,172,
127, 128,162,174,
133, 133,168,174,
138, 139,171,176,
144, 142,175,178,
149, 146,178,180,
155, 150,182,182,
161, 153,186,184,
166, 159,187,184,
172, 163,193,186,
177, 169,195,186,
183, 173,199,188,
189, 179,203,188,
194, 186,207,190,
200, 190,211,190,
206, 197,217,192,
211, 203,221,192,
217, 210,225,194,
222, 215,229,197,
228, 222,233,197,
234, 227,237,199,
239, 232,239,201,
245, 237,241,203,
251, 242,246,205,
255, 244,248,205
};
DEFINE_GRADIENT_PALETTE(GMT_ocean_gp) {
0, 0, 0, 0,
31, 0, 1, 1,
63, 0, 1, 4,
95, 0, 19, 42,
127, 0, 79,138,
159, 15,144,112,
191, 91,233, 89,
223, 155,244,158,
255, 242,255,255
};
DEFINE_GRADIENT_PALETTE(Sunset_Real_gp) {
0, 120, 0, 0,
22, 179, 22, 0,
51, 255,104, 0,
85, 167, 22, 18,
135, 100, 0,103,
198, 16, 0,130,
255, 0, 0,160
};
// CRGB(55, 59, 68)
// CRGB(66, 134, 244)
// Variables used.
CRGBPalette16 chosen_palette;
CRGBPalette16 current_palette = rainbow_gp;
CRGBPalette16 target_palette;
uint8_t palette_random = 0;
uint8_t palette_state = 0;
uint8_t led_state = 0;
boolean button_updated_palette = 0;
boolean button_updated_led = 0;
float brightness_prev = 0;
float brightness = 0;
uint8_t paletteIndex = 0;
uint8_t hue = 0;
uint8_t color_index[NUM_LEDS];
void setup() {
// This code is for the LED setup.
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(100);
FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
for (int i = 0; i < NUM_LEDS; i++) {
color_index[i] = random8();
}
// This code is for the inputs setup.
// initialize the pushbutton pin as an input:
pinMode(BUTTON_PALETTE_STATE_PIN, INPUT);
pinMode(BUTTON_LED_STATE_PIN, INPUT);
pinMode(POT_PIN, INPUT);
Serial.begin(9600);
}
void loop() {
// THIS CONTROLS THE PALETTE THAT IS USED.
switch (palette_state) {
case 0: // RAINBOW
chosen_palette = rainbow_gp;
break;
case 1: // HEATMAP
chosen_palette = heatmap_gp;
break;
case 2: // PURPLE
chosen_palette = purple_gp;
break;
case 3: // OCEAN
chosen_palette = ocean_gp;
break;
case 4:
chosen_palette = terminal_gp;
break;
case 5:
chosen_palette = celestial_gp;
break;
case 6:
chosen_palette = netflix_gp;
break;
case 7:
chosen_palette = predawn_gp;
break;
case 8:
chosen_palette = moon_gp;
break;
case 9:
chosen_palette = GMT_ocean_gp;
break;
case 10:
chosen_palette = Sunset_Real_gp;
break;
}
// THIS CONTROLS THE LED STATE THAT IS USED.
switch (led_state) {
case 0: // CLASSIC RAINBOW: ALL LEDS CYCLE THROUGH COLOR PALLETTE.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(chosen_palette, hue);
}
EVERY_N_MILLISECONDS(100) {
hue++;
}
break;
case 1: // WAVY PATTERN: CYCLE THOUGH PALETTE BUT EVERY LED IS DIFFERENT.
fill_palette(leds, NUM_LEDS, paletteIndex, 255/NUM_LEDS, chosen_palette, brightness, LINEARBLEND);
EVERY_N_MILLISECONDS(50) {
paletteIndex++;
}
break;
case 2: // RANDOM BLINKING AND FADE TO BLACK.
EVERY_N_MILLISECONDS(500) {
// Switch on an LED at random every 500 ms, with a random color from palette.
leds[random8(0, NUM_LEDS-1)] = ColorFromPalette(chosen_palette, random8(), brightness, LINEARBLEND);
}
EVERY_N_MILLISECONDS(839) {
// Switch on an LED at random every 839 ms, with a random color from palette.
leds[random8(0, NUM_LEDS-1)] = ColorFromPalette(chosen_palette, random8(), brightness, LINEARBLEND);
}
EVERY_N_MILLISECONDS(60) {
// Fade to black by 1 each time
fadeToBlackBy(leds, NUM_LEDS, 1);
}
break;
case 3: // RANDOM FLASHING AND BLENDING - NO GRADIENT CONTROL HERE.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(current_palette, color_index[i]);
}
nblendPaletteTowardPalette(current_palette, target_palette, 100);
switch (palette_random) {
case 0: // RAINBOW
target_palette = rainbow_gp;
break;
case 1: // HEATMAP
target_palette = heatmap_gp;
break;
case 2: // PURPLE
target_palette = purple_gp;
break;
case 3: // OCEAN
target_palette = ocean_gp;
break;
case 4:
target_palette = terminal_gp;
break;
case 5:
target_palette = celestial_gp;
break;
case 6:
target_palette = netflix_gp;
break;
case 7:
target_palette = predawn_gp;
break;
case 8:
target_palette = moon_gp;
break;
case 9:
target_palette = GMT_ocean_gp;
break;
case 10:
target_palette = Sunset_Real_gp;
break;
}
EVERY_N_SECONDS(5) {
palette_random = random8(0, NUM_PALETTES - 1);
}
EVERY_N_MILLISECONDS(10) {
for (int i = 0; i < NUM_LEDS; i++) {
color_index[i]++;
}
}
break;
case 4: // WHITE.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(0, 0, brightness);
}
break;
case 5: // OFF (ALL BLACK).
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(0, 0, 0);
}
break;
}
// THIS BLOCK DEALS WITH THE PALETTE STATE BUTTON.
EVERY_N_MILLISECONDS(50) {
if (digitalRead(BUTTON_PALETTE_STATE_PIN) == HIGH && !button_updated_palette) {
button_updated_palette = 1;
if (palette_state != NUM_PALETTES - 1) {
palette_state++;
} else {
palette_state = 0;
}
// This resets the LEDs to black because the state just changed.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(0, 0, 0);
}
Serial.print("palette_state is: ");
Serial.println(palette_state);
} else if (digitalRead(BUTTON_PALETTE_STATE_PIN) == LOW) {
button_updated_palette = 0;
}
}
// THIS BLOCK DEALS WITH THE LED STATE BUTTON.
EVERY_N_MILLISECONDS(50) {
if (digitalRead(BUTTON_LED_STATE_PIN) == HIGH && !button_updated_led) {
button_updated_led = 1;
if (led_state != NUM_STATES - 1) {
led_state++;
} else {
led_state = 0;
}
// This resets the LEDs to black because the state just changed.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(0, 0, 0);
}
Serial.print("led_state is: ");
Serial.println(led_state);
} else if (digitalRead(BUTTON_LED_STATE_PIN) == LOW) {
button_updated_led = 0;
}
}
// THIS BLOCK DEALS WITH THE POTENTIOMETER.
EVERY_N_MILLISECONDS(500) {
// Analog read returns a value from 0:1023. Need to
// scale it to 0:MAX_BRIGHTNESS; scalar does this.
brightness = map(analogRead(POT_PIN), 0, MAX_READING, 0, MAX_BRIGHTNESS);
//brightness = analogRead(POT_PIN) * scalar;
if (brightness_prev != brightness) {
FastLED.setBrightness(brightness); // Between 0-255
Serial.print("brightness is: ");
Serial.println(brightness);
}
brightness_prev = brightness;
}
FastLED.show(); // Update the LED
}