DIY with Liquid Chlorine, ORP Probe, Arduino

Status
Not open for further replies.
So here is the webserver code. This may or may not compile, I tried to clean it up so you can see just the webserver portions. I cannot stress enough to look at the WebDuino examples and start from there. If you are not familiar with how webservers work and in general how the HTTP protocol works it may be helpful to read up on that as well.

In general, I crafted the HTML page on my PC until the page looked the way I wanted. This included getting it to look right on my iPhone. From there, I transferred it into my sketch and made it "dynamic". This is done by outputting the variables or using case statements to make them into something human readable.

I also take parameters on the URL to change modes and set variables. These are passed with an HTTP GET, and I don't remember if I wrote that part myself or not. The buttons at the end of the code send URL parameters that actually make the changes.

This is generally difficult to maintain. Making updates is difficult, since it requires re-downloading the sketch. In my spare time, I'd make the webserver have an API for reading/writing data. Then the webpages are static, but use AJAX to make them dynamic. Since I think I recall seeing a webserver for Ardunio that can read files off an SD card, that could make updating easier. You could also host the webpages anywhere, and only have the Arduino handle AJAX requests.

Oh, and if anyone wants to tackle updating the Arduino over the network that'd be sweet. It can be done with PXE or tftp, but I haven't found working code. That would eliminate the laptop next to the Arduino for updates.

Code:
// webserver from [url]https://github.com/sirleech/Webduino[/url]
#include "WebServer.h"

// no-cost stream operator as described at 
// [url]http://sundial.org/arduino/?page_id=119[/url]
template<class T>
inline Print &operator <<(Print &obj, T arg)
{ obj.print(arg); return obj; }

//ethernet and webserver setup
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 177);
#define PREFIX ""
WebServer webserver(PREFIX, 80);

//the code that handles the webserver request
void writeCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
    if (type == WebServer::POST)
    {
    bool repeat;
    char name[16], value[16];
    do
    {
      repeat = server.readPOSTparam(name, 16, value, 16);
        if(String(name)==String("value")){
          //I don't think this code is being used - it's left over from an example
          digitalWrite(2,atoi(value));
        }
    } while (repeat);
    
    server.httpSeeOther(PREFIX "/index");
    }
    else
    {
    char name[16], value[16];
    URLPARAM_RESULT rc;
    //handle parameters on the end of the URL
    if (strlen(url_tail))
      {
      while (strlen(url_tail))
        {
        rc = server.nextURLparam(&url_tail, name, 32, value, 32);
        if (rc != URLPARAM_EOS)
          {
            if(String(name)==String("manual")){
              manual=atoi(value);
            }
            if(String(name)==String("manfeed")){
              manfeed=atoi(value);
            }
            if(String(name)==String("heatmode")){
              heatmode=atoi(value);
            }

          }
        }
      }
      
    server.httpSuccess();
    
    //output the HTML of the web page
    server << "<head>";
    server << "<title>Pool Controller</title>";
    server << "<meta id='viewport' name='viewport' content='width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;' />";
    server << "<style type='text/css'>";
    server << "table {font-family: arial; font-size:10pt;}";
    server << "button {font-family: arial; font-size:10pt;}";
    server << "div {text-align:left; font-family: arial; font-size:10pt;}";
    server << "</style>";
    server << "</head><body>";
    //refresh
    server << "<button style=\"width:280;height:30\" onClick='window.location=\"/index\"'>[b]Refresh[/b]</button>";
    server << "<table><tr>";
    server << "<td>Date: " << month() << "/" << day() << "/" << year() << "</td>";
    server << "<td colspan=2>Time: " << hourFormat12() << ":" << minute() << ":" << second() << " ";
      if(isAM()){
        server.print("AM");
          }else{
        server.print("PM");
        }
      server << "</td>";
    server << "</tr><tr>";
    server << "<td>SWT: " << ai_swt << "</td>";
    server << "<td>RWT: " << ai_rwt << "</td>";
    server << "<td>ORP: " << orp << "</td>";
    server << "</tr><tr>";
    server << "<td>Amps: " << ai_amps << "</td>";
    server << "<td>Pressure: " << ai_psi << "</td>";
    server << "</tr><tr>";
    switch (manual){
    case 1:
    server << "<td>Pump:Auto</td>";
      break;
    case 2:
    server << "<td>Pump:Low</td>";
      break;
    case 3:
    server << "<td>Pump:High</td>";
      break;
    case 4:
    server << "<td>Pump:Off</td>";
      break;
    }

    switch (manfeed){
    case 1:
    server << "<td>Feed:Auto</td>";
      break;
    case 2:
    server << "<td>Feed:On</td>";
      break;
    case 3:
    server << "<td>Feed:Semi</td>";
      break;
    case 4:
    server << "<td>Feed:Off</td>";
      break;
    }

    switch (heatmode){
    case 1:
    server << "<td>Heat:Auto</td>";
      break;
    case 2:
    server << "<td>Heat:On</td>";
      break;
    case 3:
    server << "<td>Heat:Semi</td>";
      break;
    case 4:
    server << "<td>Heat:Off</td>";
      break;
    }

    server << "</tr><tr>";
    server << "<td>S/S: " << do_ss << " ";    
    server << "L/H: " << do_hl << "</td>";
    server << "<td>Feed: " << do_feed << "</td>";
    server << "<td>Heat: " << do_heat << "</td>";
    server << "</tr><tr>";
    server << "<td>pH:" << ph << "</td>";
    server << "<td>Feed En:" << orp_enable << "</td>";
    server << "<td>Heat En:" << heat_enable << "</td>";
    server << "</tr></table>";
    //pump mode
    server << "<hr />";
    server << "<div>Pump Control</div>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manual=1\"'>[b]Auto[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manual=2\"'>[b]Low[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manual=3\"'>[b]High[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manual=4\"'>[b]Off[/b]</button>";
    //feed mode
    server << "<div>Feed Control</div>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manfeed=1\"'>[b]Auto[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manfeed=3\"'>[b]Semi[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manfeed=2\"'>[b]On[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?manfeed=4\"'>[b]Off[/b]</button>";
    //heat mode
    server << "<div>Heat Mode</div>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?heatmode=1\"'>[b]Auto[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?heatmode=3\"'>[b]Semi[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?heatmode=2\"'>[b]On[/b]</button>";
    server << "<button style=\"width:70;height:30\" onClick='window.location=\"/index?heatmode=4\"'>[b]Off[/b]</button>
";
    server << "</body>";
    }
}

