IoT Pet Feeder

Updated 07 March 2019

The objective of this project was to create an Internet of Things (IoT) device that could give pet access to a food bowl when a text message command was sent from a remote location.

I had never done an IoT project before, so I wanted to keep the rest of the build relatively simple. I decided on a box with a sliding lid on top, into which a bowl of pet food could be placed. When the user wished for their pet to be fed, they would be able to send a command from their mobile phone, causing the box’s lid to slide open giving the pet access to the food bowl.

The project consisted of four main parts: The box, the drive assembly, the controller and the client application.

I wanted to the finished product to look nice, so I decided to build the box out of timber. I initially envisioned it having rounded corners and a varnished wood finish, but I ended up having to go with a simple rectangular box due to time constraints.

The drive assembly was another area that I had limited experience with, but I didn’t think it would be overwhelmingly difficult. I was wrong, but the initial design worked well enough. Its function was to move the wooden lid of the box from one side to the other.

The controller was the area that I was most comfortable with, especially considering the simplicity of the program. However, as previously mentioned, giving the project connectivity was new ground for me, and did prove to be the most difficult part of the project. Initially, I tried to use the GSM/LTE connection, but I was unable to get the module to work and ended up using wifi instead.

The client application was an addition to the project due to the need to access a system connected to the internet through a router with local DNS.

Parts List

Tools

  • Drop saw
  • Measuring tape and square
  • Rasp
  • Jigsaw
  • 3D printer
  • Various screwdrivers
  • Laptop with Autodesk Fusion 360
  • Drill with 3.2 mm drill bit
  • Multimeter

Construction

Box

I sketched out the dimensions for the box and tried to make as many of the mistakes as possible on paper. I cut the plans to size with a drop saw. Everything fit together fine except for the sliding lid, which I had cut too narrow due to an incorrect measurement of the sliders. 

All timber pieces cut to size

Cutting out the side door in the box

Although I was going to glue everything together, I changed my mind at the last minute and opted for screws so that I could take panels on and off (a decision that I was very thankful for later on).

Overall the box design and construction was simple, but I spent some time on it so that all the sides joined up properly. The only tricky bit was cutting out the door in the side panel where the pet bowl is inserted. I made a few cuts with a handsaw and then used a (hand) jigsaw to cut finer lines and angles. I finally used a rasp and sandpaper get the edges straight and square. Granted, there are probably easier ways of doing this, but woodwork is not my forte and I was quite pleased with the outcome.

Drive Assembly

I designed the drive assembly with the following assumptions:

  1. The DC motor would be spinning fast and must be slowed down
  2. The sliding lid should offer minimal resistance
  3. The rack and pinion should have coarse teeth (I have no idea if this was correct, but it was my vibe and I went with it).

Based on these I came up with the design pictured below:

Drive assembly. The motor mounts into the hole on the left.

I started out with the measurements for the teeth on the motor’s spur gear and designed a compatible gear that would convert some of the motor’s speed into torque, and output a course-toothed rotation. I wanted course teeth so that the mounting precision of the unit (to mesh with the rack) wouldn’t be too critical.

Control

The control system (aka the fun bit) was comprised of an H-bridge motor driver controlled by an Arduino Uno, which interfaced to the world through an ESP8266 wifi module.

I started out by assembling the motor driver on a breadboard, along with a 5V power supply. There weren’t any hitches with that part, so I went ahead and copied the breadboard wiring into a diagram. Referencing the diagram, I transferred the components on veroboard and soldered them in. After I fixed my obligatory mistake of soldering the voltage regulator backwards the board worked fine. I decided to mount the motor driver in PCB header sockets so that I could change it out later if I needed to.

Testing the motor driver and power supply with the breadboard. At this stage I was using an ethernet breakout board while I waited for the wifi module to arrive.

I attached two microswitches onto the lid. One was placed at each end of the lid in such a way that they would be triggered when the lid was fully open or fully closed. I soldered wires onto these and ran them to the Arduino. The microswitches provide some feedback on when the lid is open or shut.

Soldering the power supply and motor driver into vero-board

The Blynk’s ESP8266 code didn’t work with the Arduino Uno setup I had. Changes had to be made to the Blynk ESP8266 example code, which I quickly learned through this thread:

