DIY Reef Controller

I'm the same way as far as learning. I'm no expert by any means. I'll post it later today. I'd love to figure out how to use this code I made as an override. So I don't mess with any relay functions overall.
 
The screenshot (couldn't fit entire layout):
0A193F6B-602A-4D71-85D9-96B30D5E90F8-6541-0000054ECE592D0B_zps0d6b902b.jpg


This is derived and modified from an instructible how to. So props to original creator of the layout.
 
could you leave that turn the toilet off button i am a master plumber and that would come in handy when someone forgets to pay me
 
Jodah,

Those menu screens are for the 3.2" screen. I made the home screen for the 5" screen and realized I hated the 3.2" ones and remade them. The 5" screens will be even better!
 
hahaha! I can't wait for my 5" screen. Think it's gonna be another few weeks before I can even order it. Hows the refresh rate on it? I've seen some examples using the 5" and the Mega and it's crazy slow. Almost tempted to start messing around with the Due. But, I'm just starting to dabble with arduino, and I'm sure the Due would kick my butt all over the place.
 
The refresh rate is pretty slow. I have a due lying around that I want to mess with but don't have the time.
 
I have not tinkered with aurduino at all yet but from I read the due should be backwards compatible with all arduino projects. I have not bought my mega because I think the due is going to be needed to run all of this smoothly. This is an awesome project thanks for all of the the you have invested!
 
Even with the due I don't think the 5" screen can have a refresh rate high enough to please everyone with the utft library. I have read though that the utft library is pretty slow and saw at least one person who claimed to have created a much faster library. I can't remember how much faster he claimed it to be but I think it was at least 3 times as fast but don't quote me on that.

The end goal for this project is to eliminate the arduino platform and use a single motherboard. The savings for putting an atmega2560 on the motherboard would be around $40 compared to buying an arduino mega board. Who knows I may decide to try and put the AT91SAM3X8E chip from the due on the motherboard instead.

The plus side about using the due is that since it runs at 3.3v we wouldn't need to use the shield for the lcd screen anymore which would save tons of space and another $10. Now that i'm thinking about it, it would make more sense then an onboard atmega2560 since its $4 more expensive than the AT91SAM3X8E.

This might take a while though, haha.
 
Hi Nic,

I'm very interested in your work and I'm going to buy an atmega2560 just for it. For starters if I buy the following would it be enough (just to test for now)

1 x atmega3560
1 x 3.2 LCD Touch Screen
1 x TFT Sheild with SD Card
1 x 5V Eight 8 Channel Relay Module With optocoupler For Arduino

or do you suggest anything else?

Thanks For you Help Kindest Regards,
Etienne
 
Here you guys go...
Considering this is Arduino based I figured I'd throw it up here.
Just add an ethernet module with SPI and you can have control of 16 relays

NOTE!!!
My relay board is active LOW position...but all you have to do is boolean outputInverted = false;
IF your relay board is active HIGH position :)


Code:
#include SPI.h
#include Ethernet.h
#include EEPROM.h
//THESE MUST HAVE < 
//AND > for the .h
//------wasn't displaying before

//////////////////////////////////////////////////////////////////////// 
//CONFIGURATION 
//////////////////////////////////////////////////////////////////////// 

//IP manual settings 
byte ip[] = { 
192, 168, 1, 150 }; //Manual setup only 
byte gateway[] = { 
192, 168, 1, 1 }; //Manual setup only 
byte subnet[] = { 
255, 255, 255, 0 }; //Manual setup only 

