Problem cascading TLC5917 shift registers using ShiftPWM.

Hello,

I’m working on a project to add aesthetic lighting to a set of stairs.

My brother saw this post and shared it with me, sounded fun, thought I’d give it a go.

My stairs have 13 steps, my brother’s has 15, so I thought I would make my board universal since I’ll be installing for him also.

I’m using Modern Device’s RBBB board, two cascaded TLC5917 constant-current sink drivers, 5v LEDs to sync current for the TIP125 PNP darlingtons which drive the individual LED strips.

The simple sketch below uses ShiftPWM with SPI to fade on all outputs, fade them off, then fades them all on then off sequentially. Basically it is my test/debug program.

The first shift register works as expected, however, it doesn’t appear that the serial data is being received correctly on the second register.

I’ve double checked my soldering. I’ve also popped out the first chip and jumpered pins 2 & 13, then the outputs for the second chip work as expected.

I’ve even tried de-coupling caps for the V+ and latch pins with no success.

At this point I’m wondering if there is an issue with the library, or a configuration I’ve missed for the TLC5917.

Links:
ShiftPWM: http://www.elcojacobs.com/shiftpwm/
TI TLC5917: http://www.ti.com/product/tlc5917
Modern Device RBBB: http://moderndevice.com/product/rbbb-kit/

Code:

#include <SPI.h>

const int ShiftPWM_dataPin=11; // Serial Data Out (SDO/MOSI)
const int ShiftPWM_clockPin=13; // Clock (SC/SCK)
const int ShiftPWM_latchPin=9; // Latch (PWM!) (LE/SS)
const bool ShiftPWM_invertOutputs = false; // if invertOutputs is 1, outputs will be active low. Usefull for common anode RGB led's.
const bool ShiftPWM_balanceLoad = false; // Allows you to distribute the PWM zero crossing moment for each shift register.
// #define SHIFTPWM_NOSPI

#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

const unsigned char maxBrightness = 64;
const unsigned char pwmFrequency = 75;
const int numRegisters = 2; // num bits total in registers / 8

int NUMLEDs = 0;

const unsigned long BRIGHTNESS_SM_PERIOD = 2000; /* in ?s */

void setup()   {                
    pinMode(ShiftPWM_latchPin, OUTPUT);  
    SPI.setBitOrder(LSBFIRST); // Alternate value: MSBFIRST
    // SPI_CLOCK_DIV2 is only a tiny bit faster in sending out the last byte. 
    // SPI transfer and calculations overlap for the other bytes.
    SPI.setClockDivider(SPI_CLOCK_DIV4); 
    SPI.begin(); 
 
    Serial.begin(9600);
    
    /* Turn on pullup resistor for switch */
    for(int i=5; i<=8; i++) {
        pinMode(i, INPUT_PULLUP);
    }
    
    delay(1); // allow inputs to settle
    
    // read dip switches for NUMLEDs
    for(int i=5; i<=8; i++) {
        NUMLEDs = NUMLEDs | (abs(digitalRead(i)-1) << (i-5));
    }
    NUMLEDs++;
    Serial.print("Using ");
    Serial.print(NUMLEDs);
    Serial.println(" outputs.");
    
    ShiftPWM.SetAmountOfRegisters(numRegisters);
    ShiftPWM.Start(pwmFrequency,maxBrightness);  
    // Print information about the interrupt frequency, duration and load on your program
    ShiftPWM.SetAll(0);
    ShiftPWM.PrintInterruptLoad();

}

void loop() {    
    fadeBlinkAll();
    fadeBlinkSeries();
    delay(2500);
}

void fadeBlinkAll() {
    // Fade in all outputs
    unsigned long delayMillies = 2000 / maxBrightness;
    Serial.println("Fading on (all)");
    for(int j=0;j<maxBrightness;j++){
        ShiftPWM.SetAll(j);  
        delay(delayMillies);
    }
    // Fade out all outputs
    Serial.println("Fading off (all)");
    for(int j=maxBrightness;j>=0;j--){
        ShiftPWM.SetAll(j);  
        delay(delayMillies);
    }
}

void fadeBlinkSeries() {
    // Fade in all outputs
    unsigned long delayMillies = 1000 / maxBrightness;
    Serial.println("Fading (series)");
    for(int i=0; i<NUMLEDs; i++) {
        for(int j=0;j<maxBrightness;j++){
            ShiftPWM.SetOne(i, j);  
            delay(delayMillies);
        }
        for(int j=maxBrightness;j>=0;j--){
            ShiftPWM.SetOne(i, j);  
            delay(delayMillies);
        }
    }
}

And a picture to help visualize, shown during the fadeBlinkAll() function.

Any help would be greatly appreciated!
Thanks,
Burton

burtoncarl:
I've also popped out the first chip and jumpered pins 2 & 13, then the outputs for the second chip work as expected.

Did you mean to say "jumpered pin 14 (MOSI) of the socket to pin 9 (QH*) of the socket"?

No, I jumped pins 2 & 14 (SDI & SDO) on the first register, just to verify that the circuit of the second IC was operational. Which it was, even though it was then operating as the first register.

This led me to believe that there was an issue with the second register receiving its serial data.

burtoncarl:
No, I jumped pins 2 & 14 (SDI & SDO) on the first register, just to verify that the circuit of the second IC was operational. Which it was, even though it was then operating as the first register.

Oops. My mistake. I was looking at the schematic for the project you pointed to which uses 74595 shift registers. I think the way you had it was right. Have you tried swapping the two registers to make sure both act the same in either location? If so it sounds like the second socket isn't getting one of the signals: MOSI, CLK, or SS.

I have tried swapping the registers, same results.

I thought about the clock and latch, which is why I tried jumping out the first register. So I think those are good.

Which is why I’m leaning towards thinking it’s the SDI on the second register. What I can’t figure is if I’m not initializing the registers correctly, or if perhaps the current version ShiftPWM isn’t sending the serial data correctly.

Yes, everything looks good.

The LE(ED1) and OE(ED2) pins on both registers should share the same net and the SDO of one should feed to the SDI of the other. You can check the SDI with an oscilloscope and you can also try touching a ground wire to the LE(ED1) and OE(ED2) pins.