Assignment: Digital I/O with Arduino Boards + Diffuser
Collaborators:
Description
This program lets the user control the brightness of 3 LED of different colors: Red, Green and Blue. By controlling these three primary colors, the user can make any color of the rainbow.
Components Used
Arduino Code
I used four sets of code for this project.
The first set of code fades each LED individually in sequence, red, green and blue. This I called Fading_Sean_3LEDs.
// Fading LED // by BARRAGAN <http://people.interaction-ivrea.it/h.barragan> int value9 = 0; // variable to keep the actual value //int ledpin = 9; // light connected to digital pin 9, commented out for various reasons int value10 = 127; int value11= 255; void setup() { // nothing for setup } void loop() { //Code for pin 9 for(value9 = 0 ; value9 <= 255; value9+=5) // fade in (from min to max) { analogWrite(9, value9); // sets the value (range from 0 to 255) delay(30); // waits for 30 milli seconds to see the dimming effect } for(value9 = 255; value9 >=0; value9-=5) // fade out (from max to min) { analogWrite(9, value9); delay(30); } //Code for pin 10 for(value10 = 0 ; value10 <= 255; value10+=5) // fade in (from min to max) { analogWrite(10, value10); // sets the value (range from 0 to 255) delay(30); // waits for 30 milli seconds to see the dimming effect } for(value10 = 255; value10 >=0; value10-=5) // fade out (from max to min) { analogWrite(10, value10); delay(30); } //Code for pin 11 for(value11 = 0 ; value11 <= 255; value11+=5) // fade in (from min to max) { analogWrite(11, value11); // sets the value (range from 0 to 255) delay(30); // waits for 30 milli seconds to see the dimming effect } for(value11 = 255; value11 >=0; value11-=5) // fade out (from max to min) { analogWrite(11, value11); delay(30); } }
The second set of code came from the website, which fades the LED's in and out at the same time. The program also writes the value of the three LED's back to the host computer. This I called DimmingLEDs.
/* * Code for cross-fading 3 LEDs, red, green and blue, or one tri-color LED, using PWM * The program cross-fades slowly from red to green, green to blue, and blue to red * The debugging code assumes Arduino 0004, as it uses the new Serial.begin()-style functions * Clay Shirky <clay.shirky@nyu.edu> */ // Output 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 // Program variables int redVal = 255; // Variables to store the values to send to the pins int greenVal = 1; // Initial values are Red full, Green and Blue off int blueVal = 1; int i = 0; // Loop counter int wait = 50; // 50ms (.05 second) delay; shorten for faster fades int DEBUG = 1; // DEBUG counter; if set to 1, will write values back via serial void setup() { pinMode(redPin, OUTPUT); // sets the pins as output pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); if (DEBUG) { // If we want to see the pin values for debugging... Serial.begin(9600); // ...set up the serial ouput on 0004 style } } // Main program void loop() { i += 1; // Increment counter if (i < 255) // First phase of fades { redVal -= 1; // Red down greenVal += 1; // Green up blueVal = 1; // Blue low } else if (i < 509) // Second phase of fades { redVal = 1; // Red low greenVal -= 1; // Green down blueVal += 1; // Blue up } else if (i < 763) // Third phase of fades { redVal += 1; // Red up greenVal = 1; // Green low blueVal -= 1; // Blue down } else // Re-set the counter, and start the fades again { i = 1; } analogWrite(redPin, redVal); // Write current values to LED pins analogWrite(greenPin, greenVal); analogWrite(bluePin, blueVal); if (DEBUG) { // If we want to read the output DEBUG += 1; // Increment the DEBUG counter if (DEBUG > 10) // Print every 10 loops { DEBUG = 1; // Reset the counter Serial.print(i); // Serial commands in 0004 style Serial.print("\t"); // Print a tab Serial.print("R:"); // Indicate that output is red value Serial.print(redVal); // Print red value Serial.print("\t"); // Print a tab Serial.print("G:"); // Repeat for green and blue... Serial.print(greenVal); Serial.print("\t"); Serial.print("B:"); Serial.println(blueVal); // println, to end with a carriage return } } delay(wait); // Pause for 'wait' milliseconds before resuming the loop }
The Third set of code lets the user enter in a value with a prefix r, g or b (to tell the Arduino which LED to control) controlling the brightness of that particular LED. This program is called serial_led_rgb.
/* * 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 * * Created 18 October 2006 * copyleft 2006 Tod E. Kurt <tod@todbot.com * http://todbot.com/ */ 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 void setup() { pinMode(redPin, OUTPUT); // sets the pins as output pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.begin(9600); analogWrite(redPin, 127); // set them all to mid brightness analogWrite(greenPin, 127); // set them all to mid brightness analogWrite(bluePin, 127); // set them all to mid brightness Serial.println("enter color command (e.g. 'r43') :"); } void loop () { //read the serial port and create a string out of what you read readSerialString(serInString); colorCode = serInString[0]; if( colorCode == 'r' || colorCode == 'g' || colorCode == 'b' ) { colorVal = atoi(serInString+1); Serial.print("setting color "); Serial.print(colorCode); Serial.print(" to "); Serial.print(colorVal); Serial.println(); serInString[0] = 0; // indicates we've used this string if(colorCode == 'r') analogWrite(redPin, colorVal); else if(colorCode == 'g') analogWrite(greenPin, colorVal); else if(colorCode == 'b') analogWrite(bluePin, colorVal); } delay(100); // wait a bit, for serial data } //read a string from the serial and store it in an array //you must supply the array variable void readSerialString (char *strArray) { int i = 0; if(!Serial.available()) { return; } while (Serial.available()) { strArray[i] = Serial.read(); i++; } }
The last set of code lets the user enter in the brightness of the LED based on the number of letters entered into the serial console. A string of rrrrrrr will increment the red led 7 times a brightness value of 10. If the value goes over 255, then it wraps around to 0. This code had an initial problem where it would not compile, due to a change in the latest revision of the Arduino software (version 0011 Alpha). I discovered that the issue was with the stdio.h library, and found a workaround online. I had to tell the software to not define 'int' with the command #undef int. Afterwards, the program compiled just fine.
/* * 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 5 September 2007 * copylefter 2007 Ryan Aipperspach <ryanaip@alumni.rice.edu> * */ //include support for manipulating strings. //for a useful string comparison function, see the bottom of this file... stringsEqual() #undef int #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("enter color command (e.g. 'r43 or rrrrrrrrbbbb') :"); } void loop () { //read the serial port and create a string out of what you read readSerialString(serInString, 100); //UNCOMMENT ONE OF THE FOLLOWING COMMANDS, OR NOTHING WILL HAPPEN WHEN YOU //RUN THE PROGRAM... //Uncomment the following line to read commands of the form 'r245' or 'b3' //processNumericalCommands(serInString); //Uncomment the following line to read commands of the form 'rrrb' processRepeatKeyCommands(serInString, 100); //Or write your own function... //YOUR_FUNCTION_HERE(serInString); //Erase anything left in the serial string, preparing it for the //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++; } } //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(char *strArray) { //read in the first character in the string colorCode = serInString[0]; //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+1); Serial.print("setting color "); Serial.print(colorCode); Serial.print(" to "); Serial.print(colorVal); Serial.println(); if(colorCode == 'r') analogWrite(redPin, colorVal); else if(colorCode == 'g') analogWrite(greenPin, colorVal); else if(colorCode == 'b') analogWrite(bluePin, colorVal); } } //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; } }
The diffuser I ended up using was a piece of paper towel folded over and wrapped into a cone. The LED's have a difficult time directing their light into one particular place, making any sort of flat diffuser difficult (you end up with three particularly bright spots of different colors). Oddly enough, the green LED seems to overpower the blue and red. This may be because our eyes are most sensitive to green light. It has an overall effect on the colors produced. I think the cone shape works best because it acts like a lamp shade, reflecting and diffusing the light, with enough distance from the LED's.