My Neptune Apex web interface compatible DIY reef controller

well, I feel dumber than before LOL

what I was seeing on my network with my sons PC was something he was running for some stupid game and not this controller at all LOL

I went back through this thread and figured a bunch more out, it's weird how much you can learn just from reading a little :) I actually read most of this thread before but it wasn't sinking in until a reread...I just needed to take smaller steps instead of one big leap LOL

I can now use the controller via the web but I still don't see it on my network with my PC...that ain't no problem though :)

I still have to wire up all the sensors and power relays and build the case to contain it all...still lots to do, I'm already running the Jarduino so wiring won't be too big of a challenge :)

thanks again for all the help guys and thank you big time for putting this all together doughboy, you're a genius man, you guys are awesome

what are the chances of getting the Apex dashboard and using it for the PC to control everything with ?

the mobile app actually looks nice on the PC screen too and seems plenty easy enough to configure
 
Hello d0ughb0y, I added Orp to the controller, the only problem I'm having is that I lost the graph. The readings are fine.
 
wgraham, not meaning to throw you question off topic but I have another question or 3 for ya :) a few posts back, I read that you are using 2 Arduinos together, how did you get them to communicate with each other and how do you have them wired up ?

is there a build link for this somewhere that I can follow your progress on ?

I'm using the Jarduino and like the LED color mixer within it and would really like to use both controllers together, let the Jarduino take care of light color mixing and it's true moon cycle and use this controller to ramp the daytime LEDs up and down for sunrise/sunset, do you think that would be possible ?
 
vymuregy.jpg


Pic of a board I made. This is my first attempt so immediately I notice multiple things that could have been done better/correctly. I'll still try to put it together and see what happens.

Where are you with this shield? If already ready to go, how much to buy a shield from you (just the blank board, not the pieces to it)?
 
redtop03, I'm using a modify Jarduino, the rtc library for the Jarduino does not work well with I2C so you cannot hook them together with out modifying the rtc circuit of the Jarduino. I'm just sharing the clock circuit with this controller nothing else.
 
redtop03, I'm using a modify Jarduino, the rtc library for the Jarduino does not work well with I2C so you cannot hook them together with out modifying the rtc circuit of the Jarduino. I'm just sharing the clock circuit with this controller nothing else.

Oh, OK thanks, that's interesting too, I assume you're sharing the web based clock with the Jarduino....

soooo, how do you share the clock circuit, do you just connect the SDA and SCL from each board to the RTC ?

I'm sorry for all the questions and some of 'em may be really dumb, but with all this stuff, I'm like a 2 year old kid, I have millions of questions about how and why and I really don't mean to be a pest, it just comes natural for me...

I do really appreciate you all for this stuff....

doughboy, I'm sorry for cluttering this thread, the last 2 or 3 pages are mostly of my babbling and I haven't contributed to the thread in any way, I hope to start assembly of my controller soon, then maybe I can contribute something here :)
 
Last edited:
ok, I am having problems with the LCD. Running the scanner I come up with address of 0x27. SO I changed that, my LCD goes black, no backlight. So I changed all the other values to represent:
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
I left out the POSITIVE since I do not see it defined in your sketch, however my LCD still stay black (no backlight). Decided to define the POSITIVE, finally my backlight is on, but it is still the same blocks. I adjusted the contrast still no go, it is either blank or its blocks.

The LCD define is for 2 rows 16 columns

Please let me know if I defined it right:
#define LCD_blpol POSITIVE
 
I got the LCD working using this test sketch:
http://arduino-info.wikispaces.com/LCD-Blue-I2C#v1

But cant seem to get it to work with your sketch. I am dumbfounded today.

odd I went back to define everything from my last post, and I am getting no backlight again, even unplugged it, and plugged back in, still no backlight.

#define LCD_ADDR 0x27
#define LCD_ROWS 2
#define LCD_COLS 16
#define LCD_NUM_MSGS 4+MAXPWMPUMPS/2
#define LCD_MSG_CYCLE_SECS 2
#define LCD_EN 2
#define LCD_RW 1
#define LCD_RS 0
#define LCD_D4 4
#define LCD_D5 5
#define LCD_D6 6
#define LCD_D7 7
#define LCD_BACKLIGHT 3
#define LCD_blpol POSITIVE

