How to Synchronize 360° Servo Motors for a Bipedal Robot

I am currently working on a project to create a bipedal robot, but I have encountered a significant challenge. I am using four SG90 360° continuous rotation servo motors, and I am struggling to synchronize them properly.

The main issues are:

  1. One servo tends to move faster than the others, disrupting the robot's balance.
  2. Even when I manage to synchronize them momentarily, they desynchronize after 2-3 seconds of operation.

Here are the specifics of my setup:

  • Servo Motors: Four SG90 360° continuous rotation servo motors.
  • Power Supply: A 9V battery.
  • Control Board: ESP8266.

I suspect the problem could be related to power delivery, control signal stability, or mechanical differences between the servos.

Does anyone have ideas or advice on how to address these synchronization issues? Any guidance or tips would be greatly appreciated.

Thank you in advance!

I moved your topic to an appropriate forum category @timour .

In the future, please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

What kind of battery? A PP3 block battery for fire alarm?

Servos have brushed DC motors, and no two are identical. They generally run at different speeds under otherwise identical conditions.

One of several ways to synchronize brushed DC motors requires use of shaft encoders to measure the position and speed, then adjust individual motor speeds accordingly.

One other thing to consider, are the loads on each motor identical all the time the motors are turning?

Thank you for your suggestion! That's a great point. I believe each motor is subjected to the same mass during operation, but it's possible that slight differences in mechanical resistance or alignment could be causing discrepancies in their movement. However, I don't think this is the cause, as there is really only a small difference in mass.

Thank you for this answer. Considering this, I was wondering if you have any code or suggestions on how to modify the PWM signals for each motor to adjust their speeds individually and help with synchronization?

Yes a rechargeable battery 9v

Reduce the PWM value to slow down the faster motor. There is no formula, because motor response to PWM is not linear.

I think it's a simple 9v battery

For four servos, you need a servo power supply capable of providing 4.8 to 6V at 3 to 4 Amperes, minimum. Don't forget to connect the grounds!

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Servo.h>

const char* ssid = "Timourb";
const char* password = "123456789";

Servo RightMotor, RightMotor2, LeftMotor, LeftMotor2, MiddleMotor, NutMotor;

int middleMotorPin = D0;
int rightMotorPin = D1;
int rightMotor2Pin = D2;
int leftMotorPin = D3;
int leftMotor2Pin = D4;
int nutMotorPin = D6;

ESP8266WebServer server(80);
int state = 0;  // Variable d'état

void setup() {
  Serial.begin(9600);
  
  MiddleMotor.attach(middleMotorPin);
  RightMotor.attach(rightMotorPin);
  RightMotor2.attach(rightMotor2Pin);
  LeftMotor.attach(leftMotorPin);
  LeftMotor2.attach(leftMotor2Pin);
  NutMotor.attach(nutMotorPin);
  
  WiFi.softAP(ssid, password);
  Serial.println("Point d'accès démarré. IP : ");
  Serial.println(WiFi.softAPIP());

  server.on("/", handleRoot);
  server.on("/move", handleMove);
  server.on("/release", handleRelease);

  server.begin();
  Serial.println("Serveur Web démarré !");
}

