We’ve been “watching” my mother-in-law’s fish for the better part of two years. One of my least favorite tasks in the day is feeding the fish in the morning. There are a lot of morning tasks where putting my fingers near my mouth is a factor (brushing teeth, drinking coffee, etc.) and having to put nasty fish flakes on my hand is disruptive to those tasks.
I decided to solve this with an Arduino and some stuff laying around the house. The project goal was to make a feeder that would feed the fish every 24 hours so I wouldn’t have to. I thought the hardest part would be the timer (spoiler alert: it was) but in actuality, engineering components that were never meant to feed fish was the really difficult and fun part.
Inventory
I bought and ELEGOO circuit board for the microcontroller, some random servos for the motorized mechanism, and a general electronics kit for wires and stuff. Don’t worry, those aren’t affiliate links playa… god forbid I get 20 extra cents.
I started off by testing the board and some components. So far, so good.
With that out of the way, I started working on getting the servo moving:
After realizing the electronics portion of the project was coming together quite easily, I realized I had to start thinking about the physical container the food would reside in, and how I’d deliver it. I had a bottle laying around that I cut the bottom out of for the food to reside in.
Now I had to think about how I would control the food from storage to delivery. For this, I decided to cut square of cardboard (from a JB Weld package of course) and attach it to the servo. Then, it was a quick ziptie to affix the servo-JBweld-stopper to the food storage container.
Then I just had to get that bad boy moving:
We had a working JBweld-cardboard-servo control, but it was going to need adjustment. I decided it would be a good idea at this point to start testing not only the angle to set the servo, but the frequency, friction, and amount of times to move the thing for the proper amount of food to fall.
It was in testing that I discovered some physical bugs. Some people might have used a different material to simulate how the fish food would fall. Not me, I went and grabbed the flakes that were going to be used in a real-life simulation train like you fight
was about all I learned in the Navy.
I’m glad I did, because those stupid flakes didn’t want to come out of my bottle after the first couple of times, they’d get stuck in the larger canister but wouldn’t fall out of the mouth. Not good. I thought about some possible solutions. Solution #1 was to hot glue a pizza flyer into a cone and stick it in there:

This was better but still not ideal. I needed something to disrupt the flakes and get them to fall. Ultimately I decided to hot glue a 3″ screw upside down against the JBweld-servo at the bottom so it would disrupt the entire food storage unit as it went back and forth.
With that problem solved, I was able to tweak the code until I got the appropriate amount of food to fall on each run. Once satisfied with that, all that was really left was to put all the hardware together. Well I mean, there was that little “how will I power this thing” obstacle:

Obviously that wasn’t going to work (lol) and servos require a bit more of a power draw than an LED. I remembered when I bought my house a few years ago the mortgage company gave me some small USB power banks. Perfect.

Now I could attach everything to a single contained unit! I used a plastic container that some screws came in, threw everything in there and zip tied it closed – now this is engineering!

With all that done, all that was left to do was send the device on its maiden voyage:
And that’s it! Here’s the final display:

Remember we talked about the timer? The timer situation isn’t ideal. I ran through some other options but for now I’m just going to run a delay() method for 24 hours. It’ll be off more and more every day because the processor can’t keep time like that, but I’m hoping it will run a week or so before it’s off by more than an hour. The other concern here is I have no idea what the total potential energy of the OnQ financial swag charger is or how long it will power the device for….. I guess we’ll figure it out.
If you have any ideas or experience with this sort of thing, I’d be interested in hearing about what a more efficient way to power and run the timer might be. Ideally it would wake the device up every 24 hours, run the program, then sleep for another 24 hours.
Anyway, here’s the code:
#include <Servo.h> //Servo library
Servo fish_opener; //initialize a servo object for the connected servo
int angle = 0;
int times_to_run = 2;
int start;
void setup()
{
fish_opener.attach(9); // attach the signal pin of servo to pin9 of arduino
}
void loop()
{
while(start <= times_to_run)
{
for(angle = 0; angle <= 45; angle += 6) // command to move from 0 degrees to 45 degrees / increment of 6
{
fish_opener.write(angle); //command to rotate the servo to the specified angle
delay(10);
}
delay(500);
for(angle = 45; angle >=1; angle-=6) // command to move from 45 degrees to 0 degrees / increment of 6
{
fish_opener.write(angle); //command to rotate the servo to the specified angle
delay(10);
}
delay(500);
start += 1;
}
start = 0; //reset while loop variable
delay(86400000); //24 hours
}
All in all it was a fun project. I really enjoy the hardware side of things and hadn’t put something together a little more than two years ago with my crypto miner.
Cheeky Bonus
When I decided I was going to make this into a blog post I airdropped all of my photos and videos from my iPhone to my MacBook pro.

HEIC isn’t a friendly web format and there was no way I was going to open up each file in preview and export them. A little known trick with these newer formats like HEIC
and WEBP
is you can simply rename the file extension to convert. However, there was also no way I was going to manually click each file and rename the extension so I used this handy 8 line Python script:
import os,sys
folder = '/Users/RFaile/Desktop/fishfeeder'
for filename in os.listdir(folder):
infilename = os.path.join(folder,filename)
if not os.path.isfile(infilename): continue
oldbase = os.path.splitext(filename)
newname = infilename.replace('.HEIC', '.jpg')
output = os.rename(infilename, newname)
Which fixed it right up in less than a second:

Programmers are so lazy.