Arduino Based PC Ambient Lighting

Originally published at siliconrepublic.blogspot.com on February 8, 2011.

I really like the concept of ambient lighting systems which synchronize with entertainment to create a great immersive experience. And since I had a RGB led strip lying around I decided to use my Arduino and a Processing sketch to create such a system for computers which really turned out great!

Here is a video of my setup and a nice demo of it working with a Star Wars video clip:

Materials:If you would like to setup this system, it is quite simple and does not require any Arduino shields. The materials you will need other than an Arduino are:

+RGB LED Strip (<=$15.95): You can get really cheap ones but I went with this Sparkfun LED strip due to ease of shipping (http://www.sparkfun.com/products/10261).

+ULN2003A (~$00.63): This chip is a transistor array for driving the LED strip which requires 12V signals with the 5V digital signals from the Arduino (order from DigiKey: http://www.digikey.com)

Schematic:The LED driver circuit is extremely simplified due to the ULN2003A chip which eliminates the need for a separate transistor circuit for each R, G and B channel of the LED. Here is the schematic:

A closeup of my setup:

Code:

The system works by taking screenshots continuously and averaging the all the pixel colors. This data is then sent to the Arduino over USB. The Arduino receives this data and controls the LED strip color accordingly using pulse-width modulating each channel (Red, Green, Blue).

Processing Code: (open Processing IDE: http://processing.org/, copy-paste code, run)

//Developed by Rajarshi Roy
import java.awt.Robot; //java library that lets us take screenshots
import java.awt.AWTException;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.awt.Rectangle;
import java.awt.Dimension;
import processing.serial.*; //library for serial communication
Serial port; //creates object "port" of serial class
Robot robby; //creates object "robby" of robot class
void setup()
{
port = new Serial(this, Serial.list()[0],9600); //set baud rate
size(100, 100); //window size (doesn't matter)
try //standard Robot class error check
{
robby = new Robot();
}
catch (AWTException e)
{
println("Robot class not supported by your system!");
exit();
}
}
void draw()
{
int pixel; //ARGB variable with 32 int bytes where
//sets of 8 bytes are: Alpha, Red, Green, Blue
float r=0;
float g=0;
float b=0;
//get screenshot into object "screenshot" of class BufferedImage
BufferedImage screenshot = robby.createScreenCapture(new Rectangle(new Dimension(1368,928)));
//1368*928 is the screen resolution
int i=0;
int j=0;
//1368*928
//I skip every alternate pixel making my program 4 times faster
for(i =0;i<1368; i=i+2){
for(j=0; j<928;j=j+2){
pixel = screenshot.getRGB(i,j); //the ARGB integer has the colors of pixel (i,j)
r = r+(int)(255&(pixel>>16)); //add up reds
g = g+(int)(255&(pixel>>8)); //add up greens
b = b+(int)(255&(pixel)); //add up blues
}
}
r=r/(684*464); //average red (remember that I skipped ever alternate pixel)
g=g/(684*464); //average green
b=b/(684*464); //average blue
port.write(0xff); //write marker (0xff) for synchronization
port.write((byte)(r)); //write red value
port.write((byte)(g)); //write green value
port.write((byte)(b)); //write blue value
delay(10); //delay for safety
background(r,g,b); //make window background average color
}

Arduino Code: (transfer this program to the Arduino)

//Developed by Rajarshi Roy
int red, green, blue; //red, green and blue values
int RedPin = 9; //Red pin 9 has a PWM
int GreenPin = 10; //Green pin 10 has a PWM
int BluePin = 11; //Blue pin 11 has a PWM
void setup()
{
Serial.begin(9600);
//initial values (no significance)
int red = 255;
int blue = 255;
int green = 255;
}
void loop()
{
//protocol expects data in format of 4 bytes
//(xff) as a marker to ensure proper synchronization always
//followed by red, green, blue bytes
if (Serial.available()>=4) {
if(Serial.read() == 0xff){
red = Serial.read();
green= Serial.read();
blue = Serial.read();
}
}
//finally control led brightness through pulse-width modulation
analogWrite (RedPin, red);
analogWrite (GreenPin, green);
analogWrite (BluePin, blue);
delay(10); //just to be safe
}

I hope this project is easy to understand and setup. And even if you do not intend to set up this system, I hope the code and circuit shows some concept that you will find useful for other projects :) Comments are highly appreciated and my ears are open to any new ideas!

Followup:

I am truly truly amazed by the reception of this project and I feel extremely encouraged to put up more such projects in the future :D I am truly grateful for your support!

Here is a image of a simplified layout and connections (slightly modified from the original post in terms of which Arduino pin corresponds to R, G, B):

Also, I slightly modified the Arduino code to reflect the changes in the pin numbering:

//Developed by Rajarshi Roy
int red, green, blue; //red, green and blue values
int RedPin = 10; //Red: PWM pin 10
int GreenPin = 11; //Green: PWM pin 11
int BluePin = 9; //Blue: PWM pin 9
void setup()
{
Serial.begin(9600);
//initial values (no significance)
int red = 255;
int blue = 255;
int green = 255;
}
void loop()
{
//protocol expects data in format of 4 bytes
//(xff) as a marker to ensure proper synchronization always
//followed by red, green, blue bytes
if (Serial.available()>=4) {
if(Serial.read() == 0xff){
red = Serial.read();
green= Serial.read();
blue = Serial.read();
}
}
//finally control led brightness through pulse-width modulation
analogWrite (RedPin, red);
analogWrite (GreenPin, green);
analogWrite (BluePin, blue);
delay(10); //just to be safe
}

Also, note that different led strips might have different pin ordering, so connect accordingly.

I would also like to mention that in the video, a scrolling text can be seen while the Processing code was running. This was originally there for me to debug my code. However, I removed that portion of the code in my final publish to make things slightly faster.

Finally, the comments to this post are filled with great questions, and great answers contributed by the awesome people of the DIY community. Also, many kind souls have contributed awesome snippets of code to add functionality such as multiple display and so on. Enjoy!


Originally published at siliconrepublic.blogspot.com on February 8, 2011.