PCA9685 not using external power

Hello everyone,

I am trying to drive a servo (SG90) through a PCA9685 servo driver board, so I could eventually control multiple servos using external power. I'm controlling this with an Arduino Uno R4 Wifi.

The problem is:
When using external power, instead of the V+ pin on the side of the PCA9685, the servo doesn't move at all. It DOES work when I add a wire from the 5V pin on the Arduino to the V+ pin on the side, leading me to assume that the code is at least functioning, and the servo itself is not broken and wired correctly.
The external power is the main reason I want to use this setup, so as to not create any fluctuations/crashes on the microcontroller. I am not very good with electronics, and I'm out of ideas on how to troubleshoot this. Can anyone provide some advice?

The setup is:


This is my basic wiring diagram. I have switched out the battery pack for a 5V DC (3A max) adapter at some point, but to no avail. The reference I am using for this is: https://learn.adafruit.com/16-channel-pwm-servo-driver/hooking-it-up

A photo of what this looks like:

Same setup but the wires are more clearly visible:

In the pictures the power is switched off because it interfered with the camera, but:

  • The power light on the PC9685 is bright red
  • The Arduino is powered by USB-C from a laptop

What I have done to try and figure this out:

  • Measured voltage at the terminal input on the top of the PCA9685. It gives 6.5V with the battery pack, and 5.1V with the adapter (reason I switched to the adapter, the driver board doesn't like voltages over 6V apparently)

  • Replaced every wire

  • Swapped the polarity of the battery pack / adapter
    This actually resulted in a component on the top-left of the PCB to melt... I guess I misunderstood what "reverse polarity protected" meant...

  • Swapped out my original ESP32 for the Arduino, did not switch Arduinos

  • Tried a total of 4 different PCA9685s

  • Hooked the VCC input to the 3.3V port on the Arduino (like in the sketch)

  • Hooked the VCC input to the 5V port on the Arduino (not drawn)

  • I have tried making it all "share the same ground" (advice from a different thread), however I do not know how to wire this up correctly so I might have not done this quite right... This is a sketch of how I tried to do that:

  • Hooked the V+ input to the 5V port on the Arduino. This does result in the servo sweeping, but I'm guessing it's not using the external power at all that way

  • Since it does work with the V+ being fed from the Arduino, instead of the green terminal, I did not perform any additional checks on the I2C addresses being set correctly, or the code. The code is the default Adafruit example code for servos (pasted below)

I have also done some measurements of voltage on various pins:

  • Between terminal block V+ and GND: 5.1V
  • Between Servo0-V+ and Servo0-GND with only external power: 0,5Vish
  • Between Servo0-V+ and Servo0-GND with the PCB-V+ pin fed from Arduino 5V: 4.5V
  • Between Servo0-PWM and Servo0-GND: Fluctuating between 0.2 and 0.4V (guessing these are the pulses and my multimeter just averages it out a bit)
    Not sure if these are particularly useful, but it seems like there's at least some power in the pins, just that the V+ for the servo doesn't get any (or barely any) power from the terminal.

The code is the example code that comes with the Adafruit servo package. I have commented out the part where it goes through servo 0-7, because I only have 1 connected, but otherwise this is just what comes "out of the box":

/*************************************************** 
  This is an example for our Adafruit 16-channel PWM & Servo driver
  Servo test - this will drive 8 servos, one after the other on the
  first 8 pins of the PCA9685

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/815
  
  These drivers use I2C to communicate, 2 pins are required to  
  interface.

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#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);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);

// Depending on your servo make, the pulse width min and max may vary, you 
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN  150 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // This is the 'maximum' pulse length count (out of 4096)
#define USMIN  600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
#define USMAX  2400 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

// our servo # counter
uint8_t servonum = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("8 channel Servo test!");

  pwm.begin();
  /*
   * In theory the internal oscillator (clock) is 25MHz but it really isn't
   * that precise. You can 'calibrate' this by tweaking this number until
   * you get the PWM update frequency you're expecting!
   * The int.osc. for the PCA9685 chip is a range between about 23-27MHz and
   * is used for calculating things like writeMicroseconds()
   * Analog servos run at ~50 Hz updates, It is importaint to use an
   * oscilloscope in setting the int.osc frequency for the I2C PCA9685 chip.
   * 1) Attach the oscilloscope to one of the PWM signal pins and ground on
   *    the I2C PCA9685 chip you are setting the value for.
   * 2) Adjust setOscillatorFrequency() until the PWM update frequency is the
   *    expected value (50Hz for most ESCs)
   * Setting the value here is specific to each individual I2C PCA9685 chip and
   * affects the calculations for the PWM update frequency. 
   * Failure to correctly set the int.osc value will cause unexpected PWM results
   */
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates

  delay(10);
}