ok, got it, I went to Chauvet16 and changed this value:
LiquidCrystal_I2C lcd(LCD_ADDR,LCD_EN,LCD_RW,LCD_RS,LCD_D4,LCD_D5,LCD_D6,LCD_D7,LCD_BACKLIGHT,NEGATIVE);
to
LiquidCrystal_I2C lcd(LCD_ADDR,LCD_EN,LCD_RW,LCD_RS,LCD_D4,LCD_D5,LCD_D6,LCD_D7,LCD_BACKLIGHT,POSITIVE);
and in the config.h I have it:
#define LCD_ADDR 0x27
#define LCD_ROWS 2
#define LCD_COLS 16
#define LCD_NUM_MSGS 4+MAXPWMPUMPS/2
#define LCD_MSG_CYCLE_SECS 2
#define LCD_EN 2
#define LCD_RW 1
#define LCD_RS 0
#define LCD_D4 4
#define LCD_D5 5
#define LCD_D6 6
#define LCD_D7 7
#define LCD_BACKLIGHT 3
 
Last edited:
Yes you connect the SDA and SCL of all the arduinos to the RTC. But like I said the Jarduino will not work with another arduino because of the library it uses for the time, you have to rewrite the rtc code and use a different library
 
Hello d0ughb0y, I added Orp to the controller, the only problem I'm having is that I lost the graph. The readings are fine.

did you modify the htm file and the corresponding code in apex.ino? It is not quite plug and play to add a new sensor, but more like copy paste edit. copy the code for ph and paste and edit it to work with the new orp sensor. All the code is there, you just need to duplicate it in the right place.

you will also need to do the copy paste edit to the logging so the values read are logged. That is where the graph data comes from. work it one step at a time. You are done with the first step, which is to get the correct reading.
 
Yes you connect the SDA and SCL of all the arduinos to the RTC. But like I said the Jarduino will not work with another arduino because of the library it uses for the time, you have to rewrite the rtc code and use a different library

all I using the Jarduino is for controlling the lights

AH, more than I wanna try to change LOL thanks for the info :)

I connected a DS18B20 to mine today so I could see something happening on my web browser, the temp. displays nicely....once this is running, I'll use my temp probe from the Jarduino for the water temp. this was just a temporary fix for me :)

once I have the pH circuit connected and my Neptune AC Jr. robbed of it's pH probe, I'll get to see that function working too :)

I'm debating on whether to gut my DC8 and use it for my outlets or do a complete DIY with something else, the DC8 has 2 relays that are bad, 1 is stuck on, the other is stuck off....

the AC Jr itself is still functioning perfectly but it's LCD backlight is out and it's difficult to see the display, it's past time for something new :)

I have the Jarduino set up so that I could control the temp and whatnot with it but I'm still using the AC Jr. for that and it's pH monitoring

I also ran an Ethernet cable and an outlet behind my tank today and have that ready too.....I'm still waiting on a proto shield so I can start soldering in some wiring and make things happen via the web :)

this thing is gonna be so cool once I have it assembled and running my tank
 
D0ughb0y would I lose the ph and temp graph just by adding the orp. I will go and add the logging to see if the ph and temp graph come back. Thanks
 
since I mentioned this to jross, I'd like to post the info here as well.

I used two power supplies, one 12v 1amp and one 5v 1amp. The 5v is used to power the relay board only. The 12v powers the arduino and the rest of the circuit. The 5v pin on the arduino is used to power the rest of the circuit that requires 5v.

If your circuit is suffering from relay switching transient noise (you know you have this if the arduino reboots when the relay switches), you just need to add a noise filter to the 12v line. If you bought a good quality 12v power supply, it will come with the noise filter like that shown in this picture
QuncNPQ.jpg


you can cut and splice it into your 12v line so it is filtered.
I used a simple toroid core (its just a plain iron ring) and wound the 12v and gnd line about 8x in the ring to filter the noise. You can buy the toroid core on ebay, or if you have a broken pc power supply, you will find a lot of those in the power supply. Even if you don't get the noise problem, its probably a good idea to filter the +12v line.
 
Last edited:
My Neptune Apex web interface compatible DIY reef controller

D0ughb0y would I lose the ph and temp graph just by adding the orp. I will go and add the logging to see if the ph and temp graph come back. Thanks


Actually, come to think of it, no change is needed on the htm file. I just remembered I use essentially this same htm file for Neptune apex and that works regardless of how many probes the apex has and will know to display the correct units etc. so all you need to modify is the logging to the reading to file and in apex.ino where the probes data is returned.

So to answer your question, the web page will display all your sensors, temp, ph and ORP, graph and all.
 
