Last active
November 4, 2016 20:56
-
-
Save sli/3a29861b25dfaccfbedcf2a3a433f40e to your computer and use it in GitHub Desktop.
Color-O-Tron 5000 Lighting System for the Arduino
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <math.h> | |
#define DEBUG_BAUD 9600 | |
// def to enable, undef to disable | |
#define DEBUG | |
#define TEXT_ONLY | |
#define UP 1 | |
#define DOWN -1 | |
struct Color { | |
int r, g, b; | |
}; | |
// Interrupt pins | |
const int bModePin = 7; | |
// Digital PWM output pins | |
const int oRedChannel = 8; | |
const int oGreenChannel = 10; | |
const int oBlueChannel = 12; | |
// Analog input pins | |
const int pRedPot = 0; | |
const int pGreenPot = 1; | |
const int pBluePot = 2; | |
struct Color natural_white; | |
struct Color strand_color; | |
int color_direction; | |
int mode_state = 0; | |
int mode_state_direction = 1; | |
struct Color initDefault() { | |
struct Color c; | |
c.r = 128; | |
c.g = 128; | |
c.b = 128; | |
return c; | |
} | |
struct Color initNaturalWhite() { | |
struct Color c; | |
/* this is merely a close approximation of | |
natural white | |
*/ | |
int temp = 27; // 2700K | |
c.r = 255; | |
c.g = 99.4708025861 * log(temp) - 161.1195681661; | |
c.b = 138.5177312231 * log(temp - 10) - 305.0447927307; | |
return c; | |
} | |
/* Linear Fade | |
Performs a uniform fade between all channels from | |
0 to 255, oscillating between extremes. Updates | |
once every 0.1 seconds. | |
*/ | |
Color linearFade() { | |
struct Color c; | |
int nextColor = strand_color.r + (0.1 * color_direction); | |
if (nextColor >= 255) { | |
color_direction = DOWN; | |
c.r = 254; | |
c.g = 254; | |
c.b = 254; | |
} else if (nextColor <= 0) { | |
color_direction = UP; | |
c.r = 1; | |
c.g = 1; | |
c.b = 1; | |
} | |
delay(10); // 0.1s per frame | |
return c; | |
} | |
/* Spectrum Fade | |
Performs a visible color spectrum fade oscillating | |
between red and violet. | |
*/ | |
Color spectrumFade() { | |
struct Color c; | |
if (color_direction == UP) { | |
if (strand_color.r < 255) { | |
c.r = strand_color.r + 1; | |
c.g = 0; | |
c.b = 0; | |
} else if (strand_color.r >= 255 && strand_color.g < 255) { | |
c.r = 255; | |
c.g = strand_color.g + 1; | |
c.b = 0; | |
} else if (strand_color.r >= 255 && strand_color.g >= 255) { | |
c.r = 255; | |
c.g = 255; | |
c.b = strand_color.b + 1; | |
} else if (strand_color.r >= 255 && strand_color.g >= 255 && strand_color.b >= 255) { | |
c.r = 255; | |
c.g = 255; | |
c.b = 255; | |
color_direction = DOWN; | |
} | |
} else { | |
if (strand_color.r > 0) { | |
c.r = strand_color.r - 1; | |
c.g = 255; | |
c.b = 255; | |
} else if (strand_color.r <= 0 && strand_color.g > 0) { | |
c.r = 0; | |
c.g = strand_color.g - 1; | |
c.b = 255; | |
} else if (strand_color.r <= 0 && strand_color.g <= 0 && strand_color.b > 0) { | |
c.r = 0; | |
c.g = 0; | |
c.b = strand_color.b - 1; | |
} else if (strand_color.r <= 0 && strand_color.g <= 0 && strand_color.b <= 0) { | |
c.r = 0; | |
c.g = 0; | |
c.b = 0; | |
color_direction = UP; | |
} | |
} | |
return c; | |
} | |
/* Potentiometer Fade | |
Uses three potentiometers to set red, green, and blue | |
for the entire strand. | |
*/ | |
Color potFade() { | |
struct Color c; | |
c.r = map(analogRead(pRedPot), 0, 1024, 0, 255); | |
c.g = map(analogRead(pGreenPot), 0, 1024, 0, 255); | |
c.b = map(analogRead(pBluePot), 0, 1024, 0, 255); | |
return c; | |
} | |
// next color generator distpatch function | |
Color nextColorDispatch(int mode) { | |
struct Color c; | |
switch (mode) { | |
case 1: | |
c = linearFade(); | |
break; | |
case 2: | |
c = spectrumFade(); | |
break; | |
case 3: | |
//c = potFade(); | |
//break; | |
case 0: | |
default: | |
c = natural_white; // solid natural white | |
break; | |
} | |
return c; | |
} | |
void setModeState() { | |
static unsigned long last_interrupt_time = 0; | |
unsigned long interrupt_time = millis(); | |
if (interrupt_time - last_interrupt_time > 200) { | |
mode_state = mode_state + mode_state_direction; | |
if (mode_state > 4) { | |
mode_state_direction = DOWN; | |
mode_state = 3; | |
} else if (mode_state < 0) { | |
mode_state_direction = UP; | |
mode_state = 1; | |
} | |
#ifdef DEBUG | |
Serial.print("Changing mode to "); | |
Serial.println(mode_state); | |
#endif | |
} | |
last_interrupt_time = interrupt_time; | |
} | |
void setup() { | |
strand_color = initDefault(); | |
natural_white = initNaturalWhite(); | |
#ifndef TEXT_ONLY | |
pinMode(bModePin, INPUT); | |
digitalWrite(oRedChannel, strand_color.r); | |
digitalWrite(oGreenChannel, strand_color.g); | |
digitalWrite(oBlueChannel, strand_color.b); | |
#endif | |
#ifdef DEBUG | |
Serial.begin(DEBUG_BAUD); | |
#endif | |
attachInterrupt(digitalPinToInterrupt(bModePin), setModeState, RISING); | |
} | |
void loop() { | |
noInterrupts(); | |
int current_mode = mode_state; | |
interrupts(); | |
/* now generate next strand color and set. do this | |
every frame so that it can be tested with a | |
serial debugging session | |
*/ | |
strand_color = nextColorDispatch(current_mode); | |
#ifndef TEXT_ONLY | |
analogWrite(oRedChannel, strand_color.r); | |
analogWrite(oGreenChannel, strand_color.g); | |
analogWrite(oBlueChannel, strand_color.b); | |
#endif | |
#ifdef DEBUG | |
Serial.print("Color { r: "); | |
Serial.print(strand_color.r); | |
Serial.print(", g: "); | |
Serial.print(strand_color.g); | |
Serial.print(", b: "); | |
Serial.print(strand_color.b); | |
Serial.print(" }, state: "); | |
Serial.println(current_mode); | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment