PCA9685 LED control
Moderators: adafruit_support_bill, adafruit

PCA9685 LED control

by davidb on Tue Nov 20, 2012 12:35 am

Hi,
I seem to be a little dense in figuring out some control aspects of the PCA9685 "Adafruit 16-Channel 12-bit PWM/Servo Driver". Here are some questions I need some pointers on:

1. I have everything connected correctly and have a little sketch which turns the leds on:
pwm.setPWM(0, 0, 4095);
waits a second, turns them off:
pwm.setPWM(0, 4095, 0);

What I would like to do is eventually create animations using the each of the PWM channels, but I can't seem to make the pwm value a variable. For example just a simple pulse like this:

pwm.setPWM(0, 0, intensity);
delay(5);
intensity++;
if (intensity > 4095) {
intensity = 0;
}

Doesn't actually produce anything...LED is always at full value. I imagine it's not really understanding the pwm.setPWM function entirely, so any pointers would be greatly appreciated.

2. I can't seem to get the LED's to shut off completely...always seems to always be a tiny amount of current flowing through after a pwm.setPWM(0, 4095, 0) command.

3. The current limiting resistor is too high for what I want to use it for. Should I just solder some resistors in parallel for each PWM channel to get to the desired resistance (a bit of a pain), or is there by chance a more graceful way of changing the resistance on each channel?

Thanks in advance for any pointers.

Cheers,
David
davidb
 
Posts: 6
Joined: Tue Jun 30, 2009 3:29 am

Re: PCA9685 LED control

by adafruit_support_mike on Tue Nov 20, 2012 5:37 pm

You're running into what programmers know as a 'call by name' versus 'call by value' problem. What you'd need to do looks more like this:

Code: Select all | TOGGLE FULL SIZE
intensity = 0;
while (intensity < 4095) {
    pwm.setPWM( 0, 0, intensity );
    intensity++;
}
pwm.setPWM( 0, 4095, 0 );


You have to call 'pwm.setPWM()' every time you change 'intensity' because setPWM() a 'call by value' function.. it looks at the values you feed it as parameters, sends those to the LEDs, then forgets everything.

The code you wrote uses a 'call by name' assumption: you want to tell the LEDs to watch 'intensity', and to change behavior whenever you give 'intensity' a new value.

It's possible to write software either way, but when you deal with hardware -- especially communication between different chips -- 'call by value' is more common.
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.
User avatar
adafruit_support_mike
 
Posts: 9492
Joined: Thu Feb 11, 2010 1:51 pm

Re: PCA9685 LED control

by davidb on Wed Nov 21, 2012 1:13 am

Hi mstone,
Thank you for your help. It actually looks like we are doing the same thing, just via a different mechanism. You are incrementing "intensity" in a while loop while I was using the main loop (I realize at this point it probably would have been much more helpful to include the entire sketch in my original post!). So looking a bit more closely I realized I hadn't correctly declared intensity (for some reason was trying to do so in setup()...drrr). Fixing that made it all work as expected:

Code: Select all | TOGGLE FULL SIZE
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);

int intensity = 0;

void setup() {

  pwm.begin();

  pwm.setPWMFreq(500);  // Analog servos run at ~60 Hz updates
}


void loop() {

  pwm.setPWM(0, 0, intensity);
  intensity++;
  delay(5);
  if (intensity > 4095) {
    intensity = 0;
  }

}


BUT...wanted to double check that we are in fact saying the same thing. Each time the loop is processed I'm expecting pwm.setPWM to set the led value to the current value of intensity, which itself is incremented each time the main loop is executed, which I believe is the same thing your while loop is doing.

Like I said, it's working (yeah) but wanted to make sure I fully understood what you were saying.

Thank you again!
davidb
 
Posts: 6
Joined: Tue Jun 30, 2009 3:29 am

Re: PCA9685 LED control

by davidb on Wed Nov 21, 2012 1:44 am

And following up on the other two issues I'm having:

1. it looks like it was a coding error on my part where I there was always some current going thru the leds even when I thought they should be off. I was using this command:
pwm.setPWM(0, 4095, 0);

when it looks like I should have been using this:

pwm.setPWM(0, 0, 0);

So that now works.

2. based on the LEDs I am trying to drive @ 5V I only need a 43 ohm to limit the current to 25mA. It seem like my only options are to either try to solder a 53ohm resistor in parallel to the 221 ohm resistor on the board or remove the 221 ohm resistor and replace with a 43 ohm resistor. Neither option appears to be much fun, but wanted to check.

Thanks again!
davidb
 
Posts: 6
Joined: Tue Jun 30, 2009 3:29 am

Re: PCA9685 LED control

by adafruit_support_mike on Thu Nov 22, 2012 2:53 pm

Yep, as long as you're calling pwm.setPWM() for each new value, you're good.

davidb wrote:when it looks like I should have been using this:

pwm.setPWM(0, 0, 0);

I'd wondered about that, but figured it was best to go one point at a time. Good to know you've got something that works for you.


davidb wrote:2. based on the LEDs I am trying to drive @ 5V I only need a 43 ohm to limit the current to 25mA. It seem like my only options are to either try to solder a 53ohm resistor in parallel to the 221 ohm resistor on the board or remove the 221 ohm resistor and replace with a 43 ohm resistor. Neither option appears to be much fun, but wanted to check.

Hmm.. I see where you're heading, but would probably use a line buffer myself.

To paraphrase in order to make sure I understand: the diodes you're using have a forward voltage of about 4v at 25mA, and the 220 ohm resistors built into the PCA9685 board will only give you about 5mA when you use a 5v power supply. To get 25mA, you need a current limiting resistor of about 43 ohms (I'd suggest 47 ohms since that's the closest standard value).

Instead of modding the PCA9685 board, I'd mentally re-label it from 'LED driver' to 'central pattern generator' and use its outputs to drive cheap, simple components that can get more power to the LEDs.

Starting simple, we have things like the 2N3904 NPN transistor: you can get a hundred in TO92 packages from Mouser for $3.50, and each one can handle 200mA of current.. about 8 LEDs worth. Give each LED its own resistor, use the transistor as a switch between the LED and GND, drive the transistor's base with the PCA9685 board's output, and you're set.

Moving up a notch, there's the 2N7000 mosfet: it works the same way, but it can handle pulsed current up to 800mA and draws no DC current from the control line. The only practical limit to the number you could drive from a single output line (called the 'fanout') is the capacitance of the wire connecting everything. Those are a little more expensive ($6.50 per hundred in TO92), but still a good bet.

Next up would be inverters like the 74HC04 or 74HC14. Those work from 5v supplies and each inverter can handle about 25mA of output current. They come 6 to a chip, run about $12.50 per hundred in DIP-14 packages, and work pretty much the same way the transistors/mosfets do.

From there you go to line drivers like the 74HC244 and 74HC245. Those don't invert the signal, do have 'enable' lines that can tristate the output, come 8 to a package, and cost about 50% more than the inverters.

The prices drop by about a third if you're willing to use SMT components rather than through-hole components.

The chips are more compact, and inverters are slightly more cost effective than individual transistors. Transistors can handle a lot more current than chips though. It's also true (and I still shake my head over this) that a 47 ohm resistor will cost about the same as a 3904 transistor.
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.
User avatar
adafruit_support_mike
 
Posts: 9492
Joined: Thu Feb 11, 2010 1:51 pm