shiftOut() function not working in setup() - TLC5955

Hello Everyone!

I am trying to control a TLC5955 LED driver with an Arduino Uno. The TLC5955 contains a 769 bit shift register which can be used to control the driver. I have studied the datasheet and determined the correct bit values for my project to load into the TLC 5955 register but since the Dot Correction values, Brightness Control values are 7 bits long and some other values are 3 bits long, I am unable to send each value over using the shiftOut() function (as it transfers values in a byte format). I ended up writing a program to concatenate the different values to output 6 "64 bit long integers" so that it can be shifted into the register. I then implemented a simple "for loop" to bitshift each byte of the 64 bit integer into an 8 bit integer variable which is then transferred using the shiftOut() function. This was initially implemented in the main loop of the code for testing purposes.

This seemed to work as verified by an oscilloscope. However, for the TLC5955, I initially need to send out 769 bits to set up the driver and then repeatedly send out PWM values for each of the LEDs. However, when I copy the piece of code, mentioned above, to the setup() function, the shiftOut() function no longer works. I assumed this function cannot run in the setup() section so then I tried implementing the function in the main loop with an if statement which will only allow the "setup data" to be transferred once (please see code below). This also failed to work and I'm not sure why its only failing for this particular case.

The code shown below is a simplified version of the main project code to isolate and test the shiftOut() function. The code, as shown below, is set up to send out an arbitrary 64 bit integer once in the main loop and then do nothing.

#define CLK 13
#define D 11
#define B 8
#define CLOCKOUT 9

bool set = false;
uint8_t out = 0; //final output variable
uint64_t preout = 0; //64 bit integer to hold control values

void setup() {
  
  pinMode(D,OUTPUT);
  pinMode(CLK,OUTPUT);
  
}

void loop() {
  
  if(set==false){
    preout = 0b1111110111111111111111111111111111111111111111111010111111111111;
    for(int i=7;i>=0;i--){
      out = preout >> i*B;
      shiftOut(D,CLK,MSBFIRST, out);
    }
  set = true;
  }
//do nothing
}

My Questions are as follows:

  1. Can the shiftOut() function be called in the setup() portion of an Arduino code?
  2. Why is the function failing only when configured to run once?

I'm fairly new to Arduino programming and any help would be greatly appreciated.

  1. Yes. You can call shiftOut() in setup().

  2. I added some code to display the output in hex on Serial Monitor and it displays exactly what I would expect. What makes you think it isn't working?

Did you maybe mean to use CLOCKOUT (9) instead of CLK (13)?

#define CLK 13
#define D 11
#define B 8
#define CLOCKOUT 9

bool set = false;
uint8_t out = 0; //final output variable
uint64_t preout = 0; //64 bit integer to hold control values

void setup()
{
  Serial.begin(115200);
  delay(200);
  Serial.println();

  pinMode(D, OUTPUT);
  pinMode(CLK, OUTPUT);
}

void loop()
{
  if (set == false)
  {
    preout = 0b1111110111111111111111111111111111111111111111111010111111111111;
    for (int i = 7; i >= 0; i--)
    {
      out = preout >> i * B;
      if (out < 0x10)
        Serial.print('0');
      Serial.print(out, HEX);
      shiftOut(D, CLK, MSBFIRST, out);
    }
    set = true;
  }
  //do nothing
}

Hello John,

Thank you for your response. The CLOCKOUT(9) is an unused part of the code leftover from the main project code.

I also had debugged this using serial and it seemed to work but whenever I probe the data lines with an oscilloscope, I don't see any data coming through during the setup portion. As I mentioned before, the data only appears when the shiftOut() function is in the main loop() and not configured to run once. I am attaching the oscope captures here.

The captures below were taken immediately after hitting the reset button on the Arduino. Ch 1 (yellow) is the clock pin and Ch 2 (Blue) is the data pin. In one of the captures, where the setup data is configured to transfer once, we can see that the clock pin remains idle and no data is transferred.