void setup() {  
  //startup the network card and servers
  Ethernet.begin(mac, ip);
  webserver.begin();

  //setup webserver
  webserver.setDefaultCommand(&writeCmd);
  webserver.addCommand("index", &writeCmd);
  )

void loop() {
  webserver.processConnection();  
}
 
Tom,

$550 won't touch the "power centers" required by most of the pool automation systems, much less the "brains" of the system. Besides, the fact that you can troubleshoot and repair it yourself is worth it's weight in stablizer (the stuff is expensive). The ORP and pH probes will definitely set you back fairly quick...
 
Thanks for posting the code, I'll look through it and study the webduino code and see if I can make sense of it. A web designer I am not. The gauges I posted a link to earlier too me a while to figure out. Wasn't so much getting the gauge to display as that I took directly from another site, it was getting them to display the data I wanted them to display.

Not sure how you'd update the sketch itself over the network. Now the idea of hosting the webpage elsewhere and using that to update the variables could be just the thing. I'm kinda doing that now as I send my readings and status to Xively every 30 seconds and upon power up I read certain values from there.

Haven't played with the SD card option at all yet. My ethernet shield has it but I haven't found a real use for it yet. Took me long enough to figure out the pin 53 trick to get my ethernet shield to work with the MEGA.

Hoping to get the rest of my solar collector array up tomorrow so I can start tweaking it for maximum effectiveness but that's going to depend on the weather. Once that is done, I can get back to finishing up wiring and move on to the pH part monitor. Looking forward to that....
 
