User login

Powered by Drupal, an open source content management system

Theory and Practice of Tangible User Interfaces

Lab 02: Keyboard Controlled Light Mixer

Submitted by andy on Wed, 09/17/2008 - 00:00

Assignment: Digital I/O with Arduino Boards + Diffuser

Collaborators:

Assignment: Digital I/O with Arduino Boards + Diffuser

Description

Use keyboard-entered values to control the brightness of each LED. The user enters r, g, or b make the corresponding red, green, or blue LED brighter. The user is shown the intensity value for the LED after the brightness is updated.

For my enhanced version I assembled code to accept keyboard-entered values in both upper and lower case, and the user can clear the color palette.

Use Cases:

  • User enters capital R, G, or B to make the corresponding (red, green, or blue) LED brighter.
  • User enters lower case r, g, or b to make the corresponding LED less bright.
  • User presses the space bar to clear the color mix, turning LEDs off.

For this version the user must press Enter to send the command to the board. I'm working on figuring out how to do this without the user pressing Enter, and am looking to use Processing's keyPressed function and key variable.

 

Components Used

  • (3) LEDs: red, green, blue
  • (3) 220 ohm resitors
  • Miscellaneous connecting wires
  • Diffuser

 

1. Diffuser

I fashioned a diffuser out of an inverted white candle, a tall cylinder-shaped one that had burned down quite a ways. Inverting the candle, so that the burned-away is pointed towards the breadboard, creates a nice pocket for the LEDs. I also experimented with wax paper, muslin, linen, and votive candle holders. The wax candle created the smoothest diffuse look.

 

Arduino Code, Controlling Color Through Multiple Key Presses

/* 
* Serial RGB LED
* ---------------
* Serial commands control the brightness of R,G,B LEDs
*
* Command structure is "<colorCode>*", where "colorCode" is
* one of "r","g", or "b".
* E.g. "r" increases the red LED brightness by 10
* "rrr" increases the red LED brightness by 30
* "ggb" increases the green LED brightness by 20 and the blue by 10
*
* Created 18 October 2006
* copyleft 2006 Tod E. Kurt <tod@todbot.com
* http://todbot.com/
*
* Adapted 5 September 2007
* copylefter 2007 Ryan Aipperspach <ryanaip@alumni.rice.edu>
*
* Modified September 15, 2008
* Andy Brooks <andy@ischool.berkeley.edu>
*
*/

//include support for manipulating strings.
//for a useful string comparison function, see the bottom of this file... stringsEqual()
//#include <stdio.h>

#include <string.h>

char serInString[100]; // array that will hold the different bytes of the string. 100=100characters;
// -> you must state how long the array will be else it won't work properly
char colorCode;
int colorVal;

int redPin = 9; // Red LED, connected to digital pin 9
int greenPin = 10; // Green LED, connected to digital pin 10
int bluePin = 11; // Blue LED, connected to digital pin 11

int redValue = 127;
int greenValue = 127;
int blueValue = 127;

void setup() {
pinMode(redPin, OUTPUT); // sets the pins as output
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
Serial.begin(9600);
analogWrite(redPin, redValue); // set them all to mid brightness
analogWrite(greenPin, greenValue); // set them all to mid brightness
analogWrite(bluePin, blueValue); // set them all to mid brightness
Serial.println("Control each LED's brightness by entering r, g, or b.");
Serial.println("Each value will make the corresponding LED brighter.");
}

void loop () {
//read the serial port and create a string out of what you read
readSerialString(serInString, 100);

//Read commands of the form 'rrrb'
processRepeatKeyCommands(serInString, 100);

//next loop
resetSerialString(serInString, 100);

delay(100); // wait a bit, for serial data
}

void resetSerialString (char *strArray, int length) {
for (int i = 0; i < length; i++) {
strArray[i] = '\0';
}
}

//read a string from the serial and store it in an array
//you must supply the array variable
void readSerialString (char *strArray, int maxLength) {
int i = 0;

if(!Serial.available()) {
return;
}
while (Serial.available() && i < maxLength) {
strArray[i] = Serial.read();
i++;
}
}

//go through the string, and increase the red value for each 'r',
//the green value for each 'g', and the blue value for each 'b'.
//For example "rrrg" increases red by 30 and green by 10.
void processRepeatKeyCommands(char *strArray, int maxLength) {
int i = 0;

//loop through the string (strArray)
//i = the current position in the string
//Stop when either (a) i reaches the end of the string or
// (b) there is an empty character '\0' in the string
while (i < maxLength && strArray[i] != '\0') {
//Read in the character at position i in the string
colorCode = serInString[i];

//If the character is r (red)...
if (colorCode == 'r') {
//Increase the current red value by 10, and if you reach 255 go back to 0
redValue = (redValue + 10) % 255;
analogWrite(redPin, redValue);
Serial.print("setting color r to ");
Serial.println(redValue);

//If the character is g (green)...
} else if (colorCode == 'g') {
greenValue = (greenValue + 10) % 255;
analogWrite(greenPin, greenValue);
Serial.print("setting color g to ");
Serial.println(greenValue);

//If the character is b (blue)...
} else if (colorCode == 'b') {
blueValue = (blueValue + 10) % 255;
analogWrite(bluePin, blueValue);
Serial.print("setting color b to ");
Serial.println(blueValue);
}

//Move on to the next character in the string
//From here, the code continues executing from the "while" line above...
i++;
}
}


