Nooby needs help with robot

Hi, could someone help me create a sketch for an Uno connected to a PCA9685 running 9 servos to slowly sweep all servos through 90 degrees left and right and return to 0? It would start with servo 1 through 5 which control eye movements and then followed by 6 through 9 for overall head movement. Thanks.

Hello,

welcome to the forum. What do you mean with eye movements? Are it the eyes of the robot, or does the robot eye tracking of a human?

I don't know the board, but I would suggest getting rid of it and just connect all the servo's to a power supply, connect the ground of the power supply to the Arduino and all the data cables to one off the GPIO pins of the Arduino. That way you don't have to buy the board.

Siebe

Welcome to the forum

You will get plenty of help with your project from forum members but there is an expectation that you will do most of the work yourself

Which Arduino board do you have ?
How are the servos powered ?
Which library are you using to control the PCA9685 ?
Have you written a sketch that controls the movement of at least one servo ?

1 Like

I already have the board and all servos are hooked up. They are used to move the eyes of the robot head. I have a sketch that moves different parts, but not smoothly or gently.

I have an Arduino Uno R3 connected to a PCA9685 board which is connected to 9 servos. A variable power supply is supplying 5v to the PCA board. I have a sketch that operates the servos, but it needs fine tuning to operate the servos smoothly one by one. it is supposed to control the eye movements and overall head movement of a robot head.

In order to move a servo slowly and smoothly you must move it a little, wait a while, move it a little, wait and bit and so on until it reaches the target position

If you want other things to happen while this movement occurs you must not use blocking timing such as delay(). Use millis() for timing instead.

By doing the timing this way you can have several things appear to happen at the same time

See Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

to do it efficiently, use thefor() loop

To do what, exactly? What value would the for-loop control?

To slide the servo with this for() loop:

for(char i = 0; i = 180; i++){

  Servo.write(i);
  delay(/*the time you want to wait (can be regulated with a potentiometer to test the time you actualy want)*/);

}

If you want to go faster, you can of course use more than i++.

Hi, @dspiller

Can you post your current code and a schematic of your project?

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

That will not work if you want the robot to do something else while the servo moves, hence my suggestion to use millis() for timing which allows non blocking code to be written and the for loop to be dispensed with

1 Like

search terms: Servo easing, servosmooth. libraries to smooth servo motion

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

// Initialize the PCA9685 board
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

// Servo parameters
#define SERVOMIN 150 // Minimum pulse length
#define SERVOMAX 600 // Maximum pulse length
#define NUM_SERVOS 9

// Array to hold servo target positions
int servoPositions[NUM_SERVOS] = {90, 90, 90, 90, 90, 90, 90, 90, 90};

// Map angle (0-180) to pulse length
int angleToPulse(int angle) {
  return map(angle, 0, 180, SERVOMIN, SERVOMAX);
}

void setup() {
  Serial.begin(9600);
  Serial.println("Initializing PCA9685");

  pwm.begin();
  pwm.setPWMFreq(50); // Set frequency to 50Hz for servos

  delay(10);
}

// Function to move a servo to a specific angle smoothly
void moveServoSmooth(int servo, int targetAngle, int stepDelay = 10) {
  int currentAngle = servoPositions[servo];
  if (targetAngle > currentAngle) {
    for (int angle = currentAngle; angle <= targetAngle; angle++) {
      pwm.setPWM(servo, 0, angleToPulse(angle));
      delay(stepDelay);
    }
  } else {
    for (int angle = currentAngle; angle >= targetAngle; angle--) {
      pwm.setPWM(servo, 0, angleToPulse(angle));
      delay(stepDelay);
    }
  }
  servoPositions[servo] = targetAngle;
}

void loop() {
  // Example: Move servos in a sequence
  for (int i = 0; i < NUM_SERVOS; i++) {
    int targetAngle = random(30, 150); // Generate random angles for demonstration
    Serial.print("Moving servo ");
    Serial.print(i);
    Serial.print(" to ");
    Serial.println(targetAngle);
    moveServoSmooth(i, targetAngle);
    delay(500);
  }
}

What is your question (other than post #1)? This code appears to work if your mux is connected to I2C and servos are on the first nine slots of the mux. I am only observing the Serial Monitor display the random port and the random degree, I do not have a mux. The Adafruit example seems very different.

My question is how do I slow down and smooth out the servo movements to gently activate each servo one after another with a 5 second delay between them.

Read @Geek_Emeritus Post #12 for servo handling (easing, smoothing) and ignore everything posted by @siebe.

Ok, I am sorry.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.