#include <WProgram.h>
#include <DS1307.h>
#include <OneWire.h>
#include <Wire.h>
#include <LCDI2C.h>
#include <Ethernet.h>
/*
* Web Server
*
* A simple web server that shows the value of the analog input pins.
Analog Pin 0 =
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 4 =
Digital Pin 5 =
Digital Pin 6 = Relay 3 Sump
Digital Pin 7 = Relay 1 Heater
Digital Pin 3 = Relay 2 Day Light
Digital Pin 8 = Moon light
Digital Pin 9 = Relay 4 Fan
//Digital Pin 10 =
//Digital Pin 11 =
//Digital Pin 12 =
//Digital Pin 13 =
*/
LCDI2C lcd = LCDI2C(4,20,0x4C,1); //[# of lines on LCD],[address of serial LCD controller on I2C]
OneWire ds(2); // Temp Sensor on pin 2
int day_light = 3;
int moon_light = 8;
int fan = 9;
int actinic = 4;
int sunset = 4;
int ph_probe = 1; // pH probe on Analog 1
//int ato = 10;
//int ph_1 = 11;
//int ph_2 = 12;
//int skimmer = 10;
int sump = 6;
int heater = 7;
//*******************************Output settings*******************************************************************
int actinic_on_time = 930; // Turn on the actinics at this time
int actinic_off_time = 2130; // Turn off the actinics at this time
int heater_on_temp = 2400; //Turn on the heater at this temp ex 78 degrees = 7800, 78.5 degrees = 7850
int heater_off_temp = 2550; //Turn off heater at this temp
int fan_on_temp = 2700; //Turn on fan at this temp
int fan_off_temp = 2600; //turn fan off once below this temp
int lights_off_temp = 3000; //Turn off the lights if the temp rises above this temp
int alarm_low_temp = 7600; //alarm will begin if temp falls below this value & lights will turn on to raise the temperature
int alarm_high_temp = 8300; //alarm will begin if temp is above this value
int lights_on_time = 1100; // Turn Metal Halide light on at this time (military time)
int lights_off_time = 2100; // Turn Metal Halide light off at this time
int moonl_on_time = 2000; //Turn on moon lights at this time
int moonl_off_time = 530; //Turn off moon lights at this time
int fuge_on_time = 2000; //Turn on refugium lights at this time
int fuge_off_time = 1000; //Turn off refugium 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 skimmer_off = -10; //placeholder ---don't change
//int pumps_off_second, pumps_off_minute, pumps_on_minute, pumps_off_hour, pumps_on_second, pumps_on_hour, pumps_on, skimmer_on_hour, skimmer_on_minute, skimmer_on_second;
// Useful for running kalkwasser and account for pH drop during night time.
#define NUMREADINGS_ph 60
int readings_ph[NUMREADINGS_ph]; // The readings from the analog input
#define NUMREADINGS_orp 60
int readings_orp[NUMREADINGS_orp]; // The readings from the analog input
int index_ph = 0; // The index of the current pH reading
int index_orp = 0; // The index of the current ORP reading
int total_orp = 0;
int total_ph = 0;
int average_orp = 0;
int average_ph = 0;
//int ato_time = 3; //Number of seconds for teh ATO to run each time the switch is on.
#define NUMREADINGS 10
int readings[NUMREADINGS]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
int keypad_delay = 15; //necessary delay to keep from having scrambled characters on the display
// global variables
int minute, hour, second, date, month, year, now, mil_time;
int Tc_100, temp_Low, temp_High, orp_val, orp_Low, orp_High, ph_val, ph_Low, ph_High, dosing_time;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 9 };
Server server(81);
void setup()
{
Wire.begin(); //initialize the I2C bus
lcd.init(); //initialize LCD
//RTC.stop();
//RTC.set(DS1307_SEC,01); //set the seconds
//RTC.set(DS1307_MIN,19); //set the minutes
//RTC.set(DS1307_HR,14); //set the hours (military)
//RTC.set(DS1307_DOW,2); //set the day of the week
// RTC.set(DS1307_DATE,25); //set the date
// RTC.set(DS1307_MTH,4); //set the month
// RTC.set(DS1307_YR,11); //set the year
// RTC.start();
//****** initialize inputs/outputs ************************************/
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(heater, OUTPUT); //digital pin for heater output
pinMode(actinic, OUTPUT); // digital pin for fan as output
pinMode(sump, OUTPUT); // digital pin for skimmer as output
for (int i = 0; i < NUMREADINGS; i++)
readings[i] = 0;
delay(100);
Ethernet.begin(mac, ip);
server.begin();
}
int High = 0;
int Low = 10000;
int on_minute = 1; //indicates that this is the first time through the program.
void loop(void){
int mode = 100;
if(lcd.keypad() != -1){
mode = lcd.keypad();
}
//***********Mode B Set Time*************************************************************************************************
if(mode == 101){
int minute, hour, second, date, month, year, tens, ones, key;
int set_time = 0;
while(set_time == 0){
lcd.clear();
hour = RTC.get(DS1307_HR,true); //This is in military time [0,23]
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);
lcd.setCursor(0,0);
if(hour < 10){
lcd.print(" ");
delay(keypad_delay);
}
lcd.print(hour);
delay(keypad_delay);
lcd.print(":");
delay(keypad_delay);
if(minute < 10){
lcd.print("0");
delay(keypad_delay);
}
lcd.print(minute);
delay(keypad_delay);
/* Don't print seconds
lcd.print(":");
delay(keypad_delay);
if(second < 10){
lcd.print("0");
delay(keypad_delay);
}
lcd.print(second);
delay(keypad_delay);
*/
lcd.setCursor(1,0);
if(month < 10){
lcd.print(" ");
delay(keypad_delay);
}
lcd.print(month);
delay(keypad_delay);
lcd.print("/");
delay(keypad_delay);
if(date < 10){
lcd.print(" ");
delay(keypad_delay);
}
lcd.print(date);
delay(keypad_delay);
lcd.print("/");
delay(keypad_delay);
if(year < 10){
lcd.print("0");
delay(keypad_delay);
}
lcd.print(year);
delay(keypad_delay);
lcd.setCursor(0,0);
lcd.cursor_on();
//**************Set Hour*********************************************************************************************
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 2){tens = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.print(tens);
delay(keypad_delay);
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 9){ones = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.right();
RTC.stop();
RTC.set(DS1307_HR,tens * 10 + ones);
RTC.start();
lcd.setCursor(0,0);
hour = RTC.get(DS1307_HR,true);
if(hour < 10){
lcd.print(" ");
delay(keypad_delay);
}
lcd.print(hour);
delay(keypad_delay);
lcd.right();
//**************Set Minute*********************************************************************************************
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 6){tens = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.print(tens);
delay(keypad_delay);
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 9){ones = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.right();
RTC.stop();
RTC.set(DS1307_MIN,tens * 10 + ones);
RTC.start();
lcd.setCursor(0,3);
minute = RTC.get(DS1307_MIN,true);
if(minute < 10){
lcd.print("0");
delay(keypad_delay);
}
lcd.print(minute);
delay(keypad_delay);
//**************Set Month*********************************************************************************************
lcd.setCursor(1,0);
for (;;){
key = lcd.keypad();
if(key == 0 || key == 1){tens = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.print(tens);
delay(keypad_delay);
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 9){ones = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.right();
RTC.stop();
RTC.set(DS1307_MTH,tens * 10 + ones);
RTC.start();
lcd.setCursor(1,0);
month = RTC.get(DS1307_MTH,true);
if(month < 10){
lcd.print(" ");
delay(keypad_delay);
}
lcd.print(month);
delay(keypad_delay);
//**************Set Date*********************************************************************************************
lcd.setCursor(1,3);
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 3){tens = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.print(tens);
delay(keypad_delay);
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 9){ones = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.right();
RTC.stop();
RTC.set(DS1307_DATE,tens * 10 + ones);
RTC.start();
lcd.setCursor(1,3);
date = RTC.get(DS1307_DATE,true);
if(date < 10){
lcd.print(" ");
delay(keypad_delay);
}
lcd.print(date);
delay(keypad_delay);
//**************Set Year*********************************************************************************************
lcd.setCursor(1,8);
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 9){tens = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.print(tens);
delay(keypad_delay);
for (;;){
key = lcd.keypad();
if(key >= 0 && key <= 9){ones = key; break;}
}
for (;;){
key = lcd.keypad();
if(key == -1){break;}
}
lcd.right();
RTC.stop();
RTC.set(DS1307_YR,tens * 10 + ones);
RTC.start();
lcd.setCursor(1,6);
year = RTC.get(DS1307_YR,true);
if(year < 10){
lcd.print(" ");
delay(keypad_delay);
}
lcd.print(year);
delay(keypad_delay);
//**************Finish Up*********************************************************************************************
for (;;){
lcd.cursor_off();
lcd.setCursor(2,0);
lcd.print("Time & Date Set");
delay(keypad_delay);
lcd.setCursor(3,0);
lcd.print("Choose Mode A or B");
delay(keypad_delay);
if(lcd.keypad() == 100){set_time = 1; break;}
if(lcd.keypad() == 101){break;}
}
lcd.clear();
} //end while
} //end mode 101
//*************Normal Mode 100 and Feed Mode 102*************************************************************************************************
if(mode == 100 || mode == 102 || mode == 103){
byte i;
byte present = 0;
byte data[12];
byte addr[8];
long ph_val;
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract, minute, hour, second, date, month, year, mil_time;
//int ph_read;
//Get time from DS1307**********************************************************************************************
hour = RTC.get(DS1307_HR,true); //This is in military time [0,23]
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 [0000,2400)
// 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
delay(750); // !!! keep this line for parasite power mode of DS18B20
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 = (Tc_100 * 9/5) + 3200; // Convert to fahrenheit, comment this out to display in celcius added 100 for temp correction
temp_Low = min(temp_Low, Tc_100);
temp_High = max(temp_High, Tc_100);
//Display current temperature*****************************************************************************
lcd.setCursor(0,0);
Whole = (Tc_100 / 100); // separate off the whole and fractional portions
Fract = (Tc_100 % 100);
lcd.print(Whole, DEC);
delay(keypad_delay);
lcd.print(".");
delay(keypad_delay);
if (Fract < 10)
{
lcd.print("0");
delay(keypad_delay);
}
lcd.print(Fract, DEC);
delay(keypad_delay);
lcd.write(0xDF);
delay(keypad_delay);
lcd.print("C ");
delay(keypad_delay);
//Display Time******************************************************************************************
lcd.setCursor(0,10);
if((hour < 10 && hour > 0) || (hour > 12 && hour - 12 < 10)){
lcd.print(" ");
delay(keypad_delay);
}
if(hour > 12){
lcd.print(hour - 12, DEC);
delay(keypad_delay);
}
if(hour == 0){
lcd.print(12, DEC);
delay(keypad_delay);
}
if(hour > 0 && hour < 13){
lcd.print(hour, DEC);
delay(keypad_delay);
}
lcd.print(":");
delay(keypad_delay);
if(minute < 10){
lcd.print("0");
delay(keypad_delay);
}
lcd.print(minute, DEC);
delay(keypad_delay);
lcd.print(":");
delay(keypad_delay);
if(second < 10){
//lcd.print("0");
delay(keypad_delay);
}
//lcd.print(second, DEC);
delay(keypad_delay);
if(hour < 12 || hour == 0){
lcd.print("AM");
delay(keypad_delay);
}
else{
lcd.print("PM");
delay(keypad_delay);
}
// pH on line 2 *****************************************************************************************
total_ph -= readings_ph[index_ph]; // subtract the last reading
readings_ph[index_ph] = analogRead(ph_probe); // read from the sensor
total_ph += readings_ph[index_ph]; // add the reading to the total
index_ph = (index_ph + 1); // advance to the next index
if (index_ph >= NUMREADINGS_ph) { // if we're at the end of the array...
index_ph = 0;
} // ...wrap around to the beginning
average_ph = total_ph / NUMREADINGS_ph; // calculate the average
ph_val = (-1.47 * average_ph + 1300); // ph is stored 100 times value
Whole = (ph_val / 100); // separate off the whole and fractional portions
Fract = (ph_val % 100);
lcd.setCursor(2,0);
lcd.print("pH:");
delay(keypad_delay);
if (Whole >= 10) {
Whole = 9;
}
lcd.print(Whole, DEC);
delay(keypad_delay);
lcd.print(".");
delay(keypad_delay);
if (Fract < 10){
lcd.print("0");
delay(keypad_delay);
}
lcd.print(Fract, DEC);
delay(keypad_delay);
// Day Lights
if(mil_time >= lights_on_time && mil_time < lights_off_time) {
digitalWrite(day_light, HIGH);
lcd.setCursor(1,0);
lcd.print("Mh");
delay(keypad_delay);
}
else {
digitalWrite(day_light, LOW);
lcd.setCursor(1,0);
lcd.print(" ");
}
//****************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);
}
//****************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);
}
//Display what relays are on******************************************************************************************
lcd.setCursor(1,9);
if(digitalRead(fan) == HIGH){lcd.print("Ch");delay(keypad_delay);}
else{lcd.print(" ");delay(keypad_delay);}
lcd.setCursor(1,6);
if(digitalRead(heater) == HIGH){lcd.print("Ht");delay(keypad_delay);}
else{lcd.print(" ");delay(keypad_delay);}
// Actinic lights
if(mil_time >= actinic_on_time && mil_time < actinic_off_time) {
digitalWrite(actinic, HIGH);
lcd.setCursor(1,3);
lcd.print("Ac");
delay(keypad_delay);
}
else {
digitalWrite(actinic, LOW);
lcd.setCursor(1,3);
lcd.print(" ");
}
// Sump (Upper pump, Lower pump, Skimmer, UV sterilizer, Reactor pump
digitalWrite(sump, HIGH);
lcd.setCursor(1,16);
if(digitalRead(sump) == HIGH) {lcd.print("Sump"); delay(keypad_delay);}
else {lcd.print(" ");}
// Moon light ************************************************************
if(mil_time >= moonl_on_time && mil_time < moonl_off_time){
digitalWrite(moon_light, HIGH);
lcd.setCursor(1,12);
lcd.print("Mo");
delay(keypad_delay);
}
else {
digitalWrite(moon_light, LOW);
lcd.setCursor(1,12);
lcd.print(" ");
}
//Display Version Number******************************************************************************************
lcd.setCursor(3,0);
lcd.print("Reef Controller V2.0");
//****************************************************************************************************************
Client client = server.available();
if (client) {
// an http request ends with a blank line
boolean current_line_is_blank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if we've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so we can send a reply
if (c == '\n' && current_line_is_blank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<META HTTP-EQUIV=REFRESH content=10 url='http://192.168.1.9' >");
client.println("<body style=background-color:yellow>");
client.println("<font color='blue'><h1> ReefController V2.0</h1></font>");
//client.println("<hr/>");
//client.println("<hr/>");
// output the value of each analog & digital pins
client.println("<table border=1 width=400>");
client.println("<tr>");
client.println("<td>"); client.println("Inputs"); client.println("</td>");
client.println("<td>"); client.println("Current value"); client.println("</td>");
client.println("<td>"); client.println("Min. value");client.println("</td>");
client.println("<td>"); client.println("Max. value");client.println("</td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td>"); client.print("Temperature [°C]"); client.println("</td>");
client.println("<td align=center>"); client.print(Tc_100 / 100); client.println("."); client.print(Tc_100 % 100); client.println("</td>");
client.println("<td align=center>"); client.print(temp_Low / 100); client.println("."); client.print(temp_Low % 100); client.println("</td>");
client.println("<td align=center>"); client.print(temp_High / 100); client.println("."); client.print(temp_High % 100); client.println("</td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td>"); client.print("pH value "); client.println("</td>");
client.println("<td align=center>"); client.print(ph_val / 100); client.println("."); client.print(ph_val % 100); client.println("</td>");
client.println("<td align=center>"); client.print(High / 100); client.println("."); client.print(High % 100); client.println("</td>");
client.println("<td align=center>"); client.print(High / 100); client.println("."); client.print(High % 100); client.println("</td>");
client.println("<tr>");
client.println("<td>"); client.print("ORP value "); client.println("</td>");
client.println("<td align=center>"); client.print(High / 100); client.println("."); client.print(High % 100); client.println("</td>");
client.println("<td align=center>"); client.print(High / 100); client.println("."); client.print(High % 100); client.println("</td>");
client.println("<td align=center>"); client.print(High / 100); client.println("."); client.print(High % 100); client.println("</td>");
client.println("<tr>");
//client.println("<td>"); client.print("Dosing time [min:sec]"); client.println("</td>");
client.println("</tr>");
client.println("</table>");
//client.println("<hr/>");
client.println("<table border=1 width=400>");
client.println("<tr>");
client.println("<td align=center>"); client.println(" MH Lights "); client.println("</td>");
client.println("<td align=center>"); if (digitalRead (day_light) == HIGH) { client.println("<font color='green'> ON "); } else { client.println("<font color='red'> OFF "); } client.println("</td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td align=center>"); client.println("Chiller"); client.println("</td>");
client.println("<td align=center>"); if (digitalRead(fan) == HIGH) { client.println("<font color='green'> ON "); } else { client.println("<font color='red'> OFF "); } client.println("</td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td align=center>"); client.println(" Actinic light "); client.println("</td>");
client.println("<td align=center>"); if (digitalRead(actinic) == HIGH) { client.println("<font color='green'> ON "); } else { client.println("<font color='red'> OFF "); } client.println("</td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td align=center>"); client.println(" Moon light "); client.println("</td>");
client.println("<td width=40 align=center>"); if (digitalRead(moon_light) == HIGH) { client.println("<font color='green'> ON "); } else { client.println("<font color='red'> OFF "); } client.println("</td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td align=center>"); client.println(" Sump pump "); client.println("</td>");
client.println("<td align=center>"); if (digitalRead(sump) == HIGH) { client.println("<font color='green'> ON "); } else { client.println("<font color='red'> OFF "); } client.println("</td>");
client.println("</tr>");
client.println("<tr>");
client.println("<td align=center>"); client.println(" Heater "); client.println("</td>");
client.println("<td align=center>"); if (digitalRead(heater) == HIGH) { client.println("<font color='green'> ON "); } else { client.println("<font color='red'> OFF "); } client.println("</td>");
client.println("</tr>");
client.println("<tr>");
//client.println("<td>"); client.println(" UV Sterilizer "); client.println("</td>");
client.println("</tr>");
client.println("</table>");
//client.println("<hr/>");
//client.println("<hr/>");
//client.println("<table border=1 width=400>");
//client.println("<img src=http://kiwikidstank.dyndns.info:84/>");
//client.println("</table>");
break;
}
if (c == '\n') {
// we're starting a new line
current_line_is_blank = true;
}
else if (c != '\r') {
// we've gotten a character on the current line
current_line_is_blank = false;
}
}
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
on_minute = 0; // signals that the program has been run once
}
}