Purpose: A man cave is loosely a male-only space to retreat to, watch sports matches, or play video games. According to psychiatrist and author Scott Haltzman, it is important for a man to have a place to call his own, referring to a male area to retreat to. Some psychologists claim that a man cave can provide refuge from stressful surroundings and be beneficial to marriage.
Via: Wikipedia
So I have committed myself to building one of these, at present, I have a 15′ x 15′ garage space, ready for the taking. I plan on turning the space into a male friendly (read: full of beer) area with a home cinema setup, a bar and some cool and interesting technology. To date, I already have the Projector & Screen, some basic fittings, some decent insulation for the roof, 2x Wireless access points with which I will be building a P-T-P link, and lots of ideas…
One of the things that I want to do is to install an all LED lighting system composed of high output RGB LED’s – My idea for this is to use an I2C bus linking all of the LED modules with the info and the power over CAT5; as such, I have begun development. I bought some small 3W RGB LED’s from Deal Extreme for developing my proof of concept modules. My PoC so far is comprised of an Seeeduino Mega as the LED controller and unfortunately as I havent made as much progress with my BifferBoard as of yet, I’m currently using a Bus Pirate (v2go) for controlling the I2C bus, the protocol Im using is quite simple, you send the write address of the unit, a # character and then the hexadecimal RGB values, as such the full pallet of colors is available and can be looked up online or from the majority of graphics programs… There are a few points to consider for what you want to use as the LED Controller, if I beef up my C skills, I do intend on moving away from the Arduino plaform and migrating to a smaller lower specced Atmel or PIC uC – resulting in lower costs… the controller so far has a few features…
- The Default (Startup) Color is programmable from the I2C bus so if there is a power failure etc… the lights will return automatically to a known state.
- The controller is bus configurable to be Common Cathode OR Common Anode
- There is more to add here as I complete them, such as disco mode or fade mode, or pre-defined sequences…
I have taken a photo of the test setup I have at present and will provide the sourcode below, I have also been working on a Processing application to play with the idea of doing something similar to the Phillips Ambilight tv where depending on the image on my screen, the lights in the mancave will be a particular color, while I will also post the code for this, its not commented, or pretty, or even working at this point so your on your own with it… I will update as time goes on… anyways, enough jibber jabber, time for some actuall images and real code…
General (Outdated) Flowchart for the controller:

Picture of the test setup…

And as promised, here is the source for the Arduino:
/*
Arduino I2C RGB LED Controller
EEPROM Map:
0x00 configuration block
0x01 red pwm value
0x02 green pwm value
0x03 blue pwm value
*/
#include
#include
//PIN Definitions
#define addr0 2
#define addr1 3
#define addr2 4
#define addr3 5
#define redPin 7
#define greenPin 8
#define bluePin 9
//Global Variables
byte redPWM = 0;
byte greenPWM = 0;
byte bluePWM = 0;
byte configBlock = 0;
byte i2cAddress = 0;
byte i2cData[4] = {0, 0, 0, 0};
boolean processQueue = false;
void setup() {
//Set PIN I/O's
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(addr0, INPUT);
pinMode(addr1, INPUT);
pinMode(addr2, INPUT);
pinMode(addr3, INPUT);
//Enable internal pullups
digitalWrite(addr0, 1);
digitalWrite(addr1, 1);
digitalWrite(addr2, 1);
digitalWrite(addr3, 1);
//Set I2C Address...
//i2cAddress = (digitalRead(addr0) | digitalRead(addr1) | digitalRead(addr2) | digitalRead(addr3));
i2cAddress = 7;
//Register an event to fire when we receive I2C data then join the bus...
Wire.onReceive(grabData);
Wire.begin(i2cAddress);
//Grab previous settings from EEPROM...
configBlock = EEPROM.read(0);
redPWM = EEPROM.read(1);
greenPWM = EEPROM.read(2);
bluePWM = EEPROM.read(3);
//Set the PWM outputs for the LED(s)
setPWM();
//I think we're ready to enter the main loop now...
}
void grabData(int data) {
int i = 0;
while(Wire.available()) {
i2cData[i] = Wire.receive();
i++;
}
processQueue = true;
}
void setPWM() {
if(configBlock == 'A') {
analogWrite(redPin, 255 - redPWM);
analogWrite(greenPin, 255 - greenPWM);
analogWrite(bluePin, 255 - bluePWM);
} else {
analogWrite(redPin, redPWM);
analogWrite(greenPin, greenPWM);
analogWrite(bluePin, bluePWM);
}
}
void updateEEPROM() {
EEPROM.write(0, configBlock);
EEPROM.write(1, redPWM);
EEPROM.write(2, bluePWM);
EEPROM.write(3, greenPWM);
}
void loop() {
//Check to see if we have something to do...
while(processQueue == false) {
//Do nothing... but do it quickly!
delay(1);
}
switch(i2cData[0]) {
case '#':
//we have a color
redPWM = i2cData[1];
greenPWM = i2cData[2];
bluePWM = i2cData[3];
setPWM();
break;
case 'D':
//We're setting the default startup color...
redPWM = i2cData[1];
greenPWM = i2cData[2];
bluePWM = i2cData[3];
updateEEPROM();
setPWM();
break;
case 'C':
//we're changing the LED type
if(i2cData[1] == 'A') {
configBlock = 'A';
} else {
configBlock = 'C';
}
updateEEPROM();
break;
default:
//do nothing...
break;
}
processQueue = false;
}
And here is the source for Processing:
import processing.serial.*;
PImage myImage;
Serial myPort;
float[] redpx;
float[] greenpx;
float[] bluepx;
float redtotal;
float greentotal;
float bluetotal;
int imgWidth;
int imgHeight;
void setup() {
//println(Serial.list());
myPort = new Serial(this, "COM13", 115200);
myImage = loadImage("red.jpg");
myImage.loadPixels();
redpx = new float[myImage.pixels.length];
greenpx = new float[myImage.pixels.length];
bluepx = new float[myImage.pixels.length];
for(int i=0; i> 16 & 0xFF;
greenpx[i] = myImage.pixels[i] >> 8 & 0xFF;
bluepx[i] = myImage.pixels[i] & 0xFF;
}
for(int r=0; r < redpx.length; r++) {
redtotal += redpx[r];
}
redtotal = redtotal / redpx.length;
for(int g=0; g < greenpx.length; g++) {
greentotal += greenpx[g];
}
greentotal = greentotal / greenpx.length;
for(int b=0; b < bluepx.length; b++) {
bluetotal += bluepx[b];
}
bluetotal = bluetotal / bluepx.length;
int serialData[] = { 91, 32, 48, 120, 48, 69, 32, 48, 120, 50, 51, 32, floor(redtotal), 32, floor(greentotal), 32, floor(bluetotal), 32, 93, 13}; //used for i2c control through a bus pirate
//int serialData[] = { 'R', floor(redtotal), 'G', floor(greentotal), 'B', floor(bluetotal), 'C', 'A', 'U' }; //used for serial control through rs232
for(int j=0; j 0) {
String inBuffer = myPort.readString();
if(inBuffer != null) {
println(inBuffer);
}
}
myImage.updatePixels();
}