Summary of UCL-Embedded-Automatic-Arduino-Pet-Feeder
This article presents a guide from UCL Odense on building an automatic pet feeder using an Arduino Mega 2560. The device utilizes an ultrasonic sensor to detect food levels, a stepper motor for dispensing, and an OLED display with a real-time clock module to show time and status. The project includes 3D printed components for the housing and bowl, controlled by custom C++ code that schedules feeding times based on user-defined morning and afternoon slots.
Parts used in the Automatic Pet Feeder:
- Arduino Mega 2560
- Stepper Motor 12V 28BYJ-48
- Stepper Motor Driver ULN2003
- Ultrasonic sensor HC-SR04
- Clock Module DS1307
- 0.91" IIC I2C 128x32 SSD1306 SPI OLED Display Module
- Wires M/F and M/M
- Breadboard
- Battery
- 3D Printed STL files (mounts, spacers, bowl)

Ever been in a situation where you had to leave your beloved pet at home while you’re on vacation, running errands or at work? Or perhaps your petsitter is on a tight schedule, making every minute saved invaluable in ensuring your pet’s well-being.
Well, fret not! Thanks to our recent development from the Automation Engineering department at UCL Odense, we’ve created a guide on how you can create this magnificent machine.
Using the powerful and compact hardware solutions of an Arduino Mega 2560, a Stepper Motor, Stepper Driver and an Ultrasonic Sensor making for one sturdy unit.
Step 1: Hardware Required

– 1x Arduino Mega 2560
– 1x Stepper Motor 12V 28BYJ-48
– 1x Stepper Motor Driver ULN2003
– 1x Ultrasonic sensor HC-SR04
– 1x Clock Module DS1307
– 1x 0.91″ IIC I2C 128×32 SSD1306 SPI OLED Display Module
– 20x Wires M/F & 2x Wire M/M
– 1x Breadboard
– 1x Battery
Step 2: Setup

Power = 5V
Ground = GND
OLED_MOSI = 9
OLED_CLK = 10
OLED_DC = 11
OLED_CS = 12
OLED_RESET = 13
trigPin = 2
echoPin = 3
RTC SDA = SDA 20
RTC SCL = SCL 21
motorPin1Feed = 22
motorPin2Feed = 24
motorPin3Feed = 26
motorPin4Feed = 28
Step 3: 3D Printing… 3D Printing… and Some More 3D Printing

