Skip to content

Instantly share code, notes, and snippets.

@stephkoltun
Last active February 7, 2017 11:48
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 stephkoltun/7587ca3d18f34ddc747fce7c16a9402d to your computer and use it in GitHub Desktop.
Save stephkoltun/7587ca3d18f34ddc747fce7c16a9402d to your computer and use it in GitHub Desktop.
/* Stephanie Koltun
* Feb 6, 2017
* Light Controller, Tangible Interaction Workshop
*
* How to Control an RGB LED with a Single Button
* - LED as Light
* - LED as Indicator
*
* Related Blog Post
* http://anotheridea.co/2017/02/06/the-most-verbose-the-most-concise/
*
* Code References:
* // Always be debouncing!
* https://www.arduino.cc/en/Tutorial/Debounce
*
* Final Note:
* The global brightness adjustment is wonky. Should be a ratio...
* Rather than incrementing all channels equally...
* Next time!
*/
// pin variables
const int buttonPin = 2;
const int redPin = 11;
const int greenPin = 10;
const int bluePin = 9;
// light levels
// will be replaced by use adjusted value
float blueBright = 80;
float redBright = 20;
float greenBright = 170;
float globalBright = 100;
float offLevel = 15;
float blinkLevel = 75;
float brightStep = 15;
// time tracking and intervals
unsigned long curTime;
unsigned long lastActionTime = 0;
const long actionInterval = 3000;
unsigned long prevBlinkTime = 0;
const long blinkInterval = 300;
// button detection
int buttonState;
int prevButtonState = LOW;
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 80; // the debounce time; increase if the output flickers
long timeOn = 0;
long offInterval = 1500;
// track light
boolean blinkState = false;
boolean blinkRed = false;
boolean blinkGreen = false;
boolean blinkBlue = false;
boolean blinkGlobal = false;
boolean blinkOff = 5;
int blinkCase = 5; // red = 1, green = 2, blue = 3, global = 4, off = 5
// booleans for states
boolean lightIsSet = false;
boolean selectChannel = false;
boolean dimLevel = false;
boolean off = true; // start with light off
void setup() {
pinMode(buttonPin, INPUT);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
Serial.begin(9600);
Serial.println("light is off. wait for button press");
//setColor(redBright, greenBright, blueBright);
}
void loop() {
curTime = millis();
// detect button pressed....
int reading = digitalRead(buttonPin);
// see if switch changed
if (reading != prevButtonState) {
lastDebounceTime = millis();
}
//check if it was due to noise or pressing?
if ((millis() - lastDebounceTime) > debounceDelay) {
// use as actual reading
if (reading != buttonState) {
buttonState = reading;
// only change things if the new state is HIGH
if (buttonState == HIGH) {
// button was pressed!
// track as last action
lastActionTime = millis();
Serial.print("button was pressed, time: ");
Serial.println(lastActionTime);
if (lightIsSet) {
Serial.println("change to channel selection state");
// change to select channel state
lightIsSet = false;
selectChannel = true;
// start blinking red
blinkCase = 5;
prevBlinkTime = curTime;
}
if (selectChannel) {
// change color for picking channel
if (blinkCase == 1) {
Serial.println("change channel to green");
blinkGreen = true;
blinkRed = false;
prevBlinkTime = curTime;
setColor(0, blinkLevel, 0);
}
if (blinkCase == 2) {
Serial.println("change channel to blue");
blinkBlue = true;
blinkGreen = false;
prevBlinkTime = curTime;
setColor(0, 0, blinkLevel);
}
if (blinkCase == 3) {
Serial.println("change channel to global");
blinkGlobal = true;
blinkBlue = false;
prevBlinkTime = curTime;
setColor(redBright, greenBright, blueBright);
}
if (blinkCase == 4) {
Serial.println("change channel to off fade");
blinkOff = true;
blinkGlobal = false;
prevBlinkTime = curTime;
setColor(offLevel, offLevel, offLevel);
}
if (blinkCase == 5) {
Serial.println("change channel to red");
blinkRed = true;
blinkOff = false;
prevBlinkTime = curTime;
setColor(blinkLevel, 0, 0);
}
if (blinkCase <= 4) {
blinkCase++;
} else {
blinkCase = 1;
}
} // end selectChannel
if (dimLevel) {
if (blinkRed == true) {
if (redBright <= (255 - brightStep)) {
redBright = redBright + brightStep;
} else {
redBright = 0;
}
Serial.print("red level: ");
Serial.println(redBright);
}
if (blinkBlue == true) {
if (blueBright <= (255 - brightStep)) {
blueBright = blueBright + brightStep;
} else {
blueBright = 0;
}
Serial.print("blue level: ");
Serial.println(blueBright);
}
if (blinkGreen == true) {
if (greenBright <= (255 - brightStep)) {
greenBright = greenBright + brightStep;
} else {
greenBright = 0;
}
Serial.print("green level: ");
Serial.println(greenBright);
}
if (blinkGlobal == true) {
// increment all
// i know this isnt right, it should maintain the same ratio
// to be fixed later....
if (redBright <= (255 - brightStep)) {
redBright = redBright + brightStep;
} else {
redBright = 0;
}
if (greenBright <= (255 - brightStep)) {
greenBright = greenBright + brightStep;
} else {
greenBright = 0;
}
if (blueBright <= (255 - brightStep)) {
blueBright = blueBright + brightStep;
} else {
blueBright = 0;
}
}
} // end Dim Level
if (off) {
// turn on and restore!
Serial.println("turn on!");
setColor(redBright, greenBright, blueBright);
lightIsSet = true;
off = false;
offLevel = 25;
lightIsSet = true;
}
}
}
}
// save the reading for next loop
prevButtonState = reading;
// preform actions on light
// show configured light settings
if (lightIsSet) {
setColor(redBright, greenBright, blueBright);
}
if (selectChannel) {
// blink only for the length of the action interval
// otherwise, consider choice is "locked in"
if ((millis() - lastActionTime) < actionInterval) {
if (blinkRed == true) {
// blinking red
if ( curTime - prevBlinkTime >= blinkInterval) {
// save last blink
prevBlinkTime = curTime;
if (blinkState == false) {
// LED is off, so turn it on
setColor(redBright, 0, 0);
blinkState = true;
} else {
// LED is on, so turn it off
setColor(0, 0, 0);
blinkState = false;
}
}
} else if (blinkGreen == true) {
// blinking green
if ( curTime - prevBlinkTime >= blinkInterval) {
// save last blink
prevBlinkTime = curTime;
if (blinkState == false) {
// LED is off, so turn it on
setColor(0, greenBright, 0);
blinkState = true;
} else {
// LED is on, so turn it off
setColor(0, 0, 0);
blinkState = false;
}
}
} else if (blinkBlue == true) {
// blinking blue
if ( curTime - prevBlinkTime >= blinkInterval) {
// save last blink
prevBlinkTime = curTime;
if (blinkState == false) {
// LED is off, so turn it on
setColor(0, 0, blueBright);
blinkState = true;
} else {
// LED is on, so turn it off
setColor(0, 0, 0);
blinkState = false;
}
}
} else if (blinkGlobal == true) {
// blinking white
if (curTime - prevBlinkTime >= blinkInterval) {
// save blink
prevBlinkTime = curTime;
if (blinkState == false) {
// LED is off, so turn it on
setColor(redBright, greenBright, blueBright);
blinkState = true;
} else {
// LED is on, so turn it off
setColor(0, 0, 0);
blinkState = false;
}
}
} else if (blinkOff == true) {
// fading blink
if (curTime - prevBlinkTime >= blinkInterval / 2) {
// save blink
prevBlinkTime = curTime;
if (blinkState == false) {
// LED is off, so turn it on
setColor(offLevel, offLevel, offLevel);
blinkState = true;
if (offLevel > 0) {
offLevel = offLevel - 3;
}
} else {
// LED is on, so turn it off
setColor(0, 0, 0);
blinkState = false;
}
}
}
} else {
if (blinkOff) {
Serial.println("time is up! turn off");
lastActionTime = millis();
selectChannel = false;
off = true;
setColor(0, 0, 0);
} else {
Serial.println("time is up! change to dimming");
lastActionTime = millis();
selectChannel = false;
// change to dimming level state
dimLevel = true;
}
}
} // end Select Channel
if (dimLevel) {
// blink only for the length of the action interval
// otherwise, consider choice is "locked in"
if ((millis() - lastActionTime) < actionInterval) {
// restore to previous fade level for selected channel
if (blinkRed == true) {
setColor(redBright, 0, 0);
}
else if (blinkGreen == true) {
setColor(0, greenBright, 0);
}
else if (blinkBlue == true) {
setColor(0, 0, blueBright);
}
else if (blinkGlobal == true) {
setColor(redBright, greenBright, blueBright);
}
} else {
Serial.println("diming time is up!");
lastActionTime = millis();
dimLevel = false;
// change to "light is set" state
lightIsSet = true;
Serial.print("red: ");
Serial.print(redBright);
Serial.print(", green: ");
Serial.print(greenBright);
Serial.print(", blue: ");
Serial.println(blueBright);
}
}
}
// function to easily right to the different color pins
void setColor(float red, float green, float blue) {
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment