RGB LED strip lights - common cathode - driver

Hey,
So i've been poking about this forum for the last week but haven't found quite the answer i am looking for so i figured i would just ask. Apologies if this seems like a double post, but i really swear i have searched extensively for my answer on here and have come up empty handed.

So i have some RGB LED strip lights, they are 12 VDC and take about 200 mA of current per channel. They are common cathode, so i need a high side driver IC.

At first i tried building one, but after blowing up an arduino chip i decided to just buy an IC LED driver.

Now the only LED driver chip that works for common cathode that i could find is this one: UDN 2981.
(it is my first post so i can't post a link apparently, but if you google that you will find the datasheet as the first result.)

The chip works fantastic except for one small problem. The chip takes ANY input signal from 128 to 255 and outputs a HIGH to the LEDs. And similarly takes any output signal from 0 to 128 and ourputs a LOW.

So my problem is that i can't dim the LEDs at all, they are just ON or OFF, no middle ground.

Is there a better chip that has more analog behavior, or do i have to build my own high side constant current source driver with PNPs? If so could you point me at a decent design to start with? As i understand driving high power LEDs is a bit more complicated than just using one transistor because you need a constant current source.

ANY help is REALLY appreciated!
Thanks.
Dewey

here is the link to that datasheet

The chip takes ANY input signal from 128 to 255 and outputs a HIGH to the LEDs. And similarly takes any output signal from 0 to 128 and ourputs a LOW.

This looks like you're saying that a value of 128 is both high and low.

How have you got the chip wired, and what does your code look like?
Are you expecting some kind of PWM functionality from this buffer chip?

are you sure its CC? every RGB strip we've ever seen is Common Anode:
http://www.ladyada.net/products/rgbledstrip/

ladyada:
100 % sure it is Common Cathode.

AWOL:
typo, i meant that 0 to 127 is outputs a LOW.

My code does not show my attempting to output anything below 255 anymore, i gave up on trying to make the fading for for the show last night, but it does show how i adress the pins...

const int analogInPin0 = 0; // audio in 1
const int analogInPin1 = 1; // audio in 2
const int yellowbutton1 = 2;
const int yellowbutton2 = 3;
const int greenbutton1 = 4;
const int greenbutton2 = 5;
const int redbutton1 = 6;
const int redbutton2 = 7;

const int blue1 = 21; // Analog output pin that the LED is attached to
const int blue2 = 19; // Analog output pin that the LED is attached to
const int blue3 = 20; // Analog output pin that the LED is attached to
const int red1 = 6; // Analog output pin that the LED is attached to
const int red2 = 1; // Analog output pin that the LED is attached to
const int red3 = 5; // Analog output pin that the LED is attached to
const int green1 = 23; // Analog output pin that the LED is attached to
const int green3 = 18; // Analog output pin that the LED is attached to
const int green2 = 0; // Analog output pin that the LED is attached to
const int WhiteLED = 22;

// Variable declarations for Goertzel Algorithm
int count = 0;
float normsample = 0;
float s63 = 0;
float s63_prev = 0;
float s63_prev2 = 0;
float s160 = 0;
float s160_prev = 0;
float s160_prev2 = 0;
float s400 = 0;
float s400_prev = 0;
float s400_prev2 = 0;
float s1000 = 0;
float s1000_prev = 0;
float s1000_prev2 = 0;

int power63 = 0;
int power160 = 0;
int power400 = 0;
int power1000 = 0;

// intial variables for various functions
int eqloophold = 0;
int christmasloop = 0;
int solidcolorsloop = 0;
int strobedelay = 27;

const float coeff63 = 1.961;
const float coeff160 = 1.753;
const float coeff400 = 0.618;
const float coeff1000 = -2;

int sensorValue0 = 0; // value read from the audio signal left
int sensorValue1 = 0; // value read from the audio signal right
int greenb1 = 0;
int greenb2 = 0;
int yellowb1 = 0;
int yellowb2 = 0;
int redb1 = 0;
int redb2 = 0;

int sensorValueTotal = 0; // total audio signal
int outputValue = 0; //

void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}