void loop() {
  server.handleClient();

  // Exécution de l'action en fonction de l'état actuel
  switch (state) {
    case 0:
      // Aucun bouton appuyé : ne rien faire
      Serial.println("En attente...");
      RightMotor.write(90);
      RightMotor2.write(90);
      LeftMotor.write(90);
      LeftMotor2.write(90);
      MiddleMotor.write(90);
      NutMotor.write(90);
      delay(100);
      break;

    case 1:
      // Action si "forward" (H) est appuyé
      Serial.println("Avancer");
      RightMotor.write(60);
      RightMotor2.write(60);
      delay(200);
      break;

Here is my code: when the "H" button is pressed, the right motor will run, and at the same time, the right2 motor will also run. I have several other cases in the code, but this is the most important one. I haven't included the two left motors yet, as my primary focus is to synchronize the right motors first. Once I manage that, I will apply the same logic to the left motors. But i don't understand how can i change the PWM. Can you help me to understand more. Thank you in advance

This call sets the servo PWM value (not strictly PWM, but pulse width), which with continuous rotation servos, controls the RPM, not the servo shaft position.

      NutMotor.write(90);

Those a code that allows you to input different PWM values from the keyboard and observe how the PWM changes for the servo motors (speed). This would help me see the differences in PWM values between the motors in real-time.

Have a look at the servo library reference page.
https://docs.arduino.cc/libraries/servo/

Perhaps you do not understand synchronization. You must pick the slowest motor and force the other three to move at the same speed as that one motor. DO NOT think about synchronizing all 4 motors!

Thank you for your advice! However, how can I ensure that all the motors run at exactly the same speed? Which function should I use to synchronize their speeds perfectly?

Thanks

This is not possible, nor is it needed for a robot moving through the environment. It will encounter different terrains, obstacles, make turns, change speed, etc.

Your code should instead maintain a desired direction of travel by continuously monitoring progress and adjusting motor speeds as required.

So The best solution would be to compare the speed of each motor and compensate for the differences found.

#include <Servo.h>

// Déclaration des servo moteurs
Servo right;
Servo right2;

// Variables pour stocker les signaux PWM des servos
int pwmRight = 90;  // 90 = arrêt
int pwmRight2 = 90; // 90 = arrêt

void setup() {
  // Attacher les servos à leurs pins respectifs
  right.attach(5);
  right2.attach(6);

  // Initialiser le moniteur série
  Serial.begin(9600);

  // Instructions d'utilisation
  Serial.println("=== Controle des moteurs ===");
  Serial.println("Entrez 'R' suivi d'une valeur (ex: R120) pour modifier PWM du moteur Right.");
  Serial.println("Entrez 'L' suivi d'une valeur (ex: L110) pour modifier PWM du moteur Right2.");
}

void loop() {
  // Vérifier si une commande est disponible dans le moniteur série
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n'); // Lire la commande jusqu'à un saut de ligne

    // Vérifier si la commande concerne le moteur Right
    if (input.startsWith("R")) {
      pwmRight = input.substring(1).toInt(); // Extraire et convertir la valeur numérique
      pwmRight = constrain(pwmRight, 0, 180); // Limiter la valeur entre 0 et 180
      Serial.print("PWM Right mis à jour : ");
      Serial.println(pwmRight);
    }

    // Vérifier si la commande concerne le moteur Right2
    else if (input.startsWith("L")) {
      pwmRight2 = input.substring(1).toInt(); // Extraire et convertir la valeur numérique
      pwmRight2 = constrain(pwmRight2, 0, 180); // Limiter la valeur entre 0 et 180
      Serial.print("PWM Right2 mis à jour : ");
      Serial.println(pwmRight2);
    }
  }

  // Appliquer les valeurs PWM aux servos
  right.write(pwmRight);
  right2.write(pwmRight2);

  // Petite pause pour éviter les conflits de lecture/écriture
  delay(20);
}

I have this code to compare the speeds in real-time, and I will observe the results visually. Seems it a good idea ?

You have not explained how your "bipedal robot" is constructed or configured, which forum members generally need to know, in order to constructively comment on your code.

With two wheel drive for example, the simplest way to make a robot run straight is to use shaft or wheel encoders.

Count encoder pulses for a suitable interval, and if they are not the same for each motor, adjust the power to correct for the difference in counts.

One approach uses a simple PID controller and goes something like this:

count_diff = left_counts - right_counts;
set_right_speed(base_speed + Kp*count_diff); //if left has more counts, speed up the right motor
set_left_speed (base_speed - Kp*count_diff); // and slow down the left motor

Adjust base_speed and Kp (the P term in a PID controller) to suit.

Another approach is to use a magnetometer as a compass to determine direction of travel, and likewise adjust motor speeds to move in the commanded direction.

Thank you for the detailed explanation! I appreciate the suggestion to use encoders and a PID controller for synchronization. I will try this method and adjust the parameters as you mentioned. Once I test it, I'll let you know if it works.

Thanks again for your help!