Joshua HypesMOHRAN JURDI
Published © GPL3+

Pet Feeder

Automated pet food dispenser to feed our pets when we are not at home by using an IoT device.

IntermediateFull instructions provided6 hours4,884
Pet Feeder

Things used in this project

Hardware components

Resistor 1k ohm
Resistor 1k ohm
×4
LM317T Voltage Regulator
Used this to step the voltage down from the 6.5V to 5V to operate the photon
×1
Photon
Particle Photon
×2
6.6V/2500maH Power supply by DigiPower
I already had one of these in the garage.
×1
MG958 Servo Motor
×1
PIR Motion Sensor (generic)
PIR Motion Sensor (generic)
From the maker kit
×1
PlexiGlass .75'' thick (servo mount)
Had a piece of this already. You can actually make this mount out of something cheaper.
×1
EMAX ES08A Micro Servo Motor (photon maker kit)
From the maker kit
×1
Breadboard (generic)
Breadboard (generic)
×2
4xAA battery holder
4xAA battery holder
×1
1/4-20 Socket Head Cap Screws
Use one at full length for the upper bolt hole in the servo mount. Shorten the one for the lower mount to 1/2.
×2
Jumper wires (generic)
Jumper wires (generic)
×32
AA Batteries
AA Batteries
×4
LED (generic)
LED (generic)
×2
Steel Round Rod: 0.066" Diameter, 36" Length
×1
OLED Expansion
Onion Corporation OLED Expansion
×1
Shadow Box Frame
×1
Used Food Dispenser
×1
Drinking Straw
×1

Software apps and online services

ThingSpeak API
ThingSpeak API
Fritzing For Building Circuits
Mobicle
ControlEverything.com Mobicle

Hand tools and fabrication machines

ENCO Knee Mill 100 5200
1/2 End Mill
Use this to shape the servo mount and clearance the dispenser for wiring.
1/4 Drill Bit
Use this to drill the holes in the servo mount for the 1/4-20 fasteners.
8mm End MIll
Use this to counter sink the upper socket head cap screw in the servo mount.
Screwdriver
Box Cutter
Scissor
Super Glue
Foam Board

Story

Read more

Custom parts and enclosures

Servo Mount Blueprint

This is a blueprint of the servo mount for the pet feeder.

Schematics

Pet Feeder wiring schematic

This is the wiring schematic used for the circuit in the pet feeder. The servo and open wire going to the LM317 voltage regulator are connected to a 6.6V power supply.

Shadow Box Frame Wiring Schematic

This is the wiring schematic used for the circuit in the Shadow Box Frame to display how many times the pet eats by using a servo motor that moves certain degrees every time the pet eats which changes from Skinny cat to Fatty cat during the day.

Code

Pet_Feeder_Code

Arduino
This is the code used on the photon that was on the pet feeder. It signals the mg958 servo to actuate the lever on the pet food dispenser and publishes an event to the cloud. It also reads the status of a PIR sensor and publishes a count to thingspeak. It also operates the OLED display.
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_SSD1306.h>

Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created

int pos = 0;    // variable to store the servo position
int displayTime(); //displaytime function
int inputPin = D0; // choose the input pin (for PIR sensor)
int ledPin = D7; //Onboard LED pin
int ledPin2 = D3;// LED Pin for showcase function
int pirState = LOW; // assuming no motion detected
int val = 0; // variable for reading the pin status
int count = 0;//count for the thingspeakwriteall
int calibrateTime = 10000;// wait for the calibration
int Feedings = 0;//initial feedings 

#define OLED_DC     D2 //Pin out for the OLED Display
#define OLED_CS     D4 //   "   "   "   "   "   "
#define OLED_RESET  D5 //  "   "   "   "   "   "
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS); //OLED Display function
 int  x, minX;

const String key = "write-key-here"; //Thing Speak write key
Timer timer3(15000, updateThingspeak); //Calls Thingspeak every 15000 ms

void setup()
{
  Particle.function("feed", feedf);  // create a function called "feedf" 
  Particle.function("Showcase",Showcasef); // create a function called "Showcasef"                                     
    timer3.start(); //initialize timer3 for thingspeakwrite all
    myservo.attach(D1);  // attach the servo on the D1 pin to the servo object
    myservo.write(0);    // Start from position 0 degree
    pinMode(ledPin,OUTPUT); //Sets D7 as an output
    pinMode( ledPin2, OUTPUT); // Sets showcase LED pin as an output
    pinMode(inputPin, INPUT);  // declare PIR sensor as input
    //Particle.subscribe("Feed", myHandler); //Subscribes to operate the OLED display
    Time.zone(-5); //Sets the time zone for eastern time
    Serial.begin(9600); //Begins the serial print

  display.begin(SSD1306_SWITCHCAPVCC);
  display.setTextSize(1);       // text size for OLED display
  display.setTextColor(WHITE); // text color for OLED display
  display.setTextWrap(false); // turn off text wrapping so we can do scrolling
}

