Automatic Pet Feeder 3D Printer File Image 1
Automatic Pet Feeder 3D Printer File Image 2
Automatic Pet Feeder 3D Printer File Image 3
Automatic Pet Feeder 3D Printer File Image 4
Automatic Pet Feeder 3D Printer File Image 5
Automatic Pet Feeder 3D Printer File Image 6
Automatic Pet Feeder 3D Printer File Image 7
Automatic Pet Feeder 3D Printer File Image 8
Automatic Pet Feeder 3D Printer File Image 9
Automatic Pet Feeder 3D Printer File Image 10
Automatic Pet Feeder 3D Printer File Image 11
Automatic Pet Feeder 3D Printer File Image 12
Automatic Pet Feeder 3D Printer File Thumbnail 1
Automatic Pet Feeder 3D Printer File Thumbnail 2
Automatic Pet Feeder 3D Printer File Thumbnail 3
Automatic Pet Feeder 3D Printer File Thumbnail 4
Automatic Pet Feeder 3D Printer File Thumbnail 5
Automatic Pet Feeder 3D Printer File Thumbnail 6
Automatic Pet Feeder 3D Printer File Thumbnail 7
Automatic Pet Feeder 3D Printer File Thumbnail 8
Automatic Pet Feeder 3D Printer File Thumbnail 9
Automatic Pet Feeder 3D Printer File Thumbnail 10
Automatic Pet Feeder 3D Printer File Thumbnail 11
Automatic Pet Feeder 3D Printer File Thumbnail 12

Automatic Pet Feeder

Bubba Gump avatarBubba Gump

April 16, 2025

printables-icon

Description

Summary

I designed this Automatic Pet Feeder to be a simple and reliable solution for dispensing pet food, especially large chunks that many existing feeders struggle with. Most automatic feeders on the market are designed for small cat food pellets, but I wanted something that could handle larger food pieces while remaining easy to use and maintain.

This feeder operates with a single button press, making it straightforward and efficient. The design features a modular structure that allows it to be easily removed from its wall-mounted docking for cleaning, ensuring hygiene and long-term durability. By combining 3D printing and Arduino, I created a customizable, user-friendly solution for pet owners who need a manual yet controlled feeding system without complex programming or smart app dependencies.
________________________________________________________________________________________________________________

Functions

  • Dispenses a portion of food with a single button press.
  • Easily adjust the amount of food exactly to what your pet likes.
  • Ensures a consistent portion size each time.
  • Easy to clean and maintain.

________________________________________________________________________________________________________________

Hardware and Software Used 

Hardware:

3D Printed Parts
#Part NameQuantity
1Cylinder Lid1
2Docking Station1
3Electronics Box1
4Electronics Box Lid1
5Mixing Spur Gear1
6Mixing Tank1
7Mixing Tank Floor1
8Mixing Tank Funnel1
9Spur Gear1
10Spur Gear Cover1
Electronic Components
#ComponentPN / NoteSupplierPicture
1Arduino Micro-Arduino
2Motor DriverTB6612FNGSparkFun
3MotorJGY370, 12V, 100RPMAliExpress
4Push ButtonLBJQKJ LB16A-P11/EAliExpress
5Half Breadboard-AliExpress
6DC Barrel Jack-AliExpress
712V Power Supply2 ampAliExpress
Fasteners
#FastenersQuantity
1Phillips Thread-Forming Screw M3x107
2ISO 7380 M3x8mm (socket head screw)4
3DIN 934 M3 (hex nut)1
4DIN 913 M3x6mm (set screw)1
Other

Polycarbonate (or other food-safe material) tube:

  • Outer diameter: 120 mm.
  • Wall thickness: around 3 mm.
  • Height: I used a 300 mm height. 
    Choose the height according to the amount of food you want to store.

*Make sure that the tube is made of food-safe material.

Software:

  • PrusaSlicer
  • Arduino IDE
  • SolidWorks (for designing the 3d parts)

____________________________________________________________________________________________________________

Wiring Diagram

The wiring is pretty straightforward. Just follow the wiring diagram.

Motor:
(+) → A01 on SparkFun Motor Driver
(-) → A02 on SparkFun Motor Driver

Push Button:
LED → D2 Pin on Arduino 
C (Common) → D3 Pin on Arduino
NO (Normally Open) → VCC on SparkFun Motor Driver
NC (Normally Close) → GND on SparkFun Motor Driver/Arduino
A → NC on Push Button

DC Barrel Jack:
(+) → VIN on Arduino and  VM on SparkFun Motor Driver
(-) → GND on Arduino and GND on SparkFun Motor Driver

Arduino:
D4 Pin → STBY on SparkFun Motor Driver
D5 Pin → PWMA on SparkFun Motor Driver
D6 Pin → AI1 on SparkFun Motor Driver
D7 Pin → AI2 on SparkFun Motor Driver
5V → VCC on SparkFun Motor Driver

