Library for TLC5940 16-channel PWM chip

yes, that will work inside the interrupt. See avr-libc: <avr/interrupt.h>: Interrupts

so, something like...

void myInterruptFunction(void)
{
    sei();
    delay(debounceDelay);
    //make state changes
}

...would work? I'm still not 100% sure how exactly it's supposed to work.

Or, should I just keep it simple:

void myInterruptFunction(void)
{
    if(lastInterrupt + 10 > millis())
    {
        //make state changes
        lastInterrupt = millis();
    }
    else
    {
        //do nothing
    }
}

Any time you want to use millis(), delay(), or Serial.xxx() inside an interrupt, you have call sei(); first.

This should work, but it might freeze the arduino if the interrupt is called repeatedly because it would keep getting called in the middle of the delay and would never return from the function. You could lock it like so:

volatile char isRunning;
void myInterruptFunction(void)
{
  if (!isRunning) {
    isRunning = 1;
    sei();
    delay(debounceDelay);
    //make state changes
    isRunning = 0;
  }
}

As an aside:

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

#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 :smiley:

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/

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?

joe: you should wait for the PWM cycle to end before you switch transistors, eg

#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 Tlc.update() in SPI mode but way back in August I measured bit-banging to be about ~260us for 1 tlc.

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.

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?

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.

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

I don't think you can call while(tlc_needXLAT); inside the interrupt callback, because tlc_needXLAT 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

There was a bug with the ATmega328p, which now should be fixed: see Google Code Archive - Long-term storage for Google Code Project Hosting.

The multiplexing library variant should be out soon!

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

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!!

how do you like it ?

thx acleone for library

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

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

And heres the youtube video of the board and program working

@joe912: cool stuff! care to share your program/build?

I'm sorry ahead of time if I am doing something stupidly wrong here :slight_smile:

first off,
using a Duemilanove
using version 11 of the tlc library
using the arduino software, v 13
everything connected as shown in BasicUse.pde w/2.2k resistor to pin 20
BasicUse.pde works fine

when i try to connect a servo and use the servo example it doesn't move at all

servo connected as follows
brown - ground
red - +5v
orange - pin 28 (out 0) and a resistor going to +5v
I have tried a 4.7k as well as a 2.2k resistor

maybe I have the resistor codes wrong?
4.7k is yellow / violet / red
2.2k is red / red / red

also a pull-up resistor is just a resistor used in a special way correct?

Thank you for any help

Josh