MG996R Servo won't work

I am currently working on this mini Blynk home automation project, and seem to have run into a serious problem working with servos.
Apparently, I can’t compile any code written using the default servo library and so I opted for this EspServo library instead. However, my servo only turns in one direction no matter the value, and won’t return to a zero position, when the required value has been passed to it.

Am using an MG996R servo
Here is my code so far. Every other thing seems to be working fine for now.

#define BLYNK_PRINT Serial

//LIBRARIES INCLUDED
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h>
#include <ESP32Servo.h>


//BLYNK AUTHENTICATION TOKEN
char auth[] = "90ca360db7a2438*********";


// MY WIFI CREDENTIALS
char ssid[] = "******";
char pass[] = "***************";


//SERVO INSTANCE
Servo servo1; //SERVO1
Servo servo2; //SERVO2
Servo servo3; //SERVO3

int minUs = 1000;
int maxUs = 2000;

int servo1Pin = 18; //SERVO1 PIN
int servo2Pin = 19; //SERVO2 PIN
int servo3Pin = 21; //SERVO3 PIN

ESP32PWM pwm;


// DHT INSTANCE
#define DHTPIN 27
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;


//DECLARATION OF VARIABLES
#define rain 32     
#define ldr 33
#define gas 35
#define pir 26
#define buzzer 5
int pir_value;
int pir_check;
int ldr_value;
int rain_value;
int gas_value;
bool Connected2Blynk = false;


//VOID SETUP
void setup()
{
  // Debug console
  Serial.begin(9600);
  dht.begin();
  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000, sendrain_value);
  timer.setInterval(1000, sendldr_value);
  timer.setInterval(1000, sendgas_value);
  timer.setInterval(1000, sendtemp_value);
  pinMode(pir, INPUT);
  pinMode(rain, INPUT);
  pinMode(ldr, INPUT);
  pinMode(gas, INPUT);
  pinMode(buzzer, OUTPUT);
  servo1.setPeriodHertz(50);      
  servo2.setPeriodHertz(50);     
  servo3.setPeriodHertz(330);   
}


//FUNCTIONS
//DHT TEMPERATURE
void sendtemp_value(){
   float temp_value = dht.readTemperature();
   Blynk.virtualWrite(V1, temp_value);
}

//RAIN
void sendrain_value(){
  rain_value = analogRead(rain);
  rain_value = map(rain_value, 1, 4095, 1, 100);
  Blynk.virtualWrite(V2, rain_value);
}

//LDR
void sendldr_value(){
  ldr_value = analogRead(ldr);
  ldr_value = map(ldr_value, 0, 4095, 0, 100);
  Blynk.virtualWrite(V3, ldr_value);
}

//ULTRASONIC
void sendgas_value(){
  gas_value = analogRead(gas);
  Blynk.virtualWrite(V4, gas_value);
}

//PIR
BLYNK_WRITE(V5){
  pir_check = param.asInt();
  Serial.print("PIR CHECK: ");
  Serial.println(pir_check);
} 


//READING FROM VIRTUAL PINS
// SERVO1
BLYNK_WRITE(V6){
  servo1.attach(servo1Pin, minUs, maxUs);
  servo1.write(param.asInt());
  servo1.detach();
}

//SERVO2
BLYNK_WRITE(V7){
  servo2.attach(servo2Pin, minUs, maxUs);
  servo2.write(param.asInt());
  servo2.detach();
}

//SERVO3
BLYNK_WRITE(V8){
  servo3.attach(servo3Pin, minUs, maxUs);
  servo3.write(param.asInt());
  servo3.detach();
}


//VOID LOOP RUNS CONTINUOUSLY THROUGH OUT THE PROGRAM
void loop()
{
  Blynk.run();
  timer.run();

    //EXTRA CODE FOR PIR SHOULD BE REMOVED FROM LOOP
    if (pir_check == 1){
      pir_value = digitalRead(pir);
      Serial.print("PIR VALUE: ");
      Serial.println(pir_value);
      if (pir_value == 1){
        digitalWrite(buzzer, HIGH);
      }
    else{
      digitalWrite(buzzer, LOW);
        }
      }
}

Try to use the new ESP32_ISR_Servo that can fix the issue

Your code rewritten using that library is below:

#ifndef ESP32
#error This code is designed to run on ESP32 platform, not Arduino nor ESP8266! Please check your Tools->Board setting.
#endif

#define BLYNK_PRINT Serial

//See file .../hardware/espressif/esp32/variants/(esp32|doitESP32devkitV1)/pins_arduino.h
#define LED_BUILTIN       2         // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED
#define PIN_LED           2         // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED

