Automated / Voice Activated Cat Feeder

by CompactKidney in Living > Pets

5278 Views, 69 Favorites, 0 Comments

Automated / Voice Activated Cat Feeder

IMG_9610.jpg
Automated / Voice Activated Cat Feeder
IMG_9613.jpg
IMG_9615.jpg

I feed my cat multiple times during the day. As I would head out the door, I would often notice that her bowl was empty. I wanted the ability to quickly and easily feed her any time needed. I have multiple Amazon Echos (Echoes?) around the house and love how simple it is to ask questions and execute actions. I also have a development background so I thought this was a great problem to solve as my first Instructable.

This is my first attempt at an Instructable but I hope it will be clear enough to build a voice activated / automated cat feeder of your own!

Requirements
There were a few key elements I wanted to incorporate into the final design:

  • Ability to feed by voice
  • Ability to feed on a schedule
  • Store enough food for multiple days worth of feedings
  • Ability to see or be notified when food is low
  • Ability to upgrade parts / software as time goes on

Parts list

Tools / Supplies

This project is made up of two parts: building the cat feeder and programming the cat feeder. The main work went into the programming so that will be the focus of the Instructable.

*Note: I started taking pictures after the build was in progress so you won't find images of everything.

Printing the Controls

IMG_9592.jpg

Print out the cat feeder parts using the STL files above. I have a FlashForge Creator Pro and was able to print all parts without any issues. I used ABS filament so the parts would be extra strong and could easily be glued together.

Glue Parts / Screw Parts

IMG_9628.jpg
IMG_9624.jpg

The auger screw from kitlaan is printed in two halves. In order to connect them, I made some ABS glue (or ABS slurry) by combining acetone and left over ABS filament. This doesn’t need to be a precise mixture but I added enough filament to make the acetone cloudy. I painted this on each half, combined and let it dry. After some mild sanding, it was ready to go.

I then assembled the auger to the servo using the instructions on kitlaan’s thingverse page

Cut Wood

Wood.jpg

I wanted to have the cat feeder elevated off the ground and have room underneath to give the cat feeder a table-like look. I took some old ¼ scrap wood I had laying around and cut 4 pieces to size. I then took some slightly thicker wood to reinforce the body when it was all assembled.

In order for the PVC pipe and servo to fit, I cut a 2” hole in the front of the wood and a 2” hole in the back with some extra space at the top for the servo. I traced these directly on the wood and used a Dremel drill to cut out wood.

Cut Plastic Container

IMG_9625.jpg
IMG_9636.jpg

For the food dispenser, I wanted something that was sturdy and could be sealed to preserve the freshness of the food as long as possible. I had a spare storage container from Bed, Bath and Beyond around so I decided to use that. It has thick sides and was transparent so I can keep an eye on the food level.

I cut a 1 1/2” hole in the bottom so the PVC pipe could fit in the end. I also cut a small hole in the back where the photocell will be placed.

Hot Glue Parts

IMG_9626.jpg
IMG_9623.jpg
IMG_9627.jpg
IMG_9640.jpg
IMG_9641.jpg

I wanted to keep the storage container attached to the PVC pipe so I hot glued a seal all around the outsides. It probably wasn’t necessary but I didn’t want a mess.

I also wanted to keep the auger from sliding out of the PVC pipe so I hot glued the “tubemount” to the PVC pipe as well.

I inserted the photocell into the small hole in the back and hot glued that into place.

I found a funnel on thingverse and printed that to help make sure the food ended up in the PVC instead of next to it.

Paint / Glue Wood

IMG_9621.jpg
IMG_9620.jpg

I wanted a clean look so I painted all of the wood white to match the PVC, 3D printed parts, and container.

I then glued all of the wood together to form the required box. I thought about using screws but the glue held well enough and screws weren’t needed. I did NOT glue on the back panel because I wanted the ability to quickly take apart the unit if needed.

Obtain Case for Raspberry Pi

IMG_9629.jpg

I found a VESA mount case for my Raspberry PI on thingverse and printed it to attach the Pi to the back of the unit. I needed to make sure I had access to all of the ports including, most importantly, the GPIO pins.

Final Assembly

IMG_9610.jpg
IMG_9619.jpg

With all of the parts printed and the wood cut & glued, I finished assembling the cat feeder by screwing in the Pi into the back panel and sliding the PVC pipe / plastic container / servo combo into the front panel. I then slide the back panel over the back of the servo. There’s nothing holding this in place except for gravity, but so far gravity has been doing its job.

Wiring

Wiring Diagram.jpg
Raspberry Pi.jpg
IMG_9644.jpg

