Driving 64 Leds with TLC5926

I am working on driving a ring of 64 LEDs off of four TLC5926 drivers all powered by the arduino. Eventually I’ll incorporate an encoder to allow midi control with LED feedback. I am looking for help with where to start. I built that hardware last year and can’t find any of the sketches I made. I want to start by simply lighting all of the LEDs at the same time. How would I go about addressing them individually? Thanks!

First you need to document how your hardware (that you’ve already built is wired ),and read the datasheet for the TLC 5926. It’s basically a shift register, so I’d hook it to the hardware SPI pins on the arduino. Look for tutorials and libraries that deal with shift registers.

I wouldn’t power 64 LEDs off the Arduino…

I don’t think you CAN power 64 LEDs off an Arduino…not without burning something up anyway.

Thanks for the replys :mrgreen: So my setup in 4 [TLC5926 chained with SDout → SDin on the next chip.

LE (latch) is connected to D10

CLK (clock) is connected to D13

SDI (serial data in 1st chip) to D11.

These 3 pins are connected in parallel on all 4 chips. The OE (output enable) are all tied low to ground and I have decoupling caps on all V+ near the chips.

I am trying to adapt the following code to shift 16 bit signals through all 64 LEDs and have each led light up individually so it essentially moves around the circular arrangement ive made.

// SPI commands will be used to send the data out


#include <SPI.h> // bring in SPI library

#define SS  10 // output latch for cathodes shift register.  Pin D10 needs to be an output for SPI.

byte dataArray[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};  // load up some initial data
// dataArray[0] = B00000001
// dataArray[1] = B00000010
// dataArray[2] = B00000100
// dataArray[3] = B00001000
// dataArray[4] = B00010000
// dataArray[5] = B00100000
// dataArray[6] = B01000000
// dataArray[7] = B10000000


int x=0;



void setup()
  {

    pinMode (SS, OUTPUT);

    SPI.begin();  // commits 11,12,13 for hardware SPI transfer. Make sure shift registers have 0.1uF/100nF on their VCC pins to ground.
    SPI.setBitOrder(LSBFIRST);
    SPI.setClockDivider(SPI_CLOCK_DIV8);
    SPI.setDataMode(SPI_MODE1);



  }

void loop()
{

  // turn off leds
  digitalWrite (SS, LOW);
  SPI.transfer(0); 
  digitalWrite (SS, HIGH);
  delay(1000);


  for(x=0;x<7;x++)
   {
     // turn on one led, all others off for apox. half a second
     digitalWrite (SS, LOW);
     SPI.transfer(dataArray[x]); 
     digitalWrite (SS, HIGH);
     delay(500);
   
   }

} // end void loop

Im having difficulty understanding how to modify the array for 16 and to utilize the “overflow” principle to shift through the daisy chain. My goal is to first get a single LED moving around the circle, then attach and encoder and having it control the lite LED position on the circle. Thanks!](http://www.ti.com/lit/gpn/tlc5926)

is your code currently doing what you think it should?

well this sketch was a direct copy and paste from another tutorial for chaing together 4 8 bit shift registers (I think it was 4 74HC595). It does scroll through 8 of the 16 leds on each driver innitiall but the goes crazy and randomly lights up leds in no discernable pattern. I’d Like to know how to address a 16 bit shift register. Would the data array looks like this:

// dataArray[0] = B0000000000000001

// dataArray[1] = B0000000000000010

// dataArray[2] = B0000000000000100

// dataArray[3] = B0000000000001000

// dataArray[4] = B0000000000010000

// dataArray[5] = B0000000000100000

// dataArray[6] = B0000000001000000

// dataArray[7] = B0000000010000000

// dataArray[8] = B0000000100000000

// dataArray[9] = B0000001000000000

// dataArray[10] = B0000010000000000

// dataArray[11] = B0000100000000000

// dataArray[12] = B0001000000000000

// dataArray[13] = B0010000000000000

// dataArray[14] = B0100000000000000

// dataArray[15] = B1000000000000000

So how would i go about sending a this through the latch–>shift—>latch portion of the sketch?

teamskenes:
So my setup in 4 [TLC5926 chained with SDout → SDin on the next chip.

LE (latch) is connected to D10

CLK (clock) is connected to D13

SDI (serial data in 1st chip) to D11.

These 3 pins are connected in parallel on all 4 chips. The OE (output enable) are all tied low to ground and I have decoupling caps on all V+ near the chips. [/quote]

Shirley :wink: you meant to say “These 2 pins (LE, CLK) are connected in parallel on all 4 chips” since you have SDout(n) tied to SDin(n+1). With that clarified I wonder if you aren’t getting into one of the other special modes of the driver by holding OE low all the time ? That pin along with LE serve to switch btw modes. Perhaps you could tie it to another DIO pin and start with the recommended timing diagram for normal mode. See if that works w/o any weirdness and then take it from there.

You haven’t mentioned what’s supplying power to all the drivers and LEDs. Could you be having “brown-outs” ?](http://www.ti.com/lit/gpn/tlc5926)

One of the advantages of shift registers is that by chaining them together, you can treat it all as one giant register. I recommend keeping your data array as eight bytes, as the arduino is an 8-bit processor and it will be easier on it.

Another thing to note is that this is not actually SPI protocol, just similar. You don’t need to toggle the latch like an SPI slave select pin. Try just dropping it low once you’ve fully updated the register. I don’t have your hardware set up, but see if something like this does anything:

// SPI commands will be used to send the data out
// Changed dataArray[] initialization and loop()

#include <SPI.h> // bring in SPI library

#define SS  10 // output latch for cathodes shift register.  Pin D10 needs to be an output for SPI.

byte dataArray[]= {1, 1, 1, 1, 1, 1, 1, 1};  // load up some initial data

int x=0;

void setup()
  {

    pinMode (SS, OUTPUT);

    SPI.begin();  // commits 11,12,13 for hardware SPI transfer. Make sure shift registers have 0.1uF/100nF on their VCC pins to ground.
    SPI.setBitOrder(LSBFIRST);
    SPI.setClockDivider(SPI_CLOCK_DIV8);
    SPI.setDataMode(SPI_MODE1);

    digitalWrite(SS, LOW);

  }

void loop()
{

  // send contents of dataArray to LEDs
  for(x=0;x<7;x++)
   {
     //send one byte
     SPI.transfer(dataArray[x]); 
     
	 //move lit LED over by one
	 dataArray[x] <<= 1;
   }

   // latch data to outputs
   digitalWrite (SS, HIGH);
   digitalWrite (SS, LOW);
   
   // wait a second
   delay(1000);

} // end void loop

You should see eight evenly spaced lit LEDs, moving over by one, and turning off after eight moves.

If all you’re ever going to do is display a single LED, or even a contiguous range (i.e. light only LEDs 5-21), it might be advantageous to simply bit-bang it:

//Not a complete sketch, tweak to suit

#define CLK  13
#define MOSI 11 
 
void loop()
{
	static byte position = 0;	//the LED to light
	
	digitalWrite(SS, LOW);
	digitalWrite(CLK, LOW);
	digitalWrite(MOSI, LOW);
	
	for(byte i = 0; i < 64; i++)
	{
		//test whether to light this LED
		if(position == i)
		{	digitalWrite(MOSI, HIGH); }
		else
		{	digitalWrite(MOSI, LOW); }
		
		//raise clock, TI chip will read data
		digitalWrite(CLK, HIGH);
		
		//increment LED position and clip to display size
		position = position++ & 63;
		
		digitalWrite(CLK, LOW);
	}
	
        // Latch to outputs
	digitalWrite(SS, HIGH);
	digitalWrite(SS, LOW);
	
}

I’m kind of tired so I’m probably missing some things. Let me know if any of this helps, and specific, precise results if it almost works.

teamskenes:
My goal is to first get a single LED moving around the circle, then attach and encoder and having it control the lite LED position on the circle. Thanks!

The easy way to get 1 LED to walk around the ring is to load 64 zeros (I believe a logic 0 gets you an off LED) by putting a 0 on the SDin pin and clocking 64x followed by a high LE pulse. Then make SDin a one and send 1 clock followed by 1 LE high pulse. That should turn on the 1’st LED. There after (for the next 63 clocks) all you should do is leave SDin at a low, send 1 clock followed by one LE high pulse. Each time this is done the logic one you clocked in will be sent from register to register and latched in with LE, moving the LED that’s on from position to position. I’ll follow your thinking and leave the OE low all the time (I think that should work but …).

However you will need a slightly different approach if you plan to use your encoder to move the LED both forward and backward amongst the 64 positions. Going from position 20 to position 42 is easy enough, just clock 22x and then do an LE pulse (SDin low all the time). Going from 42 to 20 will require you to clock out the existing “on bit” (do 22 or 23 clocks) and then clock in another “on bit” (SDin = high), followed by 19x more clocks (w/ SDin = low) and then an LE pulse. Alternately you could pause for some small time between each clock and pulse the LE so the LED is seen to move from position to position instead of just showing up at the new position.

BTW using SPI means you’ll be clocking 8 bits at a time, which isn’t compatible with the above. It also means the given your use of the SS function to drive the LE pin, you’ll always be moving the “on bits” 8 positions and then making them appear (assuming you leave OE enabled). I think you’re going to want your own routines to control the clock and LE (and perhaps the OE) pins.

Ok First off awesome info form both of you!

@Mee_n_Mac I’m following your logic with the single LED and clocking it around. Ill work on translating that to code. I guess my ultimate goal is to be able to address the LEDs by reading MIDI data coming into the arduino in serial format (reading CC from a virtual encoder for example). And yes I meant to say LE,CLK are paralleld, not SDI…

@sethcim

Looks like first sketch is doing what its supposed too! although I have a delay on the last TLC in the chain as you can see at the end of the loop… http://smg.photobucket.com/albums/v149/ … BFA86F.mp4

Ill check out the bit banging…Thanks dudes!

Pics … or it didn’t happen ! :twisted: :stuck_out_tongue:

The delay on the last chip should be an off-by-one error. We should have said:

for(x=0;x<8;x++)

If you remote the line with <<= you will have working code that can write arbitrary data to your display, and some good ideas on how to streamline it if you don’t need that much flexibility.

I went a little light on explanation, because I wasn’t sure it would work. Does it make sense what’s going on?

Ok so this how I am understanding this sketch: the 4 TLC are basically being treated as 1 shift register divided into 8 divisions of 8 LEDs (so 2 per TLC). When u start the sketch with data array [1,1,1,1,1,1,1,1] you are telling all of the 8 sections to light the LED in the least significant position. As the clocking/shifting happens on a 1 second delay loop, the byte is just being shifted over by 1 across all chips?? IF this is true, what would be the next step to take say serial data from and encoder and translates it output to lighting all LEDS at max encoder value and 0 at minimum encoder values. Also could the OE for each chip be “pulsed” quickly so the LEDs aren’t all lit at the same time (obviously they all appear on to the human eye). This would allow conformity to the 500ma max current from USB power supply.