Arduino Micro Board:

SparkFun Motor Driver Board:

________________________________________________________________________________________________________________

Code

The Arduino code controls the DC motor that rotates the feeder’s dispensing mechanism. 
The button press triggers the motor to turn for a set number of cycles, moving the food through the dispensing system.

Button Pressing Options

The button has 2 pressing options:

  • Short press (less than 1 second) → start the feeding process.
  • Long press (more than 1 second) → stop the motor and reset the Arduino.

Use the Long Press option to reset the Arduino if something gets stuck during the feeding process and you want to immediately stop the motor.

Key Code Functionality:
  1. The feeding amount is controlled by the feedingCycles variable.
  2. When the button is pressed, the motor completes a set number of on-off cycles to ensure a consistent portion is dispensed.
    (The LED light on the button will turn on)
  3. The default value of feedingCycles is 5, which dispenses approximately 200 grams of food.
  4. You can adjust the feeding amount by changing the feedingCycles value in the code. This variable is in the first line of the code.
  5. After dispensing, the motor stops, waiting for the next button to be pressed. 
    (The LED light on the button will turn off)
How to Adjust the Portion Size:
  • To dispense more food, increase the value of feedingCycles.
  • To dispense less food, decrease the value of feedingCycles.
Upload the code to the Arduino Micro:
  1. Open the Arduino IDE.
  2. Start a new sketch, and delete everything.
  3. Copy and paste the following code into the sketch.
  4. Make sure to select the correct Arduino Micro board.
  5. Upload the sketch.
  6. You will probably see the following message in the Arduino IDE output during the upload. Don’t worry — this is completely normal.
  7. Make sure to see the Done uploading message at the lower right corner of the Arduino IDE when it completes the upload.

This is the code to copy into a new sketch:

const int feedingCycles = 5;
#include <avr/wdt.h>

// %%%%%%%%%%  CONSTANT PARAMETERS  %%%%%%%%%%
#define CW 1
#define CCW -1
#define STP 0
#define CW_Time 4000
#define CCW_Time 500
#define feedingPWM 250

// %%%%%%%%%%  PINS DEFENITION  %%%%%%%%%%
const int buttonLedPin = 2; // push button integrated blue led
const int buttonPin = 3;    // push button
const int stbyPin = 4;      // motor driver standby
const int pwmPin = 5;       // motor driver PWM
const int AIn1pin = 6;      // motor driver INA1: CW input
const int AIn2pin = 7;      // motor driver INA2: CCW input

// %%%%%%%%%%  INITIALIZE VARIABLES  %%%%%%%%%%
int buttonState = HIGH;             
int lastButtonState = LOW;       
int cyclesCounter = 1;
unsigned long buttonPressTime = 0;    // Variable to store the time when the button was pressed
unsigned long cycleStartTime = 0;     // Variable to store the time when new cycle has started
bool longPress = false;               // Flag to track if the long-press action has been executed
bool shortPress = false;              // Flag to track if the short-press action has been executed
bool feedingInProcess = false;        // Flag for feeding process 
bool cycleInProcess = false;          // Flag for cycle initiate actions