Forum post ESP8266 with Blynk

Code

The code is essentially very simple. There are two functions: Open and Close and the Blynk function.
The Open and Close functions activate the motor driver, causing the lid to open for 500ms. If one of the microswitches is pressed during this time the motor will stop.
The Blynk function monitors the Open/Close button on the phone app and calls the Open/Close functions when appropriate.
The main loop calls the Blynk function and maintains the desired lid state by checking the microswitches every few milliseconds and activating the motor to correct any discrepancies (ie if the dog noses the lid open the program will immediately shut it again).
The code is a bit lengthy so I have attached it a the end of this document.
The Blynk App was about as simple as it gets, with a single button toggling to a ‘virtual pin’.

Full Code at the end of the project.

Testing

I tested the Blynk functionality using an ethernet shield that I had lying around. Once I got the ethernet library working the Blynk application was very straightforward. When the wifi shield arrived in the mail I exchanged it for the ethernet shield and changed the few lines of code.

All was going well until I pulled the USB programming cable out of the Arduino. I believe that the system had been drawing power from the computer as well as the 12 VDC I had plugged into the Arduino 12V jack. After I pulled the cable I assume all the current was drawn through the onboard voltage regulator, which was too much for it to handle and leaked the magic smoke.

Even though the board no-longer powered up from the 12V jack (the voltage regulator was visibly damaged) the rest of the circuitry was intact and I was able to power the board from the external 5V voltage regulator (which I had intended to be solely for running the motor), connected to the Arduino’s 5V pin.

There was also an open circuit in the veroboard where a copper track had broken and lifted, but after that was sorted out the system worked more or less as intended. 

Testing the system with the Wifi module

Tuning and Finishing

I ended up having to make some adjustments to the speed of the motor, as the lid rails were quite stiff at one end. I was never able to work out why this was, even though I completely took apart the rails and adjusted the spacing and placement. Getting the motor to run full tilt when opening gave the lid enough momentum to overcome the increased friction in the rails.

The friction in the rails on the opposite side is much less so I was able to get away with running to motor slower, which closes the lid with a little more grace.

I wanted the finished product to look a bit "sphancy", so I gave the box three layers of red spray paint. I was quite happy with how it looked, but since the red was very…there, I decided to make the lid a bit gentler by giving by sanding the plywood smooth and varnishing it. The varnished wood and red paint made a nice contrast. 

Painting the box. I started with three layers of white primer and then three layers of red. I was a little heavy handed with the red so there are unfortunately some streak/drip marks

Applying varnish to the lid cover. I used three layers of varnish

Attaching the door hinge and latch

(Almost) Finished pet feeder. I screwed the lid on late at night after work, proven by the fact that I have put in a screw in the center on the right hand side of the varnished lid cover! Hopefully no one will notice

It took Cody about 5 seconds to work out that there was food inside the box

Using the highly complex Blynk app

Code

#define BLYNK_PRINT Serial    // Define Blynk serial number
#define SHUT 0                // Define the value for when the lid is shut
#define OPEN 1                // Define the value for when the lid is open
#define MIDDLE 2              // Define the value for when the lid is neither open nor closed

#include    // Library for using multiple serial channels
#include <ESP8266_Lib.h>      // Library for WIFI module
#include    // Library for using ESP8266 with Blynk

char auth[] = "********************************";   // Blynk authentication key


// WiFi credentials.
char ssid[] = "*************";
char pass[] = "*************";

// Hardware Serial on Mega, Leonardo, Micro...
#define EspSerial Serial1

// or Software Serial on Uno, Nano...
SoftwareSerial EspSerial(8, 9); // RX, TX. This value had to be changed from the default 0,1

// ESP8266 baud rate:
#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

// constants. They're used here to set pin numbers:
const int openLimit = 2;     // the number of the pushbutton pin
const int closeLimit = 4;
const int M1 =  3;      // the number of the motor control pin
const int M2 = 5;       // the number of the second motor control pin

// variables
int openState = 0;         // variable for reading the pushbutton status
int closeState = 0;
int desired_lid_status = MIDDLE;  // The desired lid status is set when the user presses the Open/Close button on the Blynk app. After the desired state has been set, the device will strive to maintain this state

