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:
One servo tends to move faster than the others, disrupting the robot's balance.
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.
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.
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.
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?
#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.
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.
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?
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.