Go Down

Topic: Library for TLC5940 16-channel PWM chip (Read 37721 times) previous topic - next topic

nphillips

As an aside:

HTINK is probably using your library for a workshop :D
http://blog.makezine.com/archive/2009/02/electronics_workshops_at_nycs_htink.html?CMP=OTC-0D6B48984890

nphillips

#1 -- That interrupt/sli() code worked perfectly. Thanks, AC!

#2 -- If anyone else was interested, this library works PERFECTLY with the Mega168's internal clock, and running on 3.3V.

...at least it does in my scenario :D

acleone

The library now supports servos - check out the Servo example (thank you Steve Pomeroy).

http://code.google.com/p/tlc5940arduino/

and updated documentation is at
http://students.washington.edu/acleone/codes/tlc5940arduino/html_r8/

joe912

#168
Feb 27, 2009, 04:38 am Last Edit: Feb 27, 2009, 05:00 am by joe912 Reason: 1
so im trying to control 112 rgb leds with this library.

what i do is strobe which pin of a common cathode led gets 5 volts with transistors and then adjust the pwm on the tlc accordingly so i end up with

turn off all transistors
Send data to tlc for red
turnn on red transistor
turn off all transistors
Send data to tlc for green
turnn on green transistor
turn off all transistors
Send data to tlc for blue
turnn on blue transistor
then repeat

the problem im running into is the update time to the tlc since i need to change from r to g to b about once every 2 ms that means i get some flickering due to the update time of the tlc.  
my question is is this because of the update time and so how long does it take to update 7 tlc's?
if that is the limiting factor is there any way to speed up the upload?

or could i possibly modify the library to not latch the data in the tlc input buffer untill i told it to?

acleone

#169
Feb 27, 2009, 05:31 am Last Edit: Feb 27, 2009, 05:32 am by acleone Reason: 1
joe: you should wait for the PWM cycle to end before you switch transistors, eg

Code: [Select]

#define RED  0
#define GREEN 1
#define BLUE 2
uint8_t color;

void loop()
{
 color++;
 if (color == 3) {
   color = 0;
 }

 // set everything
 if (color == RED) {
   Tlc.set(0, 1000);
 } else if (color == GREEN) {
   Tlc.set(1, 1000);
 } else {
   Tlc.set(2, 1000);
 }
 Tlc.update();
 while (tlc_needXLAT)
   ;
 turn_off_transistors();
 turn_on_transistor(color);
}


I haven't measured [font=Courier New]Tlc.update()[/font] in SPI mode but way back in August I measured bit-banging to be about ~260us for 1 tlc.

joe912

does the library send all led data on an update or only those that have changed?

because when i only set the first 16 of the 112 leds the array is blink free.  however when i set all of the led's the first 16 start to blink.


acleone

The library sends all the data on an update (no other way to update).  What exactly do you mean by blink?  If you turn all the LEDs on red, do they blink green for a second?

joe912

so in tlc config .h i have the number of tlc's set to 7 which should mean 112 total led's

so when column and row is set to 4 meaning 16 total led's the array runs blink free(meaning no matter what i set the RGB color to it seems to be smooth, if set to R:0 G:255 B:255 the color appears to be aqua.)

but when i set column to 16 and row to 7 then the led's appear to blink(meaning the led's appear to be off extremely briefly between transitions from red to green ...)

hopefully you can understand the code.  i have not gotten around to commenting because i did not plan to publish it.
any questions just ask.





Code: [Select]

const int column = 16;     // change to 16
const int row = 7;        // change to 7

const byte RedPin = 6;
const byte GreenPin =7;
const byte BluePin = 8;

byte Current_Color = 'R';


struct led{
 byte red;
 byte green;
 byte blue;
 
};
 /*
  led Box[][column] = {{{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},{0,16,16},{0,16,16},{0,16,16}}};
                     
*/
led Box[][column] = {{{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},{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},{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},{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},{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},{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},{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},{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},{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()
{
 pinMode(RedPin,OUTPUT);
 pinMode(GreenPin,OUTPUT);
 pinMode(BluePin,OUTPUT);
 digitalWrite(RedPin,LOW);
 digitalWrite(GreenPin,LOW);
 digitalWrite(BluePin,LOW);
     
     
     Serial.begin(57600);
     
     Tlc.init(4096/2);
       startXLATCallback();
       Tlc.update();
       
       UCSR0C = UCSR0C | B00100000; // even parity
       UCSR0C = UCSR0C & B11101111;
}

void loop()
{
     if(Serial.available() >= (column*row+2))  Read_data();      
}

// do something every two periods, so ~1024us 4 periods
#define XLAT_PERIODS  4

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();
}








Code: [Select]
void Send_data()
{
     if(Current_Color == 'R')
     {            
           for(int i=0; i < column*row ; i++)
           {
                 Tlc.set(i, Box[i/column][i%column].red*16);
           }
           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*16);
           }
           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*16);
           }
           Turn_off();
           Tlc.update();      
               while(tlc_needXLAT);        
           Turn_on();
           Current_Color = 'R';      
     }
}






acleone

I don't think you can call [font=Courier New]while(tlc_needXLAT);[/font] inside the interrupt callback, because [font=Courier New]tlc_needXLAT[/font] is set zero in the interrupt routine! (interrupts are enabled before calling the callback, so I think you might get a stack overflow because the interrupt routine will never return.)

I'm going to clone the library and add multiplexing, eg Tlc5940Mplex
1.  Tlc.set becomes Tlc.set(multiplex_channel, channel, value)
2.  No more Tlc.update(), because the library will always be updating
3.  You have to put the interrupt code into the sketch

acleone

There was a bug with the ATmega328p, which now should be fixed: see http://code.google.com/p/tlc5940arduino/

The multiplexing library variant should be out soon!

joe912

I was wondering if you needed any help testing the multiplexing library.  

Tobia

Very interesting, so could i potentially control 35 or even 42 servo motors with max/msp? I need to do some more reading but just checking if i'm doing it in the right direction!!

dzinek

#177
Mar 13, 2009, 04:27 am Last Edit: Mar 13, 2009, 04:28 am by dzinek Reason: 1
how do you like it ?

http://www.youtube.com/watch?v=QqP_F2lPgyM&feature=channel_page

thx acleone for library

joe912

how about some details of the build
especially the equalizer effect?

joe912

So my main goal is to build a 16x7 matrix for a coffee table.  so i wrote a program to control it and also made a demo board

So right now im testing my program to control a 4x4 led matrix.

untill i figure out a faster interface method from computer to arduino the most led's i can support at 25 fps is about 125 or so

Heres the pictures of the demoboard
http://img22.imageshack.us/gal.php?g=dsc05280u.jpg

And heres the youtube video of the board and program working
http://www.youtube.com/watch?v=mQxt9vipQH8

Go Up