#define DEBUG
#include "INHK_Pot3.h"
#include <Encoder.h>
#include <JC_Button.h>
#include <FastLED.h>
FASTLED_USING_NAMESPACE
#define NUM_LEDS 120
#define LED_PIN 11
#define ENVELOPE_PIN A0 // Envelope Pin of the Sparkfun Sound Detector Module
#define LED_TYPE WS2812B // WS2801, WS2811, WS2812B, LPD8806, TM1809, etc...
#define COLOR_ORDER GRB // Default Color Order
#define HUE_INIT 10 // < 25
#define HUE_CHANGE 2 // < 255
int minVal = 20; // Min: 0, Max: 75
int maxVal = 300; // Min: 75, Max: 750
/////////////////////////////////////////////////////////////////// LED ////////////
uint8_t style = 0;
/*============= SELECT STYLE =============*/
/* */
/* 0 --> LinearFlowing (BEST) */
/* 1 --> LinearReactive */
/* 2 --> BrightnessReactive */
/* 3 --> CentreProgressive */
/* 4 --> EdgeProgressive */
CRGB leds[NUM_LEDS];
uint8_t brightness = 50;
uint8_t hue = 100;
uint8_t changingHue = 100;
uint8_t saturation = 255;
uint8_t value = 255;
uint8_t red;
uint8_t green;
uint8_t blue;
byte dynamicHue = HUE_INIT;
int analogVal = 0; // variable that captures loudness CRGB::LavenderBlush
int val = 0; // variable used to scale analogVal above
/////////////////////////////////////////////////////////////////// CONTROLS ////////////
Potentiometer slider(A1,2); // brightness control
Potentiometer pot1(A2,2); // red/hue control
Potentiometer pot2(A3,2); // green/saturation control
Potentiometer pot3(A4,2); // blue/vlaue control
Button button1(10);
Button button2(8);
Button button3(7);
Button button4(6);
Button button5(5);
Encoder encoder(3, 2);
long oldPosition = -999;
Button encoderButton(4);
/////////////////////////////////////////////////////////////////// MODE LISTS ////////////
enum Mode {
FIXED,
CHANGING,
MUSIC
};
Mode currentMode = FIXED;
enum ColourControl{
RGB_MODE,
HSV_MODE
};
ColourControl currentColourControl = HSV_MODE;
enum DJMode{
NORMAL,
RANDOM
};
DJMode currentDJMode = NORMAL;
unsigned long previousMillis = 0; // tracks the last music effect change
bool encModeMin = false; // affects if this is true encdoder adjust minVal, if false adjust maxVal
bool alternativeEffect = false; // variable for using alernative static and changing hue effects
/////////////////////////////////////////////////////////////////// SETUP ////////////
void setup() {
#ifdef DEBUG
Serial.begin(115200);
#endif
encoderButton.begin();
button1.begin();
button2.begin();
button3.begin();
button4.begin();
button5.begin();
//LEDs
pinMode(ENVELOPE_PIN, INPUT);
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER> (leds, NUM_LEDS);
FastLED.clear();
FastLED.show();
delay(1000);
FastLED.setBrightness(brightness);
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(1000);
readableColourControl(currentColourControl);
readableMode(currentMode);
}
/////////////////////////////////////////////////////////////////// LOOP ////////////
void loop() {
button1.read();
if (button1.wasPressed()) {
nextColourControl(currentColourControl);
readableColourControl(currentColourControl);
}
button2.read() ? currentDJMode = NORMAL : currentDJMode = RANDOM;
#ifdef DEBUG
if (button2.wasPressed() || (button2.wasReleased()) ){
Serial.println(currentDJMode == 0 ? ("DJ MODE: NORMAL") : ("DJ MODE: RANDOM"));
}
#endif
button3.read();
if (button3.wasPressed()){
style = (style +1) % 5;
#ifdef DEBUG
Serial.print("STYLE: "); Serial.println(style);
#endif
}
button4.read();
if (button4.wasPressed()){
alternativeEffect = !alternativeEffect;
#ifdef DEBUG
Serial.println (alternativeEffect ? ("alternative effect ON") : ("alternative effect OFF"));
#endif
}
button5.read();
if (button5.wasPressed()) {
nextMode(currentMode);
readableMode(currentMode);
}
minMaxCheck(); // checks the min and max value for the music reactive modes, set by encoder and encoder button
brightness = slider.readValue();
switch (currentColourControl){
case RGB_MODE:
red = pot1.readValue();
green = pot2.readValue();
blue = pot3.readValue();
break;
case HSV_MODE:
hue = pot1.readValue();
saturation = pot2.readValue();
value = pot3.readValue();
break;
}
if (currentMode == FIXED) {
StaticHue();
}
if (currentMode == CHANGING) {
ChangingHue ();
}
if (currentMode == MUSIC) {
MusicMode();
}
}
/////////////////////////////////////////////////////////////////// MODES switching and debugginG ////////////
void nextColourControl(ColourControl &in) {
switch (in) {
case RGB_MODE: in = HSV_MODE; break;
case HSV_MODE: in = RGB_MODE; break;
}
}
void readableColourControl(ColourControl in) {
switch (in) {
case RGB_MODE:
colourControlFlash(1);
#ifdef DEBUG
Serial.println(F("RGB_MODE"));
#endif
break;
case HSV_MODE:
colourControlFlash(2);
#ifdef DEBUG
Serial.println(F("HSV_MODE"));
#endif
break;
}
}
void colourControlFlash(int repeat){
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(250);
for (int i = 0; i < repeat; i++) {
fill_rainbow_circular(leds, NUM_LEDS, CRGB::Red); FastLED.show();
delay(250);
fill_solid(leds, NUM_LEDS, CRGB::Black);FastLED.show();
delay(250);
}
delay(250);
}
void nextMode(Mode &in) {
switch (in) {
case FIXED: in = CHANGING; break;
case CHANGING: in = MUSIC; break;
case MUSIC: in = FIXED; break;
}
}
void readableMode(Mode in) {
switch (in) {
case FIXED:
modeFlash(1);
#ifdef DEBUG
Serial.println(F("Mode: FIXED"));
#endif
break;
case CHANGING:
modeFlash(2);
#ifdef DEBUG
Serial.println(F("Mode: CHANGING"));
#endif
break;
case MUSIC :
modeFlash(3);
#ifdef DEBUG
Serial.println(F("Mode: MUSIC"));
#endif
break;
}
}
void modeFlash(int repeat){
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(250);
for (int i = 0; i < repeat; i++) {
fill_solid(leds, NUM_LEDS, CRGB::White); FastLED.show();
delay(250);
fill_solid(leds, NUM_LEDS, CRGB::Black);FastLED.show();
delay(250);
}
delay(250);
}
/////////////////////////////////////////////////////////////////// STATIC ////////////
void StaticHue(){
for(int i = 0;i < NUM_LEDS; i++){
if(currentColourControl == HSV_MODE){
if (!alternativeEffect) {
leds[i] = CHSV(hue, saturation, value);
}
else if (alternativeEffect){
leds[i] = CHSV(hue + (i * 5), 255,255); // alernative effect
}
}
else if(currentColourControl == RGB_MODE){
leds[i] = CRGB( red, green, blue);
}
}
FastLED.setBrightness(brightness);
FastLED.show();
}
/////////////////////////////////////////////////////////////////// CHANGING ////////////
void ChangingHue(){
for(int i = 0;i < NUM_LEDS; i++){
if (!alternativeEffect) {
leds[i] = CHSV(changingHue, 255, 255);
}
else if (alternativeEffect){
leds[i] = CHSV(hue + (i * 5), 255,255); // alernative effect
}
}
EVERY_N_MILLISECONDS (200){
changingHue++;
}
FastLED.show();
}
/////////////////////////////////////////////////////////////////// MUSIC ////////////
void MusicMode(){
analogVal = analogRead(ENVELOPE_PIN);
if(analogVal > maxVal)
analogVal = maxVal;
if(analogVal < minVal)
analogVal = minVal;
if(currentDJMode == RANDOM){
uint32_t interval = random(1,15); // seconds between music effects change
unsigned long now = millis();
if ((now - previousMillis) > interval*500){
style = random(1,6);
previousMillis = now;
}
}
switch (style) {
case 1:
LinearReactive();
break;
case 2:
BrightnessReactive();
break;
case 3:
CentreProgressive();
break;
case 4:
EdgeProgressive();
break;
default:
LinearFlowing();
break;
}
// Update the LED Strip
FastLED.show();
}
/////////////////////////////////////////////////////////////////// MUSIC MODES ////////////
void LinearFlowing() {
val = map(analogVal, minVal, maxVal, 0, brightness);
int dynamicDelay = map(analogVal, minVal, maxVal, 20, 1);
for (int i = 0; i < NUM_LEDS-1; i++) {
leds[i] = leds[i+1];
}
leds[NUM_LEDS-1] = CHSV(dynamicHue += HUE_CHANGE, saturation, val);
delay(dynamicDelay);
}
void LinearReactive() {
val = map(analogVal, 0, maxVal + 1, 0, NUM_LEDS);
for(int i = 0; i < NUM_LEDS; i++) {
if (i <= val)
leds[i] = CHSV(HUE_INIT+(HUE_CHANGE*i), saturation, brightness);
else
leds[i].nscale8(10);
}
}
void BrightnessReactive() {
val = map(analogVal, minVal, maxVal, 0, brightness);
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(HUE_INIT+(HUE_CHANGE*i), saturation, val);
}
}
void CentreProgressive() {
val = map(analogVal, minVal, maxVal, 0, NUM_LEDS/2);
for(int i = 0; i < NUM_LEDS/2; i++) {
if (i <= val) {
leds[(NUM_LEDS/2)+i] = CHSV(HUE_INIT+(HUE_CHANGE*i), saturation, brightness);
leds[(NUM_LEDS/2)-i] = CHSV(HUE_INIT+(HUE_CHANGE*i), saturation, brightness);
} else {
leds[(NUM_LEDS/2)+i].nscale8(10);
leds[(NUM_LEDS/2)-i].nscale8(10);
}
}
}
void EdgeProgressive() {
val = map(analogVal, 0, maxVal, 0, NUM_LEDS/2);
for(int i = 0; i < NUM_LEDS/2; i++) {
if (i <= val) {
leds[i] = CHSV(HUE_INIT+(HUE_CHANGE*i), saturation, brightness);
leds[NUM_LEDS-i] = CHSV(HUE_INIT+(HUE_CHANGE*i), saturation, brightness);
} else {
leds[i].nscale8(10);
leds[NUM_LEDS-i].nscale8(10);
}
}
}
void minMaxCheck() {
long newPosition = encoder.read();
if (newPosition != oldPosition) {
if (newPosition > oldPosition){
encModeMin ? minVal++ : maxVal+= 10;
if (minVal > 75)
minVal = 75;
if (maxVal > 800)
maxVal = 800;
}
else if(newPosition<oldPosition){
encModeMin ? minVal-- : maxVal-= 10;
if (minVal < 0)
minVal = 0;
if (maxVal < 75)
maxVal = 75;
}
oldPosition = newPosition;
#ifdef DEBUG
Serial.print("maxVal: "); Serial.print(maxVal);
Serial.print("\t minVal:"); Serial.println(minVal);
#endif
}
encoderButton.read();
if (encoderButton.wasPressed())
{
encModeMin = !encModeMin;
#ifdef DEBUG
Serial.println(encModeMin ? ("min Val setting active") : ("max Val setting active"));
#endif
}
}