Go Down

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

nphillips

Okay...I finally had a chance to play around with this today, and I'm getting a whole lot of nothing....

Are the only pins that need anything connected to them the ones listed in _pins.h? (not including VCC and GND, and whatever output pins that are in use) I'm connected to the +5V rail, though I've seen elsewhere that you should use 3.3V. If I read the spec sheet correctly, this really only effects the output amperage.

Also, on the Playground page, you (or whoever wrote it) said to tie DCPRG high, and to use a pull-up resistor on BLANK (I have a 1K resistor going to +5V; correct?). The only other pin I don't have anything documented is VPRG. THe Playground implies that it's used for something, but I don't see where/how. In the init() function, it's assigned -1 (which also mentions dot-correction, but I have no idea what purpose it serves).

So, all of that to say...what am I missing?  :-[

acleone

#16
Sep 01, 2008, 10:49 pm Last Edit: Sep 01, 2008, 11:05 pm by acleone Reason: 1
Using the v003 library from a few days ago (without changing the pins) the pin config is

  • TLC pin 28 -> LED (channel 1) short leg (cathode) -> LED1 long leg (anode) -> +5V
  • TLC pin 1 -> LED (channel 2)  cathode - anode -> +5V
  • ...
  • TLC pin 15 (lower right pin if the u is on top) - > LED (channel 16)
  • TLC pin 16 (XERR) -> nothing
  • TLC pin 17 (SOUT) -> nothing
  • TLC pin 18 (GSCLK) -> Arduino pin 3
  • TLC pin 19 (DCPRG) -> +5V
  • TLC pin 20 (IREF) - > 2.2Kohm resistor to GND (this determines max current through each output, Riref value = 39.06 / (desired current in A))
  • TLC pin 21 -> +5V
  • TLC pin 22 -> GND
  • TLC pin 23 (BLANK) -> Arduino pin 10
  • TLC pin 24 (XLAT) -> Arduino pin 9
  • TLC pin 25 (SCLK) -> Arduino pin 6
  • TLC pin 26 (SIN) -> Arduino pin 4
  • TLC pin 27 (VPRG) -> GND


Make sure you have a resistor (see above) between Iref (pin 20) and ground, and also that VPRG (pin 27) is grounded.  Hope this helps!  I'll put this at the top of all the examples.

nphillips

Bingo! Thanks, AC! I now have a glowing LED :D

Syvwlch

----------
Mathieu

nphillips

Okay...I should have posted this last night, while I had my code in front of me...but I didn't.

I'm trying to get my LEDs to pseudo-randomly fade (intensity, length of fade, and delay until fade). After 2-3 loops, it's as if the timer breaks down. Rather than a series of slow, (sort of) subtle changes, it's a horrendous seizure-inducing strobe effect.

I added some serial output to see the values getting passed, and the values are all a-ok, and the time between loops (checking millis() at the beginning of each) is appropriately spaced. Yet, everything is running at super-speed.

I originally had 6 LEDs running this, but I dropped down to one, just to see what was going on.

my code (as best as I can remember it), without the serial output.
Code: [Select]

void setup()
{
   Tlc.init();
   Tlc.resetTimers();
}
void loop()
{
   aLast = a; //our previous intensity
   a = random(0, 4095); //grab our new intensity

   fadeDuration = random(500, 1500); //duration of fade between .5 and 1.5 seconds
   fadeDelay = random(5000, 15000); //delay before fading between 5 and 15 seconds

   Tlc.newFade(3, fadeDuration, aLast, a, fadeDelay);
   while(Tlc.updateFades());
}


So, with that, I get about 2-3 "appropriately" timed fades, before it clicks into strobe mode. I should note, too, that the "strobe mode" appears to be following the code correctly, except that it's almost as if the changes are occurring at 1/100th of the time (i.e. 15000ms becomes 150ms). It's a high-intensity red LED, so I can't stand to look at it for very long, even from the side, especially when it's flickering.

acleone

#20
Sep 02, 2008, 11:10 pm Last Edit: Sep 02, 2008, 11:32 pm by acleone Reason: 1
[size=12]Updates: TLC5940LEDv004.zip[/size]

For people who want to use the TLC5940 to drive motors, use the old library from the first post for now.  The PWM period for the TLC5940LED library is fixed at 488Hz, which might be too fast for driving a DC motor.

Just as a note, the TLC should act as GND for whatever you're using with it (voltage should flow from +5V, through whatever, and into the TLC pin).  If you want to use RGB LEDs, make sure the LED is common anode (meaning each color shares the same +5V pin)

nphillips:
Code: [Select]
(unsigned long)      fadeDelay = millis() + random(5000, 15000);
The last parameter of Tlc.newFade is the start time in millis.  v004 has proper commenting in the examples (sorry)!

Also, if you need to run more than 5 fades at once (if you call newFade more than 5 times before while(Tlc.updateFades());), you need to add more parameters to Tlc.init.  For say 10 fades at once, use Tlc.init(1 tlc, 10 fades).  Tlc.newFade(...) will return false if you have too many fades running at once.

nphillips

Quote
nphillips:
Code: [Select]
(unsigned long)      fadeDelay = millis() + random(5000, 15000);
The last parameter of Tlc.newFade is the start time in millis.  v004 has proper commenting in the examples (sorry)!
Ah hah! I suppose if I paid closer attention to your example, too, it would have been obvious. (testfades002 is what I used to help construct my code)

Quote
Also, if you need to run more than 5 fades at once (if you call newFade more than 5 times before while(Tlc.updateFades());), you need to add more parameters to Tlc.init.  For say 10 fades at once, use Tlc.init(1 tlc, 10 fades).  Tlc.newFade(...) will return false if you have too many fades running at once.
Is there an upper bound to this? Rather, will it break if I try to have it run a boat-load of fades? (I may end up looking at 32+ LEDs for one project....)

acleone

Quote
Is there an upper bound to this? Rather, will it break if I try to have it run a boat-load of fades? (I may end up looking at 32+ LEDs for one project....)

Each fade takes up 12 bytes of the 1024 byte SRAM.  I don't know how much SRAM is used normally, but I'm guessing you could have like 64 fades (768 bytes) at once.  Just keep trying higher values until something breaks!

But that's only running at once; if some finish and you want to start more, you could do something like
Code: [Select]

// create a bunch of fades
Tlc.newFade(...);
Tlc.newFade(...);
Tlc.newFade(...);
...
while (Tlc.updateFades()) {
 if(Tlc.newFade(...)) {
   // added successfully!
 } else {
   // too many fades right now
 }
}


nphillips

That worked perfectly, acleone!

Once again, thanks for the amazing library, and quick, helpful responses!

Now, I just need to buy more LEDs...  :o

Syvwlch

Quote

For people who want to use the TLC5940 to drive motors, use the old library from the first post for now.  The PWM period for the TLC5940LED library is fixed at 488Hz, which might be too fast for driving a DC motor.


As far as those 3V/80mA Sparkfun vibration motors are concerned, they seem to run fine at 500Hz, ramping up and down smoothly, based on prior experience. Alas, I won't be able to confirm with the TLC5940 for at least two weeks (vacation).

Quote

Just as a note, the TLC should act as GND for whatever you're using with it (voltage should flow from +5V, through whatever, and into the TLC pin).  


Thanks for the pointer. Turns out that's how I had it wired in the old setup (PWM pins on the low side) but now I'll make sure to carry it over to the TLC5940 setup.
----------
Mathieu

nphillips

#25
Sep 03, 2008, 06:53 pm Last Edit: Sep 03, 2008, 07:37 pm by nphillips Reason: 1
Yet another question, acleone :D

Is there a way to get the immediate grayscale value of a particular channel?

In your last response, you had mentioned running additional newFade() functions inside the updateFades() while loop. I'd like to experiment with "interactions" between LEDs during the fading process and being able to grab the current value of an LED would be perfect.

Minor Example:
Code: [Select]

while(updateFades())
{
   if(getGreyscaleValue(3) > 2048)
   {
       newFade(4, 1000, 1024, 4095);
   }
}


I'll admit, I haven't delved too deeply into the code, so there may be something available I could use, without the need of anything additional. (/me goes off to skim the code as best he can)

EDIT:
Line 243 of TLC5940LED.cpp:
Code: [Select]

Tlc.set(fp->channel, fp->endValue - ((((int32_t)(fp->stopMillis - currentMillis)) * fp->dValue) / fp->duration));

That looks like it has what I'd need. Unfortunately, I don't know enough c++ to figure out whether or not I could pull that information from within the sketch itself, or if I would need to write a function for it.

I'm not 100% sure how to use structs, but it does appear that you're incrementing it, as if it's an array of data. If that's the case, it should be pretty easy to build a simple array of integers containing the current values of all active LEDs. Though, for larger numbers of LEDs, this would get fairly memory-intensive.

EDIT 2:
Would something like this work:
Code: [Select]

int TLC5940LED::getGreyscaleValue(uint8_t channel)
{
     struct fade *fp = channel;
     return (fp->endValue - ((((int32_t)(fp->stopMillis - currentMillis)) * fp->dValue) / fp->duration));
}

Again, I'm operating at Ignorance Level 10 (of 10). And I know I'm missing error-checking.

acleone

Major points for delving into my horrible code!  You're kind of close; all the current LED states are stored in the [font=Courier]_GSData[/font] array.  The problem is the array packs all the data together to save space.

I don't have my Arduino at the moment, but try this version.  I added [font=Courier]Tlc.get(channel(1-16));[/font], eg
Code: [Select]
int value = Tlc.get(1);

nphillips

Awesome. I don't have my Ardy around either...but I'll certainly give it a whirl tonight!

And, your code isn't horrible, by any means. I once had to debug an entire patchwork content manager written by a 16 year old from the Ukraine. Now, I'm not making fun of the Ukranian Language...but the kid used nothing more than 2-character variable/function/class names, and had maybe 6 comments for 2000+ lines of code. Maybe it made sense in his native tongue, but it didn't make a lick of sense to me. THAT was deserving of points for delving into horrible code!  ;D

nphillips

Hmm...finally got around to trying out the Tlc.get() function, but it doesn't compile.

the line of code with the error:
Code: [Select]
j = Tlc.get(ledPins[5]);

the error returned:
Code: [Select]
o: In function `loop':
undefined reference to `TLC5940LED::get(unsigned char)'

mikalhart

That usually means that your library's .o file is not available in the expected place.  See by comparison the EEPROM library, which is in hardware/libraries/EEPROM/EEPROM.o.

Mikal

Go Up