Skip to content

Instantly share code, notes, and snippets.

@sli
Last active November 4, 2016 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sli/3a29861b25dfaccfbedcf2a3a433f40e to your computer and use it in GitHub Desktop.
Save sli/3a29861b25dfaccfbedcf2a3a433f40e to your computer and use it in GitHub Desktop.
Color-O-Tron 5000 Lighting System for the Arduino
#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