The screen (this is connected to Neptune Apex) should look something like this

93R8815.jpg


There was no graph in this screenshot for salinity because there was no data yet. The htm script will know if it is salinity and display values in both PPM and SG.

see line 1216 of index.htm file
https://github.com/d0ughb0y/Chauvet16/blob/master/index.htm

Let me know if you are unable to get it to work.
 
Last edited:
I'm debating on whether to gut my DC8 and use it for my outlets or do a complete DIY with something else, the DC8 has 2 relays that are bad, 1 is stuck on, the other is stuck off....

I originally have X10 code in the arduino program with the intent of controlling a DC8 (I also used an AC jr, and I web enabled it, see this thread http://reefcentral.com/forums/showthread.php?t=1614847). I later abandoned that idea and removed the X10 code. I'm not sure if the relay board will fit in it, I did not open mine (already sold my DC8). It is a nice size though if the relay board will fit in it.
 
D0ughb0y this what I did in the apex.ino

FLASH_STRING(apex_temp1,"<probes>\n\t\t<probe><name>Temp</name><value>");
FLASH_STRING(apex_temp2,"</value><type>Temp</type></probe>\n\t\t");
FLASH_STRING(apex_ph1,"<probes>\n\t\t<probe><namepH</name><value>");
FLASH_STRING(apex_ph2,"</value><type>pH</type></probe>\n\t\t");
FLASH_STRING(apex_orp1,"<probe><name>Orp</name><value>");
FLASH_STRING(apex_orp2,"</value><type>Orp</type></probe>\n\t</probes>\n\t<outlets>\n");


FLASH_STRING(apex_json4,"\"probes\":[{\"did\":\"base_Temp\",\"t\":\"Temp\",\"n\":\"Temp\",\"v\":");
FLASH_STRING(apex_json5,"},{\"did\":\"base_pH\",\"t\":\"pH\",\"n\":\"pH\",\"v\":");
FLASH_STRING(apex_json5a,"},{\"did\":\"base_Orp\",\"t\":\"Orp\",\"n\":\"Orp\",\"v\":");
FLASH_STRING(apex_json6,"}],\"outlets\":[");


client << dtostrf(getTemp(), 4, 1, (char*)tmp);
client << apex_temp2;
client << apex_ph1;
client << dtostrf(getph(), 5, 2, (char*)tmp);
client << apex_ph2;
client << apex_orp1;
client << dtostrf(getorp(), 4, 0, (char*)tmp);
client << apex_orp2;

myconf.alertphlow=atof(strtok(NULL,delims));
strtok(NULL,delims);
myconf.alertphhigh=atof(strtok(NULL,delims));
strtok(NULL,delims);
myconf.alertorplow=atof(strtok(NULL,delims));
strtok(NULL,delims);
myconf.alertorphigh=atof(strtok(NULL,delims));
strtok(NULL,delims);client << F("\",\n\"aphl\":\"") << conf.alertphlow;
client << F("\",\n\"aphh\":\"") << conf.alertphhigh;
client << F("\",\n\"aorpl\":\"") << conf.alertorplow;
client << F("\",\n\"aorph\":\"") << conf.alertorphigh;

boolean apex_orpval_handler(TinyWebServer& webserver) {
if (!check_auth(webserver)) return true;
Client& client = webserver.get_client();
const char* hdrlen = webserver.get_header_value("Content-Length");
if (hdrlen!=NULL) {
int len = atol(hdrlen)+1;
char json[len];
char calval[2];
int i=0;
while (client.available() && i<len) {
json[i++]=(char)client.read();
}


beepOK();
}
webserver.send_error_code(200);
webserver.send_content_type("application/json");
webserver.end_headers();
client << F("{\"orpval\":\"") << getorp();
client << F("\"}");
return true;

In Network

{"/phval.json", TinyWebServer::ANY, &apex_phval_handler},
{"/orpval.json", TinyWebServer::ANY, &apex_orpval_handler},

client << F("pH:") <<getph() << F("\r\n");
client << F("Orp:") <<getorp() << F("\r\n");

if (strcmp_P(path,PSTR("/pwmpumpdata.json"))==0 ||
strcmp_P(path,PSTR("/phval.json"))==0 ||
strcmp_P(path,PSTR("/orpval.json"))==0) return;

In Utility


fileout_ << F("<record><date>") << buffer << F("</date><probe><name>Temp</name><value>");
fileout_ << setprecision(1);
fileout_ << getTemp()<< F("</value></probe><probe><name>pH</name><value>");
fileout_ << setprecision(2);
fileout_ << (getph()<10.0?" ":"") << getph() << F("</value></probe>");
fileout_ << setprecision(1);
fileout_ << (getorp()<500.0?" ":"") << getorp() << F("<probe><name>pH</name><value></value></probe></record>");
fileout_ << F("\n");
fileout_.close();
if (logSetup(now2(), buffer, "LOG", "log")) {
fileout_ << buffer << F(" Alarm Event : Temp=") << getTemp();
fileout_ << F(" ph=") << getph();
fileout_ << F(" Orp[=") << getorp();
fileout_ << F(" Top Off water level: ") << (uint8_t)getSonarPct() << F("%\n");
fileout_.close();
 
I copy everything that I seen with the ph code in it.

This is what I did in Sensors

#ifdef _ORP
if (initORP()) {
p(F("ORP OK. "));
logMessage(F("ORP sensor initialized."));
} else {
beepFail();
p(F("ORP Init failed "));
logMessage(F("ORP Init failed"));
}
#endif///////////////////////////////////////////////////////
// ORP section
///////////////////////////////////////////////////////
static float orpreading=0;
static boolean orpready = false;

boolean initORP() {
#ifdef _ORP
char orpchars[15];
orpchars[0]=0;
Serial2.begin(38400);
for (int i=0;i<255,strlen(orpchars)==0;i++) {
Serial2.print("e\rr\r");
delay(384);
getresponse1(orpchars);
}
if (strlen(orpchars)==0) {
orpinit=false;
return false;
}
orpreading=atof(orpchars);
if (orpreading>0) {
orpready=true;
orpinit=true;
updateORP();
orpready=false;
return true;
} else
#endif
return false;
}

void updateORP() {
if (!orpinit) return;
static float sum=0;
static float orpa = 0;
if (orpready) {
orpready=false;
if (orpreading>0) {
if (orpa) {
sum = (sum-orpa)+orpreading;
orpa = sum / numReadings;
cli();
orpavg=orpa;
sei();
} else {
sum = orpreading*numReadings;
orpa=orpreading;
orpavg=orpreading;
}
}
Serial2.print("r\r");
}
}

float getorp() {
if (!orpinit) return 0.0;
uint8_t saveSREG=SREG;
cli();
float op = orpavg;
SREG=saveSREG;
return op;
}



void getresponse1(char* orpchars) {
int i = 0;
while (Serial2.available()) {
char c = (char)Serial2.read();
if (c=='\r') {
orpchars=0;
i=0;
return;
} else {
orpchars[i++]=c;
if (i==14) {
i=0;
orpchars[0]=0;
return;
}
}
}
}

void serialEvent2() {
static char orpchars[15];
static int i = 0;
char c = (char)Serial2.read();
if (c=='\r') {
orpchars=0;
i=0;
orpreading=atof(orpchars);
orpready=true;
return;
} else {
orpchars[i++]=c;
if (i==14) {
i=0;
orpchars[0]=0;
orpreading=0;
orpready=true;
}
}
}
 
I originally have X10 code in the arduino program with the intent of controlling a DC8 (I also used an AC jr, and I web enabled it, see this thread http://reefcentral.com/forums/showthread.php?t=1614847). I later abandoned that idea and removed the X10 code. I'm not sure if the relay board will fit in it, I did not open mine (already sold my DC8). It is a nice size though if the relay board will fit in it.

yep, I downloaded all the stuff for the AC Jr back when you started that project, just never did implement it, I had never really needed a web based controller, and really, I still don't, I don't even have a smart phone, just a cheap Tracphone LOL

but I've always like the concept and since you've done it with an Arduino, I find it a lot more interesting :) and I do really like the idea of sitting on my couch and using my laptop to mess with my fish LOL

I've had my DC8 opened up and I think there's enough room for the relay board but probable not enough to make it all self contained, I think it would need to be wired remotely to the controller, but if I do decide to sacrifice it, I'll see :)

your idea of using the Chauvet was genius, yours looks as professional as any controller on the market and from what I've messed with it on mine, it works as good or better....

the only issue I see is that our web service is not 100% reliable and if/when it goes down, there's no way to operate the controller manually if a problem happens, at least not with mine, if I could get it to show up and be controllable over just my network, I'd be thrilled....

I know that is most likely possible to do and it may already be set up that way and I don't have mine configured correctly :)
 
Back
Top