void loop() {

// Display results for button presses
// Serial.print("\n yellow1 = " );
// Serial.print(yellowb1);
// Serial.print("\t yellow2 = ");
// Serial.println(yellowb2);
// Serial.print("\t green1 = ");
// Serial.println(greenb1);
// Serial.print("\t green2 = ");
// Serial.println(greenb2);
// Serial.print("\t red1 = ");
// Serial.println(redb1);
// Serial.print("\t red2 = ");
// Serial.println(redb2);
yellowb1 = analogRead(yellowbutton1);
yellowb2 = analogRead(yellowbutton2);
greenb1 = analogRead(greenbutton1);
greenb2 = analogRead(greenbutton2);
redb1 = analogRead(redbutton1);
redb2 = analogRead(redbutton2);

//************************************************************
// christmas function ***************************************
//************************************************************
if ( redb2 == 1023) { christmasloop = 1;}
while (christmasloop == 1) // christmas lights effect function
{
analogWrite(red1, 255); // red 1
analogWrite(red2, 0); // red 2
analogWrite(red3, 0); // red 3
analogWrite(green1, 0); // green 1
analogWrite(green2, 255); // green 2
analogWrite(green3, 0); // green 3
delay(100);
analogWrite(red1, 0); // red 1
analogWrite(red2, 255); // red 2
analogWrite(red3, 0); // red 3
analogWrite(green1, 0); // green 1
analogWrite(green2, 0); // green 2
analogWrite(green3, 255); // green 3
delay(100);
analogWrite(red1, 0); // red 1
analogWrite(red2, 0); // red 2
analogWrite(red3, 255); // red 3
analogWrite(green1, 255); // green 1
analogWrite(green2, 0); // green 2
analogWrite(green3, 0); // green 3
delay(100);
redb1 = analogRead(redbutton1);
if (redb1 == 1023)
{
christmasloop = 0;
analogWrite(red1, 0); // red 1
analogWrite(red2, 0); // red 2
analogWrite(red3, 0); // red 3
analogWrite(green1, 0); // green 1
analogWrite(green2, 0); // green 2
analogWrite(green3, 0); // green 3

}
}

//************************************************************
// strobe effect function ************************************
//************************************************************
while ((yellowb1 == 1023) || (redb1 == 1023) || (greenb1 == 1023))
{
// get which colors
yellowb1 = analogRead(yellowbutton1);
greenb1 = analogRead(greenbutton1);
redb1 = analogRead(redbutton1);

// get blink rate
yellowb2 = analogRead(yellowbutton2);
greenb2 = analogRead(greenbutton2);
redb2 = analogRead(redbutton2);
// set blink rate
if (redb2 == 1023) {strobedelay = 107;}
if (greenb2 == 1023) {strobedelay = 54;}
if (yellowb2 == 1023) {strobedelay = 27;}

if (yellowb1 == 1023)
{
analogWrite(blue1, 255); // blue1
analogWrite(blue2, 255); // blue2
analogWrite(blue3, 255); // blue3
}
if (greenb1 == 1023)
{
analogWrite(green1, 255); // green 1
analogWrite(green2, 255); // green 2
analogWrite(green3, 255); // green 3
}
if (redb1 == 1023)
{
analogWrite(red1, 255); // red 1
analogWrite(red2, 255); // red 2
analogWrite(red3, 255); // red 3
}
if (yellowb1 == 1023 && greenb1 == 1023 && redb1 == 1023)
{
analogWrite(WhiteLED, 255); // panel white on
}
delay(strobedelay);
analogWrite(WhiteLED,0); // panel white on
analogWrite(red1, 0); // red 1
analogWrite(red2, 0); // red 2
analogWrite(red3, 0); // red 3
analogWrite(blue1, 0); // blue1
analogWrite(blue2, 0); // blue2
analogWrite(blue3, 0); // blue3
analogWrite(green1, 0); // green 1
analogWrite(green2, 0); // green 2
analogWrite(green3, 0); // green 3
delay(strobedelay);
}

//************************************************************
// Solid colors function ************************************
//************************************************************
if (greenb2 == 1023) { solidcolorsloop = 1;}
while (solidcolorsloop == 1)
{
yellowb1 = analogRead(yellowbutton1);
yellowb2 = analogRead(yellowbutton2);
greenb1 = analogRead(greenbutton1);
greenb2 = analogRead(greenbutton2);
redb1 = analogRead(redbutton1);
redb2 = analogRead(redbutton2);

if (yellowb1 == 1023)
{
analogWrite(blue1, 255); // blue1
analogWrite(blue2, 255); // blue2
analogWrite(blue3, 255); // blue3
}
if (yellowb2 == 1023)
{
analogWrite(blue1, 0); // blue1
analogWrite(blue2, 0); // blue2
analogWrite(blue3, 0); // blue3
}
if (greenb1 == 1023)
{
analogWrite(green1, 255); // green 1
analogWrite(green2, 255); // green 2
analogWrite(green3, 255); // green 3
}
if (greenb2 == 1023)
{
analogWrite(green1, 0); // green 1
analogWrite(green2, 0); // green 2
analogWrite(green3, 0); // green 3
}
if (redb1 == 1023)
{
analogWrite(red1, 255); // red 1
analogWrite(red2, 255); // red 2
analogWrite(red3, 255); // red 3
}
if (redb2 == 1023)
{
analogWrite(red1, 0); // red 1
analogWrite(red2, 0); // red 2
analogWrite(red3, 0); // red 3
}
if (yellowb1 == 1023 && greenb1 == 1023 && redb1 == 1023)
{
analogWrite(WhiteLED, 255); // panel white on
}
else {analogWrite(WhiteLED, 0);} // panel white on}

if (yellowb2 == 1023 && greenb2 == 1023 && redb2 == 1023) {solidcolorsloop = 0;}
}

//************************************************************
// EQ DISPLAY LOOP *******************************************
//************************************************************
if ( yellowb2 == 1023 ) { eqloophold = 1;}
while (eqloophold == 1) {
yellowb1 = analogRead(yellowbutton1);
yellowb2 = analogRead(yellowbutton2);
greenb1 = analogRead(greenbutton1);
greenb2 = analogRead(greenbutton2);
redb1 = analogRead(redbutton1);
redb2 = analogRead(redbutton2);
if ( yellowb1 == 1023 ) { eqloophold = 0;}

while (count < 400){
sensorValue0 = analogRead(analogInPin0);
sensorValue1 = analogRead(analogInPin1);
sensorValueTotal = sensorValue0 + sensorValue1;
normsample = sensorValueTotal / 1023;
s63 = normsample + coeff63s63_prev - s63_prev2;
s63_prev2 = s63_prev;
s63_prev = s63;
s160 = normsample + coeff160
s160_prev - s160_prev2;
s160_prev2 = s160_prev;
s160_prev = s160;
s400 = normsample + coeff400s400_prev - s400_prev2;
s400_prev2 = s400_prev;
s400_prev = s400;
s1000 = normsample + coeff1000
s1000_prev - s1000_prev2;
s1000_prev2 = s1000_prev;
s1000_prev = s1000;
count++;
}
// compute results for Goertzel Algorithm
power63 = (int) constrain(2abs(s63_prev2s63_prev2 + s63_prevs63_prev - coeff63s63_p

const int blue1 = 21; // Analog output pin that the LED is attached to
const int blue2 = 19; // Analog output pin that the LED is attached to
const int blue3 = 20; // Analog output pin that the LED is attached to
const int red1 = 6; // Analog output pin that the LED is attached to
const int red2 = 1; // Analog output pin that the LED is attached to
const int red3 = 5; // Analog output pin that the LED is attached to
const int green1 = 23; // Analog output pin that the LED is attached to
const int green3 = 18; // Analog output pin that the LED is attached to
const int green2 = 0; // Analog output pin that the LED is attached to
const int WhiteLED = 22;

only the pins D3, D4, D12, D13, D14, D15 are analog outputs (pwm). The other pins are only digital out. It is logical that you can only switch the led on or off on this digital pins.

hmmm, only 6 pwm pins? that certainly puts a damper on my plans.
My LED strips have 10 wires (1 common, and 3 sets of RGB).

Is there some way of multiplexing the 6 pwm pins to translate into more pwm pins?

Its been a long time since i used any sort of multiplexing chips, can someone recommend one that would work for this situation?

It's perfectly fine using the analog inputs as digital I/O pins, referencing them as digital pin 14-19. But you must set them as outputs (or inputs) first!

pinMode(Pin, OUTPUT);

The chip works fantastic except for one small problem. The chip takes ANY input signal from 128 to 255 and outputs a HIGH to the LEDs. And similarly takes any output signal from 0 to 128 and ourputs a LOW.

Huh? It's a source driver, taking digital signals for input.

Ah I get it, you use analogWrite on non-PWM output pins (you cannot use analog INPUT pins for this, not on the atmega 168/328 at least).

It's a big difference between analog inputs and "analog" (PWM) outputs. Not even on the same pins. There are only a few special PWM output pins that analogWrite works on. You can read a little about PWM here: http://www.arduino.cc/en/Tutorial/PWM

And the source driver should work fine with that.

Is there a better chip that has more analog behavior, or do i have to build my own high side constant current source driver with PNPs?

Yes, and depending on what you mean by your own PNP driver, maybe.

If you mean for dimming, then no. LED's are not dimmed in an analog way (diode characterestics, slightly varying specs becomes important), but with the aforementioned PWM method for consistency.

If you ment like a switch, and you (most likely) have a common ground for your LED's and arduino, you'd better off switching the LEDs on and off with an NPN at "the bottom", near ground, not PNP. Exchange the "load" with a LED in this schematics and take a look: Transistor Circuits
It's a nice page about bipolar transistors btw.

There are probably many chips that have PWM outputs, but any of those are probably overkill for your project right now. A popular one seems to be the TLC 5940, 16-channel PWM LED driver. I've never used one so I cant say anything about it really.

I think there is a software-PWM library somewhere, extending PWM to other pins as well. Or you could write your own, its only about toggling a pin on and off with certain intervals.

Multiplexing the PWM outputs is a bad idea, unless you can synchronize the multiplexing with the PWM... not easy.