[SOLVED] Connection and power supply of 4 PCA9685 boards with Arduino

Hello everyone!

I am developing a project that involves the recognition of a person's silhouettes through the Kinect and than controls 64 engines with Arduino. To do this I'm using 4 PCA9685 boards with 64 SG90 servomotors.

The code for the Kinect is made with Processing where in practice it generates a string of 64 numbers (0 or 1) every 2 seconds that is sent to the Arduino through the serial port. The Arduino reads this string and runs the corresponding engines accordingly.

The piece of code works perfectly by connecting only one PCA9685 board.

The problem now is the connection of several boards: after making the connection the boards do not work, or rather they work but only individually, whether the external power is only on the first board or that every board is attached to the power supply (however always with the same transformer, 5V-10A)(may be this the problem?) . What I think is that the problem is the power supply but not having specific knowledge about it I hope to find someone who can help me.

Has anyone ever encountered the same problems by connecting multiple PCA9685 boards?
Could there be errors in the code?

Thank you!

This is the Processing code that with the Kinect generates a string every 2 seconds and sends it to Arduino

import org.openkinect.freenect.*;
import org.openkinect.freenect2.*;
import org.openkinect.processing.*;
import org.openkinect.tests.*;
import processing.serial.*;

Serial myPort;  //Nome porta seriale

Kinect kinect;  //Nome kinect

PImage img;

int row = 3;  //NUMERO DI RIGHE DA IMPOSTARE
int col = 5;  //NUMERO DI COLONNE DA IMPOSTARE

int nPixel = row*col;  //Totale tasselli
int skipx = 512/col;
int skipy = 424/row;

void setup() {
  size(512, 424);
  kinect = new Kinect(this);
  kinect.initDepth();
  
  myPort = new Serial(this, "COM9", 9600);
  img = createImage(kinect.width, kinect.height, RGB);
}

void draw() {
  frameRate(30);
  background(0);
  img.loadPixels();
  immagineKinect();
      
      byte[] stringa = new byte [nPixel];
      
      for (int r=0; r<row; r++) {
        for (int i=r*col; i<col*r+col; i++) {
          color pixel = get((i-col*r)*skipx+skipx/2,r*skipy+skipy/2);
          if (red(pixel) == 255 && green(pixel) == 0 && blue(pixel) == 150) {
            stringa [i] = 1;
          }else{
            //stringa [i] = 0;
          }
        }
      }
      
  myPort.write(stringa);
  println(stringa);
  delay(2000);
  img.updatePixels();
  
}

void immagineKinect() {  
  int[] depth = kinect.getRawDepth();
  
  for (int x = 0; x < kinect.width; x+=skipx) {
    for (int y = 0; y < kinect.height; y+=skipy) {
      int offset = x + y * kinect.width;
      
      int b = depth[offset];
      
      if (b > 400 && b < 800) {
        fill(255,0,150);
        rect(x,y,skipx,skipy);
        //delay(2);
      }else{
        fill(0);
        rect(x,y,skipx,skipy);
        delay(15);  //metà del ritardo del motore
      }
    }
  }
}

This is the Arduino code that reads the string and communicates with the PCA9685 boards

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver pwm2 = Adafruit_PWMServoDriver(0x41);
Adafruit_PWMServoDriver pwm3 = Adafruit_PWMServoDriver(0x42);
Adafruit_PWMServoDriver pwm4 = Adafruit_PWMServoDriver(0x43);


#define SERVOMIN  230 // this is the 'minimum' pulse length count (out of 4096) 
#define SERVOMAX  500 // this is the 'maximum' pulse length count (out of 4096) 

const int row = 4;
const int col = 16;
const int num_iter = 64; // Numero di tasselli e numero di bytes
byte bytes[num_iter];
byte rot[num_iter];

void setup () {
  Serial.begin(9600);
  
  pwm1.begin();
  pwm1.setPWMFreq(60); // Analog servos run at ~60 Hz updates

  pwm2.begin();
  pwm2.setPWMFreq(60);

  pwm3.begin();
  pwm3.setPWMFreq(60);

  pwm4.begin();
  pwm4.setPWMFreq(60);
  
  delay(10); 
}

void loop() {
  
}

