MGR996R Servo not operating correctly powered via MOSFET

Hello all, first post on these forums. Not highly experienced in electronics, but a learner. Physics major.

I am attempting to build an automated cat feeder based on similar designs found on the internet. The device uses a gravity feed with a servo to align holes for food dispensing. An RTC breakout is used for time keeping and alarm activation. The device is powered by 4x AA batteries, and uses a boost converter breakout module to provide the higher voltage needed by the servo.

An N-channel MOSFET is being used as a control switch for the boost converter. When enabled by the Arduino, it turns on the boost converter. This will help save battery life.

THE PROBLEM: As currently set up, the servo fails to operate correctly, only giving some small jerking motions. I have confirmed the servo works properly in other configurations. The circuit is prototyped as shown in the Fritzing sketch below. I'm also attaching the fritzing file.

I suspect I might have a ground path problem? Can anyone help with that?

Parts:

  • Arduino Micro
  • DS3231 break-out RTC
  • "Mod360" 2-24v boost conveter
  • IRJ520 mosfet
  • MG996R servo
  • Small parts as indicated

Current code:

// Cat Feeder Servo WIP
#include "RTClib.h"
#include "Wire.h"
#include <Servo.h>

#define sec 1000
#define FIRST_COMPILE 0

#define servoPin 4
#define servoPowerPin 12

Servo myservo;
RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
DateTime alarm1;

void setup () {
 Serial.begin(57600);
 while (!Serial);
 Serial.println("<Arduino is ready>");

  // MOSFET on
  pinMode(servoPowerPin, OUTPUT);
  digitalWrite(servoPowerPin, HIGH);

  
  myservo.attach(servoPin);

  rtc.begin();

  // Only needed when setting the RTC to compile time aka system time
  if (FIRST_COMPILE) { setRTC(); }
  
  // Clear any existing alarms in the RTC
  rtc.clearAlarm(1);
  rtc.clearAlarm(2);

  // Set servo start position
  adjustServo(0);
  

if (rtc.lostPower()) {
Serial.println("RTC lost power, setting to compile time");
    setRTC();
 }

// Alarm once every minute
alarm1 = rtc.now() + TimeSpan(60);
Ds3231Alarm1Mode alarm_mode = DS3231_A1_Second;

if (rtc.setAlarm1(alarm1, alarm_mode)) {
  
Serial.print("alarm1 was set to: ");
Serial.print(alarm1.year(), DEC);
    Serial.print('/');
    Serial.print(alarm1.month(), DEC);
    Serial.print('/');
    Serial.print(alarm1.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[alarm1.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(alarm1.hour(), DEC);
    Serial.print(':');
    Serial.print(alarm1.minute(), DEC);
    Serial.print(':');
    Serial.print(alarm1.second(), DEC);
    Serial.println();
    Serial.println();
    
} else {
  Serial.print("alarm1 was not sucessfully set!");
  Serial.println();
}

// End Setup
}


void loop () {
// Print time every X seconds
// Check to see if the alarm was triggered
// Move servo

    // Print current RTC clock time
    DateTime now = rtc.now();

    Serial.print("Current time: ");
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

    // Check for alarm
    if (rtc.alarmFired(1)) { 
        Serial.println("!!!!!!!!!!!!!!!!!!Alarm 1 fired!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        Serial.println();

       // Adjust servo to 90 deg then back to 0 deg
       adjustServo(90);
       adjustServo(0);

       // Clear alarm flag
       rtc.clearAlarm(1);
        
    }

    // Wait 10 seconds
    delay(10*sec);
}

// Sets the RTC to compile time of the sketch
// This is only needed if the RTC is off time or when first setting the time
void setRTC() {
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

// Set servo angle with 0.5 second delay
void adjustServo(int angle) {

  myservo.write(angle);
  delay(500);
}

Cat_Feeder.zip (78.9 KB)

Sorry, the circuit diagram makes no sense.

Fritzing diagrams are pretty much useless, and generally a waste of everyone's time, so please post a hand drawn diagram instead. Tutorial here: How to Read a Schematic - SparkFun Learn

I recommend that you get the circuit working with just the 4xAA battery pack powering the servo, and drop the idea of the step up converter. The servo does not "need" 7V.

  1. I may swap to fewer but more D-cells for capacity, meaning I need a voltage increase; the boost converter also provides a stable voltage. Yes, I could use a linear regulator. I don't have one on hand. The 7.0 v was simply chosen as a useful value for high-torque operation.

  2. If you don't like the fritzing diagram, you can simply just not comment. I would prefer no comments over unhelpful ones. Thank you.

"As currently set up, the servo fails to operate correctly, only giving some small jerking motions."

I don't think voltage boosters will work very well with motors. That being said, looks like the servo ground may be connected to the wrong side of the boost converter, and there does not seem to be a connection between the servo ground and the arduino.

You can't use a low side switch for active devices like servos (and in any case, the MOSFET is drawn backwards in the Fritzing idiot diagram, and the IRF520 won't work with Arduino). If you need to control power to the servo, use a high side switch instead.

If you need higher torque, choose a higher torque servo. The 4xAA battery pack is fine.

Aside -- proper schematic for a low side logic level MOSFET switch (not that it is useful here):