Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
In this post, we will learn how to build an automatic pet feeder by using the G90 Servo Motor and DS3231 Real-Time Clock Module.
The SG90 Servo Motor is known for its low cost and simplicity which makes it easy to use and integrate with many microcontrollers. In this project we will be using it to control the opening of the pet feeder. For more information on how the servo motor works, visit our other post SG90 Servo Motor Basics: What You Need to Know.
The DS3231 is a Real-Time Clock module which is used in various embedded systems and microcontroller projects to keep track of time. Because of its backup battery, you don’t have to worry about it losing track of time when external power is lost.
For more information, visit Getting to Know Your Arduino Uno: A Beginner’s Guide to Its Components.
This project uses a real-time module to keep track of time, and a keypad to input the time for feeding. When the button in the middle is pressed, a new feeding time can be inputted. When the current time reaches the feeding time, the servo motors are activated and food is dispensed.
1. Find a suitable container with a lid and make a hole on the top and bottom of the container
2. Make a cardboard cutout for the hole of the lid and a attach the servo motor onto it
3. Attach the servo motor onto the container
4. Connect the wires of the servo motor onto the breadboard and Arduino
| Servo Motor | Arduino | Breadboard |
| VCC (red) | + | |
| GND (Brown) | – | |
| SIG (Orange) | D11 |
5. Put the DS3231 Real-Time Clock Module down as shown below
6. Connect the DS3231 Module to the Arduino
| DS3231 | Arduino | Breadboard |
| SCL (white) | A5 | |
| SDA (gray) | A4 | |
| VCC (red) | + | |
| GND (black) | – |
7. Connect the LCD Module with the breadboard
| LCD Module | Breadboard |
| GND (black) | – |
| VCC (red) | + |
| SDA (blue) | Same row as DS3231’s SDA |
| SCL (orange) | Same row as DS3231’s SCL |
8. Connect the keypad to the Arduino (connect the left most wire to D2 and the rightmost to D9)
For more information about the Keypad, click the link How to Easily Setup Keypad in Arduino Projects.
9. Add the push button to the circuit
Visit How To Wire It! Buttons & Switches for more information.
10. Power the breadboard
| Arduino | Breadboard |
| 5V (red) | + |
| GND (black) | – |
11. Upload the code to the Arduino (code below)
12. Power the Arduino with a 9 volt battery
13. Set up the feeding time
Use the Keypad to set up the feeding time. Press digital buttons for hours (HH) and minutes (MM). Then press any non-digital button to finish.
#include <Keypad.h>
#include <DS3231.h>
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
//Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
#define buttonPin 10
#define servoPin 11
char key;
String feedingTime;
String currentTime;
int buttonState = 0;
// Declare a myservo object
Servo myservo;
// Declare a clock object
DS3231 clock;
// Declare a dt object
RTCDateTime dt;
// Define the Keymap
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = {2, 3, 4, 5};
// Connect keypad COL0, COL1, COL2 and COL3 to these Arduino pins.
byte colPins[COLS] = {6, 7, 8, 9};
// Create an object of Keypad
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void setup() {
Serial.begin(9600);
// Initialize the LCD
lcd.init();
// Turn on the backlight
lcd.backlight();
// Initialize the clock object
clock.begin();
pinMode(buttonPin, INPUT); // Set the buttonPin as an Input
myservo.attach(servoPin); // Attach Servo Motor to the digital pin
// Move the shaft of the servo motor to suitable degrees (50 degrees) that the hole on the lid can be covered by the cardboard.
myservo.write(50);
}
void loop() {
// Retrieve the date and time as an RTCDateTime object
dt = clock.getDateTime();
// Return the current time as a string - "hh:mm:ss"
currentTime = CurrentTime(dt.hour,dt.minute,dt.second);
// Read the state of the pushbutton value
buttonState = digitalRead(buttonPin);
// After pushing down the button, input the time for feeding the pet
if(buttonState == HIGH){
setFeedingTime();
Serial.print(feedingTime);
Serial.print(" ");
Serial.println(currentTime);
}
lcd.setCursor(0, 0);
lcd.print("Feed: ");
lcd.print(feedingTime);
lcd.setCursor(0, 1);
lcd.print("Now: ");
lcd.print(currentTime);
// Move the shaft of the servo motor to pour food when feedingTime = currentTime
if(feedingTime==currentTime){
myservo.write(180); // Move the shaft of the servo motor to 180 degrees
delay(3000); // Wait for 3 seconds
myservo.write(50); // Move the shaft of the servo motor back to 50 degrees
delay(5000); // Wait for 5 seconds
}
}
void setFeedingTime(){
int i = 0;
feedingTime = "";
// Press keys on Keypad module
while(true){
key = kpd.getKey(); // Gets the key pressed
// Keys for hour and minute
if (key >= '0' && key <= '9') // Only act on numeric keys
{
i++;
feedingTime = feedingTime + key;
if(i==2){
feedingTime = feedingTime + ":";
}
}else if(key){ // Press any non-digital button to finish
feedingTime = feedingTime + ":00";
break;
}
}
}
// Add leading zeros to single digit readings
String AddLeadingZero(uint8_t x){
String AddLeadingZeroText;
if(x<10) AddLeadingZeroText="0";
else AddLeadingZeroText="";
AddLeadingZeroText=AddLeadingZeroText+x;
return AddLeadingZeroText;
}
// Convert hour and minute into a string
String CurrentTime(uint8_t h, uint8_t m, uint8_t s){
String CurrentTimeText="";
CurrentTimeText=CurrentTimeText + AddLeadingZero(h) +":"+AddLeadingZero(m) +":"+AddLeadingZero(s);
return CurrentTimeText;
}