Servo not stops

Hi. I have this problem, my servo moves continuously even after the set angle it must reach. My circuit is as follows, I have an Esp32 with a webserver that has a joystick that sends commands to an arduino Uno, I want to control the direction of a car with an SG90 Servo. The direction is ok when I move the jpystick left and right, but the problem is that it does not stop at the set angle, but goes further. If I hold the right or left Joystick it goes continuously. Below I have put the code I am using now.

Thank you in advance!

#include <AFMotor.h>
#include <ArduinoJson.h>
#include <Servo.h>

// Motor control setup
AF_DCMotor motorLeft(3);   // Motor (back-left)
AF_DCMotor motorRight(4);  // Motor (back-right)

// Servo control setup
Servo steeringServo;

const int servoPin = 9;  // Pin connected to the servo
// Serial communication variables
const size_t bufferSize = 200;
char serialBuffer[bufferSize];
size_t bufferIndex = 0;
bool dataReady = false;

// Current servo position
int currentServoPosition = 90;  // Initial position (center)

// Previous x value for comparison
int prevX = -1;

void setup() {
  Serial.begin(115200);

  // Motor control setup
  motorLeft.setSpeed(0);  // Initialize motor speed to 0
  motorRight.setSpeed(0);
  motorLeft.run(RELEASE);  // Initialize motor state to released
  motorRight.run(RELEASE);

  // Servo setup
  steeringServo.attach(servoPin);
  steeringServo.write(currentServoPosition);  // Set initial position to default (center)

  Serial.println("Arduino Uno setup complete");
}

void loop() {
  // Read data from Serial
  while (Serial.available()) {
    char receivedChar = Serial.read();

    if (receivedChar == '{') {
      bufferIndex = 0;  // Start of new JSON object
    }

    if (bufferIndex < bufferSize - 1) {
      serialBuffer[bufferIndex++] = receivedChar;
    }

    if (receivedChar == '}') {
      serialBuffer[bufferIndex] = '\0';  // Null-terminate the string
      dataReady = true;
    }
  }

  // Process received data
  if (dataReady) {
    StaticJsonDocument<200> doc;
    DeserializationError error = deserializeJson(doc, serialBuffer);

    if (error) {
      Serial.print("Failed to parse JSON: ");
      Serial.println(error.c_str());
    } else {
      int x = doc["x"];
      int y = doc["y"];
      int angle = doc["angle"];

      // Serial.print("Received data: x: ");
      // Serial.print(x);
      // Serial.print(", y: ");
      // Serial.print(y);
      // Serial.print(", angle: ");
      // Serial.println(angle);

      controlMotors(y);
      controlSteering(x);
    }

    dataReady = false;
  }
}

void controlMotors(int y) {
  int motorSpeed = 255;  // Set a fixed motor speed

  if (y > 0) {
    // Forward
    motorLeft.setSpeed(motorSpeed);
    motorRight.setSpeed(motorSpeed);
    motorLeft.run(FORWARD);
    motorRight.run(FORWARD);
  } else if (y < 0) {
    // Backward
    motorLeft.setSpeed(motorSpeed);
    motorRight.setSpeed(motorSpeed);
    motorLeft.run(BACKWARD);
    motorRight.run(BACKWARD);
  } else {
    // Stop
    motorLeft.run(RELEASE);
    motorRight.run(RELEASE);
  }
}

void controlSteering(int x) {

  // Map the joystick x value (0 to 100) to servo angle (0 to 180 degrees)
  int servoAngle = map(x, 0, 100, 0, 180);


}

full code pls
steeringServo used only in setup()
controlSteering() function doing nothing

#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

// Replace with your network credentials
const char* ssid = "xxxxxxx";
const char* password = "xxxxxxxxxx";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<html>
<head>
   <title>Mousebot</title>
   <meta name="viewport" content="user-scalable=no">
</head>
<body style="position: fixed; font-family: '[Gill Sans]', '[Gill Sans MT]', [Calibri], '[Trebuchet MS]', sans-serif; color:rgb(128, 128, 128); font-size: xx-large;">
   <h1 style="text-align:center">MOUSEBOT</h1>
   <p style="text-align: center;"> X: 
      <span id="x_coordinate"></span> Y: 
      <span id="y_coordinate"></span> Speed: 
      <span id="speed"></span> % Angle: 
      <span id="angle"></span> 
   </p>
   <canvas id="canvas" name="game"></canvas>
<script>
var canvas, ctx;
var paint = false;
var coord = { x: 0, y: 0 };
var width, height, radius, x_orig, y_orig;
var isResting = true; // Flag to track if joystick is at rest

window.addEventListener('load', () => {
    canvas = document.getElementById('canvas');
    if (!canvas) {
        console.log("Canvas not found!");
        return;
    }
    ctx = canvas.getContext('2d');
    if (!ctx) {
        console.log("Canvas 2d context not created!");
        return;
    }
    resize();
    document.addEventListener('mousedown', startDrawing);
    document.addEventListener('mouseup', stopDrawing);
    document.addEventListener('mousemove', Draw);
    document.addEventListener('touchstart', startDrawing);
    document.addEventListener('touchend', stopDrawing);
    document.addEventListener('touchcancel', stopDrawing);
    document.addEventListener('touchmove', Draw);
    window.addEventListener('resize', resize);

    // Initialize display values
    document.getElementById("x_coordinate").innerText = 50;
    document.getElementById("y_coordinate").innerText = 0;
    document.getElementById("speed").innerText = 0;
    document.getElementById("angle").innerText = 0;
});

function resize() {
    width = window.innerWidth;
    radius = 100;
    height = radius * 6.5;
    ctx.canvas.width = width;
    ctx.canvas.height = height;
    background();
    joystick(width / 2, height / 3);
}

