Tuesday, October 11, 2011

Ambient Lighting using an RGB LED and Arduino UNO

I had some spare time today and managed to put up an ambient lighting using a single RGB LED and an Arduino UNO Micro controller.

There are many implementations of Arduino Ambient light setups like

http://siliconrepublic.blogspot.com/2011/02/arduino-based-pc-ambient-lighting.html


The above implementation is a really cool one which uses a +RGB LED Strip to create the ambient light effect from the PC's averaged screen color.

But sadly I didn't have a RGB LED Strip but only one RGB LED. So I tried to create the ambient light effect using the single RGB LED. So the setup is as following








The RGB LED is a common anode (positive) one so the 5v is connected to the common anode via a 1k resistor. And I use pin 9, 10, 11 with Pulse Width Modulation (PWM) for Blue, Green and Red cathodes (negative) respectively.  I drive the PWM pins using the Arduino analogWrite(). But since the RGB pins are cathodes it negates the driving value. Meaning if I give a high value (255) it will dim the corresponding color and if I give a low value (0) it will increase the brightness of the corresponding color.

Sketch Code for Arduino UNO


int bluePin = 9;
int greenPin = 10;
int redPin = 11;
int blueBrightness = 0;
int greenBrightness = 0;
int redBrightness = 0;

void setup() {
  // Setting Up the COM Port
  Serial.begin(9600);
  // Changing PIN modes to OUTPUT
  pinMode(bluePin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(redPin, OUTPUT);
}

void loop() {
  if(Serial.available() >= 4) {
   if(Serial.read() == 0xff) {
    // 0, 0, 0 is Black
    // 255, 255, 255 is White
    redBrightness = Serial.read();
    greenBrightness = Serial.read();
    blueBrightness = Serial.read();
   } 
  }
  
  /*
   Since the RGB LED has cathode pins for 
   RGB we need to deduct value from 255 
   meaning if the brightness is 255 from the 
   PC for a color we need to give 0 so that it
   will eluminate brightly
  */
  analogWrite(bluePin, 255 - blueBrightness);
  analogWrite(greenPin, 255 - greenBrightness);
  analogWrite(redPin, 255 - redBrightness);
  delay(10); 
}



In order to capture the Screen Averaged color I used the implementation from the above mentioned post yet I used Java instead of Processing because I am familiar with it. I used RXTX Library for COM port writing.

The Java Code is below


package com.shazin.ambientrgb;

/**
 *
 * @author Shazin Sadakath
 */
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.awt.AWTException;
import java.awt.Robot; 
import java.awt.image.BufferedImage;
import java.awt.Rectangle;
import java.awt.Dimension;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AmbientRGB implements Runnable {

    private static Robot robot; 
    private static SerialPort port = null;
    private static CommPortIdentifier cpi = null;

    public static void main(String[] args) throws AWTException {
        Enumeration enums = CommPortIdentifier.getPortIdentifiers();
        robot = new Robot();
        while (enums.hasMoreElements()) {
            cpi = (CommPortIdentifier) enums.nextElement();
            if ("COM27".equals(cpi.getName())) {
                break;
            }
        }

        if (cpi != null) {
            try {
                port = (SerialPort) cpi.open("ArduinoJavaBridge", 1000);
                if (port != null) {
                    port.setSerialPortParams(9600,
                            SerialPort.DATABITS_8,
                            SerialPort.STOPBITS_1,
                            SerialPort.PARITY_NONE);
                }

                System.out.println("Ready!");
                new Thread(new AmbientRGB()).start();

            } catch (Exception e) {
                Logger.getLogger(AmbientRGB.class.getName()).log(Level.SEVERE, null, e);
            }


        }
    }

    public void run() {
        OutputStream os = null;
        try {
            os = port.getOutputStream();
        } catch (IOException ex) {
            Logger.getLogger(AmbientRGB.class.getName()).log(Level.SEVERE, null, ex);
        }
        while (true && os != null) {
            int pixel;
            float r = 0;
            float g = 0;
            float b = 0;

            Rectangle rectangle = new Rectangle(new Dimension(1366, 768));
            BufferedImage screenshot = robot.createScreenCapture(rectangle);


            int i = 0;
            int j = 0;

            for (i = 0; i < rectangle.getWidth(); i = i + 2) {
                for (j = 0; j < rectangle.getHeight(); j = j + 2) {
                    pixel = screenshot.getRGB(i, j); 
                    r = r + (int) (255 & (pixel >> 16)); 
                    g = g + (int) (255 & (pixel >> 8)); 
                    b = b + (int) (255 & (pixel)); 
                }
            }
            int totalPixels = (683 * 384); 
            r = r / totalPixels; 
            g = g / totalPixels; 
            b = b / totalPixels;


            try {

                os.write(0xff); 
                os.write((byte) (r)); 
                os.write((byte) (g)); 
                os.write((byte) (b)); 
                os.flush();
                Thread.sleep(10);
            } catch (Exception ex) {
                Logger.getLogger(AmbientRGB.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }
}


I used a White Paper Scroll to cover the RGB LED so that the light is evenly visible.



15 comments:

  1. Nice :) enjoyed da post... If I had a board I wld hav definitely tried this :D

    ReplyDelete
  2. That's a fantastic and wounder full.I really impressed from your topic.It related to the led strip.I like and shared with my friends.Thanks for submitted ....

    ReplyDelete
  3. Its so Nice blog! I wanna to share you led undercabinet lighting here huge topics related hid lighting, motorcycle led lights and much more.......

    ReplyDelete
  4. Great post, but where do you put the java code?

    ReplyDelete
  5. Hi! Do you have this package?
    com.shazin.ambientrgb;

    ReplyDelete
  6. Yes great article..Thanks for sharing information..

    LED Strip Lights

    ReplyDelete
  7. Hi Nico,

    It is just a normal package I created. I have put the source code in that package. You can have the source code in any package as long as u renamed the class package to that at top.

    ReplyDelete
  8. Hi! How can I "run" the java code? I have tried java .java but that does not work. I have no clue even where to begin with java. THANKS!

    ReplyDelete
  9. Hello all,

    I built a small java swing app to control arduino based lighting system. At the moment it has three modes. Ambient lighting, Preset sequences (in which you can modify fade setting, interval for color change. more color sequences can be hard coded at the moment) and manual color selection. It minimizes to the system tray and there is a function to turn the lights on and off.

    I would also like to make a setting for how it scans the screenshots in ambience mode, i found some code that just scans the edge of the screen and i reckon it would be a good setting + minimize cpu usage.

    The code is open source and is available on Github here: https://github.com/micwallace/wallaceRGB and a built jar with library dependencies is in the store folder.

    Feel free to use it in the tutorial and contribute to the project if you a java wizard.

    Also if anybody know how to do this image procesing on the gpu with c++ (if it is even plausible) please get in contact with me.

    cheers,
    Michael

    ReplyDelete
  10. You can't, its java. Make sure you have jre installed and then extract the .jar file from the store folder in the repo to your computer. Double click the jar file to run.

    ReplyDelete
  11. hello sir, thanks a lot of!!!!!
    i have successfully done this project but now i want to increase time interval of transmission code because this project runs only for 100 sec duration at a time after then i have to double click on jar file...... so i want to increase time interval of transmission!!!
    what should i do ???

    ReplyDelete
  12. This comment has been removed by the author.

    ReplyDelete