Go Down

Topic: 112 RGB LED Coffee Table (Read 20132 times) previous topic - next topic

joe912

I've been working on a LED coffee table , with 112 RGB led's underneath a frosted glass top.  This is accomplished by multiplexing the common cathode leds.  the red green and blue colors are on for roughly 2ms a piece, much faster than the human eye can perceive so it appears a solid color.  

The table has two atmega's in it one to control the tlc5940 chips, and one to interface with the user and the computer.  the two chips communicate via i2c.

the master board has a ftdi chip for serial comms with a computer and  connection to a control panel.

the computer program is written completely with processing.



Here is a video
Sorry for the poor quality
http://www.youtube.com/watch?v=lgTjJe9hcU4

















Code: [Select]

// Coffee Table slave


#include "Wire.h"
const int column = 16;     // number of columns
const int row = 7;         // number of rows

const byte RedPin = 5;     // digital pin to control red color
const byte GreenPin =6;    // digital pin to control green color
const byte BluePin = 7;    // digital pin to control blue color


byte Current_Color = 'R';
int power = 16;            // allow changing the power

boolean checkreading =false;

struct led{
 byte red;
 byte green;
 byte blue;
};

// Array to hold the led colors
   
   led Box[][column] = {{{255,255,255},{0,16,16},    {255,255,255},{0,16,16},{255,255,255},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16}},
                        {{255,255,255},{0,16,16},    {255,255,255},{0,16,16},{0,16,16},    {0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16}},
                        {{255,255,255},{0,16,16},    {255,255,255},{0,16,16},{255,255,255},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16}},
                        {{255,255,255},{255,255,255},{255,255,255},{0,16,16},{255,255,255},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16}},
                        {{255,255,255},{0,16,16},    {255,255,255},{0,16,16},{255,255,255},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16}},
                        {{255,255,255},{0,16,16},    {255,255,255},{0,16,16},{255,255,255},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16}},
                        {{255,255,255},{0,16,16},    {255,255,255},{0,16,16},{255,255,255},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16},{0,16,16}}};


   
#include "tlc_config.h"
#include "Tlc5940.h"



void setup()
{
  // Setup pins
 pinMode(RedPin,OUTPUT);
 pinMode(GreenPin,OUTPUT);
 pinMode(BluePin,OUTPUT);
 digitalWrite(RedPin,LOW);
 digitalWrite(GreenPin,LOW);
 digitalWrite(BluePin,LOW);
 pinMode(2,OUTPUT);

  // setup wire
  Wire.begin(4);
  Wire.onReceive(receiveEvent); // register event


  // setup tlc5940
  Tlc.init(0);
  startXLATCallback();
  Tlc.update();
       
       
  // flash onboard led as well as cycling through the colors(debugging)
  digitalWrite(2,HIGH);
  setAll(255,0,0);
  delay(1000);
  digitalWrite(2,LOW);
  setAll(0,255,0);
  delay(1000);
  digitalWrite(2,HIGH);
  setAll(0,0,255);
  delay(1000);
  digitalWrite(2,LOW);
     
}



void loop()
{
 if(checkreading)
    savedata();
}

// save data to the led array
byte vals[column*row+2];
void savedata()
{

 
  if(vals[0] == 'R' && vals[column*row+1] == 'R')
  {
    for(int i =0; i<column*row ; i++)
    {
    Box[i/column][15-i%column].red = vals[i+1];
    }
  }
  else if(vals[0] == 'G' && vals[column*row+1] == 'G')
  {
    for(int i =0; i<column*row ; i++)
    {
    Box[i/column][15-i%column].green = vals[i+1];
    }
  }
  else if(vals[0] == 'B' && vals[column*row+1] == 'B')
  {
    for(int i =0; i<column*row ; i++)
    {
    Box[i/column][15-i%column].blue = vals[i+1];
    }
   
  }
 
checkreading = false;    
}


// load the vals buffer
void receiveEvent(int howMany)
{
  int index =0;
  checkreading=true;
  while(Wire.available())
     vals[index++]=Wire.receive();
}








// do something every 2 periods, so ~2048us
// TLC5940 multiplexing code
#define XLAT_PERIODS  2

volatile uint8_t timesCalled;

volatile void myXLATCallback()
{

 if (timesCalled != 0) timesCalled--;
 else
 {
  timesCalled = XLAT_PERIODS;
  Send_data();
  Tlc.update();
 }
 set_XLAT_interrupt(); // so this will continue to be called
}

void startXLATCallback() {
  timesCalled = XLAT_PERIODS - 1;
  tlc_onUpdateFinished = myXLATCallback;
  myXLATCallback();
}


// update the tlc5940 chip