int feedf(String command)   // Command function for mg958 servo to actuate the feed lever
{                          // be accompanied by a string.
    if(command == "morning")   // if the string is "feed now", feed once.
    {          
        Particle.publish("Feed","morning"); //publishes "Feed" event to the cloud
        oled();
        myservo.write(180);       // move servo to 180 degrees
        digitalWrite(D7, HIGH); // flash the LED (as an indicator)
        delay(800);             // wait 800 ms
        myservo.write(0);      // move servo to 0
        digitalWrite(D7, LOW);  // turn off LED
        return 1;               // return a status of "1"
    }
    
    else if(command == "lunch")   // if the string is "feed now", feed once.
    {          
        Particle.publish("Feed","lunch"); //publishes "Feed" event to the cloud
        oled();
        myservo.write(180);       // move servo to 180 degrees
        digitalWrite(D7, HIGH); // flash the LED (as an indicator)
        delay(800);             // wait 800 ms
        myservo.write(0);      // move servo to 0
        digitalWrite(D7, LOW);  // turn off LED
        return 1;               // return a status of "1"
    }
    
   else if(command == "dinner")   // if the string is "feed now", feed once.
    {          
        Particle.publish("Feed","dinner"); //publishes "Feed" event to the cloud
        oled();
        myservo.write(180);       // move servo to 180 degrees
        digitalWrite(D7, HIGH); // flash the LED (as an indicator)
        delay(800);             // wait 800 ms
        myservo.write(0);      // move servo to 0
        digitalWrite(D7, LOW);  // turn off LED
        return 1;               // return a status of "1"
    }
    
}

int Showcasef(String command) //Command function for turning the light on/off for viewing the circuit inside once installed in the feeder
{
    if(command == "On")
    {
        digitalWrite(ledPin2, HIGH); //Turns on white led on pin D3
    }
    else if(command == "Off")
    {
        digitalWrite(ledPin2, LOW); //Turns off whit led on pin D3
    }
}

void loop()
{
  
  if ( calibrated() )// if the sensor is calibrated
  {
  
    readTheSensor();// get the data from the sensor

     reportTheData();// report it out, if the state has changed
  
   }
    else {}
  
}

void readTheSensor() { //Function for reading the PIR sensor
  val = digitalRead(inputPin); //Establishes variable for reading the PIR sensor
}

bool calibrated() {
  return millis() - calibrateTime > 0;
}

void reportTheData() { //function for using the PIR sensor input to display on the OLED and publish to the cloud

  if (val == HIGH) {
        //Setup for the OLED. Splits it onto two lines
        display.clearDisplay();
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(0,0); //Starts text in upper left hand corner as the datum
        display.print("Chewie");
        display.setCursor(10,30); //Moves text over 10 and down 30 from datum
        display.print("is eating");
        display.display();
    
    if (pirState == LOW) {
     
        Feedings = Feedings+1; //Iteration adds one 
        Particle.publish("Chewie-is-eating",String(Feedings)); //Publishes the string of Feedings to use on the Picture frame and thingspeak
        pirState = HIGH;
        setLED( pirState );
    }
  } 
  else {
      static int lastSecond = 61;
  if (Time.second() != lastSecond)
  {
    char myTimeString[125] = "";
    const int currentTime = Time.now();
    sprintf(myTimeString, "%02d:%02d:%02d", Time.hour(currentTime), Time.minute(currentTime), Time.second(currentTime)); //displays time when no activity
    
    display.clearDisplay();   // clears the screen and buffer
    display.setTextSize(2); //Text size for OLED
    display.setTextColor(WHITE);
    display.setCursor(12,20); //Moves text over 12 and down 20
    display.println(myTimeString);
    display.display();
    lastSecond = Time.second(currentTime);
  }

    if (pirState == HIGH) {
      pirState = LOW;
      setLED( pirState );
    }
}
}
void oled()
{
//void myHandler(const char *event, const char *data) //Function for displaying on the OLED that the pet feeder was activated
//{
 //if (strcmp(data,"Chewie_was_fed!")==0) {
        display.clearDisplay();
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(0,0);
        display.print("Chewie");
        display.setCursor(10,30);
        display.print("was fed!");
        display.display();
        delay(3000); //Will Display this message for 3000ms before returning to the time
 //}
}

void setLED( int state )
{
  digitalWrite( ledPin, state );//turns the d7 led on/off based on PIR status
}

bool updateThingspeak() //ThingsSpeak code from John McAlpine
{
    count++;
    Serial.print("Updating Thingspeak:");
    Serial.print(count);
    

      bool success = Particle.publish("thingSpeakWrite_All", +
     "{ \"1\": \"" + String(Feedings) + "\"," +
       "\"k\": \"" + key + "\" }", 60, PRIVATE);
    return success; 
    
}

Picture_Frame

Arduino
This is the code used on the picture frame to move the servo.
Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created
int pos = 0;    // variable to store the servo position
int ledpin = D7; //Onboard LED pin


void setup()
{
    myservo.attach(D1);   // attach the servo on the D0 pin to the servo object
    myservo.write(180);    // test the servo by moving it to 20
    Particle.subscribe("Feed", myHandler); //Subacribes to published PIR sensor string and calls muHandler function
    pinMode(ledpin,OUTPUT);
}

void myHandler(const char *event, const char *data) //Uses the variable from the subscribed event from the PIR sensor
{
 if (strcmp(data,"morning")==0) {
    
     myservo.write(135);       // Mutiplies the string iteration by the number of degrees of movement per picture in the frame plus the inital 20 degrees
     digitalWrite(ledpin,HIGH);
     delay(2000);
     digitalWrite(ledpin,LOW);
 }
 
 else if (strcmp(data,"lunch")==0) {
    
     myservo.write(105);       // Mutiplies the string iteration by the number of degrees of movement per picture in the frame plus the inital 20 degrees
     digitalWrite(ledpin,HIGH);
     delay(2000);
     digitalWrite(ledpin,LOW);
 }
 
 else if (strcmp(data,"dinner")==0) {
    
     myservo.write(65);       // Mutiplies the string iteration by the number of degrees of movement per picture in the frame plus the inital 20 degrees
     digitalWrite(ledpin,HIGH);
     delay(2000);
     digitalWrite(ledpin,LOW);
 }
 
 else {
 }
 
}

Credits

Joshua Hypes

Joshua Hypes

3 projects • 4 followers
MOHRAN JURDI

MOHRAN JURDI

1 project • 0 followers

Comments