Introduction: Enormous Led Mood Light

The Enormous led Mood light is basically a huge 3x3x3 led cube, but in order to make it huge each led is put into a paper lantern.
Once finished this makes for a great disco light. This instructable will show you step by step how to Build the huge LED cube that will be controlled by an Arduino. I included all the code used near the end : )

Step 1: Gather Your Tools

To start of you will need these tools...

.hot glue gun
.soldering iron
. Wire Strippers
.scissors
. ruler
 Optional ladder 

Step 2: Gather Your Materials

To start of you will need these materials:

. stranded wire about 24 feet
. solid core wire 5 feet
. fishing string
. paper lanterns(27)
. Arduino uno
. pcb
. 12 Resistors (~220 ohms)
. cat 5 cable
. electrical tape
. 3 NPN Transistors (2N2222, 2N3904, BC547, etc.)
. 27 LEDs Color is optional i used these:http://www.radioshack.com/product/index.jsp?productId=2062588
. Optional- breadbord

Step 3: Make the Led Lanterns

To make the 27 led lanterns first :test leds first .Then snip two wires 3in long twist the wires with the led leads and tape with electrical tape or solder them.
test the leds again
now cut a solid core wire 4 in. and wrap it around the electrical insulation of the led you just made and hot glue it in place.
take he paper lenterns and open them up. Next rest the solid core wire on the the lantern and hot glue it in place.
now make 26 more! don't forget to label the negative wire

Step 4: Constructing the Cube

now its time to construct the mood light .
First cut 9 strings five feet in length then with a ruler draw a squarer that is 16 in by 16 in 
mark at the 0,8,and16 inches . then draw a line from the 8 in mark to the other 8 in mark . do this for both sides and you should end up with a cross . now tape or hot glue the 5 feet long strings on the 0,8,16 in marks including the center . now you can begin the first layer .
Tie the first layer of nine lanterns then measure 5in and cut the fishing wire then pass the fishing wire 
through the tiny hole underneath the next lantern and tie a knot to keep the lantern beneath from falling do this for all of the next layer now for the last layer do the same and tie the rows of 3 lanterns to the remaining wire hanging from the ceiling .

Step 5: Time for the Wiring

For the wiring cut 27 five inch long stranded wires to connect all of the cathodes or negative side of an led together in one layer
then cut  16 six inch long wires to connect all the positives in the nine columns of three.

Step 6: Building the Circuit

the Circuit is very basic. Each of the nine columns will connect to a pin on the Arduino through a current limiting resistor (220 OHMS).
Each of the three levels connects to ground via a NPN transistor when activated by an Arduino pin . following the schematic solder 9 resistors to the pcb leaving as much room as possible then solder the 3 NPN transistors and there corresponding resistors  to the pcb.


Step 7: Wiring the Arduino

now number the resistors 1,2,3,4,5,6,7,8,9, and the transistor Circuit L1,L2,L3 then number the lanterns(1,2,3,4,5,6,7,8,9) and with the 
cat 5 cable connect the resistors to its corresponding columns by number like resistor 1 to column 1.
Connect resistor  No. 1 to pin 2 on the arduino. 
connect resistor 2 to pin 3 and so for  until you get to resistor 9 connected to pin 10.
L1 connects to pin 11; L2 connects to pin 12 and L3 connects to pin 13.

Step 8: Software

Please rate this instructable if you like it! :) here is the code that i used so that you can copy and paste it:
 #define DRAW_PWM_DELAY 10
#define MAX_INTENSITY 8

* LED Driver 

byte columnPins[] = {2,3,4,6,7,8,11,12,13}; // connections of matrix colums
byte levelPins[] = {5,9,10}; // connections of matrix levels

// initializes the LED driver (sets pin modes and turns all LEDs off)
void ledInit() {
  for (byte i=0; i<9; i++) {
    pinMode(columnPins[i], OUTPUT);
digitalWrite(columnPins[i], LOW);
}
for (byte i=0; i<3; i++) {
pinMode(levelPins[i], OUTPUT);
digitalWrite(levelPins[i], HIGH);
}
}

