/* 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 }