void serialEvent() {
  while (Serial.available()) {
    for (int n=0; n <num_iter; n++) {
      bytes[n] = Serial.read();
      delay(2);      
    }
    
    for (int n=0; n < 16; n++) {
      if (bytes[n] == 1 && rot[n] == 0) {
        SetservoMax(n);
        rot[n] = 1;
      } 
      else if (bytes[n] == 0 && rot[n] == 1) {
        SetservoMin(n);
        rot[n] = 0;
      }
      delay(20);
    }

    for (int n=16; n < 32; n++) {
      if (bytes[n] == 1 && rot[n] == 0) {
        SetservoMax1(n-16);
        rot[n] = 1;
      } 
      else if (bytes[n] == 0 && rot[n] == 1) {
        SetservoMin1(n-16);
        rot[n] = 0;
      }
      delay(20);
    }    
    for (int n=32; n < 48; n++) {
      if (bytes[n] == 1 && rot[n] == 0) {
        SetservoMax2(n-32);
        rot[n] = 1;
      } 
      else if (bytes[n] == 0 && rot[n] == 1) {
        SetservoMin2(n-32);
        rot[n] = 0;
      }
      delay(20);
    }
    for (int n=48; n < 64; n++) {
      if (bytes[n] == 1 && rot[n] == 0) {
        SetservoMax3(n-48);
        rot[n] = 1;
      } 
      else if (bytes[n] == 0 && rot[n] == 1) {
        SetservoMin3(n);
        rot[n] = 0;
      }
      delay(20);
    }
  }
}
  


void SetservoMax (int servoIndex) {  
      pwm1.setPWM(servoIndex, 0, SERVOMAX);  
}

void SetservoMin (int servoIndex) {  
      pwm1.setPWM(servoIndex, 0, SERVOMIN); 
}

void SetservoMax1 (int servoIndex1) {  
      pwm2.setPWM(servoIndex1, 0, SERVOMAX);
}

void SetservoMin1 (int servoIndex) {  
      pwm2.setPWM(servoIndex, 0, SERVOMIN); 
}

void SetservoMax2 (int servoIndex) {  
      pwm3.setPWM(servoIndex, 0, SERVOMAX);  
}

void SetservoMin2 (int servoIndex) {  
      pwm3.setPWM(servoIndex, 0, SERVOMIN); 
}

void SetservoMax3 (int servoIndex) {  
      pwm4.setPWM(servoIndex, 0, SERVOMAX);        
}

void SetservoMin3 (int servoIndex) {  
      pwm4.setPWM(servoIndex, 0, SERVOMIN); 
}

The scheme of the components is attached.

Have you set the addresses of each board differently?

Have you arranged that only one board has the pull up resistors enabled?

Grumpy_Mike:
Have you arranged that only one board has the pull up resistors enabled?

I don't think that's relevant for four boards.
A combined pull up resistance of 10k/4= 2.5k, plus a bit of the internal pull up of the wire library is well within the specs of standard I2C.
Different addresses is ofcourse important.
Leo..

64 SG90 servos draw about 64*~0.6A = ~38.4Amp on startup.
A switching 10A supply is likely to go in shutdown mode when booting more than one board.

You should have four 10Amp supplies connected to the four PCA9685 boards.
The Arduino should be powered separately.
Leo..

Grumpy_Mike:
Have you set the addresses of each board differently?

Have you arranged that only one board has the pull up resistors enabled?

Yes i followed this tutorial on every step: Chaining Drivers | Adafruit PCA9685 16-Channel Servo Driver | Adafruit Learning System

Wawa:
64 SG90 servos draw about 64*~0.6A = ~38.4Amp on startup.
A switching 10A supply is likely to go in shutdown mode when booting more than one board.

You should have four 10Amp supplies connected to the four PCA9685 boards.
The Arduino should be powered separately.
Leo..

I really hope this is the solution, now I've just bought a new 10A supplies to test 2 boards, I will let you know the outcome.

Wawa:
64 SG90 servos draw about 64*~0.6A = ~38.4Amp on startup.
A switching 10A supply is likely to go in shutdown mode when booting more than one board.

You should have four 10Amp supplies connected to the four PCA9685 boards.
The Arduino should be powered separately.
Leo..

This was the solution thank you so much!