/*
**WS2811-HolidayLights-PushButton-Modes**
The WS2811 circuit:
* Uses the FastLED library
* DIN to digital pin 8
The push-button circuit:
* Uses the Bounce2 library to 'mimic' interrupts
* Pressed state is LOW
* Input to digital pin 3
The LCD circuit:
* LCD RS pin to digital pin 4
* LCD Enable pin to digital pin 9
* LCD D4 pin to digital pin 10
* LCD D5 pin to digital pin 11
* LCD D6 pin to digital pin 12
* LCD D7 pin to digital pin 13
* LCD R/W pin to ground
* LCD VSS pin to ground
* LCD VCC pin to 5V
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
* https://docs.arduino.cc/learn/electronics/lcd-displays
*/
// include the library code:
#define FASTLED_INTERRUPT_RETRY_COUNT 1
#include <LiquidCrystal.h>
#include <FastLED.h>
#include <Bounce2.h>
FASTLED_USING_NAMESPACE
Bounce2::Button button = Bounce2::Button();
#define NEXT_PIN 3
#define DATA_PIN 8
#define DATA_PIN2 7
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS 50
CRGB leds[NUM_LEDS];
CRGB leds2[NUM_LEDS];
#define BRIGHTNESS 200
#define FRAMES_PER_SECOND 10
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
#define RS 4
#define EN 9
#define D4 10
#define D5 11
#define D6 12
#define D7 13
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);
int gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
uint8_t displayUpdated = 0;
void updateDisplay(char* text){
if(displayUpdated == 0){
lcd.clear();
lcd.print("Current Mode: ");
lcd.print(gCurrentPatternNumber);
lcd.setCursor(0, 1);
lcd.print(text);
displayUpdated = 1;
}
}
void solidColor(CRGB::HTMLColorCode color){
for(int i = 0; i < NUM_LEDS; i++){
leds[i] = color;
}
}
void red(){
updateDisplay("Red");
solidColor(CRGB::Red);
}
void green(){
updateDisplay("Green");
solidColor(CRGB::Green);
}
void blue(){
updateDisplay("Blue");
solidColor(CRGB::Blue);
}
uint8_t fade_min = 50;
uint8_t fade_max = 240;
uint8_t fade_current = 200;
uint8_t state_compare = 128;
void spooky_purple(){
updateDisplay("Spooky Purple");
spooky(CRGB::Indigo);
}
void spooky_red(){
updateDisplay("Spooky Red");
spooky(CRGB::DarkRed);
}
void spooky(CRGB::HTMLColorCode color){
fill_solid(leds, NUM_LEDS, color);
for(int i = 0; i < NUM_LEDS; i++){
leds[i].maximizeBrightness(fade_current);
}
uint8_t rand = random8();
if(rand > 245){
long rand_number = random(5, NUM_LEDS - 6);
leds[rand_number].maximizeBrightness(0);
leds[rand_number-1].maximizeBrightness(random8());
leds[rand_number+1].maximizeBrightness(random8());
leds[rand_number-2].maximizeBrightness(random8());
leds[rand_number+2].maximizeBrightness(random8());
}
if(fade_current >= fade_min && rand < state_compare){
fade_current -= 2;
}
if(fade_current <= fade_max && rand > state_compare){
fade_current += 2;
}
}
void rainbow()
{
updateDisplay("Rainbow");
// FastLED's built-in rainbow generator
fill_rainbow( leds, NUM_LEDS, gHue, 7);
}
int position = 0;
boolean forward = true;
void idk()
{
fill_gradient_RGB(leds, 0, CRGB::CRGB::CRGB::Indigo, position, CRGB::CRGB::Purple);
fill_gradient_RGB(leds, position, CRGB::CRGB::CRGB::Purple, NUM_LEDS, CRGB::CRGB::Indigo);
if(forward){
position++;
} else {
position--;
}
if(position > NUM_LEDS){
forward = !forward;
}
}
void rainbow2()
{
// FastLED's built-in rainbow generator
fill_rainbow( leds2, NUM_LEDS, gHue, 7);
}
void rainbowWithGlitter()
{
updateDisplay("Rainbow w/ Glitter");
// built-in FastLED rainbow, plus some random sparkly glitter
fill_rainbow( leds, NUM_LEDS, gHue, 7);
addGlitter(80);
}
void addGlitter( fract8 chanceOfGlitter)
{
if( random8() < chanceOfGlitter) {
leds[ random16(NUM_LEDS) ] += CRGB::White;
}
}
void confetti()
{
updateDisplay("Confetti");
// random colored speckles that blink in and fade smoothly
fadeToBlackBy( leds, NUM_LEDS, 10);
int pos = random16(NUM_LEDS);
leds[pos] += CHSV( gHue + random8(64), 200, 255);
}
void sinelon()
{
updateDisplay("Sine");
// a colored dot sweeping back and forth, with fading trails
fadeToBlackBy( leds, NUM_LEDS, 20);
int pos = beatsin16( 13, 0, NUM_LEDS-1 );
leds[pos] += CHSV( gHue, 255, 192);
}
void bpm()
{
updateDisplay("BPM");
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
for( int i = 0; i < NUM_LEDS; i++) { //9948
leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
}
}
void juggle() {
updateDisplay("Juggle");
// eight colored dots, weaving in and out of sync with each other
fadeToBlackBy( leds, NUM_LEDS, 20);
uint8_t dothue = 0;
for( int i = 0; i < 8; i++) {
leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255);
dothue += 32;
}
}
SimplePatternList gPatterns = { idk, spooky_purple, spooky_red, red, green, blue, rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
void forwardState(){
displayUpdated = 0;
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void loop() {
button.update();
if ( button.pressed() ) {
forwardState();
}
// Call the current pattern function once, updating the 'leds' array
gPatterns[gCurrentPatternNumber]();
rainbow2();
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
}
void setup() {
delay(1000); // 3 second delay for recovery
// tell FastLED about the LED strip configuration
FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN2,COLOR_ORDER>(leds2, NUM_LEDS).setCorrection(TypicalLEDStrip);
// set master brightness control
FastLED.setBrightness(BRIGHTNESS);
FastLED.setMaxPowerInVoltsAndMilliamps(5,1000);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
button.attach(NEXT_PIN, INPUT);
button.interval(5);
button.setPressedState(LOW);
// Setup Serial Monitor
Serial.begin(9600);
}