Code Version 1.0
From Reef Projects
Code is fairly well commented.
Current Features:
- Controls lights/timer function
- Kills lights in the event of over heating
- If lights are killed because of restart (power fail) or overheating, there is a delay before turning on
- Controls heater/fan
- Feed mode button
- ATO
- Alarm, although not used yet
- Prints to LCD
#include <OneWire.h>
#include <LCDI2C.h>
//#include <stdio.h>
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
/*
Arduino Reef Controller
Analog Pin 1 = **PH Probe?
Analog Pin 2 = **ORP Probe?
Analog Pin 3 =
Analog Pin 4 = SDA for I2C
Analog Pin 5 = SCL for I2C
Digital Pin 0 = RX
Digital Pin 1 = TX
Digital Pin 2 = Temp Sensor
Digital Pin 3 = ATO Input
Digital Pin 4 = Feed Mode Button
Digital Pin 5 = Relay 1 Heater
Digital Pin 6 = Relay 2 Day Light
Digital Pin 7 = Relay 3 Moon Light
Digital Pin 8 = Relay 4 Fan
Digital Pin 9 = Relay 5 Automatic Top-off
Digital Pin 10 = Relay 6 Power Head #1
Digital Pin 11 = Relay 7 Power Head #2
Digital Pin 12 = Relay 8 Skimmer
Digital Pin 13 = Alarm
*/
LCDI2C lcd = LCDI2C(4,0x4C); //[# of lines on LCD],[address of serial LCD controller on I2C]
OneWire ds(2); // Temp Sensor on pin 2
int ato_input = 3; //ATO input on pin 3
int feed = 4; //Feed Mode Button
int heater = 5;
int day_light = 6;
int moon_light = 7;
int fan = 8;
int ato = 9;
int ph_1 = 10;
int ph_2 = 11;
int skimmer = 12;
int alarm = 13;
int heater_on_temp = 7950; //Turn on the heater at this temp ex 78 degrees = 7800, 78.5 degrees = 7850
int heater_off_temp = 8000; //Turn off heater at this temp
int fan_on_temp = 8150; //Turn on fan at this temp
int fan_off_temp = 8050; //turn fan off once below this temp
int lights_off_temp = 8300; //Turn off the lights if the temp rises above this temp
int lights_on_time = 1300; //Turn day lights on at this time (military time)
int lights_off_time = 2100; //Turn day lights off at this time
int on_minute; //sets the turn on time.
int wait_time = 30; //how long to wait before turning on lights if they are turned off due to power loss or overheating
int lights_out = -100; //placeholder --don't change
int moonl_on_time = 2100; //Turn on moon lights at this time
int moonl_off_time = 700; //Turn off moon lights at this time
int feed_time = 5; //Turn off power heads for this amount of time when feed mode button is pressed.
int pumps_off = -10; //placeholder --don't change
int c2f(int cel){ //Function to convert celcius to Fahrenheit
return (cel * 9/5) + 3200;
}
void setup(void) {
/* Un-comment to set the time
RTC.stop();
RTC.set(DS1307_SEC,01); //set the seconds
RTC.set(DS1307_MIN,22); //set the minutes
RTC.set(DS1307_HR,13); //set the hours (military)
RTC.set(DS1307_DOW,2); //set the day of the week
RTC.set(DS1307_DATE,17); //set the date
RTC.set(DS1307_MTH,3); //set the month
RTC.set(DS1307_YR,9); //set the year
RTC.start();
*/
lcd.init(); //initialize LCD
//****** initialize inputs/outputs ************************************/
pinMode(heater, OUTPUT); // digital pin for heater as output
pinMode(day_light, OUTPUT); // digital pin for day light as output
pinMode(moon_light, OUTPUT); // digital pin for moon light as output
pinMode(fan, OUTPUT); // digital pin for fan as output
pinMode(ato, OUTPUT); // digital pin for auto top off as output
pinMode(ph_1, OUTPUT); // digital pin for power head 1 as output
pinMode(ph_2, OUTPUT); // digital pin for power head 2 as output
pinMode(skimmer, OUTPUT); // digital pin for skimmer as output
pinMode(ato_input, INPUT); //digital pin for ATO float switch as input
pinMode(feed, INPUT); //digital pin for feed mode button as input
pinMode(alarm, OUTPUT); // digital pin for alarm as output
on_minute = 1;
delay(2000);
digitalWrite(day_light, LOW);
}
int High = 0;
int Low = 10000;
void loop(void){
byte i;
byte present = 0;
byte data[12];
byte addr[8];
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract, minute, hour, second, date, month, year, mil_time;
char buf[12]; //used to convert int to string for displaying on LCD
//Get time from DS1307**********************************************************************************************
hour = RTC.get(DS1307_HR,true); //This is in military time
minute = RTC.get(DS1307_MIN,false);
second = RTC.get(DS1307_SEC,false);
date = RTC.get(DS1307_DATE,false);
month = RTC.get(DS1307_MTH,false);
year = RTC.get(DS1307_YR,false);
mil_time = (hour * 100) + minute; //create military time output
//Get temp data from DS18B20 ***************************************************************************************
if ( !ds.search(addr)) {
ds.reset_search();
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
Tc_100 = c2f(Tc_100);
//Display current temperature*****************************************************************************
lcd.position(0,0);
Whole = (Tc_100 / 100); // separate off the whole and fractional portions
Fract = (Tc_100 % 100);
lcd.println(itoa(Whole, buf, 10));
lcd.println(".");
if (Fract < 10)
{
lcd.println("0");
}
lcd.println(itoa(Fract, buf, 10));
lcd.print(0xDF);
lcd.println("F");
//Display Time******************************************************************************************
lcd.position(0,10);
if(hour == 0){
hour = 12;
}
if( hour > 12){
if(hour - 12 < 10){
lcd.println(" ");
}
lcd.println(itoa(hour - 12, buf, 10));
}
else{
if(hour < 10){
lcd.println(" ");
}
lcd.println(itoa(hour, buf, 10));
}
lcd.println(":");
if(minute < 10){
lcd.println("0");
}
lcd.println(itoa(minute, buf, 10));
lcd.println(":");
if(second < 10){
lcd.println("0");
}
lcd.println(itoa(second, buf, 10));
if(hour > 11){
lcd.println("PM");
}
else{
lcd.println("AM");
}
//Display High Temp***********************************************************************************
if(on_minute == 0){ //used so if bad data is sent for the first reading, it is not saved
lcd.position(1,0);
if(Tc_100 > High){
High = Tc_100;
}
Whole = (High / 100); // separate off the whole and fractional portions
Fract = (High % 100);
lcd.println("H= ");
lcd.println(itoa(Whole, buf, 10));
lcd.println(".");
if (Fract < 10)
{
lcd.println("0");
}
lcd.println(itoa(Fract, buf, 10));
lcd.print(0xDF);
lcd.println(" ");
}
//Display Low Temp***************************************************************************************
if(on_minute == 0){ //used so if bad data is sent for the first reading, it is not saved
if(Tc_100 < Low){
Low = Tc_100;
}
Whole = (Low / 100); // separate off the whole and fractional portions
Fract = (Low % 100);
lcd.println("L= ");
lcd.println(itoa(Whole, buf, 10));
lcd.println(".");
if (Fract < 10)
{
lcd.println("0");
}
lcd.println(itoa(Fract, buf, 10));
lcd.print(0xDF);
}
//Relay Controls ***************************************************************************************
//****************Heater
if(Tc_100 < heater_on_temp){ // turn heater on if temp is below heater_on_temp
digitalWrite(heater, HIGH);
}
if(Tc_100 > heater_off_temp){ //turn heater off if temp is above heater_off_temp
digitalWrite(heater, LOW);
}
//****************Day Lights
if((lights_off_temp < Tc_100 && digitalRead(day_light) == HIGH) || (digitalRead(day_light) == LOW && on_minute == 1)){
lights_out = (minute + wait_time) % 60;
}
if((lights_out == minute || lights_out == -100) && (lights_off_temp > Tc_100 && lights_on_time <= mil_time && lights_off_time > mil_time)){
digitalWrite(day_light, HIGH);
lights_out = -100;
}
else{
digitalWrite(day_light, LOW);
}
//****************Moon Lights
if(moonl_on_time <= mil_time || moonl_off_time > mil_time){
digitalWrite(moon_light, HIGH);
}
else{
digitalWrite(moon_light, LOW);
}
//****************Fan
if(Tc_100 > fan_on_temp){ // turn fan on if temp is above fan_on_temp
digitalWrite(fan, HIGH);
}
if(Tc_100 < fan_off_temp){ //turn fan off if temp is below fan_off_temp
digitalWrite(fan, LOW);
}
//****************Auto top off
if(digitalRead(ato_input) == LOW){
digitalWrite(ato, HIGH);
delay(3000); //Turn on ATO pump for 3 seconds
digitalWrite(ato, LOW); //Turn off ATO Pump
}
//****************Power heads and skimmer feed mode
if(digitalRead(feed) == LOW){
pumps_off = (minute + feed_time) % 60;
}
if(pumps_off == minute || pumps_off == -10){
digitalWrite(ph_1, HIGH);
digitalWrite(ph_2, HIGH);
digitalWrite(skimmer, HIGH);
pumps_off = -10;
}
else{
digitalWrite(ph_1, LOW);
digitalWrite(ph_2, LOW);
digitalWrite(skimmer, LOW);
}
//Display what relays are on********************************************************
lcd.position(2,0);
if(digitalRead(heater) == HIGH){lcd.println("H1 ");}
else{lcd.println("H0 ");}
if(digitalRead(day_light) == HIGH){lcd.println("D1 ");}
else{lcd.println("D0 ");}
if(digitalRead(moon_light) == HIGH){lcd.println("M1 ");}
else{lcd.println("M0 ");}
if(digitalRead(fan) == HIGH){lcd.println("F1 ");}
else{lcd.println("F0 ");}
lcd.position(3,0);
if(digitalRead(ato) == HIGH){lcd.println("A1 ");}
else{lcd.println("A0 ");}
if(digitalRead(ph_1) == HIGH){lcd.println("P1 ");}
else{lcd.println("P0 ");}
if(digitalRead(ph_2) == HIGH){lcd.println("P1 ");}
else{lcd.println("HP ");}
if(digitalRead(skimmer) == HIGH){lcd.println("S1");}
else{lcd.println("S0");}
on_minute = 0; //signals that the program has been run once
} //end loop