#define PIN_D0            0         // Pin D0 mapped to pin GPIO0/BOOT/ADC11/TOUCH1 of ESP32
#define PIN_D1            1         // Pin D1 mapped to pin GPIO1/TX0 of ESP32
#define PIN_D2            2         // Pin D2 mapped to pin GPIO2/ADC12/TOUCH2 of ESP32
#define PIN_D3            3         // Pin D3 mapped to pin GPIO3/RX0 of ESP32
#define PIN_D4            4         // Pin D4 mapped to pin GPIO4/ADC10/TOUCH0 of ESP32
#define PIN_D5            5         // Pin D5 mapped to pin GPIO5/SPISS/VSPI_SS of ESP32
#define PIN_D6            6         // Pin D6 mapped to pin GPIO6/FLASH_SCK of ESP32
#define PIN_D7            7         // Pin D7 mapped to pin GPIO7/FLASH_D0 of ESP32
#define PIN_D8            8         // Pin D8 mapped to pin GPIO8/FLASH_D1 of ESP32
#define PIN_D9            9         // Pin D9 mapped to pin GPIO9/FLASH_D2 of ESP32
  
#define PIN_D10           10        // Pin D10 mapped to pin GPIO10/FLASH_D3 of ESP32
#define PIN_D11           11        // Pin D11 mapped to pin GPIO11/FLASH_CMD of ESP32
#define PIN_D12           12        // Pin D12 mapped to pin GPIO12/HSPI_MISO/ADC15/TOUCH5/TDI of ESP32
#define PIN_D13           13        // Pin D13 mapped to pin GPIO13/HSPI_MOSI/ADC14/TOUCH4/TCK of ESP32
#define PIN_D14           14        // Pin D14 mapped to pin GPIO14/HSPI_SCK/ADC16/TOUCH6/TMS of ESP32
#define PIN_D15           15        // Pin D15 mapped to pin GPIO15/HSPI_SS/ADC13/TOUCH3/TDO of ESP32
#define PIN_D16           16        // Pin D16 mapped to pin GPIO16/TX2 of ESP32
#define PIN_D17           17        // Pin D17 mapped to pin GPIO17/RX2 of ESP32     
#define PIN_D18           18        // Pin D18 mapped to pin GPIO18/VSPI_SCK of ESP32
#define PIN_D19           19        // Pin D19 mapped to pin GPIO19/VSPI_MISO of ESP32

#define PIN_D21           21        // Pin D21 mapped to pin GPIO21/SDA of ESP32
#define PIN_D22           22        // Pin D22 mapped to pin GPIO22/SCL of ESP32
#define PIN_D23           23        // Pin D23 mapped to pin GPIO23/VSPI_MOSI of ESP32
#define PIN_D24           24        // Pin D24 mapped to pin GPIO24 of ESP32
#define PIN_D25           25        // Pin D25 mapped to pin GPIO25/ADC18/DAC1 of ESP32
#define PIN_D26           26        // Pin D26 mapped to pin GPIO26/ADC19/DAC2 of ESP32
#define PIN_D27           27        // Pin D27 mapped to pin GPIO27/ADC17/TOUCH7 of ESP32     
   
#define PIN_D32           32        // Pin D32 mapped to pin GPIO32/ADC4/TOUCH9 of ESP32
#define PIN_D33           33        // Pin D33 mapped to pin GPIO33/ADC5/TOUCH8 of ESP32
#define PIN_D34           34        // Pin D34 mapped to pin GPIO34/ADC6 of ESP32
#define PIN_D35           35        // Pin D35 mapped to pin GPIO35/ADC7 of ESP32
#define PIN_D36           36        // Pin D36 mapped to pin GPIO36/ADC0/SVP of ESP32
#define PIN_D39           39        // Pin D39 mapped to pin GPIO39/ADC3/SVN of ESP32

#define PIN_RX0            3        // Pin RX0 mapped to pin GPIO3/RX0 of ESP32
#define PIN_TX0            1        // Pin TX0 mapped to pin GPIO1/TX0 of ESP32

#define PIN_SCL           22        // Pin SCL mapped to pin GPIO22/SCL of ESP32
#define PIN_SDA           21        // Pin SDA mapped to pin GPIO21/SDA of ESP32  

#define USE_SPIFFS    true
//#define USE_SPIFFS    false

//#define USE_BLYNK_WM    true            // https://github.com/khoih-prog/Blynk_WM
#define USE_BLYNK_WM    false

//LIBRARIES INCLUDED
#include <WiFi.h>
#include <WiFiClient.h>

#if USE_BLYNK_WM
  #include <BlynkSimpleEsp32_WM.h>                    // https://github.com/khoih-prog/Blynk_WM
#else
  #include <BlynkSimpleEsp32.h>

  //BLYNK AUTHENTICATION TOKEN
  char auth[] = "******";
  
  
  // MY WIFI CREDENTIALS
  char ssid[] = "****";
  char pass[] = "****";
  