Now that the feeder was fully built, it’s time to wire it up and tell it do what you want.

Note: You could do the wiring prior to the final assembly of the feeder but I found that the wires kept slipping off the GPIO pins so I attached them at the end.


The servo requires a dedicated 5v power supply to receive enough power without shorting out the Raspberry Pi. I read a number of articles online about splitting the power to the Pi or driving the servo off the Pi itself but was always unsuccessful. The servo would either not receive enough power to move or it would short out the Pi and reset it anytime the servo was expected to move. I’m sure there is a way, but two power supplies was most reliable in my testing.

To wire the servo, simply attach the 5V power of the power supply to the 5V (Red) input on the servo. Connect a common ground between the power supply, the ground (black) on the servo and the Raspberry Pi. Lastly, connect the control pin (yellow) of the servo to one of the IO pins on the PI (I chose pin 18). Don't forget to connect the ground of the servo power supply to the Pi!

I also connected a photocell to the Pi to let me know when I need to add more food. The photocell reads the amount of light it sees. The idea is dark = there’s food, light = there’s no food.

One side of the photocell connects to a 3.3v pin on the pi and the other leg connects to one of the IO pins (I chose pin 24). This leg also gets connected to the positive leg of a 1uF capacitor. The negative leg of the capacitor gets connected to ground.

I soldered a few wires together but was able to get by with male/male or female/female jumper cables.

Writing Servo Control Program

I created a simple python program to control the servo and the photocell. The program connects to the servo, spins forward and backwards a few times, then reads the value of the photocell. If the photocell has a high value, it means that there is low light so it must be covered with food. If the photocell has a low value (more light), it sends an email to me indicating that the food is low and needs a refill.

Log into your Raspberry Pi and create a new file called continuous-servo.py with the content included in the attachment. If you are following along with my code, the script should go into a folder in /home/pi/echotest/.

At this point, you can run the python program and verify that the servo rotates and dispenses food. If you simply want to schedule feedings, you can add this script to the crontab on your Pi. If you want to also enable voice feeding, read on!

I included two versions of the script: One with notification support and one without.

*Note: You will find several placeholders in the notification script and values that may need to be updated based on your needs:

  • addresses - should be populated with a list of email addresses. SMS can be used by including the provider gateway at the end
  • MAIL_SERVER = "smtp.gmail.com" (would need to change if not using gmail)
  • MAIL_PORT = 587 (would need to change if not using gmail)
  • EMAIL = "YOUREMAIL@gmail.com" (enter your sending email address here)
  • PASS = "PASSWORD" (enter your sending email address password here)

Create New Alexa Skill

alexa-skill-1.png
alexa-skill-2.png

If you don’t already have one, create a new developer account at https://developer.amazon.com/.

Once registered, navigate to the Alexa section and get started with the Alexa Skills Kit. Add a new skill and provide the following information:

  • Skill Information
    • Skill Type = Custom Interaction Model
    • Name = (I chose “Cat feeder”)
    • Invocation Name = (This is the phrase you will use to talk to Alexa. I also chose “cat feeder”)
  • Interaction Model
    • Intent Schema = { "intents" : [ { "intent": "ActionIntent" }, { "intent": "AMAZON.HelpIntent" } ] }
    • Sample Utterances (These are the phrases you can say to execute your action. I included a few different phrases to give me multiple options)
      • ActionIntent feed the cat
      • ActionIntent feed my little girl
      • ActionIntent give bella some food
      • ActionIntent feed bella
      • ActionIntent give the little girl some food
      • ActionIntent feed the little girl
    • Configuration
      • Endpoint = (Put a placeholder for now. This will be updated later)
    • SSL Leave blank for now. This will be updated in the next step.

Save the settings for now

Setting Up SSL

Follow the steps here to create a self signed certificate: https://developer.amazon.com/public/solutions/ale...

You will end up with a pem file, private key, and a cnf file. Follow the steps to Update the Alexa Skill Configuration with the Self-Signed Certificate. You will need to update the skill created earlier with this certificate information.

Setting Up Alexa Service

Following the steps provided by Amazon (Using the alexa skills kit samples & Deploying a sample skill as a web service), I configured my development environment to support the Alexa sample application:

  • Clone the git repository:
  • Create a new maven project called "raspberry" with web-app archtype
  • From the git repository, copy the src/main/java/helloworld directory structure to the new project as well as the pom.xml file

*Note: The above steps aren't necessary if you are going to start with my code.

  • Right click on the project and choose Maven -> Update project to download all of the dependencies
  • In the POM settings, change the output type to be a war instead of a jar file
  • I also updated the POM file to log system out data to the tomcat logs (POM file included with project source code)
  • Generate a new keystore file and update the POM file following the steps here
  • Upload the keystore file to the raspberry pi
    • scp /path/to/keystore pi@raspberrypi:/home/pi/

