LEDs with 2 shift registers over PWM

Hi,

I searched for a solution for my problem but i didn't found a fitting one here over the search so if I missed an already existing one I am sorry for dublicate it.

I am really new at the Arduino programming and have the problem that i want to control 16 LEDs with two 74HC595 shift registers via PWM to have the possibility of dimming them. I take the basic build of the curcuit to the official shift out exsample (http://arduino.cc/en/Tutorial/ShiftOut) taht works fine. Then I changed the connection of the 3rd Pin to a PWM Pin of the Arduino to enable it for the shift registers. Basicly it also works fine but I am not able to set the brightness of 2 or more LEDs independent from the others :( and always the second register have the same state like the first one because i did not understand how the addresses have to be defined :S

My actually code is:

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
int outputEnablePin = 3;
int brightness;
byte leds = 0;

void setup()
{
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(outputEnablePin, OUTPUT);
}

void loop()
{
setBrightness(1 ,200);
setBrightness(2,10);
}

void setBrightness(int led, int brightness)
{
digitalWrite(latchPin, LOW);
bitSet(leds, led);
shiftOut(dataPin, clockPin, LSBFIRST, leds);
analogWrite(outputEnablePin, 255-brightness);
digitalWrite(latchPin, HIGH);
}

I thought now that the first and the second LED is on and the second one is much darker than the first (both on the first shift register) but both are bright as the first one and the also the LED 1 and 2 of the second Register are on.

I hope somebody can help me here (in a easy way ;) ) and thanks alot for taking care of this 'dummy problem' :)

Greetings

byte leds = 0; is a global variable. The first call to setBrightness, setBrightness(1 ,200);, sets the first bit of this variable using the built-in function call: bitSet(leds, led);. The second call to setBrightness, setBrightness(2,10);, sets the second bit. Thereafter, both bits are set. They are never being reset because that variable is global, not local. So both LEDs will be always operated with the same brightness over and over, first 200 and then 10 for an average of 105.

The second bank of LEDs are being set because after the first shiftOut, the byte sent to the first shift register is forwarded to the second shift register. Since you have 16 bits with, do another shiftOut of a byte 0 to make sure that second register is unset. You will want to send the byte 0 first and then your other byte second.

To fix this, just move the global declaration byte leds = 0; inside your setBrightness function.

Also, you might want a delay call after each call to setBrightness because otherwise the PWM may not really have time to work its magic.

Now, things to consider here. You are giving each of your two LEDs half of the time, one of them is always off while the other is outputting at a selected PWM frequency. This is called duty cycle. 1:2 duty cycle will work for you. 1:16 might not work so great. As you enable LEDs, you will see brightness decrease. Experimenting with this is fun, but there are some ICs available to do all this for you like the TLC5940 which gives you 16 channels each with a dedicated PWM state machine attached to it so there is no duty cycle at all (or you can call it 1:1), every LED is always outputting its selected PWM frequency.

So you are trying to modulate the brightness of all 8 LEDs connected to the shift register by controlling the OE pin on the shift register itself? That may work if the outputs from the shift register were pulled down to ground when the outputs were disabled, however if they're left to Z ( high impedence state ) you may not get off state you would need on the pin to turn the LED off and to get the dimming effect you are looking for.

If you want to use a PWM pin to control a set of LEDs, perhaps you could use an additional PWM pin controlling a transistor to modulate the voltage to all the LEDs instead of feeding the shift reg. This should in theory allow you to switch all 8 or 16 LEDs on and off rapidly to adjust all their brightnesses together.

If you're looking to control the brightness of each LED attached to the shift regs, then a different method would be needed. For example, you could use a method where you run through a loop, say 8 times, where you shift the LEDs states through the registers over and over, varying the on/off state of each LED each time through the loop.

In this example, if you want LED 0 to be full brightness, each time you pass the state of the LEDs to the shift registers, ensure that LED 0's state is on. If you want LED 3 to be half as bright, then pass the shift registers an on state for LED 3 for 4 of the 8 passes through the loop, and off for the other 4 passes. If you want the dimmest possible ( but not off ) LED, only turn that LED on for 1 pass out of 8.

Suppose you had 8 LEDs you want to control with 1 shift reg, and you wanted to vary them in brightness from most to least:

pass through loop shift out byte 0 11111111 1 11111110 2 11111100 3 11111000 4 11110000 5 11100000 6 11000000 7 10000000 repeat

As you can see above, each time through the loop LED0 would be on, so it would appear brightest, LED7 would only be on 1/8 of the time through the loop and would appear dimmest.

@bad_crc A lot of that information is just wrong, especially the paragraph. Controlling the output of all LEDs connected to a shift register by PWM of the output enable works well no matter how the outputs are wired.

Note this results in all the LEDs always being set at the same brightness level. To set individual LEDs you must use the techniques used in the shift PWM library.

What is the shift PWM library doing under the covers? I suspect something similar to what I described. That is updating the shift regs in rapid succession to get a PWM effect on each shift reg output.

It might very well be doing exactly that, but it doesn't stop the first paragraph being utterly wrong and the second paragraph being a bit silly.

If you want to use a PWM pin to control a set of LEDs, perhaps you could use an additional PWM pin controlling a transistor to modulate the voltage to all the LEDs instead of feeding the shift reg. This should in theory allow you to switch all 8 or 16 LEDs on and off rapidly to adjust all their brightnesses together.

Which is exactly what PWMing the output enable does.

It is no good offering information if it is wrong or confusing to beginners. The fact that one section is in theory correct but possibly useless for a beginner does not compensate for the incorrect premiss you started your post on, which was:-

So you are trying to modulate the brightness of all 8 LEDs connected to the shift register by controlling the OE pin on the shift register itself? That may work if the outputs from the shift register were pulled down to ground when the outputs were disabled, however if they're left to Z ( high impedence state ) you may not get off state you would need on the pin to turn the LED off and to get the dimming effect you are looking for.

The TC never stated exactly what the goal of the circuit was, hence my first paragraph. Does the TC wish to control the brightness of all the LEDs together or each independently?

In any case, thank you for correcting me on the OE. I learned something new today :)