Your results are certainly bizarre. I have no explanation for what you are seeing. I suspect that the 64-bit operations are encountering some kind of error. Have you tried an 8-byte array?

const uint8_t preout[8] = {0b11111101, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b10101111, 0b11111111};

I tried using an array instead but still no luck. :frowning:

Here is the modified code:

#define CLK 13
#define D 11
#define B 8
#define CLOCKOUT 9

bool set = false;
uint8_t out = 0; //64bit variable used as output buffer
//uint64_t preout = 0;
const uint8_t preout[8] = {0b11111101, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b10101111, 0b11111111};

void setup() {
  
  pinMode(D,OUTPUT);
  pinMode(CLK,OUTPUT);
  
}

void loop() {
  
  if(set==false){
  //preout = 0b1111110111111111111111111111111111111111111111111010111111111111;
  for(int i=0;i<=sizeof(preout);i++){
      out = preout[i];
      shiftOut(D,CLK,MSBFIRST, out);
  }
  set = true;
  }
}

This is the oscope capture:

You have one bug but it should not cause shiftOut() to fail:
for(int i=0; i <= sizeof(preout); i++){
should be:
for(int i=0; i < sizeof(preout); i++){

So now it doesn't work in loop() either?!? Something is very strange.

I have simulated the OP's latest sketch with wokwi.com, doing only what damages were necessary, and no surprise it functions as expected.

I did spot the same error in the for loop as @johnwasser, but only after adding some printing - all of which printing is entirely correct.

Earlier I had no trouble with the 64 bit constant representation.

What shift register are you using this test sketch with? Does it have the same clock polarity as, say, the 74HC595 I had to use?

HTH

a7

Oops. Thanks for correcting the bug. The array also works in the loop() section but whenever it is configured to run only once, the shiftOut() function stops working and clock pin remains idle. It seems like the effect is exactly the same as before but instead of pulling the data pin high at the end of setup, it pulls the data pin low. It still doesn't transfer the initial setup data "once".

Is it possible that there are some hardware connection conflicts with the 2 pins that I'm using? I'll try to switch up the pins and see if I can get any different results. Any other advice or suggestions you may have would be greatly appreciated.

I am using the TLC5955 LED driver. The register of the device is configured to shift in data on the rising edge of the clock signal. Please see this datasheet for additional reference: https://www.ti.com/lit/ds/symlink/tlc5955.pdf?ts=1628254307570&ref_url=https%3A%2F%2Fwww.google.com%2F

In my trials, 64 bit integers did work but only when the shiftOut() was configured to run in a loop. It does not want to run when configured to send the 64 bit value only once during startup. Any suggestions or tips would be appreciated.

That makes me wonder if the problem is in the "do only once" technique. Maybe something is writing into 'set' and changing it to true before loop()?!?

Since you aren't including the SPI library it is unlikely the SPI pins (10, 11, 12, 13) are doing anything you don't tell them to do. Are you testing with nothing connected to the pins?

I just tested with other pins and its the exact same effect. The pins have no load on them. They are only probed with the oscope.

It may be possible. But wouldn't that still allow data to be transmitted when implemented in the setup() section? I just tested the code in setup() and the clock pin remains idle.

#define CLK 9 
#define D 6
#define B 8

bool set = false;
uint8_t out = 0; //64bit variable used as output buffer
//uint64_t preout = 0;
const uint8_t preout[8] = {0b11111101, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b10101111, 0b11111111};

void setup() {
  
  pinMode(D,OUTPUT);
  pinMode(CLK,OUTPUT);

  for(int i=0;i<sizeof(preout);i++){
      out = preout[i];
      shiftOut(D,CLK,MSBFIRST, out);
  
  }
}

void loop() {
  /*
  if(set==false){
  //preout = 0b1111110111111111111111111111111111111111111111111010111111111111;
  for(int i=0;i<sizeof(preout);i++){
      out = preout[i];
      shiftOut(D,CLK,MSBFIRST, out);
  }
  set = true;
  }
  */
}