As you might’ve noticed there’s quite the amount of STL-files attached to this Instructable, so it’s quite a necessity for our construction to have a 3D printer at hand.
Although we used all of our designs to create this machine, there are a couple of STL-files you can technically live without;
- “mount-base-pet-feeder.stl” – Depends on how you intend to set up the cabin containing the wiring, Arduino, Stepper Motor and Step Driver
- “left-mount-adjuster-pet-feeder.stl” –
- “right-mount-adjuster-pet-feeder.stl” –
- “left-spacer-mount-adjuster-pet-feeder.stl” –
- “right-spacer-mount-adjuster-pet-feeder.stl” –
- “Bowl-v2.stl” – We won’t hold a grudge if you don’t use our purpose-built bowl.
- “M&M’s.stl” – This was only used for rendering and illustrating our Automatic PetFeeder in Autodesk Fusion 360. **Not to be used as food for your pet. We hold no responsibility in improper usage**
Step 4: Let’s Add Some Code
<p>//Basic Embedded Programming 2. Semester Project UCL</p><p>//TinyRTC I2C module DS1307
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}</p><p>#include
#include
#include
#include
#include
#include
RTC_DS1307 RTC;
//#include DS1307 rtc(SDA, SCL);</p><p>//declaring variables for the motor (driver) pins
int motorPin1Feed = 22;
int motorPin2Feed = 24;
int motorPin3Feed = 26;
int motorPin4Feed = 28;</p><p>//if(hour >=
int petFeedMorning;
int petFeedAfternoon;</p><p>int petFedMorning;
int petFedAfternoon;</p><p>//Declare ultrasonic sensor pins
int trigPin = 2; // Trigger
int echoPin = 3; // Echo
long duration, cm, inches;</p><p>// Variables will change:
//Millis()
long previousMillis = 0; // will store last time LED was updated</p><p>// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000; // interval at which to blink (milliseconds)</p><p>//Disp millis()
//int period = 1000;
unsigned long time_now = 0;</p><p>#define STEPSFeed 64
#define STEPSTop 64 //Number of steps per revolution
#define STEPSBottom 64 //Number of steps per revolution</p><p>//The pin connections need to be 4 pins connected
// to Motor Driver In1, In2, In3, In4 and then the
// here in the sequence 1-3-2-4 for proper sequencing of 28BYJ48
Stepper small_stepperFeed(STEPSFeed, motorPin1Feed, motorPin3Feed, motorPin2Feed, motorPin4Feed);</p><p>Stepper small_stepperTop(STEPSTop, motorPin1Top, motorPin3Top, motorPin2Top, motorPin4Top);</p><p>int Steps2TakeFeed;
int Steps2TakeTop;</p><p>unsigned long startMillis; //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 1000; //the value is a number of milliseconds</p><p>#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels</p><p>// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI 9
#define OLED_CLK 10
#define OLED_DC 11
#define OLED_CS 12
#define OLED_RESET 13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);</p><p>// 'Logo 2', 128x32px
static const unsigned char myBitmap [] PROGMEM = {
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbc, 0x3c, 0xc6, 0x1e, 0x0e, 0x07, 0xfc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbc, 0x3c, 0xc6, 0x3c, 0x0f, 0x07, 0xfc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xb4, 0x7c, 0xc6, 0x78, 0x1f, 0x07, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbe, 0x7c, 0xc6, 0xf0, 0x1b, 0x87, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbe, 0x7c, 0xc7, 0xe0, 0x1b, 0x87, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xb6, 0x7c, 0xc7, 0xe0, 0x39, 0x87, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xba, 0x5c, 0xc7, 0xf0, 0x31, 0xc7, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbb, 0xdc, 0xc7, 0x70, 0x7f, 0xc7, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbb, 0xdc, 0xc6, 0x38, 0x7f, 0xc7, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbb, 0xdc, 0xc6, 0x1c, 0x60, 0xe7, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xbb, 0x9c, 0xc6, 0x1e, 0xe0, 0xe7, 0xfc, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xb9, 0x9c, 0xc6, 0x0e, 0xe0, 0x67, 0xfc, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xe7, 0xfc, 0xe0, 0xc7, 0x0e, 0x73, 0x83, 0x07, 0xe1, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xc7, 0xfc, 0xf0, 0xc7, 0x0e, 0x73, 0x83, 0x0f, 0xf1, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xe7, 0x00, 0xf8, 0xc7, 0x8e, 0x73, 0xc3, 0x1c, 0x39, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xe7, 0x00, 0xf8, 0xc7, 0x8e, 0x73, 0xe3, 0x38, 0x19, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xc7, 0x00, 0xfc, 0xc6, 0xce, 0x73, 0x63, 0x38, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xe7, 0xfc, 0xec, 0xc6, 0xee, 0x73, 0x73, 0x38, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xe7, 0xfc, 0xee, 0xc6, 0x6e, 0x73, 0x33, 0x38, 0xf9, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xc7, 0x00, 0xe6, 0xc6, 0x7e, 0x73, 0x1b, 0x30, 0xf9, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xc7, 0x00, 0xe3, 0xc6, 0x3e, 0x73, 0x1b, 0x38, 0x19, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x60, 0xe7, 0x00, 0xe3, 0xc6, 0x3e, 0x73, 0x0f, 0x38, 0x39, 0xff,
0xff, 0xbf, 0xff, 0xff, 0xfc, 0x60, 0xc7, 0xfc, 0xe1, 0xc6, 0x1e, 0x73, 0x0f, 0x1e, 0x79, 0xff,
0xff, 0xbf, 0xff, 0xff, 0xfc, 0x60, 0xc7, 0xfc, 0xe1, 0xc6, 0x0e, 0x73, 0x07, 0x0f, 0xf9, 0xff,
0xff, 0xbf, 0xff, 0xff, 0xfc, 0x60, 0xe7, 0xfe, 0xe0, 0xc6, 0x0e, 0x73, 0x07, 0x07, 0xc9, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff
};</p><p>void setup() {</p><p> Wire.begin();
//Serial Port begin
Serial.begin(9600);
// Using this to set the initial time:
// DS1307 seconds, minutes, hours, day, date, month, year
// setDS1307time(30,9,19,1,1,4,19);
// 1 = Sunday
//Define inputs and outputs (Ultrasonic sensor)
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);</p><p> startMillis = millis(); //initial start time</p><p> // put your setup code here, to run once:
small_stepperFeed.setSpeed(200);
small_stepperTop.setSpeed(200);</p><p> // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}</p><p> // Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(500); // Pause for 2 seconds</p><p> // Clear the buffer
display.clearDisplay();</p><p>}</p><p>void loop() {
//Over 35 cm display length, time, day and date
if(cm >= 45) {
ultrasonic();
displayTimeSerial();
displayTimeDisplay();
delay(750);
displayDayDateDisplay();
delay(750);
checkTime();
Serial.print("Morning: ");
Serial.println(petFeedMorning);
Serial.print("Afternoon: ");
Serial.println(petFeedAfternoon);
}
//Between 35 cm (under) and 5 cm (over) feed pet, turn motor CW
//else if(cm <= 20 && hour >= 7 && hour <= 13) {
if(cm <= 45 && cm >8) {
ultrasonic();
stepMotorFeed();
}
//Under 5 cm display length, time, day and date
else if(cm <= 8) {
ultrasonic();
displayTimeSerial();
displayTimeDisplay();
if(petFedMorning <1) {
petFedMorning +1;
Serial.print(petFedMorning);
}
}
}</p><p>void setDS1307time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
// sets time and date data to DS1307
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0); // set next input to start at the seconds register
Wire.write(decToBcd(second)); // set seconds
Wire.write(decToBcd(minute)); // set minutes
Wire.write(decToBcd(hour)); // set hours
Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
Wire.write(decToBcd(month)); // set month
Wire.write(decToBcd(year)); // set year (0 to 99)
Wire.endTransmission();
}</p><p>void readDS1307time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0); // set DS1307 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// request seven bytes of data from DS1307 starting from register 00h
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}</p><p>void checkTime() {
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// retrieve data from DS1307
readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
&year);
if(hour >= 6 && hour <= 11) {
petFeedMorning = 1;
}
else if (hour >= 5 && hour <= 13) {
petFeedMorning = 0;
}
if(hour >= 17 && hour <= 21) {
petFeedAfternoon = 1;
}
else if(hour <= 16 && hour >= 18) {
petFeedAfternoon = 0;
}
}</p><p>void displayTimeSerial()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// retrieve data from DS1307
readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
&year);
//Current function prints this on the serial monitor
Serial.print(hour, DEC);
// convert the byte variable to a decimal number when displayed
Serial.print(":");
if (minute<10)
{
Serial.print("0");
}
Serial.print(minute, DEC);
Serial.print(":");
if (second<10)
{
Serial.print("0");
}</p><p> //Print seconds on serial monitor
Serial.print(second, DEC);
Serial.print(" ");
//Print numerical day of the month on serial monitor
Serial.print(dayOfMonth, DEC);
Serial.print("/");
//Print month on serial monitor
Serial.print(month, DEC);
Serial.print("/");
//Print year on serial monitor
Serial.print(year, DEC);
Serial.print(" Day of week: ");
//Determine specific day of the week
switch(dayOfWeek){
case 1:
Serial.println("Sunday");
break;
case 2:
Serial.println("Monday");
break;
case 3:
Serial.println("Tuesday");
break;
case 4:
Serial.println("Wednesday");
break;
case 5:
Serial.println("Thursday");
break;
case 6:
Serial.println("Friday");
break;
case 7:
Serial.println("Saturday");
break;
}
}</p><p>void displayTimeDisplay()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// retrieve data from DS1307
readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
&year);
//Current function shows this on the OLED display
//Display
//TODO Millis
/*
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //test whether the period has elapsed
{
display.clearDisplay();
display.display();
display.setCursor(0,0);
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(WHITE);
display.print(cm);
display.println(" Millis");
display.display();
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
*/
//Display distance measured from Ultrasonic sensor on OLED
display.clearDisplay();
display.display();
display.setCursor(0,0);
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(WHITE);
display.print(cm);
display.println(" cm");
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.println();
//Display hours on OLED
display.print(hour, DEC);
//Converting the byte variable to a decimal number when displayed
display.print(":");
if (minute<10)
{
display.print("0");
}
//Display minutes on OLED
display.print(minute, DEC);
display.print(":");
if (second<10)
{
display.print("0");
}
//Display seconds on OLED
display.print(second, DEC);
display.print(" ");</p><p> //Between 35 cm (under) and 5 cm (over) feed pet, turn motor CW
//else if(cm <= 20 && hour >= 7 && hour <= 13) {
if(cm <= 35 && cm >5) {
display.setCursor(85,25);
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.print("FEEDING");
}
//Under 5 cm display length, time, day and date
else if(cm <= 5) {
display.setCursor(85,25);
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.print("DONE");
}
display.display();
//TODO Millis
//delay(1000);
}</p><p>void displayDayDateDisplay()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
//Retrieving data from DS1307
readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
&year);
//Sending it to the OLED display
//Display
//TODO Millis
//Day
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.println();</p><p> //Determine specific day of the week
switch(dayOfWeek){
case 1:
display.println("Sunday");
//display.println();
break;
case 2:
display.println("Monday");
break;
case 3:
display.println("Tuesday");
break;
case 4:
display.println("Wednesday");
break;
case 5:
display.println("Thursday");
break;
case 6:
display.println("Friday");
break;
case 7:
display.println("Saturday");
break;
}
//Date
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(WHITE);
display.print(dayOfMonth, DEC);
display.print("/");
display.print(month, DEC);
display.print("/");
display.print(year, DEC);
display.println(" ");
display.display();
//TODO Millis
//delay(500);
}</p><p>void ultrasonicTimeout() {
// The sensor is triggered by a HIGH pulse of 10 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
/*
//Without Millis
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
*/</p><p> currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //test whether the period has elapsed
{
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
// Convert the time into a distance
cm = (duration/2) / 29.1; // Divide by 29.1 or multiply by 0.0343
inches = (duration/2) / 74; // Divide by 74 or multiply by 0.0135
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();</p><p> //delay(200);
}</p><p>void ultrasonic() {
// The sensor is triggered by a HIGH pulse of 10 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
/*
//Without Millis
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
*/
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //test whether the period has elapsed
{
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
// Convert the time into a distance
cm = (duration/2) / 29.1; // Divide by 29.1 or multiply by 0.0343
inches = (duration/2) / 74; // Divide by 74 or multiply by 0.0135
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
}</p><p>void stepMotorFeed() {
/*
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //test whether the period has elapsed
{
//function to turn stepper motor 32 steps left
small_stepperFeed.setSpeed(300); // 200 as max speed?
//ultrasonic();
Steps2TakeFeed = -3200; // Rotate CW
//ultrasonic();
small_stepperFeed.step(Steps2TakeFeed);
startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
*/
//function to turn stepper motor 32 steps left
small_stepperFeed.setSpeed(300); // 200 as max speed?
//ultrasonic();
Steps2TakeFeed = -520; // Rotate CW
//ultrasonic();
small_stepperFeed.step(Steps2TakeFeed);
}</p><p>void testdrawlogo() {
display.clearDisplay();</p><p> display.drawBitmap(
(display.width() - SCREEN_WIDTH ),
(display.height() - SCREEN_HEIGHT),
myBitmap, SCREEN_WIDTH, SCREEN_HEIGHT, 1);
display.display();
// Invert and restore display, pausing in-between
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(8000);
}</p>
Source: UCL-Embedded-Automatic-Arduino-Pet-Feeder
-
What hardware is required to build this pet feeder?
The project requires an Arduino Mega 2560, a 12V 28BYJ-48 Stepper Motor, a ULN2003 driver, an HC-SR04 Ultrasonic sensor, a DS1307 Clock Module, an OLED Display, wires, a breadboard, and a battery. -
How does the system detect when to feed the pet?
The ultrasonic sensor measures the distance to the food; if the distance is between 8 cm and 45 cm, the motor turns clockwise to dispense food. -
Can I use the provided STL files without printing everything?
Yes, some files like the mount bases and spacers depend on your cabin setup, and the bowl or M&M rendering file can be skipped or substituted. -
Which pins are connected to the OLED display?
The OLED connections are MOSI to pin 9, CLK to pin 10, DC to pin 11, CS to pin 12, and RESET to pin 13. -
How does the code determine morning and afternoon feeding times?
The checkTime function sets morning feeding if the hour is between 6 and 11, and afternoon feeding if the hour is between 17 and 21. -
What happens when the food level drops below 5 cm?
When the distance is under 5 cm, the system displays DONE on the screen and increments the morning fed counter. -
Is the M&M STL file safe to use as a food container?
No, the M&M STL file was only used for rendering in Autodesk Fusion 360 and should not be used for actual pet food. -
What libraries are included in the embedded programming code?
The code includes Wire.h, Adafruit_SSD1306.h, Adafruit_GFX.h, RTClib.h, and the Stepper library.
