Introduction: Fish Feeder

Introduction

Why this project

My aquarium is a Juwel Rekord 800 and has a Juwel feeding machine. I bought the machine to be able to feed my fish on regular times when I'm not around. It's a great machine, but as an engineer I see some room for improvement.

For example:

– There is no way to see when there will be a next feeding.

– You have only 1 feed per day or 2 feedings per day with an interval of 6 hours.

– To store a time of feeding you have to physically push a button at that time.

– I have children who like to push buttons, so I have to reset the machine.

In short I don't know for sure when and much the fish are fed when I'm not around.

The plan

The temperature of the aquarium is monitored by a Raspberry Pi which is going to send an e-mail when something is wrong. Also the Raspberry Pi controls the leds of the diorama which emulates a sunrise and a sundown. I would like to use the Raspberry Pi to monitor the feeding of the fish.

The plan is to build a feeding machine with an Arduino controller which reports to the Raspberry Pi.

The Arduino has the following tasks:

– Receive trough the USB power and data from the Raspberry Pi.

– Send trough the USB dat to the Raspberry Pi

– Rotate the servo’s of the moving parts.

– 1 Servo for the turning of the feeding container.

– 1 Servo for the closing the hatch of the feedig machine against moist.

– Display with a LCD the time, time to/of the next feeding and other important values.

– Measuring the quantity of food of a feeding (under development).

The raspberry Pi has the following tasks:

– Retrieve the CET from the internet and pass this to the Arduino.

– Send tasks to the Arduino.

– Receiving and processing of the measurements of the quantity of a feeding (under development).

This project

This project is divided in several subproject:

- The build of the feeding machine

- The build of the sensor

- The link between Raspberry Pi and Arduino

The build of the sensor array can be found here: Fish Feeder Sensor Array

The link between Raspberry Pi and Arduino can be found here:Fish Feeder Arduino Raspberry Pi Serial Link

This project only describes the build of the feeding machine.

Step 1: Principle

There are several ways to add a certain amount of food to an aquarium. The filling of the machine must be easy, the amount of food must be controllable and the amount must be constant.

The Juwel feeding machine uses a rotating container with a gap. By rotating the container an amount of food is allowed to pass. This principle works well. One downside is that the amount of food inside the container affects the amount of food that is passed.

For our feeding machine I want to use this principle. To avoid the problem of the variable amount of food I use a second chamber to stock/limit the food. This feeding machine has a feeding container which is rotated as the Juwel feeding machine. Added is the tube inside the feeding container, which has an opening which allows a certain amount of food to enter the tube. When rotated the food is poured from the tube into the aquarium.

The tube inside the feeding container has (at postion 1, the start position):

- A plug (red)

- An slot opening at the right, above the plug.

- An opening at the top.

The food is in green, the rotation direction is indicated with the blue arrow.

Step 2: Materials, Parts, Tools

To build this feeding machine several materials and parts are needed. As this is a proto, cheap and off the shelf parts are used. The feeding container is made from parts of a DIY-shop. The controller is an Arduino clone from China. The housing is out of plywood.

When this proto has proven to be durable and functional parts can be swapped for a better quality one and the machine can be overall build more permanent.

Feeding container

1x Transparant PVC 2x socket DN32

1x Alu tube ø10x1 L=1m

1x Cap DN32

1x Screw cap DN32

2x Hose clamp ø10

Controller

1x Arduino Uno R3 ATMega328P compatible €7,52

2x Servo, container, hatch, 2x €2,93

1x LCD Display 1602 with keypad €4,89

1x Green led (LDR has a peak response for green light)

5x LDR5506

Other materials

– 3mm plywood

– 5mm plywood

– waterresistant wood glue

– perfboard 9x18 with horizontal conductors

– soldertin

– resistor 5x 10kΩ, 2x 220Ω, 2x 47Ω, 1x 470Ω

– condensator 1x 100µm

– transistor NPN 2x 2N2222

– pin

– wire

– coating

– 2-component expoxy

– paperclip

Tools

– CAD-station

– Woodsaw

– Ruler

– Dril

– Soldering iron

– Multimeter

Step 3: Test Setup

