This Update contains the wiring diagram and code for the temperature compensated feeder. This code is enough for you to make a unit to test if it works for you. I am pulling my time of day from another MCU running in the greenhouse, I advice wiring in a gps unit if you are making this a standalone unit.I will be doing a tutorial on this and how we use the time for regulating feeding timings in the near future. This is just a basics of how we compensate for temperature changes.



So why Compensate for Temperature

 

Most Species of Fish are cold blooded animals and as such the water temperature that they live in has a big effect on how they behave. In short cold water makes the fish slow and less hungry. As engineers what does this mean to us, well it means we have an input to a system that needs to vary with temperature if we want to use open-loop control. Luckily almost every aspect of a fish can be represented mathematically or at least  closely approximated.

 

Below is a table representing the amount to feed fish [Tilapia] as a function of temperature to maximise food productivity[1]:

132b.GIF

DFR: Daily Feed Rate, represent as percent of fish mass in the system.

 

As you can see the Water Temperature has quite a large effect on the amount of food Fish will Eat. I prefer Closed-Loop Feedback Systems, see the previous blog [Blog 5] to see how we can implement this to systems with floating food, but for systems with sinking food I am yet to think of a way to measure the food present in the system [Not to say one of you wont have a solution they feel like sharing?]

 

Other things that will effect how much to feed fish:

Screenshot 2015-08-17 12:40:21.png

So far we have only considered the effects of temperature on Feed amount, the coming Blogs will address the other Factors in great detail, but for now here are some outlines:


Feed Spacing/Timings

The optimum time between feeding of fish depends on the size of the stomach of the fish, when they are young they require feeding regularly, decreasing as they grow larger.

 

Feed Chemistry

The percent of protein you fed fish is related to the age of the fish and the water temperatures.

 

A Note On DO:

Dissolved Oxygen measurements are expensive, measuring probes need constant calibration and as such we will be assuming the pond has adequate oxygenation for growing fish. Spreading the feed serving over the day will spread the demand for DO over the day also. So in short, feeding multiple times a day decrease the peak demands for dissolved oxygen of the system. [this is a good thing]



The Wiring diagram:

 

AruinoTemp2_bb.jpg

You might notice that there are no external pull up/down resistors in this circuit, I dislike soldering resistors so every thing is implemented not to need them.

The button is connected to Pin A4, that is set up as an input with the internal pull up set to on, when the button is pressed it will pull A4 to LOW.

The Temperature sensor usually has an external pull up, but we are using a modified one-wire library that does this using the internal pull ups for the data pin.

 

 

The Code

I am sure a lot of you on Element14 will have the coding side nailed down, The code below is offered as a proof of concept, is it refined, pretty or making good use of the resources available, No. But it does work and will do for a proof of concept code, Later on we will be including extra hardware and refining the code then:

 

>Touch screen for GUI and imputing system detail

>Gps module to pull time from [used later for feed spacings]

 

Remember we are not using the default one-wire library, add a pull up to the temperature probe or install the custom library [see www.michaelratcliffe.com/projects]

 

Arduino Uno Proof of Concept Code

/*
  Automated Fish Feeder:
 
  This Program will give you a temperature based feed controller. See Read me in download file for more info.
  4/8/2015 Michael Ratcliffe
 
 
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program. If not, see .

*/

 

//************************** Libraries Needed To Compile The Script [See Read me In Download] ***************//

 

#include <OneWire.h> // We Need This Libaray To Read The Temperature Sensor, SEE READ ME In Downloaded Zip If You Dont Know how To install This

#include <DallasTemperature.h>

 

 

//************** User Defined Variables *******************************//

/*
Alter your variables by changinf the numbers below, they only aceept whole numbers

*/

 

long feedSpacing =60; //the time between feeds in mnuits

const int FeedsPerDay =24//Change this only is you change the feeding interval or total number of feeds a day

 

 

long MinWeight =5; //Minimum Weight [Kg] Of Fish You Want The Potentiometer To Represent

long  MaxWeight =20;//Maximum Wight [Kg] Of Fish You Want The Potentiometer To Represent

const int FeedRate=8.3; // g/s How Much Feed in Grams Your Feeder Dispnces In A Second [You need to Work This out]

 

 

int PercentTenC =3; //percent of Body weight to feed fish daily at 10*C

int PercenTwentSixC=12;//Percent of Body weight to feed fish daily at 26*C

 

int  MaxFeedPercent=16;

int MinFeedPercent=1//InCase The Sensor Breaks, We Will StillFeed Them a Minimum Amount

 

// The Ones Below Should Be ok as they are, unless your Relay uses pull Low Triggers

const int  OFF=1;

const int ON=0;

 

 

//****************** End Of User Variables ***************************//

 

 

 

//************ ONLY Cange These Values Below If You Have Wired To different Pins *****///

 

 

const int Potentiometer = A5;  // Analog input pin that the potentiometer is attached to

const int ButtonPin =A4;  //Button Connected to Pin A4

const int Motor = A3;  // Pin That Relay Triger wire is connected to

 

 

const int TempProbeNegative=8//Temp Probe Negative connected to pin 8