function background() {
    x_orig = width / 2;
    y_orig = height / 3;

    ctx.beginPath();
    ctx.arc(x_orig, y_orig, radius + 20, 0, Math.PI * 2, true);
    ctx.fillStyle = '#ECE5E5';
    ctx.fill();
}

function joystick(width, height) {
    ctx.beginPath();
    ctx.arc(width, height, radius, 0, Math.PI * 2, true);
    ctx.fillStyle = '#F08080';
    ctx.fill();
    ctx.strokeStyle = '#F6ABAB';
    ctx.lineWidth = 8;
    ctx.stroke();
}

function getPosition(event) {
    var mouse_x = event.clientX || event.touches[0].clientX;
    var mouse_y = event.clientY || event.touches[0].clientY;
    coord.x = mouse_x - canvas.offsetLeft;
    coord.y = mouse_y - canvas.offsetTop;
}

function is_it_in_the_circle() {
    var current_radius = Math.sqrt(Math.pow(coord.x - x_orig, 2) + Math.pow(coord.y - y_orig, 2));
    return radius >= current_radius;
}

function startDrawing(event) {
    paint = true;
    isResting = false; // Joystick is being moved
    getPosition(event);
    if (is_it_in_the_circle()) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        background();
        joystick(coord.x, coord.y);
        Draw();
    }
}

function stopDrawing() {
    paint = false;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    background();
    joystick(width / 2, height / 3);
    document.getElementById("x_coordinate").innerText = 50; // Set x to 50 when in rest position
    document.getElementById("y_coordinate").innerText = 0;
    document.getElementById("speed").innerText = 0;
    document.getElementById("angle").innerText = 0;

    if (!isResting) {
        // Send rest position coordinates once
        send(50, 0, 0, 0);
        isResting = true;
    }
}

function Draw(event) {
    if (paint) {
        getPosition(event);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        background();

        var angle_in_degrees, x, y, speed;
        var angle = Math.atan2((coord.y - y_orig), (coord.x - x_orig));
        if (Math.sign(angle) == -1) {
            angle_in_degrees = Math.round(-angle * 180 / Math.PI);
        } else {
            angle_in_degrees = Math.round(360 - angle * 180 / Math.PI);
        }
        if (is_it_in_the_circle()) {
            joystick(coord.x, coord.y);
            x = coord.x;
            y = coord.y;
        } else {
            x = radius * Math.cos(angle) + x_orig;
            y = radius * Math.sin(angle) + y_orig;
            joystick(x, y);
        }

        speed = Math.round(100 * Math.sqrt(Math.pow(x - x_orig, 2) + Math.pow(y - y_orig, 2)) / radius);

        // Map x_relative to the range [0, 100]
        var x_relative_raw = x - x_orig;
        var x_relative_mapped = ((x_relative_raw + radius) / (2 * radius)) * 100;

        var y_relative = Math.round(y - y_orig);
        document.getElementById("x_coordinate").innerText = Math.round(x_relative_mapped);
        document.getElementById("y_coordinate").innerText = y_relative;
        document.getElementById("speed").innerText = speed;
        document.getElementById("angle").innerText = angle_in_degrees;

        isResting = false; // Joystick is being moved

        // Send updated coordinates during drawing
        send(Math.round(x_relative_mapped), y_relative, speed, angle_in_degrees);
    }
}

function send(x, y, speed, angle) {
    var data = {
        x: x,
        y: y,
        speed: speed,
        angle: angle
    };
    // Send the data as an HTTP POST request
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/data", true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify(data));
    console.log("Sending data:", data);
}
</script>
</body>
</html>





)rawliteral";

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void handleData(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
  StaticJsonDocument<200> doc;
  DeserializationError error = deserializeJson(doc, data);
  if (error) {
    request->send(400, "text/plain", "Invalid JSON");
    return;
  }

  int x = doc["x"];
  int y = doc["y"];
  int speed = doc["speed"];
  int angle = doc["angle"];

  Serial.printf("{\"x\":%d,\"y\":%d,\"speed\":%d,\"angle\":%d}\n", x, y, speed, angle);
  request->send(200, "text/plain", "Data received");
}

void setup() {
  Serial.begin(115200);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Serve the HTML page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html);
  });

  // Handle incoming data
  server.on("/data", HTTP_POST, [](AsyncWebServerRequest *request){}, NULL, handleData);

  // Handle not found
  server.onNotFound(notFound);

  // Start server
  server.begin();
}

void loop() {

}

Welcome to the forum

What you have is a "continuous rotation servo". You cannot control its angle only its direction of rotation and speed. Please post a link to where you got it from

You need to buy a proper servo

no Servo lib included
why you waste my time?

The 2nd code that I posted is the code from the webserver, and in the first post I have the code from the Arduino Una that has the servo library in it.

Hi. I buy it from Aliexpress, here it is the link link Servo. I buy Servo 360

That is your problem. As @zmyl3 pointed out, a 360 degree servo is intended for continuous rotation. You need the 180 degree model if you want to control position.

Hi, @zmyl3
Welcome to the forum;
Unfortunately you purchased this one;


Instead of this one;

Tom.. :smiley: :+1: :coffee: :australia:
PS. A typical very misleading AliExpress page... you have to read everything at least 3 times to see what they are actually going to send you.

As mentioned before, a 360 servo "stop" point is near 90 degrees - servo.write(90); but you will find the true "stop" value is a little more or a little less than 90. You will need to experiment with the value.

To help you with your project, here is a simulation with code showing the control of a 360 servo. It keeps a 360 servo rotating between 15rpm and 30rpm by simulating a microswitch (a button) being pressed at every rotation, then calculating "rotate faster" or "rotate slower".