Variable opening of de container tube

The amount of food must be adjustable. The choise is to use a container with food which has an adjustable tube with a fixed slot. Sliding the tube results in a larger or smaller opening.

Results of the tube slots

The aluminium tube, size ø10x1, can be provided with different slots. The internal diameter of the tube is ø8mm. The width of the slot is therefore limited to 5mm. The internal diameter of the feeding container is ø32mm. The height of the slot is therefore limited to 10mm. For the results of the test see the above pictures.

The 3rd test result has the amount of food which I feed my fish, so for the time being this is my setting. Feel free to experiment!

Step 4: Preliminary Feeding Container

The test results of the tube slot are conducted by hand. To approach the final feeding container a preliminary container is build from first container. The caps on both sides are removed and replaced with plywood caps with an axle.

The results of the preliminary feeding container are equal of the test container. No deviations are found.

See picture 5: on the left the preliminary feeding container, on the right the juwel feeder.

Step 5: Sensor

In the feeding machne an Arduino is used as a controller. A servo, connected to a digital pin of the Arduino, rotates the food container. A second servo opens and closes a hatch to avoid moisture from the aquarium entering the feeding machine and feeding container. The analog pins of the Arduino are used to measure the amount of food delivered to the aquarium/fish.

There are several methods to measure, therefore the design of the sensor is designed to be detachable and replaceable when redesign is needed. The most easy method is to use a beam of light and a light sensor.

The sensor is another subproject. A short test to verify this method is feasible is conducted.

At the right side a led is drawn. A beam of light is send to the photo resistors on the left. When the beam of light is interrupted, the resistance of the photo resistors will change.

The principle is tested in a simple test. Food was poured between a led and a photo resistor. A simple multimeter was able to measure changes in resistance of the photo resistors. These results are promising.

The final results can be checked when both the feeding machine and sensor are build. So no guaranties for now!

Step 6: Model / Drawings

To build the feeding machine SolidWorks is used to make a model and drawings.

Structure model

The structure of the assembly in components is:

– 001 Main assembly

– 010 Feeding container

– 019 Feeding container coupling plate

– 020 Houding feeding machine

– 040 Housing Arduino

– 050 Cover

– 060 Sensor

– 080 Hatch

The drawings are in Dutch, my excuses. Please verify the drawings before starting your build. Also check the dimensions of your components (servo’s, Arduino, LCD).

Step 7: Building

My choice of building materials is plywood.

- It's a cheap material I have lying around.

- It’s easy to work on.

- You can grind, saw, cut, drill, sand it, until the parts and components fit.

- Glue it, paint it.

When this feeding machine has proven to be durable and reliable I could consider to 3D-print this machine to make it more sophisticated.

The opening on top the aquarium releases hot air with high levels of moisture. The hot water inside the aquarium evaporates and wants to rise. To avoid moisture to affect the feeding machine, I use:

- Watertight glue, to ensure the bondings.

- Watertight epoxy, to avoid moisture getting inside the plywood.

- Hatch, to avoid moisture, which will destroy your components, inside the machine.

Always check regularly if parts, components, sub assemblies fit correctly. Adjust before applying the coatings.

- Use a pencil, a ruler and a 90degrees ruler to draw the parts on the plywood. Always check the straightness before sawing and drilling your parts.

- Glue the parts together with watertight glue. Check with a 90degrees rulers if your parts are glued correctly.

- Apply a first layer of watertight 2 component epoxy. Read carefully the instructions of the products. Use the correct personal protective equipment. Next apply the color. Seal with a epoxy layer. Before applying a coating remove dust, remove grease and sand properly.

See the pictures above of the progress in building the machine.

Step 8: Electrics

In this build a power supply of 5V and 2 A is recommended for the Raspberry Pi. The Raspberry Pi powers the Arduino trough USB cable. The Arduino powers the Servos, LCD, led and other. The maximum electric current from a Raspberry Pi is limited, also the maximum current from an Arduino is limited. In the feeding machine I’m using 2 servos, which are known to draw a lot of current.

The power supply for the Raspberry Pi can deliver 2A. The maximum current from the 4x USB-ports combined is 1.2A. The default current is 0.6A. The goal is to minimize the power consumption. The default current setting is used.