#endif
  
#include <DHT.h>

#define USE_ESP32_ISR_SERVO       true

#if USE_ESP32_ISR_SERVO

  #define TIMER_INTERRUPT_DEBUG       1
  #define ISR_SERVO_DEBUG             1
  
  // Select different ESP32 timer number (0-3) to avoid conflict
  #define USE_ESP32_TIMER_NO          3

  #include "ESP32_ISR_Servo.h"

  // MG996R servo has a running current of  500mA to 900mA @6V and a stall current of 2.5A @ 6V
  // Power supply must be adequate
  // Published values for SG90 servos; adjust if needed
  #define MIN_MICROS      800  //544
  #define MAX_MICROS      2450
  
  int servoIndex1  = -1;
  int servoIndex2  = -1;
  int servoIndex3  = -1;

  int servo1Pin = PIN_D25; //SERVO1 PIN
  int servo2Pin = PIN_D26; //SERVO2 PIN
  int servo3Pin = PIN_D27; //SERVO3 PIN
    
#else

  #include <ESP32Servo.h>

  //SERVO INSTANCE
  Servo servo1; //SERVO1
  Servo servo2; //SERVO2
  Servo servo3; //SERVO3
  
  int minUs = 1000;
  int maxUs = 2000;

  int servo1Pin = 18; //SERVO1 PIN
  int servo2Pin = 19; //SERVO2 PIN
  int servo3Pin = 21; //SERVO3 PIN

  ESP32PWM pwm;
  
#endif


// DHT INSTANCE
#define DHTPIN 27
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

BlynkTimer timer;

//DECLARATION OF VARIABLES
#define rain 32     
#define ldr 33
#define gas 35
#define pir 26
#define buzzer 5
int pir_value;
int pir_check;
int ldr_value;
int rain_value;
int gas_value;
bool Connected2Blynk = false;

//FUNCTIONS

void send_values()
{
  sendrain_value();
  sendldr_value();
  sendgas_value();
  sendtemp_value();
  
}

//DHT TEMPERATURE
void sendtemp_value()
{
  float temp_value = dht.readTemperature();
  Blynk.virtualWrite(V1, temp_value);
}

//RAIN
void sendrain_value()
{
  rain_value = analogRead(rain);
  rain_value = map(rain_value, 1, 4095, 1, 100);
  Blynk.virtualWrite(V2, rain_value);
}

//LDR
void sendldr_value()
{
  ldr_value = analogRead(ldr);
  ldr_value = map(ldr_value, 0, 4095, 0, 100);
  Blynk.virtualWrite(V3, ldr_value);
}

//ULTRASONIC
void sendgas_value()
{
  gas_value = analogRead(gas);
  Blynk.virtualWrite(V4, gas_value);
}

//PIR
BLYNK_WRITE(V5)
{
  pir_check = param.asInt();
  Serial.print("PIR CHECK: ");
  Serial.println(pir_check);
} 


//READING FROM VIRTUAL PINS
// SERVO1
BLYNK_WRITE(V6)
{
  #if USE_ESP32_ISR_SERVO
    ESP32_ISR_Servos.setPosition(servoIndex1, param.asInt());
  #else
    // Too much work inside BLYNK_WRITE()
    servo1.attach(servo1Pin, minUs, maxUs);
    servo1.write(param.asInt());
    servo1.detach();
  #endif
}

//SERVO2
BLYNK_WRITE(V7)
{
  #if USE_ESP32_ISR_SERVO
    ESP32_ISR_Servos.setPosition(servoIndex2, param.asInt());
  #else
    // Too much work inside BLYNK_WRITE()
    servo2.attach(servo2Pin, minUs, maxUs);
    servo2.write(param.asInt());
    servo2.detach();
  #endif  
}

//SERVO3
BLYNK_WRITE(V8)
{
  #if USE_ESP32_ISR_SERVO
    ESP32_ISR_Servos.setPosition(servoIndex3, param.asInt());
  #else
    // Too much work inside BLYNK_WRITE()
    servo3.attach(servo3Pin, minUs, maxUs);
    servo3.write(param.asInt());
    servo3.detach();
  #endif  
}

//PIR Alarm
void pir_alarm()
{
  if (pir_check == 1)
  {
    pir_value = digitalRead(pir);
    Serial.print("PIR VALUE: ");
    Serial.println(pir_value);
    if (pir_value == 1)
    {
      digitalWrite(buzzer, HIGH);
    }
    else
    {
      digitalWrite(buzzer, LOW);
    }
  }
}

