LEDs Brightness Affected by 595 and Multiplexing

Hello,
I have 2 595 shift registers daisy chained together controlling 16 total transistors that turn 16 LEDS on and off. The LEDs are common anode RGB and all of the cathodes of each color are connected together and then the common anodes are controlled by the transistors. I can control the LEDs and can make them light up, but I’m having problems with the brightness of the LEDs. The brightness is obviously dimmed when I use multiplexing techniques to make them appear all on. When I just turn one on, the LED’s brightness seems fine. Also, when the brightness is turned down with PWM controlling the cathodes, the lights flicker.

I think the problem is the efficiency of my code; it’s just too slow and cumbersome. Can you guys look through it and make suggestions. Also, if you have any good examples of multiplexing code, please share it. Thank you.

I think the problem is the runTrans() function. It sets one bit, updates the shift register, then clears it and moves onto the next bit. It does this for ledsOne and ledsTwo separately. Any suggestions are welcome. Thank you. (Code is below.)

int redPin = 9;
int greenPin = 10;
int bluePin = 11;

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;


void setup()
{
 pinMode(latchPin, OUTPUT);
 pinMode(dataPin, OUTPUT);  
 pinMode(clockPin, OUTPUT);
 
 pinMode(redPin, OUTPUT);
 analogWrite(redPin, 255);
 pinMode(greenPin, OUTPUT);
 analogWrite(greenPin, 255);
 pinMode(bluePin, OUTPUT);
 analogWrite(bluePin, 255);
}

byte ledsOne=0;
byte ledsTwo=0;



void loop()
{
 setColor(255,0,255);
 runTrans();
}

   
   
//call to set the colors
void setColor(int redColor, int greenColor, int blueColor)
{
 analogWrite(redPin, redColor);
 analogWrite(greenPin, greenColor);
 analogWrite(bluePin, blueColor);
}



//call to run through the trnasistors using the shift register
void runTrans()
{
 ledsOne =0;
 ledsTwo =0;
 for (int i=0; i<=7; i++)
 {
   bitSet(ledsOne,i);
   updateShift();
   bitClear(ledsOne,i);
 }
 for (int i=0; i<=7; i++)
 {
   bitSet(ledsTwo,i);
   updateShift();
   bitClear(ledsTwo,i);
 }  
 
}




//updates the shift register by looking at the global integer, leds
void updateShift()
{
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, ledsTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, ledsOne);
  digitalWrite(latchPin, HIGH);
}

Try adding some "on-time" with each color change is held a little bit before the next color starts up. As it is now, you cycle thru everything at full speed all the time - slow it down a little so the eye has a chance to perceive it.

CrossRoads: Try adding some "on-time" with each color change is held a little bit before the next color starts up. As it is now, you cycle thru everything at full speed all the time - slow it down a little so the eye has a chance to perceive it.

Should I do that in the updateShift function? Because I tried adding a delay(1) after ledsOne and ledsTwo are shifted out, but it didn't help. And anything over that just caused it to noticeably flicker.

I’m not really sure. You’ll have to experiment and figure out where you get the best results.

CrossRoads:
I’m not really sure. You’ll have to experiment and figure out where you get the best results.

Yeah I have been. I still can’t get them to appear at full brightness without flickering. This only happened when I daisy chained two shift registers. With one, I had no trouble, but I want 16 LEDs instead of 8. I can get individual or 2 or 3 LEDs to appear at full brightness at the same time, using the delay(1), but when I try to cycle through all of the LEDs, they start flickering or it has no effect on the brightness. I think my code just needs to be more efficient. And I know that this can be done because so many people make the LED cubes where that have shift registers shifting out to other shift registers. That should be a lot slower than my configuration, so I know there is a way of doing this. Do you have any good examples or general outlines of codes for this? Thank you.

You haven't given any information on what is controlling the cathodes.

You also haven't put your code in a "code" box by using the tags generated by that "scroll" icon - you should "modify" your first post and do that to make it more readable.

If you were driving either cathodes or anodes with only Arduino pins or HC logic chips such as the 595s, then I would point out that you would get much better performance (and vastly simpler design of both hardware and software) using a single MAX7219 to drive your 16 RGB LEDs.

In general, the code to drive a multiplex display should function starting with a byte array containing the display data. In the main loop, the millis() function polls the time and thereby at an interval set so that it will fall due at 50 times the multiplex value per second, moves the display strobe on to the next phase, reading from the corresponding data in the array. In other words, all multiplex phases are executed about 50 times per second and the rest of the program processing is performed during passes through the main loop as it moves on past this display multiplex code.

In fact, all functions of any kind should be executed in this fashion - the loop should consist of a number of "steps", none of which ever "wait" for an event but instead poll to see if it has occurred, process it immediately if it has and in either case, pass on promptly to the next program "step". Any processing-intensive step must be broken up into brief stages which can - by means of state or "switch" variables - be dealt with on successive passes through the master loop.

Hi Joshua.

Try this: put the delays after the updateShift to 1000. Each led should light for 1 second in turn. Is each one lit with full brightness and without flicker? If so, half the delays to 500 and re-test. Keep halving the delays. What delay do you get to before the flickering begins?

Paul

Have a look at Shift PWM library Elco Jacobs

PaulRB: Hi Joshua.

Try this: put the delays after the updateShift to 1000. Each led should light for 1 second in turn. Is each one lit with full brightness and without flicker? If so, half the delays to 500 and re-test. Keep halving the delays. What delay do you get to before the flickering begins?

Paul

I have done this, and the LEDs light up fine given enough time. I hit a problem when the delay gets to about 5 milliseconds. The lights themselves aren't flickering, they just don't turn on then off and back on again quick enough to just appear on. I need the code to function better.

I think I understand what Paul__B is suggesting, but right now, all I am trying to do is get the LEDs to all appear lit up at the same time, I don't have any events to check for. The cathodes are controlled by 3 PWM pins, one for each color. Heres an outline of what happens in the code: loop(): sets the output for the LEDs by calling the setColor function. Then it calls runTrans() runTrans(): sets one bit of ledsOne to on, updates the shift register with updateShift(), then turns off the bit and moves on the the next. It uses two for loops, one for ledsOne and one for ledsTwo.

There are no delays in this code because I couldn't find a delay length or spot that would stop the appearance of flickering. All that should happen are all the leds individually turn on then off so fast that they appear on. This worked with only one shift, but now that two are daisy chained, I can see the flickering.

JoshuAc00k: I have 2 595 shift registers daisy chained together controlling 16 total transistors that turn 16 LEDS on and off. The LEDs are common anode RGB and all of the cathodes of each color are connected together and then the common anodes are controlled by the transistors. I can control the LEDs and can make them light up, but I'm having problems with the brightness of the LEDs. The brightness is obviously dimmed when I use multiplexing techniques to make them appear all on.

If you would, present that as a schematic.