// switch on single LEDs
// causes other LEDs to light up if driver is not in initialized state
// (you can not address all the 27 LEDs with just 12 pins at a time)
void ledOn(byte column, byte level) {
digitalWrite( columnPins[column], HIGH );
digitalWrite( levelPins[level], LOW );
}

// same like ledOn
void ledOff(byte column, byte level) {
digitalWrite( columnPins[column], LOW );
digitalWrite( levelPins[level], HIGH );
}

/********************************************************************************
* Basic Drawing API (voxel buffer, cartesian coordinate system, etc.)
********************************************************************************/

byte buffer[27]; // voxel buffer

// draws the voxel buffer (ignoring intensities)
// any voxel >1 will turn on the corresponding LED
void draw(byte n) {
int col,lvl;
for (byte t=1; t<n; t++) {
for (byte i=0; i<27; i++) {
if (buffer[i]) {
col = i/3;
lvl = i%3;
ledOn(col,lvl);
delayMicroseconds(DRAW_PWM_DELAY);
ledOff(col,lvl);
} else {
delayMicroseconds(DRAW_PWM_DELAY);
}
}
}
}

void draw() {
draw(1);
}

// draws the voxel buffer (takes intensities into account)
// this functions uses a software PWM and is about 128 times slower
// than the binary draw function
void drawPwm() {
int col,lvl;
for (byte t=1; t<=128; t++) {
for (byte i=0; i<27; i++) {
if (!(t % (1<<(8-buffer[i])))) {
col = i/3;
lvl = i%3;
ledOn(col,lvl);
delayMicroseconds(DRAW_PWM_DELAY);
ledOff(col,lvl);
} else {
delayMicroseconds(DRAW_PWM_DELAY);
}
}
}
}

// clears voxel buffer
void clearBuffer() {
for (byte i=0; i<27; i++) {
buffer[i] = 0;
}
}

// fills voxel buffer
void fillBuffer(byte value) {
for (byte i=0; i<27; i++) {
buffer[i] = value;
}
}

// retrieves values from voxel buffer (using cartesian coordinates)
byte getVoxel(char x, char y, char z) {
byte i = 9*x - y + 3*z + 13;
return buffer[i];
}

// sets values from voxel buffer (using cartesian coordinates)
void setVoxel(char x, char y, char z, byte value) {
byte i = 9*x - y + 3*z + 13;
if (i>=0 && i <= 27) {
buffer[i] = value;
}
}

// interpolates arbitrary points between voxels
void setPoint(float x, float y, float z, byte value) {
char xint = x>0 ? 1 : -1;
char yint = y>0 ? 1 : -1;
char zint = z>0 ? 1 : -1;

interpolate(x,y,z,value,0,0,0);
interpolate(x,y,z,value,0,yint,0);
interpolate(x,y,z,value,0,0,zint);
interpolate(x,y,z,value,0,yint,zint);
interpolate(x,y,z,value,xint,0,0);
interpolate(x,y,z,value,xint,yint,0);
interpolate(x,y,z,value,xint,0,zint);
interpolate(x,y,z,value,xint,yint,zint);
}

void interpolate(float x, float y, float z, byte value, char xint, char yint, char zint) {
float d = sqrt(pow(xint-x,2) + pow(yint-y,2) + pow(zint-z,2));
byte i = 9*xint - yint + 3*zint + 13;
if (i>=0 && i <= 27) {
buffer[i] += (value * (1-d));
}
}

/********************************************************************************
* Some Demos
********************************************************************************/

