I love my cat, Charlie. I really do. But every morning, it's "meow meow meow feed me meow meow meow". The second I'm home from work, "meow meow meow feed me meow meow meow. I can't ask him to wait a second and I'll be right there, he just doesn't understand. He's hungry, and I am the purveyor of food.
I don't free-feed him, as that's an easy way for cats to get fat. And anyone could buy an automatic feeder. But where's the fun in that? I'd rather build my own.
If you take a look at the numerous pet feeders on Hackster, you'll find most use a cereal dispenser, which is the approach I've taken. There are other implementations where people have crafted their own dispensing system, but who can argue for $20 on Amazon. And it comes with two dispensers, so you can make one for each pet, or have a backup when you explode the first one.
My initial plan was to attach a motor hub to the dispenser handle and attach a motor to the hub. As I started working with the handle, I noticed it slides right out, and has a not that let me use a standard motor coupler instead. So I cut off the silver handle and did just that.
To give Charlie enough room, I mounted the dispenser to a new frame. The motor+coupler is partially supporting the bottom, and I added a couple 3" bolts at the top to reduce the load and keep it steady. At the bottom, I added a large arcade style button.
The system is using an Adafruit Feather board based around an ESP8266 WiFi chip. The motor is then driven by one of their convenient FeatherWing motor drivers. I chose a stepper motor to regulate how much turning is required.
What I want is for Charlie not to bother me when he's hungry. I want to stay in bed a few more minutes. I wanna just relax after work. I could tell Alexa to feed the cat. I could setup schedules online and have it check in online, or make a simple web app so I can feed him from my phone. And I may very well do some of those things. But automation is about letting the system just go. Who's got time and energy to pull out their phone? I might as well scoop some food manually at that point.
So at the core, the system has a button and a timer. When the button is pressed, the food is dispensed, and the timer is started. When the timer expires, food is dispensed again, and the timer is restarted. Thus continuing the flow of food for the next 50 days or so, when the millis() value overflows.
To feed, I rotate the motor 100 steps, which is halfway on my motor. When I calculate the next feeding time, I check to see if that happens to overflow past the unsigned long integer count of millis() (4,294,967,295, or about 50 days worth of milliseconds). If it does, we set a flag that will clear once millis() overflows, resuming standard logic. Otherwise, I just update the next time to feed and continue to check that against millis() in the loop.
ms_lastFeeding = ms_nextFeeding; ms_nextFeeding = millis() + TWELVE_HOURS_MS; overflow = (ms_lastFeeding > ms_nextFeeding);
if(overflow) overflow = (millis() < ms_lastFeeding); if(millis() > ms_nextFeeding && !overflow) FeedCharlie();
Twelve hour feeding has been pretty good so far. But there's always room for improvement. I'm using a WiFi Feather board, so I can certainly added all sorts of connectivity to it -> adjust feeding times via an app or web interface, Alexa integration, sync time with NTP. The motor I have is not able to handle the load of a full feeder, so if I can find a higher torque version I'll swap that out. But Charlie is happy and full, so I'm happy too