Servos

The power usage of the servos can be too high. The power consumption is the result of it:

- Design.

- Operating speed.

- Friction.

To limit the power consumption the following is considered:

- Design: I use a small and not so powerful servo. This results in a lower power consumption. My choice for the TowerPro servos is more cost driven. If you want to lower the power consumption even more, power efficient servos are available. I can’t give advice, because I’m a noob for servos.

- Operating speed: The rotating speed is kept low. To get a smooth rotation, small rotations with a little delay is used. In Arduino programmig use writeMicroseconds instead of write(angle) (writeMicroseconds is more accurate).

- Friction: The feeding container with a wooden axle surrounded with an aluminum tube. This aluminum tube rotates on an epoxy bedding.

Other tricks are:

- The use of the attach and detach commands. When in detach the servo uses 5mA.

- The use of a capacitor to dampen fluctuations.

- The use of a transistor to shut down a part of the circuit (including the servos).

- The servos are not used simultaniously.

LCD

The LCD has a constant current usage. On average this is 23mA. Be aware of the D10-bug. To avoid this bug simply clip off the D10 pin.

The backlight of the LCD can be turned on/off by the D10 pin. When used incorrectly there can be a current overload to the Atmel chip. For this build there is no use for turning on/off the backlight. I do not use the keypad.

Led

The colour of the led is green. The CDS photo sensors are more sensitive for green light. To prevent a current overload a 470Ω resistor in series is used. This results in a current of 10mA.

Transistor

Pin D12 en D13 are used to power on/off the servo and led. Typically a transistor can transmit the 10-fold of current on the base (Ic/Ib=10). The maximum current from an Arduino digital pin is 20mA. So the maximum switching current of the transistor is 10x20=200mA. I use 1 transistor to power on/of the servos. The led and photo resistors are switched on/off with a second transistor.

Power consumption Arduino

The command lsusb -v|egrep "^Bus|MaxPower" results in a power consumption which the Arduino tells the Raspberry Pi. This is not the real consumption.

Real power consumption

To get the real power consumption I use a standard multimeter. The following values are measured:

Arduino 50-60mA
LCD 23mA
Servo 1 5-110mA
Servo 2 5-110mA
Led 10-20mATransistor NPN 20mA

Servo 1 and 2 are not used simultaneously.

The maximum current the Raspberry Pi must deliver is 60+23+110+10+20=223mA. This is less than the 600mA a Raspberry Pi can deliver.

The maximum current the Arduino must deliver is 23+110+10+20=163. This is less than the 2x200mA an Arduino can deliver.

Step 9: Electric Schematic

If you want advice on soldering, please search the web for instructions.

I have used a perfo-board with horizontal conductors. You can use something else.

Please note:

- Line 2 and 16 remove the horizontal cundoctor from left to right until the transistor.

- Line 3 remove the horizontal conductor from transistor until the servo datapins.

- Line 17 remove the horizontal conductor from transistor to led.

- I have used 2 resistors I series between D12, D13 and the transistor. If you want you can use a single 270Ω resistor.

- I have color coded the board to make the board more easy to understand.

- I prefer a detachable board to be able to service.

After you have soldered and tested your board, you can solder the wires to the Arduino. Cut the wires to the correct size before soldering.

Step 10: Coding

Please note this code is without the subprojects!

/*
Arduino is connected with USB to Raspberry PI
Two programs are running
1 Rasberry PI is the master Sending lines: - line01 : date - line02 : time - line03 : water temperature - line04 : when is the sunrise - line05 : when is the sundown - line06 : when is the time/manual/off and result of feeding of the fish 1 - line07 : when is the time/manual/off and result of feeding of the fish 2 - line08 : when is the time/manual/off and result of feeding of the fish 3 - line09 : when is the time/manual/off and resukt of feeding of the fish 4 - line10 : optional Sending times: - time01 : minutes until next feed - time02 : minutes until sunrise - time03 : minutes until sundown Receiving: - resullt of the feeding - request for sending line 01 to 10

2 Arduino is the slave Sending & Receiving to Raspberry PI Pins - LiquidCrystal (8, 9, 4, 5, 6, 7) & A0 - Softwareserial (10, 11) RX, TX - ReadingCds (A1, A2, A3, A4, A5) - Servo 1 (2) - Servo 2 (3) - Servo aan/uit (12) - Led aan/uit (13) Looping 1 Request & Read line 01 to 10 Request & Read time 01 to 03 If time 01 < 1 Display a countdown & Feed If time 02 or 03 < 1 Display a countdown Dispay current setting line01 to line10 1 per second */