Well, too windy today to sweat pipe. Kept blowing the torch out... :-( Have the rest of the array in place, just have to get the pipe work done. Have 30+ degree differential in my one panel today. Equates to about a 1 degree rise in pool temp per hour. Too bad the clouds rolled in as early as they did....

Mike
 
Thanks a lot for posting this info. I just bought a house with a pool and was thinking about doing my own automation system like this. My plans include liquid chlorine and acid injection, solar heater system and variable speed pump control.

When I build mine, I'm going to use a Synapse wireless module instead of an arduino. You can code simple python scripts and remote flash the modules via their free tool. I have several now forming a mesh network in my house that allow me to control my garage doors, monitor temps (including pool temp). Hmmm - just realized this will mean 3 rs232 interfaces 1 orp, 1ph, 1 rs485 to pump) where the synapse only has 2 rs232 ports. Might need some sort of mux chip.

On the pump side, I was going to get the VF pump since it has flow meter built in. But now that I think about it, the VS is like $400 cheaper. Not sure I really need a pump that can maintain constant flow. A constant speed might be enough. If I do a good job of decoding the communication, perhaps I can remotely program the speed from my module. I could always get a flow meter from atlas scientific.

I'm also waiting on a Pinoccio board to arrive sometime in July/August. It has a pretty cool API that looks easy to use. Good news is I can install their software onto the synapse modules if I choose to go that route.
 
yzf600 - They have a mux for just that purpose: https://www.atlas-scientific.com/produc ... ector.html. You use a couple of Digital outs to control which device the serial port is connected to. I wish the modules were addressable, so you could connect them on a bus.

I like those synapse modules. I might need to order a couple of those. It wouldn't take much to port my control code to python, and take the web server out. Since it has an API to access the data, you could just run a webserver on an embedded device (like a SheevaPlug or RPi). I've looked at the digi xbees but I see now they just are making them "programmable". The synapse has plenty of IO for the job and being able to program OTA is a plus.

I too debated a flow meter. Too expensive IMO. I found a reasonable priced meter somewhere - I'll need to find that again. As for the variable speed pump, you could roll your own, rather than screw with their protocol - look for a single phase speed controller. I'll look for that link too.

Tom
 
I'd like to have a two speed pump but when my motor crapped out on my 4 months ago they didn't have one in stock and I didn't really have the extra $140. Oh well, maybe next time the situation will be different...
 
tomt said:
yzf600 - They have a mux for just that purpose: https://www.atlas-scientific.com/produc ... ector.html. You use a couple of Digital outs to control which device the serial port is connected to. I wish the modules were addressable, so you could connect them on a bus.

I like those synapse modules. I might need to order a couple of those. It wouldn't take much to port my control code to python, and take the web server out. Since it has an API to access the data, you could just run a webserver on an embedded device (like a SheevaPlug or RPi). I've looked at the digi xbees but I see now they just are making them "programmable". The synapse has plenty of IO for the job and being able to program OTA is a plus.

I too debated a flow meter. Too expensive IMO. I found a reasonable priced meter somewhere - I'll need to find that again. As for the variable speed pump, you could roll your own, rather than screw with their protocol - look for a single phase speed controller. I'll look for that link too.

Tom

Where did you get your relay boards from? The purple makes me wonder if you did your own design and sent them to OSH park.

I'm not sure I'm up to doing a speed controller for a motor. I'll take my chances decoding the Pentair protocol on a VS motor. I'd also rather but the Pentair IntelliFlo VS pump since I know it's a fairly quiet motor.

I'm starting to wonder if it might be worth the effort to build a custom PCB for what I want. My personal requirements for an automation system would be:

  • VS pump control via RS485[/*:m:2zsqxhqk]
  • solar heater control - (sunlight and temp sensors, valve actuator. includes pool temperature reporting to xively.com)[/*:m:2zsqxhqk]
  • remote control to switch between filter and waterfall mode[/*:m:2zsqxhqk]
  • pH and sanitizer (ORP) monitoring (also reported to xively.com)[/*:m:2zsqxhqk]

Without too much extra cost, maybe I could throw in a few more features that would make this board useful for other folks interested in rolling their own solution:

  • ORP and PH measurement with atlas scientific probes. 74hc4052d mux chip to select channel [/*:m:2zsqxhqk]
  • 4 DPDT 240v rated relays to switch up to 4 motorized devices. Dual pole because I've seen motor documentation that says when switching a 240v supply, you must switch both supply lines. These relays could also be used to switch a 24V valve actuator open and close, hence the dual throw for +24v and -24v. I'm not quite sure about this, however. I'm sure with your commercial automation background you can set me straight here. [/*:m:2zsqxhqk]
  • 2 Analog to digital screw terminals. For thermistor temperature measurement and/or analog light sensor[/*:m:2zsqxhqk]
  • 10-15 GPIO screw terminals. Usable for 1 wire interface for digital temperature monitor and countless other digital interfacing[/*:m:2zsqxhqk]
  • 1 RS485 interface, half duplex[/*:m:2zsqxhqk]

I know I could cobble this system together with a bunch of different boards (multiple relay boards, rs485 converter board, 2 probe boards, synapse board, etc). I think the perfectionist in me just likes to see nice and tidy PCB instead of a hodgepodge of components and breadboards. On the other hand, I have a nice stack of PCBs on my desk that "almost worked". And even if the separate module approach costs more than a single PCB, it's still an order of magnitude cheaper than an off the shelf pool automation system. Plus it can be monitored and controlled on the Internet. I think the kids these days call this the IoT.
 
The disadvantage to the custom board would be ease of repairs or upgrades. I too would rather a nice, clean solution but I'm not going to make it difficult on myself. You are correct that its cheaper either way and you have infinitely more control. The intelliflo protocol is already decoded and available, it's intellichlor unit I'd like to have access to. I got an RS-485 USB adapter but I'm not sure it's up to the job. I'll try again when I get the rest of my current projects done.....
 

Enjoying this content?

Support TFP with a donation.

Give Support
I've been thinking a lot about a redesign, and here's where I'm at.

First, I think I'm going to abandon the Ethernet shield, and pair it with a Raspberry Pi. Total cost is about the same, and the RPi has a lot more functionality. It would allow remote firmware updates to the Arduino. I'd keep all critical control functions in the Arduino, and seperate all the webserver/logging/UI into the RPi. Since it can have a standard linux distribution that should be easy. Adding WiFi to the RPi is also only $10 or so. I've done some reading on communicating between the two - It can be done over RS232/USB, or I2C. The protocol would be simple - on startup, the Arduino would request parameters, and have safe defaults. The RPi could periodically poll for status, and the Arduino could send on status change for more instant response. For control, by the time you add on LCD's and buttons, I think I'll just grab a $100 Android tablet and dedicate that for the UI.

As for hardware, as much as I want to use something off the shelf for the Arduino, by the time you start designing a board/shield for that, you might as well design it with the Atmel chip on it... There really isn't much on the Arduino board anyway. Probably stick with the 328P. I'd also want higher resolution AD converters. Harden all the IO. Put relays on, but for no more than 24V. IMHO, leave the high voltage off the PCB all together. I've never done a PCB board, but I want to. It could be general purpose enough where it could be used for other purposes too.

Physical Points I would like to see:
Digital Start/Stop
Digital High/Low
Digital Heat Enable
Digital Feed Enable
Temperature Inputs (3 - return, supply, outside air)
Flow Input (pulse or analog)
2 Pressure Inputs (analog)
Inputs for hard buttons

Also, put a serial mux, and places to put in Atlas Scientific modules. The mux will avoid the need for a surface mount atmel chip that has more serial IO.

Expander Port (I2C) for adding IO.
 
tomt said:
As for hardware, as much as I want to use something off the shelf for the Arduino, by the time you start designing a board/shield for that, you might as well design it with the Atmel chip on it... There really isn't much on the Arduino board anyway. Probably stick with the 328P. I'd also want higher resolution AD converters. Harden all the IO. Put relays on, but for no more than 24V. IMHO, leave the high voltage off the PCB all together. I've never done a PCB board, but I want to. It could be general purpose enough where it could be used for other purposes too.

Physical Points I would like to see:
Digital Start/Stop
Digital High/Low
Digital Heat Enable
Digital Feed Enable
Temperature Inputs (3 - return, supply, outside air)
Flow Input (pulse or analog)
2 Pressure Inputs (analog)
Inputs for hard buttons

Also, put a serial mux, and places to put in Atlas Scientific modules. The mux will avoid the need for a surface mount atmel chip that has more serial IO.

Expander Port (I2C) for adding IO.

If I were to go the Raspberry PI route, I would skip the external arduino/atmel board/chip. The raspberry pi has lots of GPIO ports, so all your digital needs are there (start,high,heat, buttons). You still would want to make a PCB to break out the GPIO header to your own terminals. At this point you could slap down a serial mux and a 10 channel analog2digital chip This chip has a SPI bus to communicate with comm back with the raspberry pi. That Adafruit site already has the python code to work with that chip. Heck, you could even plug in a touch screen instead of the hard buttons. I'd probably take that python code and add all the other read/write stuff to implement the other features.

If you want some good PCB tutorials, check out the sparkfun Beginning Embedded Electronics section 8-11. It is a nice tutorial on EagleCAD. EagleCAD is a popular PCB tool for "makers" since it's free for small 2 layer boards.
 
Using RPi as the controller goes against my inclination of using a "computer" to directly control devices - it stems from my work in HVAC automation. Yes it could, but I wouldn't want a reboot, updates, or anything else to stop my pool from running. I prefer doing basic safety items such as keeping the pump running if the heater is on, or interlocking relays if needed in a dedicated device. Something simple like a JeeNode would also do the trick as a controller. What I'm proposing below is generic enough where you can pick your controller.

Thoughts are flowing on the hardware, though. I've yet to find a good, hardened IO for Arduino or Pi that doesn't cost an arm and a leg. The Ruggeduino comes pretty close. So I've come down to a few modules, all connected to an I2C bus. PCB's for the modules are standard size so they fit in snap track. IO all goes to good terminal strips. DIP switches for addressing the I2C modules, if applicable. I envision a row of devices - Rpi, Arduino, IO modules - all nice and neat next to each other. Make the modules mate directly or with short jumpers.

1) Analog Input Board
I2C 12bit Dac 8 Inputs (something similar to the MCP3008)
Each input selectable with jumpers: 0-5V, 4-20ma, Thermistor

2) Digital Output Board w/o relays
MCP23008 with ULN2830 darlington array
provide a second power source (24VDC) to run relays, or other outputs
should be cheaper for the board if you prefer external relays (like me)

3) Digital Output Board w/ relays
same as above
add relays (SPST?) capable of higher voltages (within good limits)

4) Atlas Scientific Interface
Atmel 328P (arduino chip), running as i2C slave
use software serial ports on 328P to control multiple Atlas boards
this will allow them to be accessed over i2c bus - pass through the Atlas serial commands using an address per module
would have headers and BNC - bring your own Atlas modules

I think this has many other applications besides pools. This is all very much like a PLC. Harden the inputs and outputs to protect from stupid mistakes. Bring your own processor - Arduino, Pi, whatever.
 
So, is this still alive?
Currently I'm using a Raspberry Pi to monitor my water temps (inlet and outlet) and to control the lights, pump, SWG and the heater. I would like to extend this with pH and ORP (automatic inserinting chemicals is for later, first start with measuring).
Problem is (as I understand) most of the probes are made for periodical measuring the water and then put away in dry condition. I want a probe to be permanent in the plumbing and then power it on every hour to do the measurement.

My setup is as follow:
Raspberry Pi
2 DS18B20 sensors directly in plumbing (down side: wrong numbers when not pumping)
3 Solid State Relays for the 'heavy' equipment (heatpump, filterpump and SWG)
1 small relay for controlling the LED's in de the pool
1 push button for the lid of the pumphous, when the lid is opened it will send a pushmessage to my phone.




I'm using a combination of pilight and pimatic (Dutch and Germany home-automation software). The Pimatic software allows me to control everything with flexible rules. Currently working on a way to tell the system how many pump hours I need for that day, and let it figure out on what moments it should to through out the day.

 
I know this is an old post so I hope someone is looking

I saw the pictures in the beginning with the compression fitting for the probe but I do not see how or where the thermistors are connected. Please post a pic.

Anthony

My temperature measurement is via a waterproof, solar powered otterbox. It sits on the pool deck with the thermistor cord dropped into the water. This way I can take temperature measurements all the time without having to keep the pump running for accurate readings.

If I were to put the thermistor inline with the sensors, I'd probably just buy another threaded PVC T junction and the equivalent male threaded cap. Just drill a small hole in the cap for the wire to come out, and JBWeld the hole when done.
 

Enjoying this content?

Support TFP with a donation.

Give Support
Status
Not open for further replies.
Thread Status
Hello , This thread has been inactive for over 60 days. New postings here are unlikely to be seen or responded to by other members. For better visibility, consider Starting A New Thread.