Daisy chaining from a TLC5947 to a TLC5940

Hi Im working on a project and reading the datasheets i couldnt see any reason why you couldnt use the data out from a tlc5947 and send it to a tlc5940 chip.

This suited my needs and PWM count for the project. Also the 40 chip was cheaper, I couldnt see any reason to waste 8 channels by using a third 5947.

So I wired it all up, Generated a PWM from my arduino pin 5 with a 50% duty cycle wired that to teh PWM in on the 5940... aaaand
Nothing.

While my program is sending a long enough data string of PWM commands, my first 2 TLC5947s do their lighting. The Third chip in the Chain the 5940, doesnt seem to be getting its data.

I had assumed that the second 5947 would bit shift the remainders to the 5940 as if the third ship was another 5947. Have I assumed wrong? Or am i missing something?

Code? Schematic? Please read the forum guidelines in the sticky post.

I wont post the schematic because its a bit messy and might be hard to follow. (by messy i mean there are a ton of jumper wires between different boards)

But schematic wise, its correct. Only difference to some designs is I have Blank floating, however i might changed that down the line.

i have the SOUT from my tlc5947 going into the SIN on the TLC5940, running a PWM signal from the arduino to the GSCLK pin. XLAT SCLK are on the same lat and clk line as the other tlc59 chips.

XERR is floating as well...

Code wise, im using a slightly edited version of adafruits library, but instead of working on the number of 5947 drivers it now works on the PWM channel total...

Mangy_Dog_TLC5947::Mangy_Dog_TLC5947(uint16_t n, uint8_t c, uint8_t d, uint8_t l) {
  numpwm = n;
  _clk = c;
  _dat = d;
  _lat = l;

  //pwmbuffer = (uint16_t *)calloc(2, 24*n);
  pwmbuffer = (uint16_t *)malloc(2 *n);
  memset(pwmbuffer, 0, 2*n);
}

void Mangy_Dog_TLC5947::write(void) {
  digitalWrite(_lat, LOW);
  // 24 channels per TLC5974
  for (int16_t c=numpwm - 1; c >= 0 ; c--) {
    // 12 bits per channel, send MSB first
    for (int8_t b=11; b>=0; b--) {
      digitalWrite(_clk, LOW);
      
      if (pwmbuffer[c] & (1 << b))  
        digitalWrite(_dat, HIGH);
      else
        digitalWrite(_dat, LOW);

      digitalWrite(_clk, HIGH);
    }
  }
  digitalWrite(_clk, LOW);
  
  digitalWrite(_lat, HIGH);  
  digitalWrite(_lat, LOW);
}



void Mangy_Dog_TLC5947::setPWM(uint16_t chan, uint16_t pwm) {
  if (pwm > 4095) pwm = 4095;
  if (chan > numpwm) return;
  pwmbuffer[chan] = pwm;  
}

This is snippet of the library code. As you can see its a simple bitbanged method of sending the data.

Like i said the first two TLC5947s run the leds as they should. But the TLC5940 doesnt.

Mangy_Dog:
I wont post the schematic

Good luck with your project.

well... want to be like that? Heres the schematic. Dont say i didnt warn you...

Update...
I've almost got it working.
If i put my finger across the xlat and blank pin, the leds flash in the correct sequence I'm commanding them to.

So i assumed theres a floating issue. Blank is floating. So i gave it a pull up resistor ive also tried pulling it down. Neither worked. However it flashed in sequence if i touch the resistor. But only flashed at teh length of the duty in the pwm, so it wouldnt flash on and off and on.... Just once. This is obviously the Blank resetting after each pulse.

Ive also tried a pullup on the xlat pin.
So is the daisy chain data compatible... Yes it is. My issue is electrical...

And im not sure what.

Yes, it is a bit of a "dog's breakfast". But at least you are using a proper schematic editor of some kind. Just needs a bit of tlc.

Its just a functional one to be linked in the pcb editor, not for human consumption...

Anyway, further testing.... And like i said if i put my finger across lat and blank pins the leds lit in the correct order... So i tried tying blank to ground.
Didnt work.
Also put blank onto a arduino pin and controlled it... Didnt work...

Ive even swapped the chip out to see if it was just a duff chip.... didnt work :confused:

Ive ran out of options. Im 99.9999% sure its understanding the data being daisy chained to it as the leds did flash in the correct sequince when i touched the blank, xlat pins...
Im not sure what else to try.

You have Blank input floating and wonder the chip behaves as if Blank input were floating? The datasheet says the Blank pin should be grounded to enable outputs...

EDIT: sorry I did not read your last post carefully. Are you SURE the BLANK was connected properly to GND? Check with a DMM if there is low resistance between the pin and GND when you believe they are connected.

interesting update...

i built a simple circuit on the breadboard with it being driven by an Uno...