// You can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. It's not precise!
void setServoPulse(uint8_t n, double pulse) {
  double pulselength;
  
  pulselength = 1000000;   // 1,000,000 us per second
  pulselength /= SERVO_FREQ;   // Analog servos run at ~60 Hz updates
  Serial.print(pulselength); Serial.println(" us per period"); 
  pulselength /= 4096;  // 12 bits of resolution
  Serial.print(pulselength); Serial.println(" us per bit"); 
  pulse *= 1000000;  // convert input seconds to us
  pulse /= pulselength;
  Serial.println(pulse);
  pwm.setPWM(n, 0, pulse);
}

void loop() {
  // Drive each servo one at a time using setPWM()
  Serial.println(servonum);
  for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
    pwm.setPWM(servonum, 0, pulselen);
  }

  delay(500);
  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(servonum, 0, pulselen);
  }

  delay(500);

  // Drive each servo one at a time using writeMicroseconds(), it's not precise due to calculation rounding!
  // The writeMicroseconds() function is used to mimic the Arduino Servo library writeMicroseconds() behavior. 
  for (uint16_t microsec = USMIN; microsec < USMAX; microsec++) {
    pwm.writeMicroseconds(servonum, microsec);
  }

  delay(500);
  for (uint16_t microsec = USMAX; microsec > USMIN; microsec--) {
    pwm.writeMicroseconds(servonum, microsec);
  }

  delay(500);

  // servonum++;
  // if (servonum > 7) servonum = 0; // Testing the first 8 servo channels
}


I really hope someone can help me with this, thank you in advance. If there is any more tests I can do, pictures/sketches to share or information I can give, please let me know.

Didn't read the whole thread, but PCA9685 power (VCC) and servo power (screw terminal) are two completely independent circuits. Only their grounds are shared.
Leo..

2 Likes

Hi Leo, thanks for your response. As I understand it the VCC only powers the PCA9685 itself, while the screw terminal is supposed to power the servos. The latter part is what I don't get working, even though I have supplied sufficient power to the screw terminal, there doesn't seem to be any sent to the servos.

I also thought that the PCA9685 has 2 ports for "servo power", the screw terminal and the V+ pin on the side, where the V+ pin is really intended for chaining multiple PCA9685s together.
If I use the V+ pin on the side to provide power, everything does work, but not when I use the screw terminal.

No, as said, the (+)screw terminal is only connected to the red middle pins of the 16 pinheaders.

VCC on both sides is to power the PCA and the PCA on the next board.

You seem to have a PCA9685 board, with a large buffer capacitor, an indicator LED and a fet??
Never seen that version before (link?).
Does the LED light up when you connect power to the screw terminal?

The fet, if it has one, is there for reverse voltage protection.
You don't get any power to the servos if the battery is low or connected with the wrong polarity.
Leo..

1 Like

No, as said, the (+)screw terminal is only connected to the red middle pins of the 16 pinheaders

Alright, then my problem seems to be that I do not see any voltage between the red and black pins on the 16 pinheaders, when the power is connected through the screw terminal.

This is now the current setup, to avoid any issues with battery power:

For reference, this is the setup that DOES work, but doesn't use the screw terminal or the external power at all:


With this setup I can also measure voltage on the red middle pin of the pinheader.

You seem to have a PCA9685 board, with a large buffer capacitor, an indicator LED and a fet??
Never seen that version before (link?).

This is interesting, I didn't realize there might be differences in manufacturers. Turns out the Adafruit one is a bit hard to get where I live, and these alternatives are everywhere. I mainly bought these because they had everything soldered on already. I will keep this in mind in the future.

This PCA comes from some company called Opencircuit, however I cannot find a datasheet, and their only description is in Dutch. For posterity the link is: https://opencircuit.nl/producto/pca9685-16-channel-pwm-servo-module-i2c
I did order a few more from AZ-Delivery, they should be arriving tomorrow. They look very similar, but have some non-Adafruit brand printed on them. They do however come with a datasheet: https://cdn.shopify.com/s/files/1/1509/1638/files/PCA9685_Servotreiber_Datenblatt.pdf?17187252465155634920
I will try one of those as soon as they come in.

Does the LED light up when you connect power to the screw terminal?

It does not. It lights up when the PCA itself is powered on, so essentially when the Arduino is on. There is no visual indication of power coming in through the screw terminal, although I did measure a voltage across the screw terminal solder points, so the connection should be fine. I'm also confident the polarity is correct, since it matches up with the information printed on the board/connector, and if I switch it around the transistor instantly burns up (bye bye 2 boards for trying that).

@entalyan
From the opencircuit website:

If you use a combination of servo motors that together consume more than 500mA, you must use the V+ header pins on the sides to power the servos. If the current exceeds 500mA significantly for an extended period of time, the transistor on the module may burn out.

So the transistor is burnt out