// sets pin states manually (driver not used)
void demoLowLevel() {
ledInit();
// nothing visible happens here
for (byte lvl=0; lvl<3; lvl++) {
digitalWrite( levelPins[lvl], LOW );
}
// now we select entire colums
for (byte cycle=0; cycle<2; cycle++) {
for (byte col=0; col<9; col++) {
digitalWrite( columnPins[col], cycle % 2 == 0 ? HIGH : LOW );
delay(100);
}
}

ledInit();
// nothing visible happens here
for (byte col=0; col<9; col++) {
digitalWrite( columnPins[col], HIGH );
}
// now we select entire levels
for (byte cycle=0; cycle<2; cycle++) {
for (byte lvl=0; lvl<3; lvl++) {
digitalWrite( levelPins[lvl], cycle % 2 == 0 ? LOW : HIGH );
delay(200);
}
}

ledInit();
}

// some rotations (no driver used as well)
void demoRotation() {
// rotation sequence
byte seq[] = {0,1,2,5,8,7,6,3};

ledInit();
// active all levels
for (byte lvl=0; lvl<3; lvl++) {
digitalWrite( levelPins[lvl], LOW );
}
// middle column
digitalWrite( columnPins[4], HIGH);

// now we select entire colums
int cycles = 3*3*9;
for (int cycle=0; cycle<cycles; cycle++) {
digitalWrite( columnPins[seq[cycle%8]], HIGH);
digitalWrite( columnPins[seq[(cycle-1)%8]], LOW);
if (cycle >= 3*9) {
digitalWrite( columnPins[seq[(cycle+4)%8]], HIGH);
digitalWrite( columnPins[seq[(cycle+3)%8]], LOW);
}
if (cycle >= 2*3*9) {
digitalWrite( columnPins[seq[(cycle+2)%8]], HIGH);
digitalWrite( columnPins[seq[(cycle+1)%8]], LOW);

digitalWrite( columnPins[seq[(cycle+6)%8]], HIGH);
digitalWrite( columnPins[seq[(cycle+5)%8]], LOW);
}
delay(100);
}

ledInit();
}

// direct access to voxel buffer (cartesian coordinates not used)
void demoFill() {
clearBuffer();
for (int cycle=0; cycle<2; cycle++) {
for (int i=0; i<27; i++) {
if (cycle % 2 == 0) {
buffer[i] = 8;
} else {
buffer[i] = 0;
}
draw(50);
}
}
}

// treats voxels as bins and fill them bit by bit randomly
void demoBinFill() {
clearBuffer();
for (int i=0; i<100; i++) {
buffer[random(0,28)]+=2;
drawPwm();
}
}

// neat random sparkle
void demoSparkle() {
for (int density = 0; density<50; density++) {
for (int cycle = 0; cycle < 3; cycle++) {
clearBuffer();
for (int i=0; i<density; i++) {
buffer[random(0,28)] = random(0,9);
}
drawPwm();
}
}
}

// makes all LEDs pulse synchronously
void demoPulse() {
for (int cycle=0; cycle<80; cycle++) {
fillBuffer(-abs(cycle%16-8)+8);
drawPwm();
}
}

// pulsing wave
void demoPulseWave() {
byte r;
for (byte cycle=0; cycle<80; cycle++) {
for (char x=-1; x<=1; x++) {
for (char y=-1; y<=1; y++) {
for (char z=-1; z<=1; z++) {
r = (x*x + y*y + z*z);
setVoxel(x, y, z, -abs((cycle-r)%16-8)+8);
}
}
}
drawPwm();
}
}

// demonstrates interpolation
void demoGlowfly() {
float dx,dy,dz;
byte steps = 10;

float px = random(-100,101)/100.0;
float py = random(-100,101)/100.0;
float pz = random(-100,101)/100.0;

for(int cycle=0; cycle<8; cycle++) {
dx = (random(-100,101)/100.0 - px) / steps;
dy = (random(-100,101)/100.0 - py) / steps;
dz = (random(-100,101)/100.0 - pz) / steps;

for (int i=0; i<steps; i++) {
px += dx;
py += dy;
pz += dz;

clearBuffer();
setPoint(px, py, pz, MAX_INTENSITY);
drawPwm();
}
}
}    

LED Contest

Finalist in the
LED Contest

Toy Challenge

Participated in the
Toy Challenge

Microcontroller Contest

Participated in the
Microcontroller Contest