/* Power consumption General power consumption Arduino: 50-60mA LCD screen Checking the USB-port, Arduino only, Arduino with LCD lsusb -v|egrep "^Bus|MaxPower" Bus 001 Device 006: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter MaxPower 96mA USB devices must tell the controller how much current they draw Using a multimeter reports 23mA Servo 1 Library: Servo, Delay 10ms, angle When detached the multimeter reports 5mA When attached the multimeter reports 150mA 1 Library: Servo, Delay 30ms, angle When detached the multimeter reports 5mA When attached the multimeter reports 125mA 2 Library: VarSpeedServo, speed 30 When detached the multimeter reports 5mA When attached the multimeter reports 150mA 3 Library: Servo, writeMicroseconds When detached the multimeter reports 5mA When attached the multimeter reports 110mA

For servo please note: Keep friction low

Total Servo1 Servo2 Arduino 50mA 50mA LCD 25mA 25mA Servo1 110mA 5mA Servo2 5mA 110mA LED 20mA 20mA NPN 20mA 20mA --- + --- + 230mA 230mA */

// Setting up the Keypas LCD #include LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 ); /* initialize the library with the numbers of the interface pins Arduino : LiquidCrystal lcd(12, 11, 5, 4, 3, 2); Clone : LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 ); A note about the Pin 10 bug Just one thing to mention, they all happen to have a flaw in the design, so don’t use pin 10 when using this shield. The library has functions to enable and disable the backlight. But in the design, a flaw exists, that when pin 10 is set to output, and set high, it could cause the IO pin of the MCU (the main Atmel chip) to deliver too much current (over the datasheet’s maximum rating) to the backlight LED. This may cause the over stressing of the MCU and may reduce its life, or maybe even blow it up. - To set the backlight on, set pin 10 as input. - To set the backlight off, set pin 10 as output, and immediately set output low (never high!)

Clip off pin 10 */

// Setting up the serial link with Raspberry pi // #include // SoftwareSerial mySerial(10, 11); // RX, TX // * RX is digital pin 10 (connect to TX of other device) // * TX is digital pin 11 (connect to RX of other device)

// Setting up the servo #include Servo servo1; // create servo1 object to control servo feeder Servo servo2; // create servo2 object to control servo hatchh int servo1_pos = 0; // variable to store the servo1 position int servo2_pos = 0; // variable to store the servo2 position

// Setting up the Led & LDR int var_blink_led = 0; // Setting up the array for A1-A5 int var_A1[99]; int var_A2[99]; int var_A3[99]; int var_A4[99]; int var_A5[99]; int led_pos=0; int wacht=100;

