Servo MG996R not working well

hi guys , i have a project with 8 sensors connected with arduino nano and the nine one is servo mg996r , when i run my code the servo starts moving in strange way and not as required of it and its main task in the project , anyone knows why?

this is my code :


#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <MPU6050_light.h>
#include <HX711.h>
#include <Servo.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>

// ==== Pins ====
#define LDR_PIN A0
#define SERVO_PIN 9
#define DHT_PIN 2
#define DHT_TYPE DHT22
#define SCALE_DT 6
#define SCALE_SCK 5
#define GPS_RX 4
#define GPS_TX 3
#define LED_OK 11
#define LED_ERR 12
#define BUZZER 10

// ==== Objects ====
Servo servo;
DHT dht(DHT_PIN, DHT_TYPE);
MPU6050 mpu(Wire);
HX711 scale;
SoftwareSerial gpsSerial(GPS_RX, GPS_TX);
TinyGPSPlus gps;

// ==== Thresholds ====
const int lightThresh = 300;
const float tempMin = 30.0, tempMax = 38.0;
const float humMin = 45.0, humMax = 75.0;
const float mpuThresh = 0.5;
const float theftRadius = 100.0;
const float originLat = 32.411438;
const float originLng = 35.341606;

// ==== States ====
bool manualMode = false;
bool doorOpen = false;
bool alertActive = false;
bool redState = false;
bool servoMoving = false;

// ==== Sensor Readings ====
float temp = 0, hum = 0;
float accX = 0, accY = 0, accZ = 1;
float weight = 0;
float lat = 0, lng = 0, dist = 0;
int lightVal = 0;

// ==== Servo Control ====
int servoPos = 0, targetPos = 0;
unsigned long lastServoMs = 0;
const int servoDelay = 15;

// ==== Timing ====
unsigned long tLdr = 0, tDht = 0, tMpu = 0, tWeight = 0, tGps = 0, tPrint = 0, tBlink = 0;
const unsigned long iLdr = 1000, iDht = 3000, iMpu = 500, iWeight = 3000, iGps = 1000, iPrint = 1000;

String cmd = "", reason = "";

