User login

Powered by Drupal, an open source content management system

Theory and Practice of Tangible User Interfaces

Lab 2: Digital Input and Output with Arduino Boards + Diffuser

Submitted by Seth Horrigan on Fri, 09/12/2008 - 16:56

Assignment: Digital I/O with Arduino Boards + Diffuser

Collaborators:

Description

This lab used pulse with modulation to simulate intensity using LEDs. Three LEDs - red, green, and blue - allow color mixing to simulate a multitude of different colors. After experiementing with different diffusers, I found a combination of two simple elements to be very effective. First, spread a two-ply, white facial tissue over the three LEDs bunched closely together. Second, place a ping-pong ball (with the bottom removed) over the LEDs and tissue. This allows for a robust diffusion such that no points of light from any one LED are visible, but still has a low enough opacity to allow the colors to be clearly seen (even in when the sun is streaming in from the window directly behind the board as in the photographs).

 

Components Used

  • 3 220 Ohm resistors
  • 3 LEDs - red, green and blue
  • 2 rubber bands to secure the Arduino board to the breadboard
  • 1 Arduino board
  • 1 ping-pong ball
  • 1 Walgreens white unscented facial tissue
  • Wires

Images

Step 1: set up board

Step 1: set up LEDs

Step 2: cover LEDs with tissue

Step 3: cover with ping-pong ball

 

Unlit

Red

Combination

Subtract red

Reduce blue to 100, r to 25

 

Code

Note: the code allows you to control the LEDs in two ways

  1. use multiples: '+rrr' increases red by 75, and '-rggb' decreases red by 25, green by 50, and blue by 25
  2. specify values: 'r125' sets red to 125, and 'r35g55' sets red to 35 and green to 55

/*
* Serial RGB LED
* ---------------
* Serial commands control the brightness of R,G,B LEDs
*
* Command structure is "<colorCode><colorVal>", where "colorCode" is
* one of "r","g",or "b" and "colorVal" is a number 0 to 255.
* E.g. "r0"   turns the red LED off.  
*      "g127" turns the green LED to half brightness
*      "b64"  turns the blue LED to 1/4 brightness
*
* Alternate 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 12 September 2008
* Seth Horrigan
*
*/

//include support for manipulating strings.
#include <string.h>

int maxLength = 100;
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("There are two ways of adjusting the LED intensity:");
Serial.println("1. use multiples; '+rrr' increases red by 75, and '-rggb' decreases red by 25, green by 50, and blue by 25");
Serial.println("2. specify values; 'r125' sets red to 125, and 'r35g55' sets red to 35 and green to 55");
Serial.println("enter color command :");  
}

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

//Or write your own function...
if(strlen(serInString) > 0){
handleInput();
}

//Erase anything left in the serial string, preparing it for the
//next loop
resetSerialString();  

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

void resetSerialString() {
for (int i = 0; i < maxLength; i++) {
serInString[i] = '\0';
}
}

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

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

int newColorValue(int colorValue, int increment){
colorValue = colorValue + increment;
if(colorValue < 0)
colorValue = 0;
else if(colorValue > 255)
colorValue = 255;

return colorValue;
}

//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 60 and green by 20.
void handleInput() {
int i = 0;
int increment = 0;

switch(serInString[0]){
case '-':
i++;
increment = -25;
break;
case '+':
i++;
increment = 25;
break;
default:
processNumericalCommands();
return;
}

//loop through the string (serInString)
//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 && serInString[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 = newColorValue(redValue, increment);

//If the character is g (green)...
} else if (colorCode == 'g') {
greenValue = newColorValue(greenValue, increment);

//If the character is b (blue)...
} else if (colorCode == 'b') {
blueValue = newColorValue(blueValue, increment);

}    
//Move on to the next character in the string
//From here, the code continues executing from the "while" line above...
i++;
}
//Tell the user what we did
Serial.print("setting LED intensities r = ");
Serial.print(redValue);
Serial.print(", g = ");
Serial.print(greenValue);
Serial.print(", b = ");
Serial.println(blueValue);

analogWrite(redPin, redValue);
analogWrite(greenPin, greenValue);
analogWrite(bluePin, blueValue);

}

//change the value of the red, green, or blue LED according to the command received.
//for example, r240 sets the red LED to the value 240 (out of 255)
void processNumericalCommands() {
int i = 0;

while (i < maxLength && serInString[i] != '\0') {
//read in the first character in the string
colorCode = serInString[i];
i++;
//if the first character is r (red), g (green) or b (blue), do the following...
if( colorCode == 'r' || colorCode == 'g' || colorCode == 'b' ) {
//convert the string to an integer
//(start at the second character, or the beginning of the string '+1')
colorVal = atoi(serInString + i) % 256;
Serial.print("setting color ");
Serial.print(colorCode);
Serial.print(" to ");
Serial.println(colorVal);

if(colorCode == 'r')
analogWrite(redPin, colorVal);
else if(colorCode == 'g')
analogWrite(greenPin, colorVal);
else if(colorCode == 'b')
analogWrite(bluePin, colorVal);

//skip past the numeric component
i++;
if(colorVal != 0){
while(colorVal > 10){
colorVal /= 10;
i++;
}
}
}
}
}