Intro: Phone Based Treat Dispenser (Motion Detection, Video and More)
Do you miss your dog while at work? Or do you love someone who does? This could be a great present for yourself or that special someone in your life who has a furry friend but isn't always with him/her.
Here is next generation treat machine, this one with much more flexibility than others I've seen, including
- motion detection system (e.g. to identify if the dog is home or away, to make sure any video captures the real action)
- Real time MQTT server
- allows for easy extension of the treat machine into a series of interactive toys for your dog and / or games you can play remotely with your furry friend
- real time dispensing of treats from anywhere in the world
You'll soon see another Instructable on how I used this platform to easily build a ball launcher / catcher that gives Pickles treats when he successfully completes the mission of returning the ball.
1) Trigger the machine (currently via email, Alexa, iPhone app, or Adafruit IO site)
2) When treat is received, start the process
- Speaker plays a custom sound (in this use case, Shirin's voice)
- Dog jumps for joy
- Dispense treats
- Check for motion
3) If motion is detected
- take picture
- take video
- Send email from dog to submitter, complete with picture, video and randomized cute comment (e.g. "I already loved you infinity. Now I love you infinity + 1")
4) If no motion detected
- send back a "I'm not home but will enjoy the treats when I get back" note
- Include a couple of pictures of the dog, perhaps enjoying the outdoors
Step 1: Background
My fiancee, Shirin, and I have been dating for about 4 years and I wanted to do something really nice for her birthday. She misses our dog Pickles while she’s at work so I built her a device that allows her to give him treats while she is away and Pickles is home. My goal was to give her a little burst of dopamine and, if I’m lucky, a little heart flutter when she uses it. She has been consistently using - nearly every day - so it apparently both works and was well received.
Step 2: Parts
Here is the complete list of required parts
- Raspberry Pi B+ or 3
- 16 GB SD Card
- Pi Camera
- Stepper Motor and Driver Board (I suggest this one because I know it works but others will clearly work)
- Speakers (can use anything that plugs into the Pi)
- 2 Power supply - one for Pi and a separate one for the stepper motor
- 1 Power cable adaptor to power stepper motor (Link is to 10 pack but you only need one)
- Wifi dongle for the PI
- Acrylic (I bought mine from TAP Plastic)
- 1/4" Acrylic - 18" x 32"
- 3" x 12" acrylic cylinder
- 2.5" x 10" acrylic cylinder
The most expensive components are the Pi and the Pi Camera. All in BOM is ~$130
Step 3: Physical Design
Cutting the parts
I used a laser cutter, as you can probably tell, at a local MakerSpace. Not necessary of course but it does make some things easier, like attaching the rPi and Camera.
For the cylinders, I used the rotary attachment and then used a block of scrap wood inside the cylinder to absorb the laser, once it cut through. Not sure I'd recommend this approach because it caused a bunch of smoke and I ruined several cylinders. I'd probably just hand cut it next time.
The hardest part of designing the treat machine was delivering a few treats at a time (not zero and not so many that Pickles becomes the poster child for dog obesity)
After many trials, I ended up with the design you see above. It's a cylinder with two components
- Storage (~80% of the volume)
- Dispenser (~20% of the volume
Between the two you will see two half circles of acrylic. The first one is cemented in place. The 2nd on is attached to the first one with velcro and can make enlarge or reduce the opening between the Storage and Dispenser. If the treats are bigger, or you want more treats delivered, make the opening wider.
The dispenser contains the only permanent opening to the cylinder. When the cylinder is rotated, gravity causes the treats to fall out of the cylinder. The only key requirement of the opening is that it is big enough that treats don't get stuck. So make it at least ~3x the diameter of the treats. Really, there is no reason not to make it quite large.
At rest, the opening faces up. When triggered, the cylinder rotates 180 and stops for 1/4 second, enough time for all the treats to drop out. It then rotates another 180 back to the original position.
As the cylinder rotates, gravity causes treats to flow through the opening between Storage and Dispenser, refilling the Dispenser with treats for the next round.
In the photos, you'll see two different cases that I made. The first one, made out of wood and before I had access to any tools other than a handsaw and drill, shows a more rudimentary method. The second, made out of acrylic, was designed in Illustrator and cut on a laser cutter at my local maker space (Tech Shop). Originally, I was going to put a front cover on the wood piece so that Pickles couldn't get after it but he leaves it alone. Well, he stares at it quite a bit (I imagine him saying to himself, "Think, Pickles. Think! How do I get this thing turned on again?")
Step 4: Wiring
Wiring this up is fairly straightforward. See the pictures above for the detail.
- 4 Raspberry Pi GPIO pins need to be connected to the stepper motor
rPi Pin #07 -> Stepper Motor In 1
rPi Pin #11-> Stepper Motor In 2
rPi Pin #16-> Stepper Motor In 3
rPi Pin #18-> Stepper Motor In 4
- Stepper motor positive and ground should be connected to a separate power supply. That is not ideal. Powering the stepper motor separately will lead to much higher reliability. Without separate power and under a high load (aka full Storage container of treats), it will miss some steps and eventually cause problems.
- Speakers need to be connected and powered (can use Pi for power if you'd like)
Note - if you are following the instructions for the acrylic version of the device, it will be easiest if you wire up the stepper motor with one set of wires, wire up the Pi with another set of wires, install both while leaving the ends on the outside back of the machine, then connect the exposed ends of each with connecting wires.
Step 5: 4 Ways to Trigger the Treat Machine
There are four primary ways to trigger the treat machine
The attached code has a separate config file so that you can put your dog's email account info. Note that this has only been tested for a gmail account. This email address will be polled every 10 minutes, looking for unread emails. Apparently, if you check much more frequently, you run the risk of getting shut down by Google.
2) Adafruit IO interface
Of course, waiting for 10 minutes to see a video of your dog eating treats is, to many, an unacceptable delay so I implemented an MQTT based trigger. This gets you a real time response. Adafruit's implementation of MQTT is called Adafruit IO and I used that. Go to Adafruit IO and follow the instructions to set up an account and feed. In the config file, make sure the feed name matchs the name of the feed you created. I called mine TreatMachine.
On the Adafruit IO interface, go to the feed you created and select the Action of Add Data. Add an email address and the treat machine will then send the response content to that email address.
3) The IFTTT (If This Then That) Do App
Adafruit IO is connected to IFTTT so it was really easy to set up the IFTTT Do App to trigger the treat machine.
a) Register for IFTTT Account if you don't have one yet
b) Set up applet. IF is the Button app and THEN is Adafruit IO. If you haven't already done so, you'll need to create an Adafruit IO feed on io.adafruit.com and then select that feed on IFTTT. The data you send to Adafruit IO should be your email address
c) To use the Button app, you'll need to download it to your smartphone from IFTTT.
This gets you a real time response as well and is a lot cleaner than using the Adafruit IO interface, at least for the non programmers amongst us.
The last trigger I have currently in place is Alexa. Really, it can be any Alexa in the world as long as you have control of it. For example, my nieces love Pickles but they live 3,000 miles away. I set up their Alexa to trigger the treat machine at our house. It took 5 minutes because both Alexa and Adafruit IO are on IFTTT
a) Register for IFTTT if you don't have one yet
b) Create applet. IF is Alexa and THEN is Adafruit IO. For Alexa, select something like "treat machine" or "Give [dog name] a treat". THEN is the same as Option 3 above.
Side note - If you are setting up the Alexa for multiple people, you can easily program this into IFTTT. For example, a trigger phrase for Alexa is "Give Pickles a treat from Emily" and, in IFTTT, when that phrase is received, it sends Emily's email address to Adafruit IO.
This is surprisingly real time as well.
Note: the Alexa triggering method can also be used to distract the dog if, for example, you and your significant other need some alone time.
Step 6: Setting Up the Raspberry Pi and Other Software Components
You'll need to install the following
1) Install the foundation for the motion detection software
Adrian at PyImageSearch does an amazing job of instructing the world on how to implement a basic motion detection system. Follow his tutorial here and you'll have the basics set up. It includes OpenCV, which takes a lot of space, hence the requirement to use a 16GB SD Card.
2) Install the Adafruit IO packages
Follow the instructions to install Adafruit IO. Everything on the treat machine is written in Python
3) Install the PiCamera
Follow the instructions here on the PiHut to install the camera hardware and prepare the software.
4) Create Gmail Account
The dog should get his/her own email account. You can set the gmail account, password in the config file
5) Create I'm Away Images
Nothing worse than getting a video of an empty floor full of treats so I implemented the motion detection system. When no motion is detected, the software sends back an email with some happy images of Pickles playing outside. Find a couple of those images and put them into the /pi directory of your raspberry pi
6) Upload the software
See attached files software files. Put all of them in the /pi directory of your raspberry pi
7) Update conf.json
You'll see the config file in the /pi directory has a whole bunch of variables to set e.g. gmail account, Adafruit IO Key, etc. It even includes things like the length of video to take, the threshold for motion detection, etc.
8) Logging files
You'll likely want to see the logging files. The log files are kept in the /log sub directory and there is one file for each major python script. The log files will be created automatically when you run it
Step 7: The Software - Architecture, How It Works
OK, so you've made it through to actual running the code. Here's how it works
There are 3 scripts running at all times
listenEmail is pretty simple. It periodically polls the gmail account and, if any unread messages are found, it marks the message as read and then sends the Sender's email address to the Adafruit IO feed.
This is a hack, required due to a limitation of the Adafruit MQTT limitation (or a limitation of my abilities, which may be more likely). In order to keep the connection with Adafruit IO alive, we need to ping it periodically to say, "Hey, I'm alive! don't forget about me!" But there is no ping method in the Python library, that I can find. So, instead, this Python script send the text "ping" every X minutes (2 for me) to the TreatMachine feed. This allows the listener to receive a new MQTT message every 2 minutes, thereby keeping everything alive
This listens to the Adafruit IO feed for any new data. When it receives data, it takes action. Most of the time, it receives the "ping", which it discards. Sometimes, it receives an email address. If so, it activates the dispenser. You'll see the various classes I created (Person, TreatDispenser, Camera, EmailServer) and hopefully the methods in those are fairly straightforward and/or commented. It's also set up to easily handle other messages coming from the Adafruit IO feed, creating an extensible platform to build additional ways to interact with your dog. You'll see some of the other uses in the code e.g. I built Pickles a ball launcher and ball receptacle that launches balls that he then puts into a specially designed box that triggers the treat machine.
Separate Publish and Subscribe: I separated sendMQTT and listenMQTT because, when I combined them, I found it much harder to do error checking and to reconnect everything when something failed. If anyone has a better way of doing this, I'm all ears but I'm not having any reliability issues is so it's not worth a lot more of my time.
Restarting on [Error]: Anything internet connected will need to be restarted periodically e.g. power outage. I created a cronjob that runs a shell script every 5 minutes, checking if each script is running and restarting it, if it isn't currently running. It seems to be working well
Person Class: the Person class was created originally because I was contemplating sending the messages out via text and/or email so I was going to store my family's preferences. This ended up being a little overkill but I didn't bother to remove the class.
Step 8: Assembly
Assembly of the acrylic version should be reasonably easy.
Step 1 - Assemble the Base (including the wiring)
Screw in the camera and the rPi before you assemble everything. The laser will cut the holes for you to make this easy
Start with the platform and snap in the pieces. Note that the columns are not bi-directional so you'll need to snap them in the right way. If you're wrong, just flip the part
Step 2 - Assemble the Cylinder (including the wiring)
Start with the inner cylinder.
Screw the stepper motor to the bottom discs (the ones with the holes in them to allow for the wires to come in).
One disc will have a small notch cut in it, just a tad bigger than the stepper motor rod. Gravity will keep it on so no need for glue
You may want to cement the half disc in place that separate Storage from Dispenser. That'll make it more stable
Add some velcro to the half discs so that you can grow/shrink the opening between Storage and Dispenser areas.
Step 3 - Connect the wires
(see Wiring section)
Step 4 - Connect Cylinder to base
I used velcro strips as a temporary solution but it worked well and is effectively invisible so I've kept it.
Step 9: Summary
By now, you DIYers should have a functional treat machine that you and your family / friends can trigger in a variety of ways.
Look a little more closely at the software and you'll see that the architecture allows you to easily extend the functionality to create additional interactive ways to play with your dog while you aren't at home. As an example, I'll be publishing an Instructable shortly showing how I've already extended this to include a ball launcher and a RFID based ball receptacle. We can trigger the ball launcher via any of the real time triggering methods described previously and then Pickles gets treats when he drops the ball in the receptacle.
If you see any way to improve it, please let me know. Even better, if you extend or improve the functionality by creating additional toys / steps / games, I'd love to see it in action!