32768:
… I’ll parse the datasheet and figure out what is “okay” for a duty cycle.
You won't find that in any datasheet. It's a matter of not having any 1 (or 2) block(s) off for so long that the human can detect that it's off. And that's completely separate from what colors are on.
The B595 SR holds the color data. Four of it’s outputs control the R LEDs and the other 4 control the green LEDs. You only have to load the SR up with the proper data to make whatever color you want happen. The “driver” loads up that appropriate bits for each block and loads the SR. The LEDbargraph() function is where what colors are to be on is determined. ATM just to keep things simple (to understand and to debug), it only calculates the green LEDs. Extending that to turn on other colors isn’t that hard. Let’s look at mode1 (as it is), which presently takes a 0 to 100 % input, and turns on 0 to 12 LEDs, presently only the green ones.
switch (mode){
case 1:
//this is the processing the will setup the left to right filling
//first determine how many LEDs need to be on
Mag = int(map(data, 0, 100, 0, 12));
if(Mag > 0){
for(int i = 1; i <= Mag; i++){
LEDs_on += 1 << (i-1);
}
}
//now turn on/off the colors as dictated by this mode
//right now we're doing a single color
GLEDs_working = LEDs_on;
break;
Let’s assume for the moment that my code correctly (ha!) determines the variable LEDs_on. This variable is a bitwise map of which LEDs need to be on. The lsb corresponds to the least significant LED. A 1 in any bit position indicates that LED should be on. But now the question is … which LEDs, the green and/or the red, should be on ? Above (again KISS) it’s all green and so the in-process working variable, GLEDs_working, is just a copy of LEDs_on.
But now let’s make it like your original GIF. The least significant 5 LEDs, if on, are green. The next 4 LEDS, if on, are yellow. And the 3 remaining LED, if on, are red. No doubt there are many ways to do this, here’s just one. See if you can find a more efficient way. Let me use masking to copy those bits that are supposed to be on from LEDS_on to both working variables for G and R LEDs. Know that bitwise AND’ing of the mask copies only those bits that are a 1 in both the source and the mask.
http://arduino.cc/en/Reference/BitwiseAnd
//for green or yellow the G LED must be on so allow the bottom 9 bits to be on if needed
GLEDs_working = LEDs_on & 0x01FF ;
//for yellow or red the R LEDS must be on
//so allow the top 7 (out of 12) bits to be on if needed
RLEDs_working = LEDs_on & 0x0FE0 ;
Later on in the function the working variables are copied into the variables GLEDs and RLEDs which the driver uses to configure the B595 SR.
FWIW I’ve typed the Hex equivalent (I think in hex better than in binary) of the masks but if you convert hex to binary you can see how the mask does what it does and why I bothered to have a variable called LEDs_on.
0x01FF = 0000 0001 1111 1111 b
0x0FE0 = 0000 1111 1110 0000 b
Recall that the upper 4 bits in the 16 bit word aren’t used in your 12 LED case.