Firstly i copied how I have my design. And same issue... It wouldnt run properly.

And when it did run the Led would just flash in the order theyre are meant to run at...

I had pullup resistors on all the data lines and blank line too to rule out interference.

I then tried acleone popular library and rewired my board to use his hardware SPI layout...

And it Kinda worked... i ran the knight rider basic test sketch, and the leds did there thing. However, it didnt fully work. As half way through the sequence the leds would randomly flicker. i dont know if this is a bug in the fade code he wrote, I havnt really investigated that.

if i switch it to bitbanged mode on his library config, it doesnt work at all...

I must admit I cant really make much head or tails of his library as much of it seems to be written in HAL.

This might suggest my 5947 library isnt quite compatible with the 5940, maybe the xlat or clk or even blank has to be pulsed in a slightly different order, does anyone know?

I really would like to get this working with the 5940, as im a hairs breath away from bodging in a ttsop 5947 chip into my pcb as a dirty fix :confused:

So, on further reading on other topics it appears the blank pin must be pulsed once every 4096 pulses of the gsclk pin.

So commonly people use the timer to do this. I have tried to setup a timer... But it isn't working. I had assumed when you set a timer, the own frequency changed to this timer?

So I thought running own on pin 9 and the blank pulse pin 10... I'm getting the 10 pulse, I assume every 4096 own pulses... But pin 9 is blank when I check it on the ociliscope. I have analogwrite(9,127) for pin 9.... But nothing.

I've also read that using timers in ctc mode kills the pwm. So how am I meant to pulse blank once every 4096?

I looked again at the datasheet of the TLC5940. It is right it does not contain an internal oscillator as TLC5947 does. What is worse it needs for some strange reason the pulse on Blank pin after 4096 pulses on GSCLK pin. If you want to do this you need to use another counter (internal hardware of Arduino's ATMega) to either count the pulses or better count time and generate pulse when it is needed. Example:
you set Timer/Counter2 to generate pulses with 4MHz frequency (TLC5947 uses this frequncy of PWM) which means every 4 clock cycles of Uno. It means you need to generate pulse on Blank pin every 4*4096~16k cycles. So you set Timer/Counter1 to do so. It is not easy to do so if you know nothing about timers. But learning timers is very rewarding - I think it is the most powerful peripheral of microcontrollers.
Ofc. you may simply get rig of the ancient TLC5940 and use TLC5947 instead.

nods but how do i setup timer1 to pulse every 4096 cycles of the timer? As turning CTC on while does give me a perfectly timed pin10 (blank) pulse, it turns off PWM... How can i get the clock pulse as well? (i guess from pin 9)

	cli();
	//stop interrupts
	TCCR1A = 0;	  // set entire TCCR1A register to 0
	TCCR1B = 0;	  // same for TCCR1B
	TCNT1 = 0;	  //initialize counter value to 0
	
	OCR1A = 4096;    
	// turn on CTC mode
	TCCR1B |= (1 << WGM12);
	
	TCCR1B |=  (1 << CS11) | (1 << CS10); 
	// enable timer compare interrupt
	TIMSK1 |= (1 << OCIE1A);

	sei();
[/code}

You cannot get clock signal from the timer. You need use one timer to generate the GSCLK pulses and another one to generate the blank pulse. For generating the blank pulse you may either use GSCLK pulses as input to the second timer or (maybe easier way) calculate how often blank pulse must be send.

:confused: i cant use a second timer. I need it for SPI :confused:

For SPI? AFAIK SPI does not use (need) a timer. Anyway Arduino has 3 timers. Timer0 is used for millis() and is better to keep untouched. Timer1 and Timer2 are free to use (but it breaks corresponding PWM).

ok if i must use two timers... how would i set it up?

I used a couple of TLC5940's a while ago, and used a 12 stage binary counter to provide a blank pulse.

I'm not 100% sure anymore, but I think I remember this gave me only 11 bit resolution, as it gives a blank pulse and resets every half cycle of Q11, so maybe you need a 13-stage counter to get full 12 bit duty cycle resolution.

I gave up D: Hacking in a third tlc5947 :frowning:

Though thanks jobi will keep this in mind if i use the chips for another thing later down the line... 11bit is perfectly fine for my uses tbh... 8bit would be fine too :stuck_out_tongue:

Take a look at the Sparkfun Library for the TLC5940, it's available on Github.
You can see how they setup the timers there, it's actually pretty easy.

Also, the lack of an internal oscillator is a feature rather than a nuisance: It allows you to multiplex a matrix of LEDs by chaining e.g. a single HC595 with the TLC and then syncing XLAT and Blank to switch planes.

OR you could artificially lower the PWM resolution in exchange for a higher PWM frequency.

These are just two examples, I'm sure people could come up with more...
The 5940 may be a bit more difficult to set up than e.g. the 5947, but you get a lot more versatility in turn.