void setup() {

  Serial.begin(9600);
  delay(1000);

  pinMode(buttonLedPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(stbyPin, OUTPUT);
  pinMode(pwmPin, OUTPUT);
  pinMode(AIn1pin, OUTPUT);
  pinMode(AIn2pin, OUTPUT);

  digitalWrite(buttonLedPin, LOW);
  digitalWrite(stbyPin, LOW);
  digitalWrite(pwmPin, LOW);
  digitalWrite(AIn1pin, LOW);
  digitalWrite(AIn2pin, LOW);
}

void loop() {
  buttonState = digitalRead(buttonPin);

  // Check for a button press
  if (buttonState == HIGH && lastButtonState == LOW) {
    buttonPressTime = millis();     // Record the time when the button was pressed
    longPress = false;              // Reset the long press action flag
    shortPress = false;             // Reset the short press action flag
    Serial.println("Button pressed: ");
  }

  // Long press
  if (buttonState == HIGH && (millis() - buttonPressTime >= 1000) && !longPress) {
    Serial.println("Long press");
    longPress = true; 
    setMotor(STP, 0);
    delay(50);
    Serial.println("Arduino about to reset");
    for (int i = 0; i < 8; i++) {
      digitalWrite(buttonLedPin, HIGH);
      Serial.print("-");
      delay(150);
      digitalWrite(buttonLedPin, LOW);
      Serial.print("-");
      delay(150);
    }
      wdt_enable(WDTO_15MS); // Enable watchdog timer (15ms timeout)
      while (1);  // Force reset
  }
  
  // Short press
  if (buttonState == LOW && lastButtonState == HIGH && !shortPress && !longPress && !feedingInProcess) {
    Serial.println("Short press --> Feeding start");
    shortPress = true;
    feedingInProcess = true;
    delay(10);
  }
  if(buttonState == LOW && feedingInProcess) {
    feeding(feedingCycles);
  }
  lastButtonState = buttonState;
}

// Motor function
void setMotor(int direction, int pwmVal) {
  analogWrite(pwmPin, pwmVal);
  if (direction == 1) {
    digitalWrite(stbyPin, HIGH);
    digitalWrite(AIn1pin, HIGH);
    digitalWrite(AIn2pin, LOW);
    //Serial.println("Motor Go CW");
  } else if (direction == -1) {
    digitalWrite(stbyPin, HIGH);
    digitalWrite(AIn1pin, LOW);
    digitalWrite(AIn2pin, HIGH);
    Serial.println("Motor Go CCW");
  } else {
    digitalWrite(stbyPin, LOW);
    digitalWrite(AIn1pin, LOW);
    digitalWrite(AIn2pin, LOW);
    Serial.println("Motor Stop");
  }
}

// Feeding function
void feeding (int cyclesNumber) {
  if (buttonState == LOW && feedingInProcess && cyclesCounter <= cyclesNumber) {
    if (!cycleInProcess) {
      cycleStartTime = millis(); // store the time when new cycle start
      Serial.print("Cycle number: ");
      Serial.println(cyclesCounter);
      Serial.println("Motor Go CW");
      digitalWrite(buttonLedPin, HIGH);
    }
    // Motor Go CW as long as the time difference is between the CW_Time range 
    if (millis() - cycleStartTime < CW_Time) {
      cycleInProcess = true;
      setMotor(CW, feedingPWM);
    }
    // Cycle last actions
    else {
      setMotor(STP, 0);
      delay(100);
      setMotor(CCW, feedingPWM);
      delay(CCW_Time);
      setMotor(STP, 0);
      cycleInProcess = false;
      cyclesCounter++;
      delay(50);
    }
  }
  else {
  // Feeding finish
    feedingInProcess = false;
    cyclesCounter = 1;
    Serial.println("Feeding finished");
    Serial.println("-----------------------------------------");
    Serial.println();
    digitalWrite(buttonLedPin, LOW);
    delay(100);
  }
}

________________________________________________________________________________________________________________

Printing Instructions

  • Material: PLA (make sure that you use a food-safe material).
  • Layer height: 0.2 mm.
  • All the printable parts files are already correctly oriented for printing.
#Part NameImageInfill [%]WallsSupport
1Cylinder Lid152No
2Docking Station204Yes
3Electronics Box152No
4Electronics Box Lid152No
5Mixing Spur Gear504No
6Mixing Tank152Yes
7Mixing Tank Floor204No
8Mixing Tank Funnel152No
9Spur Gear1004No
10Spur Gear Cover152No

________________________________________________________________________________________________________________

Assembly Instructions

It is recommended to review the attached STEP files for the top and sub-assemblies. 
This will help you understand how each component fits together.

Docking Station Assembly
  1. Connect the motor the the docking station part using 4 ISO 7380 M3x8mm (socket head screw).
  2. Insert 1 DIN 934 M3 (hex nut) into the spur gear.
  3. Connect the spur gear to the motor shaft using 1 DIN 913 M3x6mm (set screw).
    Pay attention to tighten the screw on the flat part of the shaft.
  4. Insert the spur gear lid on top of the spur gear to cover it.
  5. Insert the push button into the docking station and lock it with its nut from the other side.
  6. Connect the electronic box assembly to the docking station using 3 Phillips Thread-Forming Screw M3x10. 
    It is recommended to wire everything on the breadboard before inserting the breadboard and the components inside the electronics box.
  7. Insert the motor and the push button wires inside the electronics box via the side slot. Wire the wires to the breadboard.
  8. Arrange all the wires inside and outside the electronics box to have a nice and clean look.
  9. Close the electronics box lid.
Mixing Tank Assembly
  1. Insert the mixing tank funnel into the mixing tank. You can use a bit of super glue to get a better connection between the parts.
  2. Insert the mixing spur gear into the center hole in the mixing tank floor. Try to rotate the mixing spur gear with your hand and see that it rotates freely.

  3. Connect the mixing tank floor (with the mixing spur gear on it) to the mixing tank using 4 Phillips Thread-Forming Screw M3x10. Make sure to align the groove in the mixing tank floor to the groove in the mixing tank.
  4. Insert the polycarbonate tube into the mixing tank. 
Top Assembly
  1. Insert the mixing tank assembly into the docking station assembly. Make sure to align them so the groove in the mixing tank will be positioned where the spur gear is. 
    The spur gear and the mixing spur gear should properly engage with each other.
  2. Push the button and check that the motor rotates the mixing spur gear properly.
  3. Attach the docking station assembly to the wall using the 2 mounting holes.

________________________________________________________________________________________________________________

Video

________________________________________________________________________________________________________________

If you have any further questions, please feel free to send me a message.