Last Updated: 05/01/2024
#55 Multiple PCA9685 Servo boards controlling LED's and Servos
Projects >> #55 Multiple PCA9685 Servo boards controlling LED's and Servos
Using multiple PCA9685 boards to control servos and LED's
In this tutorial we will learn how to use multiple PCA9685 boards to control Servos and LED's at the same time.
One set of servos will move rapidly with a matching set of LED's turning on and off.
A 2nd set of servos will move slowly with some LED's changing brightness deoending on the servo position.
WARNING
WARNING: Power Consumption
You will need a seperate 5v power supply for the PCA9685 boards.
Your UNO/Mega/ESP32 Computer USB connection will not be able to provide enough power and damage can be caused...you have been warned.
.
Wiring diagrams
Although the wiring diagram only showss 1 servo on each PCA9685 board the sketch is actually moving every port on the PCA9685 so 16 servos could be moving at the same time.
It is the same with the LED's, the code is controlling all 16 ports.
WARNING The 5V to the PCA9685 board and relays MUST NOT come from the Arduino 5V pin. You will be drawing too many Amps for the Arduino and may cause damage to your Arduino.
Pins
A5 to PCA9685 SCL
A4 to PCA9685 SDA
Make sure you have 5v going to the PCA9685 as well as the VCC and GND. One powers the circuitry, the other supply powers the servo.
Wiring:for a few common boards
SDA/SCL connections
Arduino UNO:
A4 (SDA), A5 (SCL)
:
Arduino Mega 2560:
20 (SDA), 21 (SCL)
:
ESP32: 21(SDA), 22 (SCL)
For other Arduino boards see:https://www.arduino.cc/en/reference/wire
Connection Test 1 ...IMPORTANT
Bad wiring is one of the biggest problems with Arduino projects so run this test to make sure your board is being found before doing anythine else.
Once you have connected your boards up as shown above check that it can be found.
If you are using an Arduino board go to File>Examples>
Wire>I2c_scanner and upload the skecth to your board.
if all goes well your serial Monitor will display something like.
Don't forget to solder across the gaps to right on the board to change the board addresses
Scanning...
I2C device found at address 0x40 !
I2C device found at address 0x41 !
I2C device found at address 0x46 !
done
Servos can be added to the 2 servo boards and LED's to the board you want to attach to them
Connection Test 2 ...Board and Servo Test
First make sure you have the Adafruit PWM Servo Library installed.
Tools>Manage Libraries>
Type Adafruit PWM Servo Library in the serach bar.
If it is not installed install it.
Connect the board according to the circuit diagram.
Now download a test file from the Adafruit PWM servo Library examples.
File>Examples>Adafruit PWM servo Driver Library>servo.
Load the sketch and in the Serial Monitor you should see something like:
8 channel Servo test!
0
1
2
3
4
5
6
7
If you have a servo in any of the first 8 connections (nearest board connection end) you servo should move back and forth a couple of times.
At this point although we may not understand the sketch we know the board and servos work.
Example 1: PCA9685MultipleBoardsV1.ino
Click to Download code: PCA9685MultipleBoardsV1.ino
This version uses nested if statements to read the buttons and although it works would be very complicated if it was controlling 16 servos.
Thios version has NO relay control.
/* PCA9685MultipleBoardsV1
05/01/2024
Serial.print() statements have been left in the code to try and help you see what is happeneing at various points
WARNING: You will need an alternate power supply for the PCA9685 boards
Arduino/Computer USB will become overloaded..leading to weird results/SMOKE
You have been warned!
Goals
control servos on multiple boards
Control LED's on another board
LED's 0-7 to flash on and off in time with Servo's on Board0 rapid move
LED's 8-15 to vary brightness as servos on board1 sweep slowly
My Board address
0x40 ... servos
0x41 ... servos
0x46 ...leds
*/
#include "Wire.h"
#include "Adafruit_PWMServoDriver.h"
//Create all the servo objects.
Adafruit_PWMServoDriver servoBoard0 = Adafruit_PWMServoDriver(0x40);//Address found from I2C scanner
Adafruit_PWMServoDriver servoBoard1 = Adafruit_PWMServoDriver(0x41);//Address found from I2C scanner
Adafruit_PWMServoDriver LEDBoard = Adafruit_PWMServoDriver(0x46);//Address found from I2C scanner
#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
#define LED_FREQ 1600 //frequency required to make LEDS light correctly
unsigned long currentMillis; //stores values of milliseconds since board started
int rapidMoveDir;
int rapidMovePos;
unsigned long rapidMoveTimer;
int slowSweepTarget;
int slowSweepPos;
unsigned long slowSweepTimer;
void setServoPos(int servoBoard, int servo, int pos) {
//This first bit of code makes sure we are not trying to set the servo outside of limits
int sendPos;
if (pos > 179) {
pos = 179;
}
if (pos < 0) {
pos = 0;
}
sendPos = USMIN + ((USMAX - USMIN) / 180 * pos);
if (servo > -1 && servo < 16) { //only try to move valid servo addresses
//this switch statement decides what board is being controlled
//
switch (servoBoard) {
case 0:
servoBoard0.writeMicroseconds(servo, sendPos);
break;
case 1:
servoBoard1.writeMicroseconds(servo, sendPos);
break;
//add more servo boards as below
// case 2:
// servoBoard2.writeMicroseconds(servo, sendPos);
// break;
default:
Serial.println("Invalid Board, add to system");
break;
}
}
}
void setup() {
Serial.begin(9600);
Serial.println("PCA9685MultipleBoardsV1");
//Start servo boards
servoBoard0.begin();
servoBoard0.setOscillatorFrequency(27000000);
servoBoard0.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates
//2nd board
servoBoard1.begin();
servoBoard1.setOscillatorFrequency(27000000);
servoBoard1.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates
//LED Board
LEDBoard.begin();//start the PCA9685 for the station building
LEDBoard.setPWMFreq(LED_FREQ); // This is the maximum PWM frequency and suited to LED's
delay(10);//let everything settle down
}
void loop() {
int q;
int ledBrightness;
currentMillis = millis();
//Do rapid move of Servo
if (currentMillis - rapidMoveTimer >= 3000) { //3000 will move every 3 seconds
rapidMoveTimer = currentMillis;//reset timer for next move
Serial.println(rapidMoveTimer);
if (rapidMoveDir > 0) {
rapidMoveDir = 0;
rapidMovePos = 0;//position to move servos to
Serial.println("Rapid to 0");
//Leds off
for (q = 0; q < 8; q++) {
LEDBoard.setPWM(q, 0, 4096);//turn lights off
}
} else {
rapidMoveDir = 1;
rapidMovePos = 179;//position to move servos to
Serial.println("Rapid to 179");
//leds on
for (q = 0; q < 8; q++) {
LEDBoard.setPWM(q, 0, 4095);//turn lights on
}
}
//now set the servos on board0
for (q = 0; q < 16; q++) {
setServoPos(0, q, rapidMovePos);//moves servo board 0, Servo number q, position = rapisMovePos
}
}
//end of rapid moves
//start slow movement of servos
if (currentMillis - slowSweepTimer >= 50) { //move every 0.05 secs 1 degree
slowSweepTimer = currentMillis;//reset timer for next move
if (slowSweepTarget != slowSweepPos) { //if target not reached
if (slowSweepTarget > slowSweepPos) {
slowSweepPos++;//if target is greater move towards it
} else {
slowSweepPos--;//if target is smaller move towards it
}
for (q = 0; q < 16; q++) {
setServoPos(1, q, slowSweepPos);//1 = servoboard1, q servo number, angle to move to
}
} else { //if the values..reached destination so change destination
if (slowSweepTarget > 0) {
slowSweepTarget = 0;
} else {
slowSweepTarget = 179;
}
}
//set LED brightness depending on position
ledBrightness = ((4096 / 180) * slowSweepPos) - 1; //4906 brightness levels/180 positions gives brightness per step
Serial.println(ledBrightness);//brightness value out of a max of 4094
for (q = 8; q < 16; q++) {
LEDBoard.setPWM(q, 0, ledBrightness);//set led brightness
}
}
//end of slow movement of servos
}
Additional Resource Links
PCA9685 PWM Servo Board 27/12/2023
Lesson 3: Using "if else" to control code 19/07/2021
Lesson 5: Using "switch" to control code 21/07/2021
Lesson 7: delay() v's millis(), controlling timing of programs 23/07/2021
Comments
This site has been designed to be child friendly, this means that comments cannot be added to videos or directly to the site. To add a comment or ask a question please email the address in this image: and use #55 Multiple PCA9685 Servo boards controlling LED's and Servos as a reference.