const int TempProbePossitive =9//Temp Probe power connected to pin 9

#define ONE_WIRE_BUS 10  // Data wire For Temp Probe is plugged into pin 10 on the Arduino

//************* End Of Pin Selection ********************************//

 

 

 

 

int ResistorValue = 0// value read from the pot

int outputValue = 0// value output to the PWM (analog out) 

int Button =1;

float FeedLength =0;

float Temperature=10;

long FishWeight = 1;

long  feedSpacingMillis =0;

long FeedPercent =1;

 

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)

OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.

DallasTemperature sensors(&oneWire);

 

//******************************* Setus up Things, This Loop Runs Once at Startup ***************************//

void setup() {

 

  Serial.begin(9600);

 

  pinMode(Motor, OUTPUT);

digitalWrite(Motor,OFF);

 

  pinMode(Potentiometer, INPUT);

  pinMode(ButtonPin, INPUT_PULLUP);

 

  pinMode(TempProbeNegative , OUTPUT );

  digitalWrite(TempProbeNegative , LOW );

  pinMode(TempProbePossitive , OUTPUT );

  digitalWrite(TempProbePossitive , LOW );

 

  delay(100);// gives sensor time to settle

  sensors.begin();

  feedSpacing=feedSpacing*60000; //Converts from minutes to milli seconds

 

 

 

 

  //************************************* Runs a Tester If You Hold the Feed Button When You Turns Power Switch On*************//

  GetReadings();

  if(Button==0){

 

  digitalWrite(Motor,ON);

  delay(FeedLength*1000);

  digitalWrite(Motor,OFF);

  delay(5000);

 

  };

 

};

 

//*******************************Main Loop [This Once Loops indefinatly ***************************************//

 

void loop() {

 

 

  GetReadings();

 

//*************** Checks if it is Time to Start The Feeder and delays to stop entering the loop twice *************************************************// 

 

  if( (millis()%feedSpacing<=1000  &&millis()>=1010)) {  //

  delay(1000); //stoprs multiple eneies into the loop

  digitalWrite(Motor,ON);

  delay(FeedLength*1000);

  digitalWrite(Motor,OFF);

  };

 

//************** Allows the Button To operate the feeder Only While Pressed ****************************//

  if (Button==0){

  digitalWrite(Motor,ON);  //Turns the Motor on

 

  }

  else {

  digitalWrite(Motor,OFF);

  };

 

 

 

//**************************** Makes The code Hang Here While The Sensors Settle ********************// 

 

delay(200);

PrintResults();

};

 

 

 

 

  //************************ Reads The Sensors and Calcalates the Feed Length ***********************************// 

  void GetReadings() {

  Button=digitalRead(ButtonPin);  //Reads The Button To Check If It Is Pressed

  ResistorValue = analogRead(Potentiometer);  //Checks what possition the potentiometer is at 

  sensors.requestTemperatures();  // Send the command to get temperatures

  Temperature=sensors.getTempCByIndex(0);

  Temperature=Temperature*100//easiest way to get

 

  //************ Turns Those Readings Into Something Useful [Optimum Feed Length ******************************// 

 

  FishWeight = map(ResistorValue,0,1023, MinWeight*1000, MaxWeight*1000);  //Turns The Potentiometer Reading Into Something Usefull);

  FeedPercent=map(Temperature,1000,2600,PercentTenC*100,PercenTwentSixC*100);

 

 

  if (FeedPercent >= (MaxFeedPercent*100)){

  FeedPercent= (MaxFeedPercent*100);

  }

 

  if (FeedPercent<= (MinFeedPercent*100)){

  FeedPercent=(MinFeedPercent*100);

  };

 

 

  FeedLength =((FeedPercent*FishWeight)/(FeedRate*FeedsPerDay));

  FeedLength = FeedLength/10000;

 

 

  };

 

 

 

//*************************** Prints The Variables To The Computer ************************************// 

void PrintResults(){

 

  Serial.print(" Water Temperature: ");

  Serial.print(Temperature/100 );

  Serial.println("*C");

 

  Serial.print(" User Has Selected: ");

  Serial.print(FishWeight/1000);

  Serial.println(" Kg of Fish");

 

  Serial.print(" Feed: ");

  Serial.print(FeedLength*FeedRate);

  //Serial.print(FeedLength);

  Serial.print(" Grams of food Every: ");

  Serial.print(feedSpacing/60000);

  Serial.println(" minute");   

};

 

The map feature will only output whole numbers and that is the reason we multiply the variables before the map and divide after [It could be better].

So I set this up for Tilapia, if you are using other fish you will need to read up about how much of their body weight to feed them at 10*C and 26*C and change the variables in the code to suit:

 

User Defined Species Specific

int PercentTenC =3; //percent of Body weight to feed fish daily at 10*C

int PercenTwentSixC=12;//Percent of Body weight to feed fish daily at 26*C

 

This Controller is still in its infancy, In the coming weeks we will be implementing control over the feeding intervals, expanding the species of fish it can feed and adding a screen to output the data.

 

Keep watching,

Mike

 

 

 

Reference

[1] [I will be adding the reference once I remember where I saved it]