You will have the same problem with the ones from AZ-Delivery

1 Like

V+ seems indeed connected to the red pinstrips, and you could connect external servo power to that, but that pin is not commonly seen on other boards.

I think the fet (small 3-pin part) next to the big cap is defect.
Adafruit uses a fet in a larger package for that, but I have seen boards with SMD fets like that.
Powering the servos with an external 5volt supply on V+ is possible, but you won't have that reverse voltage protection (ompoolbeveiliging) that the fet should have given you.

Small SG90 servos have a stall current of ~650mA@5volt, so don't power the servo from the 5volt pin of the Uno. Unless you have a spare Uno and a spare laptop.

Geen probleem.
Leo..

1 Like

Hi, @entalyan

Do you have a DMM? Digital MultiMeter

Tom... :grinning: :+1: :coffee: :australia:

@jim-p
I saw that, but (wrongfully) assumed this wasn't the case due to:

  • Only a single SG90 being connected
  • No visible burning out happening
    When I did actually burn out the transistor by reversing the polarity it literally went up in smoke :stuck_out_tongue:
    It does sound likely, especially combined with the answer Wawa gave.

@Wawa
When comparing the different variants of PCA9685 out there I did notice that the Adafruit one had a much larger transistor in the place than the ones on either the Opencircuit or AZ-Delivery boards.

I don't necessarily need the reverse voltage protection, as long as I just connect + to + and - to - (or GND), so I could just use the V+ pin on the side I guess. In that scenario, where would the - wire of the power supply go? Into the GND of the Arduino? I'm a bit confused at how "creating a common ground" would work with multiple power supplies.

The goal of the project is to control 1 to 3 SG90 (or SG92R actually, those are in the final product), and controlling them sequentially is fine. Powering a single one directly from the Arduino works fine 95% of the time, but the other 5% it causes the controller to reset itself, which leads to a failure-state in the overall project.
The idea was to power the servos independently from the Arduino, which is really all I'm trying to achieve. I figured the PCA9685 provided a nice way of doing that without soldering, or having to strap a breadboard to each of these devices. (I would have gotten a shield for the Arduino, but my main platform is actually ESP32, and I didn't see any that fit the bill).

Alternatively I could just do away with the PCA9685 altogether, and use a breadboard to connect the external power. Would this be the correct wiring for that (ignoring that I didn't check if D2 and D3 are actually servo-capable, I picked the most expedient ones for the sketch, and that the Arduino itself is still powered through USB)?

Yes I do, but I'm very clumsy at using it :wink: And I've only gotten it to measure voltage so far, I either don't know how to do current readings or it's just not sensitive enough.

I think the conclusion is already that the transistor is broken in some way, possibly by burning out. If you let me know between where and where to measure something I'll post the results. I get some fresh PCA9685s in tomorrow so they shouldn't be burned out by ME yet :wink:

Hi,
When you have the external battery connected, what voltage do you measure on the terminals it is connected to?

Check the voltage between the external battery negative termnal and the gnd on the Arduino connection?

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

Yes that will work if you use the perma- proto like you show and NOT a solderless breadboard

1 Like

As I pointed out you will have the same problem with the ones from AZ

Between the GND on Arduino and the negative terminal it shows around 0.013V. Between the GND of the PCA and the negative terminal it shows 0.

Besides that solderless breadboard aren't very permanent, is there any reason why it wouldn't work? I don't mind ordering a perma-proto board like that one and soldering on the connections, but preferably after I've verified that this will even work on a solderless one :wink:

The cheap ones can't handle large currents.
You can cut and strip the wires and twist them together or use connectors like these:

1 Like

Thank you everyone! I have tested the wiring without the PCA9685 and this does seem to be working, so I can continue with my project :slight_smile:.

I have ordered a few perma-proto boards to finalize this, and in the mean time I will make do with terminal blocks/twisted wires/solderless breadboards. I will try to find another use for the cheap PCAs, and in the future will at least make sure to buy the Adafruit ones, so any problems at least won't be caused by deviating from the source.

I bought 20 of these boards to use on a project with my students. The same thing happened and the only way to get things working was to connect the external power to v+ pin as the screw terminal for the v+ did not work. I used the ground terminal to connect to the ground on the power source.

It seems like all of the boards are broken, maybe a massive defective batch.

Some students had 10+ motors, and in this case we needed to power them directly from the power supply, using only the signal pin from the PCA9685

Just got two of the generic PCA9685 boards from Amazon and they both apparently had bad MOSFETs out-of-the box (it's the version with the tiny FET and 100uF capacitor).
I just removed the MOSFET and jumpered drain and source so I could still use the screw terminal (but without any reverse polarity protection).
Note that the gate of the MOSFET is connected to the pad at the edge of the board, so you leave that pad disconnected and just solder a short chunk of wire across the other two.