void setup() {
  Serial.begin(9600);
  gpsSerial.begin(9600);

  servo.attach(SERVO_PIN);
  servo.write(servoPos);

  dht.begin();
  Wire.begin();
  mpu.begin();
  mpu.calcOffsets(true, true);

  scale.begin(SCALE_DT, SCALE_SCK);
  scale.set_scale(27.2);
  scale.tare();

  pinMode(LED_OK, OUTPUT);
  pinMode(LED_ERR, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  digitalWrite(LED_OK, HIGH);

  Serial.println("Ready.");
}

void loop() {
  unsigned long now = millis();

  updateGPS();
  handleCmd();
  moveServo();

  if (!manualMode && !servoMoving && now - tLdr >= iLdr) {
    tLdr = now;
    lightVal = analogRead(LDR_PIN);
    controlDoor();
  }

  if (now - tDht >= iDht) {
    tDht = now;
    temp = dht.readTemperature();
    hum = dht.readHumidity();
  }

  if (now - tMpu >= iMpu) {
    tMpu = now;
    mpu.update();
    accX = mpu.getAccX();
    accY = mpu.getAccY();
    accZ = mpu.getAccZ();
  }

  if (now - tWeight >= iWeight) {
    tWeight = now;
    weight = scale.get_units(4);
  }

  alertCheck();

  if (now - tPrint >= iPrint) {
    tPrint = now;
    printData();
  }
}

void updateGPS() {
  while (gpsSerial.available()) gps.encode(gpsSerial.read());
  if (millis() - tGps >= iGps && gps.location.isUpdated()) {
    tGps = millis();
    lat = gps.location.lat();
    lng = gps.location.lng();
  }
}

void handleCmd() {
  if (Serial.available()) {
    cmd = Serial.readStringUntil('\n');
    cmd.trim();
    if (cmd == "open")  { startServo(servoPos, 90); doorOpen = true; manualMode = true; }
    if (cmd == "close") { startServo(servoPos, 0);  doorOpen = false; manualMode = true; }
    if (cmd == "auto")  manualMode = false;
  }
}

void startServo(int from, int to) {
  servoPos = from;
  targetPos = to;
  servoMoving = true;
  lastServoMs = millis();
}

void moveServo() {
  if (servoMoving && millis() - lastServoMs >= servoDelay) {
    lastServoMs = millis();
    if (servoPos < targetPos) servoPos++;
    else if (servoPos > targetPos) servoPos--;
    else servoMoving = false;
    servo.write(servoPos);
  }
}

void controlDoor() {
  if (lightVal > lightThresh && !doorOpen) {
    startServo(servoPos, 90);
    doorOpen = true;
  } else if (lightVal <= lightThresh && doorOpen) {
    startServo(servoPos, 0);
    doorOpen = false;
  }
}

void alertCheck() {
  bool dhtOk = !isnan(temp) && !isnan(hum);
  bool fall = accZ < 0.5;
  bool tilt = abs(accX) > mpuThresh || abs(accY) > mpuThresh;
  bool tempA = dhtOk && (temp < tempMin || temp > tempMax);
  bool humA = dhtOk && (hum < humMin || hum > humMax);

  dist = calcDist(lat, lng, originLat, originLng);
  bool theft = dist > theftRadius;

  alertActive = fall || tilt || tempA || humA || theft;

  reason = "";
  if (fall)   reason += "Fall,";
  if (tilt)   reason += "Tilt,";
  if (tempA)  reason += "Temp,";
  if (humA)   reason += "Humidity,";
  if (theft)  reason += "Theft,";
  if (reason.endsWith(",")) reason.remove(reason.length() - 1);

  if (alertActive) {
    if (millis() - tBlink > 500) {
      tBlink = millis();
      redState = !redState;
      digitalWrite(LED_ERR, redState);
      digitalWrite(BUZZER, redState);
    }
    digitalWrite(LED_OK, LOW);
  } else {
    digitalWrite(LED_ERR, LOW);
    digitalWrite(BUZZER, LOW);
    digitalWrite(LED_OK, HIGH);
  }
}

void printData() {
  Serial.print("{");
  Serial.print("\"temp\":" + String(temp) + ",");
  Serial.print("\"hum\":" + String(hum) + ",");
  Serial.print("\"accX\":" + String(accX) + ",");
  Serial.print("\"accY\":" + String(accY) + ",");
  Serial.print("\"accZ\":" + String(accZ) + ",");
  Serial.print("\"weight\":" + String(weight) + ",");
  Serial.print("\"light\":" + String(lightVal) + ",");
  Serial.print("\"door\":\"" + String(doorOpen ? "open" : "closed") + "\",");
  Serial.print("\"alert\":" + String(alertActive ? "true" : "false") + ",");
  Serial.print("\"reason\":\"" + reason + "\",");
  Serial.print("\"lat\":" + String(lat, 6) + ",");
  Serial.print("\"lng\":" + String(lng, 6));
  Serial.println("}");
}

float calcDist(float lat1, float lon1, float lat2, float lon2) {
  const float R = 6371000;
  float dLat = radians(lat2 - lat1);
  float dLon = radians(lon2 - lon1);
  float a = sin(dLat / 2) * sin(dLat / 2) +
            cos(radians(lat1)) * cos(radians(lat2)) *
            sin(dLon / 2) * sin(dLon / 2);
  float c = 2 * atan2(sqrt(a), sqrt(1 - a));
  return R * c;
}

Probably inadequate power. Impossible to say without any hardware information though.

  • Always show us a good schematic of your proposed circuit.
    Show us good images of your ‘actual’ wiring.

  • Does the servo work when you use a simple servo example sketch ?

A dozen donuts on that never having been tried.

:smiling_face_with_three_hearts:

The lineup is still insane at the new shop in town. Or so I'm told. :smirking_face:

I am sure that the problem is not in the hardware. Yes, I tried a simple sketch and there is no problem. The servo works well.

i dont think so , i tried a simple sketch, and the servo is working fine.

As you will then. If you won't provide useful information about your hardware setup, I have no interest in guessing. Good luck with your project.

what do u want to know about

It seems that about 95% of beginners try to power the servo from the Arduino 5V output, and discover that this does not work well, or at all.

1 Like

Post a wiring diagram.

iam not a beginner and i powerd the servo from external source connected with lm2596 buck converter

i didnt make a wiring digram but i can tell u the connections if u want

Good to know that you are not a beginner, thanks.

Yes, I tried a simple sketch and there is no problem.

Excellent! As an intermediate to advanced programmer, you know to start with working code and add ONE new option or function at a time, testing as you go.

  Serial.print("\"temp\":" + String(temp) + ",");

Use of the String class on MCUs with small amounts of memory like the Classic Nano tends to cause malfunctions or crashes because of memory problems.

Get rid of all the String objects. They are never necessary.

Make a wiring diagram. Draw it by hand. Pin numbers, device names, legible.

1 Like

Guys, I think the problem is due to the GPS. I am using the NEO 6M GPS MODULE in my project, and when I succeed in writing a code to read the GPS data and it works properly, the servo has a problem and starts moving on its own and hangs all the time. When I fix the servo problem, the GPS malfunctions and starts giving me lines of length and width that are zeros.

... guessing without documentation.