/* Function for opening the lid of the box */
void open_lid(int motor_timer)
{
  for(int i = 0;i < motor_timer;i++)
            {
              digitalWrite(M1, HIGH);
              digitalWrite(M2, LOW);
              if(digitalRead(openLimit)==LOW) // If the limit switch has been pressed (ie the lid is fully open) stop the motor
              {
                digitalWrite(M1, LOW);
                digitalWrite(M2, LOW);                
                break;
              }
            delay(1);
            digitalWrite(M1, LOW);
            digitalWrite(M2, LOW);
            }
}

void close_lid(int motor_timer)
{
  for(int i = 0;i < motor_timer;i++) // Run the motor for the length of time specified by the "motor_timer" variable
            {
              digitalWrite(M1, LOW);
              digitalWrite(M2, HIGH);
              if(digitalRead(closeLimit)==LOW) // If the limit switch has been pressed (ie the lid is fully shut) stop the motor
              {
                digitalWrite(M1, LOW);
                digitalWrite(M2, LOW);
                break;
              }
              delay(5);			// Slow down the lid when closing Part I
            digitalWrite(M1, LOW);
            digitalWrite(M2, LOW);
            delay(4);				// Slow down the lid when closing Part II. This is basically PWM
          }
}

/*Function to process presses of the "Open/Shut" button on the Blynk app */
BLYNK_WRITE(V1)
{
  int pinValue = param.asInt();
   Serial.print("pinValue: "); // For debugging only
    Serial.println(pinValue);   
          if (pinValue == 1)    // Check the value of the (virtual) pin
          {
            desired_lid_status = OPEN;  // If the button value is high, set the desired status of the device to Open.
            open_lid(600);              // Run the open lid function. The function will run the motor continually for 600 milliseconds before beginning a hunting routine.
          }
          if (pinValue == 0)            // If the button value is low, set the desired status of the device to Closed
          {
            desired_lid_status = SHUT;
            close_lid(600);
          }
}

void setup() {
  //Debug console
  Serial.begin(9600);

  delay(10);

  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);

  // initialize the motor pins as an output:
  pinMode(M1, OUTPUT);
  pinMode(M2, OUTPUT);
  
  // initialize the pushbutton pin as an input:
  pinMode(openLimit, INPUT_PULLUP);
  pinMode(closeLimit, INPUT_PULLUP);

  Serial.println("status");
}

void loop() {
  Blynk.run();
  closeState = digitalRead(closeLimit);               // Check the status of the close microswitch
  openState = digitalRead(openLimit);                 // Check the status of the open microswitch
  if((desired_lid_status==SHUT)&&(closeState==HIGH))  // If the lid is meant to be shut but for some reason it has been forced open:
  {
    Serial.println("Closing lid");
    delay(100);                                       // Wait 100 ms and close the lid. This will result in 100ms pauses between motor pulses.
    close_lid(10);                                    // Run the motor for 10ms at a time. This value was found to effectively 'debounce' the lid, ie deliver such small amounts of movement that the lid dounced rebound when it hits the end of the box.
  } 
  else if
    ((desired_lid_status==OPEN)&&(openState==HIGH))   // If the lid is meant to be open but for some reason it has been forced shut:
    {
      delay(100);
      open_lid(10);
    }
}

Have a question? Ask the Author of this guide today!

Please enter minimum 20 characters

Your comment will be posted (automatically) on our Support Forum which is publicly accessible. Don't enter private information, such as your phone number.

Expect a quick reply during business hours, many of us check-in over the weekend as well.

Comments


Loading...
Feedback

Please continue if you would like to leave feedback for any of these topics:

  • Website features/issues
  • Content errors/improvements
  • Missing products/categories
  • Product assignments to categories
  • Search results relevance

For all other inquiries (orders status, stock levels, etc), please contact our support team for quick assistance.

Note: click continue and a draft email will be opened to edit. If you don't have an email client on your device, then send a message via the chat icon on the bottom left of our website.

Makers love reviews as much as you do, please follow this link to review the products you have purchased.