//VOID SETUP
void setup()
{
  // Debug console
  Serial.begin(115200);
  Serial.println("\nStarting");
  
  dht.begin();

  #if USE_BLYNK_WM
    Blynk.begin();
  #else
    Blynk.begin(auth, ssid, pass);
  #endif

  // 1s timer to check PIR alarm
  timer.setInterval(1000, pir_alarm);
  
  // Change to 10s timer
  timer.setInterval(10000, send_values);
  //timer.setInterval(1000, sendrain_value);
  //timer.setInterval(1000, sendldr_value);
  //timer.setInterval(1000, sendgas_value);
  //timer.setInterval(1000, sendtemp_value);
  
  pinMode(pir, INPUT);
  pinMode(rain, INPUT);
  pinMode(ldr, INPUT);
  pinMode(gas, INPUT);
  pinMode(buzzer, OUTPUT);

  #if USE_ESP32_ISR_SERVO
    //Select ESP32 timer USE_ESP32_TIMER_NO
    ESP32_ISR_Servos.useTimer(USE_ESP32_TIMER_NO);
    
    servoIndex1 = ESP32_ISR_Servos.setupServo(servo1Pin, MIN_MICROS, MAX_MICROS);
    servoIndex2 = ESP32_ISR_Servos.setupServo(servo2Pin, MIN_MICROS, MAX_MICROS);
    servoIndex3 = ESP32_ISR_Servos.setupServo(servo3Pin, MIN_MICROS, MAX_MICROS);
    
    if (servoIndex1 != -1)
      Serial.println("Setup Servo1 OK");
    else
      Serial.println("Setup Servo1 failed");
  
    if (servoIndex2 != -1)
      Serial.println("Setup Servo2 OK");
    else
      Serial.println("Setup Servo2 failed");    

    if (servoIndex3 != -1)
      Serial.println("Setup Servo3 OK");
    else
      Serial.println("Setup Servo3 failed");    

  #else
    servo1.setPeriodHertz(50);      
    servo2.setPeriodHertz(50);     
    servo3.setPeriodHertz(330);
  #endif
}

//VOID LOOP RUNS CONTINUOUSLY THROUGH OUT THE PROGRAM
void loop()
{
  Blynk.run();
  timer.run();

#if 0
  //EXTRA CODE FOR PIR SHOULD BE REMOVED FROM LOOP
  if (pir_check == 1)
  {
    pir_value = digitalRead(pir);
    Serial.print("PIR VALUE: ");
    Serial.println(pir_value);
    if (pir_value == 1)
    {
      digitalWrite(buzzer, HIGH);
    }
    else
    {
      digitalWrite(buzzer, LOW);
    }
  }
#endif
}

I change the servo pins to different ones to test and OK so far (on SG90 servo as I don’t have MG996R). Remember to use very good power supply for those servos as they are using high current to achieve high torque.

  int servo1Pin = PIN_D25; //SERVO1 PIN
  int servo2Pin = PIN_D26; //SERVO2 PIN
  int servo3Pin = PIN_D27; //SERVO3 PIN

Adjust these values UP and DOWN to achieve the best and accurate results

 #define MIN_MICROS      800  //544
 #define MAX_MICROS      2450

Good luck and remember to post test results, good or bad.

Thanks, I’ll surely get back to you on the result.

It says error compiling to Esp board.
Exit status 1

Did you install the library ESP32_ISR_Servo from Arduino Library Manager ?

The compiler will be OK after you install the library

This is the output from terminal when running it

Starting
[172] Loading config file...
[172] OK
[172] Header = ESP32, SSID = ****, PW = ****
[172] Server = ****.duckdns.org, Port = 8080, Token = *****
[176] Board Name = ****
[179] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.6.1 on ESP32

[284] connectToWifi: start
[785] connectToWifi: connected OK
[785] IP: 192.168.2.104
[785] begin: WiFi connected. Try connecting to Blynk
[907] Ready (ping: 7ms).
[976] begin: WiFi and Blynk connected
ESP32TimerInterrupt: _timerNo = 3, _fre = 1000000.00, _count = 0 - 10
Setup Servo1 OK
Setup Servo2 OK
Setup Servo3 OK

Yeah. It uploads now, seems to be working fine with an SG90 model. But am still having trouble with the MG996R.
Am guessing it’s a power issue. But am using a 9v battery.

Remember to use very good power supply for those servos as they are using high current to achieve high torque.

// MG996R servo has a running current of 500mA to 900mA @6V and a stall current of 2.5A @ 6V
// Power supply must be adequate

I don’t think 9V battery can provide enough current to drive MG996R servo. Please use a good 2A+, 6-9V Adaptor separately for each MG996R. You drive 3 of them, it’s better to use 10A, 6-9V power adaptor.
You can also Google research as many people have had the power issues driving this MG996R beast.

And you also have to use an external driver (MOSFET, etc.) to drive them, not directly from ESP32 as they need 4.8V to 7.2V PWM amplitude.

So the problem is not because of Blynk. You can change the title to reflect that.

Sure! Thanks for your help so far