void setup() { // - Servo aan/uit (12) pinMode(12, OUTPUT); // - Led aan/uit (13) pinMode(13, OUTPUT); }

void servo_on(){ digitalWrite(12, HIGH); // power on to the servo delay (1000); // wait until the capacitor is filled }

void servo_off(){ digitalWrite(12, LOW); // power off to the servo delay (1000); // wait until the capacitor is empty }

void blink_led(){ // just a simple test when feeding starts or stops for (var_blink_led=0; var_blink_led<5; var_blink_led +=1) { digitalWrite(13, HIGH); // Turn the led on delay (1000); digitalWrite(13, LOW); // Turn the led off delay (1000); } }

void led_on(){ // turn on the led digitalWrite(13, HIGH); // Turn the led on }

void led_off(){ // turn on the led digitalWrite(13, LOW); // Turn the led off }

void feeding() { /* Normally a servo is attached at the setup void setup() { myservo.attach(9); // attaches the servo on pin 9 to the servo object } The servo receives commands through the program and works to keep the right angle In this program the servos runs for a few seconds and keeps idle until next command To keep power consumption and noise low the feeding loop has an internal attach en detach Attaching and detaching affects the power consumtion of the servo-pin The second step is using the power circuit that turns on/off the 5V Position start | 75% servo position 6:00 1100 Move to loading position / 100% servo position 7:30 700 Move to horizontal position - 25% servo position 3:00 1900 Move to empty position / 0% servo position 1:30 2300 Return to start position | 75% servo position 6:00 1100 */ for (led_pos = 1; led_pos <= 99; led_pos += 1) { // 1 to 99 clear analog array var_A1[led_pos]=0; var_A2[led_pos]=0; var_A3[led_pos]=0; var_A4[led_pos]=0; var_A5[led_pos]=0; } servo1.attach(2); // attaches the servo on pin 2 to the servo object // Move to loading postion for (servo1_pos = 1100; servo1_pos >= 710; servo1_pos -= 1) { // goes from 6:00 to 7:30 servo1.writeMicroseconds(servo1_pos); // tell servo to go to position in variable 'pos' delay(5); // waits 5ms for the servo to reach the position } // Move to horizontal position for (servo1_pos = 710; servo1_pos <= 1900; servo1_pos += 1) { // goes from 7:30 to 3:00 servo1.writeMicroseconds(servo1_pos); // tell servo to go to position in variable 'pos' delay(5); // waits 5ms for the servo to reach the position } // Move to empty position led_on(); for (servo1_pos = 1900; servo1_pos <= 2290; servo1_pos += 10) { // goes from 3:00 to 1:30 servo1.writeMicroseconds(servo1_pos); // tell servo to go to position in variable 'pos' delay(5); // ((2300-1900)/10)*5 = 200ms desceend time 100-150ms } // Measure quantity for (led_pos = 1; led_pos <= 99; led_pos +=1) { //A1 analogRead(A1); // read analog input A1 delay(10); var_A1[led_pos]=analogRead(A1); //A2 analogRead(A2); delay(10); var_A2[led_pos]=analogRead(A2); //A3 analogRead(A3); delay(10); var_A3[led_pos]=analogRead(A3); //A4 analogRead(A4); delay(10); var_A4[led_pos]=analogRead(A4); //A5 analogRead(A5); delay(10); var_A5[led_pos]=analogRead(A5); } led_off(); // Return to start position for (servo1_pos = 2290; servo1_pos >= 1100; servo1_pos -= 1) { // goes from 1:30 to 6:00 servo1.writeMicroseconds(servo1_pos); // tell servo to go to position in variable 'pos' delay(5); // waits 5ms for the servo to reach the position } servo1.detach(); // detaches the servo on pin 2 to the servo object }

void openhatch() { /* See also void feeding Position start closed | 100% servo position 12:00 2300 Position end open | 0% servo position 6:00 700 */ servo2.attach(3); // attaches the servo on pin 3 to the servo object for (servo2_pos = 2290; servo2_pos >= 710; servo2_pos -= 1) { // goes from 12:00 to 6:00 servo2.writeMicroseconds(servo2_pos); // tell servo to go to position in variable 'pos' delay(5); // waits 5ms for the servo to reach the position } servo2.detach(); // detaches the servo on pin 2 to the servo object }

void closehatch() { /* See also void feeding Position start closed | 100% servo position 12:00 2300 Position end open | 0% servo position 6:00 700 */ servo2.attach(3); // attaches the servo on pin 3 to the servo object for (servo2_pos = 710; servo2_pos <= 2290; servo2_pos += 1) { // goes from 6:00 to 12:00 servo2.writeMicroseconds(servo2_pos); // tell servo to go to position in variable 'pos' delay(5); // waits 5ms for the servo to reach the position } servo2.detach(); // detaches the servo on pin 2 to the servo object }

void loop() { servo_on(); // power on to the servo blink_led(); openhatch(); // open the hatch blink_led(); feeding(); // turn the feeding tube blink_led(); closehatch(); // close the hatch blink_led(); servo_off(); // power off to the servo }