Introduction: Ambient Computer Lights - Using an Arduino With NeoPixel Strip

About: I am a recent graduate from the University of Pittsburgh. While i was there i got a Bachelors degree in Computer Science and explored a few new hobbies, one of which being circuitry. I purchased a few Arduino'…
Hey everyone,

i decided to revisit an old project of mine, adding ambient light's to my computer. This time i decided to use a NeoPixel 30 rgb led strip instead of individually wiring up rgb led's. This project is incredibly simple and requires very little money to put it all together.

Parts Needed:
1 - NeoPixel Strip of rgb leds (I used the Adafruit NeoPixel Digital RGB LED Weatherproof strip  http://www.adafruit.com/products/1376)
1 - Arduino
some pins to make connecting the strip to the arduino easier

Wiring the strip is very simple so i wont go into any details. There might also be an additional 5v and Ground which does not need to be attached.

Red = 5v
White = Ground
Green = pwm pin

done!

Adafruit recommends using an additional power supply. However, as long as you keep the strip to 30 led's you wont need one.

If you have any troubles with getting the NeoPixel strip to work, please refer to one of adafruits many tutorials.
http://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library

If you do not have Processing installed already, this would be the time to do it!
http://www.processing.org/download/?processing





Step 1: The Code

The real meat and bone of this project is the code which makes the ambient lights possible. A while back i found some code by Rajarshi Roy which took average rgb values from a screenshot of the computer screen (using Processing) to be used with an rgb led. I then modified the code to scan the screenshot in 10 sections (192x1080 resolution). Once i had the average value of each section i was then able to output the values to the arduino, and then to the NeoPixel strip. Since there are 30 led's to work with, i assigned 3 led's to represent each section of the screen.

I experimented with more sections, but any more than 10 caused too much cpu usage.

I soon after decided to implement TouchOSC into the program to allow for iPhone control. That code is not included in this instructable, however if you email me (cgmalantonio@gmail.com) i will gladly send you the code. This code allows for a toggle on the Ambient lights, as well as RGB sliders and an XY touch pad for generating even more colors.


Well, lets begin!

First we have the Arduino code, this is responsible for taking the rgb values from the Processing sketch and outputting those values to the NeoPixel strip.

--------------------------------------------------------------------------------------------
--------------------------------Arduino Sketch----------------------------------------
--------------------------------------------------------------------------------------------

//Ambi: AmbientNeoPixel Arduino Sketch
//Created By: Cory Malantonio

#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

int r[11]; // array for each color value
int g[11];
int b[11];

void setup() {
  Serial.begin(9600);
  strip.begin(); // prep the neopixel
  strip.show();
}

void loop() {

  if (Serial.available()>=31) {
    if (Serial.read() == 0xff){
            for (int x = 1; x < 11; x++){
        r[x] = Serial.read(); // read in the values from processing
        g[x] = Serial.read(); // in the same order we sent them
        b[x] = Serial.read();

        r[x] = constrain(r[x], 0, 255); // just incase any values slip away
        g[x] = constrain(g[x], 0, 255);
        b[x] = constrain(b[x], 0, 255);

      }
    }
  }


int Xval = 1; // count to 30
int Yval = 2; // while loading rgb values
int Zval = 3; // into 3 led's at a time

for (int z = 1; z < 11; z++){

strip.setPixelColor(Xval, r[z], g[z], b[z]);
strip.setPixelColor(Yval, r[z], g[z], b[z]);
strip.setPixelColor(Zval, r[z], g[z], b[z]);

Xval = Xval + 3;
Yval = Yval + 3;
Zval = Zval + 3;
}

  strip.show(); //output to the neopixel
  delay(20); //for safety
}


--------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------

Here is the processing sketch,
the only real adjustment you will have to make will be the line
port = new Serial(this, Serial.list()[#], 9600;

the # is referring to the usb device number the arduino is plugged into.
i would suggest trying 0, then 1, then 2, etc until you find the one you are using.


--------------------------------------------------------------------------------------------
--------------------------------Processing Sketch-----------------------------------
--------------------------------------------------------------------------------------------
edit: i got a great email asking about changing the resolution on the processing sketch.
Since then, i changed out the processing sketch with one more fit to edit (without having to dive into the code).
--------------------------------------------------------------------------------------------

/*  Ambi2: AmbientNeoPixel Processing Sketch
**  Created by: Cory Malantonio
**  ambiArray is based on a design by Rajarshi Roy
*/


import cc.arduino.*;
import java.awt.Robot;
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.*;


//-------Set Resolution Here-----//
int resX = 1920;
int resY = 1080;
//-------------------------------//

int sectW = resX / 10;  //Section Width for the 10 sections
int SectRx = sectW / 4; //Section resolution for x
int SectRy = resY / 4;  //Section resolution for y

Serial port;
Robot GrabRGBval;

void setup()
{
  port = new Serial(this, Serial.list()[2], 9600);
  //Serial.list()[#], # = usb device number

  try
  {
    GrabRGBval = new Robot();
  }
  catch (AWTException e)
  {
    println("Robot class not supported by your system!");
    exit();
  }

  size(200, 200);
  background(0);
  noFill();
}

void draw()
{
  int pixel;

  float[] rA = new float[11];
  float[] gA = new float[11];
  float[] bA = new float[11];
  int[] reso = new int[11];

  for (int Ar = 1; Ar < 11; Ar++){  //load the resolutions into the array
  reso[Ar] = sectW * Ar;              //192 is 1/10th of the 1920 resolution
  }

  float r=0;
  float g=0;
  float b=0;
  reso[0]=0;

 BufferedImage screenshot = GrabRGBval.createScreenCapture(new Rectangle(new Dimension(resX, resY)));

for (int LED = 1; LED < 11; LED++){
  int x=0;
  int y=0;

  //reso array increments in 10ths of the 1920 resolution, starting at 0
  for ( x = reso[LED-1] ; x < reso[LED]; x = x + 4) {  //"x + 4" is skipping pixels
    for (y = 0; y < resY; y = y + 4) {                 // to help it run faster
      pixel = screenshot.getRGB(x, y);
      r = r+(int)(255&(pixel>>16));
      g = g+(int)(255&(pixel>>8));
      b = b+(int)(255&(pixel));
    }
  }

  r=r/(SectRx*SectRy); //48 is 1/4th each 10th of the screen. Above we are skipping pixels
  g=g/(SectRx*SectRy); //we are left with 1/4th the pixels.
  b=b/(SectRx*SectRy); //270 is 1/4th of the 1080 resolution
rA[LED] = r;
gA[LED] = g;
bA[LED] = b;

}

   port.write(0xff); //write marker, arduino is looking for this
   for (int Br = 1; Br < 11; Br++){
   port.write((byte)(rA[Br]));
   port.write((byte)(gA[Br]));
   port.write((byte)(bA[Br]));
  }

  delay(10); //delay for safety

    for (int cOne = 1; cOne < 11; cOne++){  
  fill(0);
  stroke(rA[cOne], gA[cOne], bA[cOne]);
  rect((cOne - 1)*20, 0, cOne*20, 200);
  fill(rA[cOne], gA[cOne], bA[cOne]);
  rect((cOne - 1)*20, 0, cOne*20, 200);
}
}





Make It Glow Contest

Participated in the
Make It Glow Contest