Creating animations with the tlc5940 arduino library

i have a 2x2 matrix of rgb leds, and i plan to make a much larger one with 338 rgb leds. Right now i have an animation of a red light going around the square and a green light going the opposite way on while all the unused lights are blue. The problem is that it takes a lot of lines to program. I have to do a Tlc.set(pin, brightness); for each color. I have seen most people just write hex code or binary in place of all that. How do i do that? The other issue, which is a bit more important, is that the colors are mixing. When i switch the anodes, the cathodes dont switch as fast. No matter what the delay is set to, the cathodes switch after the anodes. So the colors that dont share anodes are mixing.

/*
  Tlc.set(0, 255 * b);  //TOP RED
  Tlc.set(1, 255 * b);  //TOP GREEN
  Tlc.set(2, 255 * b);  //TOP BLUE
  Tlc.set(3, 255 * b);  //BOTTOM RED
  Tlc.set(4, 255 * b);  //BOTTOM GREEN
  Tlc.set(5, 255 * b);  //BOTTOM BLUE
 */

#include <Tlc5940.h>
int b = 16;
int d = 2;
int dm = 100;
int i;

void setup() 
{
  Serial.begin(9600);
  Tlc.init();
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
}

void loop() 
{  
  for(i = 0; i < 35; i++) //frame 1
    {
    Tlc.clear();            //left
    Tlc.set(0, 255 * b);
    Tlc.set(4, 255 * b);
    Tlc.update();
    digitalWrite(7, 1);
    delay(d);
    digitalWrite(7, 0);
    delayMicroseconds(dm);
    Tlc.clear();            //right
    Tlc.set(2, 255 * b);
    Tlc.set(5, 255 * b);
    Tlc.update();
    digitalWrite(6, 1);
    delay(d);
    digitalWrite(6, 0);
    }
  for(i = 0; i < 35; i++) //frame 2
    {
    Tlc.clear();            //left
    Tlc.set(2, 255 * b);
    Tlc.set(5, 255 * b);
    Tlc.update();
    digitalWrite(7, 1);
    delay(d);
    digitalWrite(7, 0);
    delayMicroseconds(dm);
    Tlc.clear();           //right
    Tlc.set(0, 255 * b);
    Tlc.set(4, 255 * b);
    Tlc.update();
    digitalWrite(6, 1);
    delay(d);
    digitalWrite(6, 0);
    } 
  for(i = 0; i < 35; i++) //frame 3
    {
    Tlc.clear();            //left
    Tlc.set(2, 255 * b);
    Tlc.set(5, 255 * b);
    Tlc.update();
    digitalWrite(7, 1);
    delay(d);
    digitalWrite(7, 0);
    delayMicroseconds(dm);
    Tlc.clear();            //right
    Tlc.set(3, 255 * b);
    Tlc.set(1, 255 * b);
    Tlc.update();
    digitalWrite(6, 1);
    delay(d);
    digitalWrite(6, 0);
    }
  for(i = 0; i < 35; i++) //frame 4
    {
    Tlc.clear();            //left
    Tlc.set(3, 255 * b);
    Tlc.set(1, 255 * b);
    Tlc.update();
    digitalWrite(7, 1);
    delay(d);
    digitalWrite(7, 0);
    delayMicroseconds(dm);
    Tlc.clear();            //right
    Tlc.set(2, 255 * b);
    Tlc.set(5, 255 * b);
    Tlc.update();
    digitalWrite(6, 1);
    delay(d);
    digitalWrite(6, 0);
    } 
}

Does nobody want to share what they know or is this just a dumb question not worth answering?

somebody help me! This is so unbelievably frustrating. This is weeks of my time i have spent putting this together and i have no hope at all. EVERYTHING I DO IS A FAILURE. i think im just going to end the project if i cant get help. You people have shown me that new members of the community arnt welcome.

I think it would help a lot if you asked better questions. You seem to have two here that are a bit mixed up.

There are two ways of making patterns on a display:-

  1. One is by writing lines of code that generate the patterns. This can take a lot of lines but these can be drastically reduced by using good code techniques like for loops. For example in what you posted you can use a for loop outside the frame's loop to generate all the frames. It will help a lot if you break your code down into functions, it makes it easier to handle.

  2. Is by having an array or an array of arrays ( multidimensional arrays ) that define the patterns, then the code just shifts the appropriate array or part of array into the display buffer. Using arrays like is is outlined in these two links here:-
    Arrays

http://www.thebox.myzen.co.uk/Workshop/LED_Matrix.html

The next question is a bit more vague. You need to post the schematic along with your code so we can see what you are doing wrong. For example what is this all about?

   digitalWrite(7, 1);
    delay(d);
    digitalWrite(7, 0);

You can not multiplex a TLC5940 like this, it will not work, I think you have been told that before. If you want to multiplex this chip then you need a driver that will do this. This involves having two or more buffers, the driver software will then load in a different buffer at the end of each PWM cycle. So for example for 4:1 multiplexing you have four buffers, one for each phase of the multiplexing. The TlC.set function has to be changed as well so that it writes in the correct buffer. Again I have pointed you at code that does this.