Writing Java Program

java-1.png
java-2.png
java-3.png
You will need to either update and build Amazon's sample code or mine to create a deployable package.
  • Edit SpeechletRequestStreamHandler.java and replace the application ID place holder with the one in the Alexa Skill
  • I modified the original HelloWorld program to call a new function instead of just returning text.
    • I decided to go hacky and just used java’s Runtime class to execute the python script from the java program.
  • Once I was ready with the code, I created a new Run Configuration in eclipse for the maven project and added a goal of “package”.
  • I selected Run and let eclipse generate a war file for me under the target folder.
  • Next you copy the war file to the Raspberry Pi
    • scp /path/to/raspberry.war pi@raspberrypi:/home/pi/

Full source code is included with the Instructable.

Downloads

Setting Up Tomcat

tomcat-2.png
tomcat-1.png

I then downloaded and installed Tomcat on the Pi to host the web service that Alexa will communicate with. There are better ways that standing up a whole tomcat environment but Amazon offers a Java sample application to it was quick to get it up and running.

  • Installation:
    • Visit the Apache Tomcat webpage (https://tomcat.apache.org/download-70.cgi) and find a link for your version of Tomcat. I used Tomcat 7.0.67 but higher versions should work as well. Once you find the link, use the “wget” command to download the file:
      • wget http://shinyfeather.com/tomcat/tomcat-7/v7.0.69/bi...
        • *Note: I ran into issues using apt-get and decided to install manually
      • Uncompress the archive:
        • tar xzf apache-tomcat-7.0.67.tar.gz
      • Change to the uncompressed directory
        • cd apache-tomcat-7.0.67.tar.gz
      • Edit server.xml to enable SSL. (Alexa requires SSL for communication)
        • vi conf/server.xml
        • Uncomment the SSL port 8443 (Connector port="8443" …) and add in a reference to the keystore file: keystoreFile="/home/pi/java-keystore.jks" keystorePass="YOURPASS"
          • These are the ones created and uploaded earlier.
      • Move war file to webapps directory
        • mv /home/pi/raspberry.war /home/pi/apache-tomcat-7.0.67/webapps/
      • Start tomcat
        • /home/pi/apache-tomcat-7.0.67/bin/startup.sh

Configuring Router / External Web Service

endpoint.png

In order for all of this to come together, the Tomcat servlet needs to be exposed to the Internet. This process varies depending on your router but the basic concept is going into the router settings and allowing port forwarding from port 8443 to port 8443 on the IP of the Raspberry Pi. I tried changing the ports but it seemed like the Alexa skill could only send requests on port 8443. I suppose I could change the tomcat port but it didn’t really matter to me.


Optional: You could use your external IP address for the service URL or, if you prefer, use a dynamic DNS service like no-ip.com to give you a friendly static domain name.

Go back into your Alexa skill and update the endpoint with your IP/domain name, port, app name (context), servlet name (Eg: https://mysite.no-ip.org:8443/raspberry/raspberry)

Testing

alexa-skill-3.png

Now you are all set! You can either test using the Alexa testing tools in the developer portal or simply ask your Amazon Echo.

Error Detection / Troubleshooting

The catalina.out log under /home/pi/apache-tomcat-7.0.67/logs/ will give you a lot of good information about what’s going on.

My most common problems:

  • Servo not spinning: Check your wiring / check your python code
  • Alexa not working:
    • Verify your endpoint is accessible in a web browser (use your phone or a computer not on your local network)
    • Verify SSL certificate is working (errors should appear in the catalina logs)
  • Python app can't send email: If you are using gmail, make sure you allow requests from less secure apps

Lesson Learned

Occasionally I would lose power at my house which would restart the Raspberry Pi. I did not have tomcat configured to run at startup so my web service was down.

To resolve this, I simply updated /etc/rc.local to execute the tomcat startup command at boot:

  • vi /etc/rc.local
  • Add in this line right before exit 0: /home/pi/apache-tomcat-7.0.67/bin/startup.sh

Wish List / Future Plans

There are always ways that a project could be improved. I captured a list of things which I intend to do in the future or you might want to incorporate in your design:
  • The cat food gets stuck in the feeder every so often so I want to add something to agitate the food while feeding
  • Take picture or cat when she eats
  • Auto feed based on weight of food dish
  • Swap out Raspberry Pi for a Raspberry Pi Zero
  • Host python as web server and eliminate Tomcat
  • Write a mobile app to feed from phone
  • Options to change amount of food