// if need to change the MAC address (Very Rare) 
byte mac[] = { 
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 

//Ethernet Port 
EthernetServer server = EthernetServer(84); //default html port 80 

//The number of outputs going to be switched. 
int outputQuantity = 16; //should not exceed 10 

//Invert the output of the leds 
boolean outputInverted = true; //true or false 
// This is done in case the relay board triggers the relay on negative, rather then on positive supply 

//Html page refresh 
int refreshPage = 30; //default is 10sec. 
//Beware that if you make it refresh too fast, the page could become inacessable. 

//Display or hide the "Switch on all Pins" buttons at the bottom of page 
int switchOnAllPinsButton = true; //true or false 
 

// Select the pinout address 

byte outputAddress[8] = {22,23,24,25,26,27,28,29}; //Allocate 10 spaces and name the output pin address. 
byte outputAddress2[8]= {30,31,32,33,34,35,36,37}; 
//PS pin addresses 10, 11, 12 and 13 on the Duemilanove are used for the ethernet shield, therefore cannot be used. 
//PS pin addresses 10, 50, 51 and 52 and 53 on the Mega are used for the ethernet shield, therefore cannot be used. 
//PS pin addresses 4, are used for the SD card, therefore cannot be used. 
//PS. pin address 2 is used for interrupt-driven notification, therefore could not be used. 

// Write the text description of the output channel 
String buttonText[16] = { 
"01. Right Lamp","02. Left Lamp","03. Bedroom","04. Kitchen","05. Water Heater","06. Gate","07. Toilet","08. Main Heater","09. Roof Light","10. Basement","11. Test","12. TEST2","13. TEST3","14. TEST4","15. TEST5","16. TEST6"}; 

// Set the output to retain the last status after power recycle. 
int retainOutputStatus[16] = { 
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//1-retain the last status. 0-will be off after power cut. 

//////////////////////////////////////////////////////////////////////// 

//////////////////////////////////////////////////////////////////////// 
//VARIABLES DECLARATION 
//////////////////////////////////////////////////////////////////////// 
int outp = 0; 
boolean printLastCommandOnce = false; 
boolean printButtonMenuOnce = false; 
boolean initialPrint = true; 
String allOn = ""; 
String allOff = ""; 
boolean reading = false; 
boolean outputStatus[16]; //Create a boolean array for the maximum ammount. 
 
unsigned long timeConnectedAt; 
boolean writeToEeprom = false; 





///////////////////////////////////////////////// 

// Temperature Related Reading 
const int tempInPin = A1; 
int tempInValue = 0; //temperature read 
int tempScaleOutValue = 0; //temperature formatted 
int tempOutValue = 0; //temperature formatted 
float tempOutDeg = 0.0; 



//////////////////////////////////////////////////////////////////////// 
//RUN ONCE 
//////////////////////////////////////////////////////////////////////// 
//Beginning of Program 
void setup(){ 
Serial.begin(57600); 

initEepromValues(); 
readEepromValues(); 

//Set pins as Outputs 
boolean currentState = false; 
for (int var = 0; var < 9; var++){ 
digitalWrite(outputAddress[var], HIGH); 
pinMode(outputAddress[var], OUTPUT); 

} 

for (int var2 = 0; var2 < 9; var2++){

    pinMode(outputAddress2[var2], OUTPUT); 
    digitalWrite(outputAddress2[var2], HIGH);
  }




//Setting up the IP address. Comment out the one you dont need. 
//Ethernet.begin(mac); //for DHCP address. (Address will be printed to serial.) 
Ethernet.begin(mac, ip, gateway, subnet); //for manual setup. (Address is the one configured above.)


server.begin(); 
//Serial.print("Server started at "); 
//Serial.println(Ethernet.localIP()); 

} 


//////////////////////////////////////////////////////////////////////// 
//LOOP 
//////////////////////////////////////////////////////////////////////// 
//Run once 
void loop(){ 


//Read Temperature Sensor 
tempInValue = analogRead(tempInPin); 

// Connecting a 10K3 Thermistor to the Arduino Input 
// +5V �—————————[10Kohms]—————————[Thermistor]——� 0V 
// To Arduino IP �———————————| 
tempScaleOutValue = map(tempInValue, 0, 1023, 1023, 0); //Arduino value and NTC of the 10K3 Thermistor 
tempOutValue = map(tempScaleOutValue, 130, 870, -170, 730); //range of Arduino Value compared with Temperature 
tempOutValue = tempOutValue -45; //Adjustments 
tempOutDeg = tempOutValue /10; 



// listen for incoming clients, and process requests. 
checkForClient(); 
} 
void process_data (char * data) 
{ 
// for now just display it 
Serial.println (data); 
} // end of process_data 
//////////////////////////////////////////////////////////////////////// 
//checkForClient Function 
//////////////////////////////////////////////////////////////////////// 
// 
void checkForClient(){ 

EthernetClient client = server.available(); 

if (client) { 

// an http request ends with a blank line 
boolean currentLineIsBlank = true; 
boolean sentHeader = false; 

while (client.connected()) { 
if (client.available()) { 
//if header was not set send it 

//read user input 
char c = client.read(); 
Serial.println(c); 
if(c == '*'){ 

printHtmlHeader(client); //call for html header and css 
printLoginTitle(client); 
printHtmlFooter(client); 
//sentHeader = true; 
break; 
} 

if(!sentHeader){ 

printHtmlHeader(client); //call for html header and css 
printHtmlButtonTitle(client); //print the button title 

//This is for the arduino to construct the page on the fly. 
sentHeader = true; 
} 

//read user input 
// char c = client.read(); 

//if there was reading but is blank there was no reading 
if(reading && c == ' '){ 
reading = false; 
} 

//if there is a ? there was user input 
if(c == '?') { 
reading = true; //found the ?, begin reading the info 


} 

// if there was user input switch the relevant output 
if(reading){ 

//if user input is H set output to 1 
if(c == 'H') { 
outp = 1; 
} 

//if user input is L set output to 0 
if(c == 'L') { 
outp = 0; 
} 

//Serial.print(c); //print the value of c to serial communication 
//Serial.print(outp); 
//Serial.print('\n'); 

switch (c) { 

case '0': 
//add code here to trigger on 0 
triggerPin(outputAddress[0], client, outp); 
break; 
case '1': 
//add code here to trigger on 1 
triggerPin(outputAddress[1], client, outp); 
break; 
case '2': 
//add code here to trigger on 2 
triggerPin(outputAddress[2], client, outp); 
break; 
case '3': 
//add code here to trigger on 3 
triggerPin(outputAddress[3], client, outp); 
break; 
case '4': 
//add code here to trigger on 4 
triggerPin(outputAddress[4], client, outp); 
break; 
case '5': 
//add code here to trigger on 5 
triggerPin(outputAddress[5], client, outp); 
// printHtml(client); 
break; 
case '6': 
//add code here to trigger on 6 
triggerPin(outputAddress[6], client, outp); 
break; 
case '7': 
//add code here to trigger on 7 
triggerPin(outputAddress[7], client, outp); 
break; 
case '8': 
//add code here to trigger on 8 
triggerPin(outputAddress[8], client, outp); 
break; 
case '9': 
// add code here to trigger on 9 
triggerPin(outputAddress[9], client, outp); 
break; 
case 'A': 
triggerPin(outputAddress[10], client, outp); 
break; 
case 'B': 
triggerPin(outputAddress[11], client, outp); 
break; 
case 'C': 
triggerPin(outputAddress[12], client, outp); 
break; 
case 'D': 
triggerPin(outputAddress[13], client, outp); 
break; 
case 'E': 
triggerPin(outputAddress[14], client, outp); 
break; 
case 'F': 
triggerPin(outputAddress[15], client, outp); 
break; 
} 
} 

//if user input was blank 
if (c == '\n' && currentLineIsBlank){ 
printLastCommandOnce = true; 
printButtonMenuOnce = true; 
triggerPin(777, client, outp); //Call to read input and print menu. 777 is used not to update any outputs 
break; 
} 




} 
} 

printHtmlFooter(client); //Prints the html footer 

} 
else 
{ //if there is no client 

//And time of last page was served is more then a minute. 
if (millis() > (timeConnectedAt + 60000)){ 

if (writeToEeprom == true){ 
writeEepromValues(); //write to EEprom the current output statuses 
Serial.println("No Clients for more then a minute - Writing statuses to Eeprom."); 
writeToEeprom = false; 
} 

} 
} 


} 


//////////////////////////////////////////////////////////////////////// 
//triggerPin Function 
//////////////////////////////////////////////////////////////////////// 
// 
void triggerPin(int pin, EthernetClient client, int outp){ 
//Switching on or off outputs, reads the outputs and prints the buttons 

//Setting Outputs 
if (pin != 777){ 

if(outp == 1) { 
if (outputInverted ==false){ 
digitalWrite(pin, HIGH); 
} 
else{ 
digitalWrite(pin, LOW); 
} 
} 
if(outp == 0){ 
if (outputInverted ==false){ 
digitalWrite(pin, LOW); 
} 
else{ 
digitalWrite(pin, HIGH); 
} 
} 


} 
//Refresh the reading of outputs 
readOutputStatuses(); 


//Prints the buttons 
if (printButtonMenuOnce == true){ 
printHtmlButtons(client); 
printButtonMenuOnce = false; 
} 

} 

//////////////////////////////////////////////////////////////////////// 
//printHtmlButtons Function 
//////////////////////////////////////////////////////////////////////// 
//print the html buttons to switch on/off channels 
void printHtmlButtons(EthernetClient client){ 

//Start to create the html table 
client.println(""); 
//client.println("
"); 
client.println(""); 
client.println(""); 


//Printing the Temperature 
client.print("\n"); 

client.print(""); 
client.print("Temperature"); 
client.print("\n"); 
client.print(""); 
client.print(""); 
client.print(""); 
client.print(tempOutDeg); 
// client.print(tempOutValue); 
client.print(" °C\n"); 


client.print(""); 
client.print(""); 


//Start printing button by button 
for (int var = 0; var < outputQuantity; var++) { 

//set command for all on/off 
allOn += "H"; 
allOn += outputAddress[var]; 
allOff += "L"; 
allOff += outputAddress[var]; 


//Print begining of row 
client.print("\n"); 

//Prints the button Text 
client.print(""); 
client.print(buttonText[var]); 
client.print("\n"); 

//Prints the ON Buttons 
client.print(""); 
//client.print(buttonText[var]); 
client.print(" //client.print(buttonText[var]); 
client.print("\" onClick=\"parent.location='/?H"); 
//Serial.print(var, HEX); 
client.print(var, HEX); 
client.print("'\">\n"); 

//Prints the OFF Buttons 
client.print(" //client.print(var); 
client.print("\" onClick=\"parent.location='/?L"); 
// Serial.print(var, HEX); 
client.print(var, HEX); 
client.print("'\">\n"); 


//Print first part of the Circles or the LEDs 

//Invert the LED display if output is inverted. 

if (outputStatus[var] == true ){ //If Output is ON 
if (outputInverted == false){ //and if output is not inverted 
client.print(" \n"); //Print html for ON LED 
} 
else{ //else output is inverted then 
client.print(" \n"); //Print html for OFF LED 
} 
} 
else //If Output is Off 
{ 
if (outputInverted == false){ //and if output is not inverted 
client.print(" \n"); //Print html for OFF LED 
} 
else{ //else output is inverted then 
client.print(" \n"); //Print html for ON LED 
} 
} 




//Print end of row 
client.print("\n"); 
} 

//Display or hide the Print all on Pins Button 
if (switchOnAllPinsButton == true ){ 

//Prints the ON All Pins Button 
client.print("\n client.print("\" onClick=\"parent.location='/?"); 
client.print(allOn); 
client.print("'\">\n"); 

//Prints the OFF All Pins Button 
client.print(" client.print("\" onClick=\"parent.location='/?"); 
client.print(allOff); 
client.print("'\">\n\n\n\n"); 
} 

//Closing the table and form 
client.println(""); 
client.println(""); 
//client.println("

"); 

} 

//////////////////////////////////////////////////////////////////////// 
//readOutputStatuses Function 
//////////////////////////////////////////////////////////////////////// 
//Reading the Output Statuses 
void readOutputStatuses(){ 
for (int var = 0; var < outputQuantity; var++) { 
outputStatus[var] = digitalRead(outputAddress[var]); 
//Serial.print(outputStatus[var]); 
} 

} 

//////////////////////////////////////////////////////////////////////// 
//readEepromValues Function 
//////////////////////////////////////////////////////////////////////// 
//Read EEprom values and save to outputStatus 
void readEepromValues(){ 
for (int adr = 0; adr < outputQuantity; adr++) { 
outputStatus[adr] = EEPROM.read(adr); 
} 
} 

//////////////////////////////////////////////////////////////////////// 
//writeEepromValues Function 
//////////////////////////////////////////////////////////////////////// 
//Write EEprom values 
void writeEepromValues(){ 
for (int adr = 0; adr < outputQuantity; adr++) { 
EEPROM.write(adr, outputStatus[adr]); 
} 

} 

//////////////////////////////////////////////////////////////////////// 
//initEepromValues Function 
//////////////////////////////////////////////////////////////////////// 
//Initialiaze EEprom values 
//if eeprom values are not the correct format ie not euqual to 0 or 1 (thus greater then 1) initialize by putting 0 
void initEepromValues(){ 
for (int adr = 0; adr < outputQuantity; adr++){ 
if (EEPROM.read(adr) > 1){ 
EEPROM.write(adr, 0); 
} 

} 

} 


//////////////////////////////////////////////////////////////////////// 
//htmlHeader Function 
//////////////////////////////////////////////////////////////////////// 
//Prints html header 
void printHtmlHeader(EthernetClient client){ 
// Serial.print("Serving html Headers at ms -"); 
timeConnectedAt = millis(); //Record the time when last page was served. 
// Serial.print(timeConnectedAt); // Print time for debbugging purposes 
writeToEeprom = true; // page loaded so set to action the write to eeprom 

// send a standard http response header 
client.println("HTTP/1.1 200 OK"); 
client.println("Content-Type: text/html"); 
client.println("Connnection: close"); 
client.println(); 
client.println(""); 
client.println(""); 

// add page title 
client.println("Ethernet Switching"); 
client.println(""); 

// add a meta refresh tag, so the browser pulls again every x seconds: 
client.print(" client.print(refreshPage); 
client.println("; url=/\">"); 

// add other browser configuration 
client.println(""); 
client.println(""); 
client.println(""); 

//inserting the styles data, usually found in CSS files. 
client.println(""); 
client.println(""); 

//now printing the page itself 
client.println(""); 
client.println("
"); 
client.println("
"); 
client.println(" Ethernet Switching"); 
client.println("
"); 

////// 

} //end of htmlHeader 

//////////////////////////////////////////////////////////////////////// 
//htmlFooter Function 
//////////////////////////////////////////////////////////////////////// 
//Prints html footer 
void printHtmlFooter(EthernetClient client){ 
//Set Variables Before Exiting 
printLastCommandOnce = false; 
printButtonMenuOnce = false; 
allOn = ""; 
allOff = ""; 

//printing last part of the html 
client.println("\nAndrew Palmer 
Home Automation 
Version 1.0"); 
//client.println(rev); 
client.println("
\n\n\n"); 

delay(1); // give the web browser time to receive the data 

client.stop(); // close the connection: 

//Serial.println(" - Done, Closing Connection."); 

delay (2); //delay so that it will give time for client buffer to clear and does not repeat multiple pages. 

} //end of htmlFooter 


//////////////////////////////////////////////////////////////////////// 
//printHtmlButtonTitle Function 
//////////////////////////////////////////////////////////////////////// 
//Prints html button title 
void printHtmlButtonTitle(EthernetClient client){ 
client.println("
"); 
client.println("Switch the required output."); 
client.println(); 
} 


//////////////////////////////////////////////////////////////////////// 
//printLoginTitle Function 
//////////////////////////////////////////////////////////////////////// 
//Prints html button title 
void printLoginTitle(EthernetClient client){ 
// client.println("
"); 
client.println(" Please enter the user data to login."); 
client.println(); 
}
 
Last edited:
nkd5024:
If you're interested in ethernet control/display of info...I'm still working on developing this code to include dual temperature readouts on the webpage with the DallasTemperature.h lib

Just seeing your interest or anyone else's interest for that matter. :)

We might need to work together a bit as I'm fearful that what I'm doing with the code would contradict what you're writing...IE: overrides and relay control via the ethernet module...so let me know how you'd like to go about this IF you're interested.

By no means do I want to jack this awesome thread...just trying to add to the awesomeness :)
 
thanks for sharing with us. I been needing to order a 5100 Internet card anyway so to make sure I got a Handel on this I can run this script the way it is just have to change it for my network settings and connect the arduino pins to the 16 relays and it should work right ? don't need any other sketch's to make it work.

sorry for asking such beginner questions but that is where I am at.
 
thanks for sharing with us. I been needing to order a 5100 Internet card anyway so to make sure I got a Handel on this I can run this script the way it is just have to change it for my network settings and connect the arduino pins to the 16 relays and it should work right ? don't need any other sketch's to make it work.

sorry for asking such beginner questions but that is where I am at.

Basically, make sure your MAC address is unique for your network...pick the IP address you want (static), set your pins you want to use for the Arduino to control the relays. Just make sure if you are using a DB serial cable to trace the wires to both ends of the cable...sometimes (depending on the manuf) the wires can cross or change positions on the other end of the cable. IE: (pin 1 on end A can come out at pin9 end B). :thumbsup:
Other than that...make sure you have the libraries at the top in the Arduino libraries folder and you'll be good to go!

Addition: I should mention that you can set up port forwarding through your router...
SO..... EthernetServer server = EthernetServer(84); //default html port 80
This line of code is default port 80...(I have it as 84 because I have multiple things using ports.)
You'll need your WANIP: mywanip in google
So on your router you can: Port forward (80) to your static IP address (192, 168, 1, 150 in the example code).
Then when you're out of your network (on a cell phone or whatever)...you just browse to WANIP:80 <-you need ":" in there to tell your device what port to go to. Then, you can control relays from anywhere in the world (where there is data :) ).
 
Last edited:
very cool I plan on using this to kinda go a different way I want to automate some stuff around my property and this will be a good way to do it I think like turning on and off irrigation lines and under ground storage tanks for fertilizer and water for gardening and pond it wont be long and it will be wireless hopefully :)
 
very cool I plan on using this to kinda go a different way I want to automate some stuff around my property and this will be a good way to do it I think like turning on and off irrigation lines and under ground storage tanks for fertilizer and water for gardening and pond it wont be long and it will be wireless hopefully :)

Cool...I intend to automate my home...but it still applies to aquariums as well (I have one of course) :)

I added more information to the last post...make sure you refresh your page (if you didn't see the part about port forwarding that is....)
 
Back
Top