I think you are trying to do things that are too complex for your current skill level. While an Arduino can produce great results the simplicity of the system can lull you into the sense that things are always as easy as they might at first appear. Pushing what libraries will do requires you to understand what they are doing and how to modify them to do what you want.

So the only time i can switch anodes is during the XLAT pulse? Then i would need to use the volatile,
uint8_t tlc_needXLAT; from the library to tell it when to write the pin high or low. i know digitalWrite is slow, so a port command should be fast enough. Why would i need a buffer to do this? Also, how do i open the librarys code in the IDE. i could only get it to open with notepad so the spaces are all messed up so it's hard to read.

So the only time i can switch anodes is during the XLAT pulse?

Yes or just after it.

Then i would need to use the volatile, uint8_t tlc_needXLAT; from the library to tell it when to write the pin high or low

No I am sure that would not work because you would have to be looking constantly at the variable to catch it changing, that is just not feasible. It has to be part of the code that pulses and then selects what data to shift in next, that is what buffer.

Why would i need a buffer to do this?

When you multiplex say two things you need two buffers one for each of the multiplexed stages, so that you can control the LEDs in each of the two phases of multiplexing.
Did you read my code here:-
http://www.thebox.myzen.co.uk/Hardware/Mini_Monome.html
That does what you are asking but the wiring will be different to the wiring required by another library. That gives you a 4 by 4 matrix of RGB LEDs with 4 channels left over not used, you could add another column if you like.

i could only get it to open with notepad so the spaces are all messed up so it's hard to read.

Sorry I do not play with windoze stuff but I am sure there is a text editor somewhere on the machine, if not do a search for a text editor. Alternatively make a copy of the .cpp and .h files inside the folder of any application and they will appear as tabs when you open the sketch. At least you can look at them and edit them from there. However I don't think you can run them, you would have to move them back into the library folder for that.

Grumpy_Mike:
No I am sure that would not work because you would have to be looking constantly at the variable to catch it changing, that is just not feasible.

I found a modification of this library made to make multiplexing easy. It looks like that's exactly how they did it, only disabling the XLAT durring the shift for some reason.

before the setup in the example is this:

volatile uint8_t isShifting;
uint8_t shiftRow;

ISR(TIMER1_OVF_vect)
{
  if (!isShifting) {
    disable_XLAT_pulses();
    isShifting = 1;
    sei();
    TlcMux_shiftRow(shiftRow);
    PORTC = shiftRow++;
    if (shiftRow == NUM_ROWS) {
      shiftRow = 0;
    }
    enable_XLAT_pulses();
    isShifting = 0;
  }
}

Here is the whole example

/*
    Analog 0-2 (PORTC) is hooked to a 3:8 line decoder (74LS138) which pull the
    Base of a PNP darlington (MPSA63) low through a 10k resistor for each row.
    +5V is connected to the Emitter of the PNP's, and all the anodes (+) of the
    leds for each row are connected to the Collector.
    
    Currently I'm trying to fix timing issues by putting some D-type positive
    edge triggered latches between PORTC and the 3:8 line decoder, clocked on
    the rising edge of XLAT, but this doesn't seem to help.  I'm bringing the
    circuit in to the logic analyzer this weekend to see exactly when the ISR
    runs and how long it takes to shift in the GS data.
    
    Alex Leone, 2009-04-30
*/

#define  NUM_TLCS  3           //define the number of chips
#define  NUM_ROWS  8            //define the number of rows
#include "Tlc5940Mux.h"         //include the library

volatile uint8_t isShifting;    //look for when it's time to shift rows
uint8_t shiftRow;               //shift to this row

ISR(TIMER1_OVF_vect)            //timer to determin when to switch rows
{
  if (!isShifting) {            //if isShifting is 0
    disable_XLAT_pulses();      //disable xlat
    isShifting = 1;             //make isShifting 1
    sei();                      //?
    TlcMux_shiftRow(shiftRow);  //shift a number of times
    PORTC = shiftRow++;         //use port c to change rows
    if (shiftRow == NUM_ROWS) { //reset to 0 after the end of the rows
      shiftRow = 0;
    }
    enable_XLAT_pulses();       //turn xlat back on
    isShifting = 0;             //make isShifting 0. so this loops?
  }
}

void setup()                                        //setup
{
  DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC2);           //bitwise OR, to leave everything high until timer starts?
  TlcMux_init();                                    //start timers
}

uint8_t color;                                      //give a variable for color, probably based on the remainder after deviding the pin number by 3 for rgb leds
void loop()                                         //loop
{
  TlcMux_clear();                                   //clear values
  for (uint8_t col = 0; col < 11; col++) {          //cycle through colums
    for (uint8_t row = 0; row < NUM_ROWS; row++) {  //cycle through rows while on a colum
      TlcMux_set(row, col + color * 16, 4095);      //set color of a row to colum number plus color * 16 to full brightness
    }
    color++;                    //go to the next color
    if (color == 3) {           //after the last color, reset it
      color = 0;
    }
  }
  delay(2000);                  //wait 2 seconds

First multi line comment is from the creator, the rest are my comments describing what i understand. Whats all that uint8_t stuff? is a normal int not good enough?

A normal int is two bytes long, where as that is only one byte, so you save memory.