//compare two strings to see if they are equal
//compares the first 'numCharacters' characters of string1 and string2 to
//see if they are the same
//
//E.g. stringsEqual("hello","hello",5) => true
// stringsEqual("hello","helaabbnn",3) => true
// stringsEqual("hello","helaa",5) => false
boolean stringsEqual(char *string1, char *string2, int numCharacters) {
if (strncmp(string1, string2, numCharacters) == 0) {
return true;
} else {
return false;
}
}

 

Arduino Code, Controling Color Through Upper Case, Lower Case, and the Space Bar

/*
*
* This program allows the user to control the brightness of each of three LEDs (red, green, blue).
* The user enters either R, G, or B (and presses Enter) to brighten red, green, and blue, respectively.
* The user enters either r, g, or b (and presses Enter) to darken red, green, and blue, respectively.
* The user can clear the color mix by pressing the space bar and Enter.
*
* I started out wanting to figure out how to allow the user to simply press any of a set of keys
* to manipulate the brightness of each LED. For example, the user could compose a color combination
* using keys s, d, and f to make the red, green, and blue LEDs brighter respectively. S/he would
* use the j, k, and l keys to make the red, green, and blue LEDs dimmer respectively. The user wouln't
* have to press enter at all to send the command, which is what s/he has to do in this version.
*
* For the next version I'd like to figure out how to accept values without the user having to press Enter.
* I could probably use keyPressed and key values to get values form the keyboard, though this would take
* some work with Processing, which I've just started learning.
*
* Guidance and reference:
* http://www.ladyada.net/forums/viewtopic.php?t=4592&sid=c1695bb50d40eec72...
* Ryan Aipperspach's code, as posted on the intranet site
* Tod Kurt's code, also posted on the intranet.
*
* Andy Brooks <andy@ischool.berkeley.edu>
* September 16, 2008
*
*/

int redPin = 9; // pin location for red LED
int greenPin = 10; // pin location for green LED
int bluePin = 11; // pin location for blue LED

int redValue = 0; // initial color value for red LED
int greenValue = 0; // initial color value for green LED
int blueValue = 0; // initial color value for blue LED

int upRed = 82; // ascii code for the key we'll use to brighten the red LED
int downRed = 114; // ascii code for the key we'll use to darken the red LED
int upGreen = 71; // ascii code for the key we'll use to brighten the green LED
int downGreen = 103; // ascii code for the key we'll use to darken the green LED
int upBlue = 66; // ascii code for the key we'll use to brighten the blue LED
int downBlue = 98; // ascii code for the key we'll use to darken the blue LED
int onSpaceBar = 32; // ascii code for the key we'll use to reset all colors

int nextChar; // hold the integer version (ASCII) of the key pressed

void setup() {
Serial.begin(9600); // opens up the serial port to talk at 9600 baud
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
analogWrite(redPin, redValue);
analogWrite(greenPin, greenValue);
analogWrite(bluePin, blueValue);

Serial.println("Mix your LEDs by entering R, G, or B and pressing enter.");
Serial.println("Too much of a color? Just key the lower case version and press enter.");

}

void loop(){

int colorBright;

// All these IF's are really ugly, but this was quick and dirty and worked for the proof of concept.

if (Serial.available()) {
nextChar = Serial.read();

if (nextChar == upRed) {
if (redValue >= 250) { // If the value exceeds the LED's range, don't loop back to a low number! Max the color out.
Serial.println("It ain't gettin' brighter!"); // Tell the user s/he can't make it any brighter.
} else {
colorBright = redValue + 10;
analogWrite(redPin, colorBright);
redValue = colorBright;
Serial.println("Redder!");
}
}

if (nextChar == downRed) {
if (redValue <= 0) { // If the value is below the LED's range, don't loop back to a high number! Min the color out.
Serial.println("That's as dim as it'll get!"); // Tell the user s/he can't make it any dimmer.
} else {
colorBright = redValue - 10;
analogWrite(redPin, colorBright);
redValue = colorBright;
Serial.println("Less red!");
}
}


if (nextChar == upGreen) {
if (greenValue >= 250) {
Serial.println("It ain't gettin' brighter!");
} else {
colorBright = greenValue + 10;
analogWrite(greenPin, colorBright);
greenValue = colorBright;
Serial.println("Greener!");
}
}

if (nextChar == downGreen) {
if (greenValue <= 0) {
Serial.println("That's as dim as it'll get!");
} else {
colorBright = greenValue - 10;
analogWrite(greenPin, colorBright);
greenValue = colorBright;
Serial.println("Less green!");
}
}

if (nextChar == upBlue) {
if (blueValue >= 250) {
Serial.println("It ain't gettin' brighter!");
} else {
colorBright = blueValue + 10;
analogWrite(bluePin, colorBright);
blueValue = colorBright;
Serial.println("Bluer!");
}
}

if (nextChar == downBlue) {
if (blueValue <= 0) {
Serial.println("That's as dim as it'll get!");
} else {
colorBright = blueValue - 10;
analogWrite(bluePin, colorBright);
blueValue = colorBright;
Serial.println("Less blue!");
}
}

if (nextChar == onSpaceBar) {
colorBright = 0;
analogWrite(redPin, colorBright);
analogWrite(greenPin, colorBright);
analogWrite(bluePin, colorBright);
Serial.println("Clear the palette!");
}
}
}

 

Photographs

Breadboard

 

 

 

Diffuser