void Send_data()
{
     if(Current_Color == 'R')
     {            
           for(int i=0; i < column*row ; i++)
           {
                 Tlc.set(i, Box[i/column][i%column].red*power);
           }
           Turn_off();
           Tlc.update();
           while(tlc_needXLAT);    
           Turn_on();
           Current_Color = 'G';
     }
     else if(Current_Color =='G')
     {
           for(int i=0; i <column*row ; i++)
           {
                 Tlc.set(i, Box[i/column][i%column].green*power);
           }
           Turn_off();
           Tlc.update();
               while(tlc_needXLAT);        
           Turn_on();
           Current_Color = 'B';  
     }
     else
     {
           for(int i=0; i < column*row ; i++)
           {
                 Tlc.set(i, Box[i/column][i%column].blue*power);
           }
           Turn_off();
           Tlc.update();      
               while(tlc_needXLAT);        
           Turn_on();
           Current_Color = 'R';      
     }
}


// turn on or off the respective anode transistor

void Turn_off()
{
     pinMode(RedPin,INPUT);
     pinMode(GreenPin,INPUT);
     pinMode(BluePin,INPUT);
     digitalWrite(RedPin,LOW);
     digitalWrite(GreenPin,LOW);
     digitalWrite(BluePin,LOW);  
       delayMicroseconds(10);

}

void Turn_on()
{
 //delayMicroseconds(75);
 switch(Current_Color){
   case 'R':
   pinMode(RedPin,OUTPUT);
   delayMicroseconds(10);
   digitalWrite(RedPin, HIGH);
   digitalWrite(GreenPin, LOW);
   digitalWrite(BluePin, LOW);
   break;
   
   case 'G':
   pinMode(GreenPin,OUTPUT);
   delayMicroseconds(10);
   digitalWrite(RedPin, LOW);
   digitalWrite(GreenPin, HIGH);
   digitalWrite(BluePin, LOW);
   break;
   
   case 'B':
   pinMode(BluePin,OUTPUT);
   delayMicroseconds(10);
   digitalWrite(RedPin, LOW);
   digitalWrite(GreenPin, LOW);
   digitalWrite(BluePin, HIGH);
   break;  
 }
}


// used for the initial debug
void setAll(byte sred, byte sgreen , byte sblue)
{
for(int i=0 ; i< column ; i++)
{
  for(int j=0 ; j< row ; j++)
  {
   Box[j][i].red = sred;
   Box[j][i].green = sgreen;
   Box[j][i].blue = sblue;
  }
}
}




If you want any more information i can provide it.




Khao

It looks awesome! This is exactly the kind of stuff I'd like to build (my arduino is in the mail right now  ::))

How long did it take you to build it?

joe912

~1year since testing began. probably could be done in 2-3 months without school.

nphillips

Wow. Very impressive, Joe.

Do you have any schematics? I'm curious as to how you've multiplexed the LEDs with the TLCs.

I'm assuming you have your manual controls and the processing sketch tied to the master board, which updates the slave? The master sends a rough equivalent of the Box[] array via I2C?

joe912

#4
Feb 17, 2010, 03:37 am Last Edit: Feb 17, 2010, 03:38 am by joe912 Reason: 1
http://i50.tinypic.com/33nxapf.jpg
the line above the capacitor on the left is VCC at 5v
the line below is gnd


yea i send almost the box array, except to speed it up i only send red green or blue at a time

the slaves only job is to listen to i2c and update the tlc5940 array.  this was done to ensure minimal cpu time available


the_chuck

Hey Joe. First, that is awesome. Seriously well done.

Still a noob to this stuff, but I was wondering if you could talk a bit more about multiplexing the anode. I looked at your schematic but it's not fully clicking for me.
- the chuck.

joe912

Well they are common cathode led's so they have 3 positive leads and one negative.  You can control which color is lit by activating a separate transistor in my schematic. when the program begins the first red grayscale pwm information gets loaded onto the TLC5940.  then the red transistor pin is driven high by the atmega, while the two other transistors are driven low. after an amount of time has passed ~ 2 ms all of the transistors are shut off and the next information is uploaded to the tlc5940, this time its the green pwm info.  then after the upload has finished the green transistor is driven high.  this process cycles over and over...

hope this is helpful,  take a look at the send_data() function in my code

zitroneneis

I'm truely impressed. This is by far my favourite Arduino Project I've seen.

joe912


spookybonus

that table is so cool, i want one now

daveg360

That is in serious need of tetris!
Great work
If your system involves lethal voltages/life critical/flamable elements - you probably shouldn't need to ask.
The Arduino != PC.

Jeremy1998

im hooked... i want to make one... i guess step one is getting all the leds... im making mine 18" by 42", with 3" by 3" squares... so i need 84 leds... where did you get yours?

joe912

Ebay

they probably not the best or brightest, but by far the cheapest.  to get brighter you could use three separate Red green and blue led's to get a better color spread and brightness.

Jeremy1998

lol im going to go with cheap for my prototype... lol

designer2k2

wow, the build itself is already good, but the software takes it all  :)
http://www.designer2k2.at

Go Up