Swimming Pool

Blogspot limits the number of pages I can have, so I'm putting all my pool changes on this page as I get to them.  I installed a Hayward variable speed permanent magnet pool pump to save power when filtering the pool.  This led to problems with the solar heater sucking air at low speeds so I installed a valve on the roof to allow it to drain for freeze protection.  Not much point to having a low speed pump if you have to run it at high speed to support the solar heater.  I also built my own interface to the Goldline controller I have that allows control and monitoring from anywhere.  That's right, if there is an internet, I can control my pool.  Over time I installed an Acid Pump to try and keep the alkalinity of the pool under control, then I added a pre-filter to catch a lot of the trash before it got to those expensive cartridges in my main filter.


Controlling the Pool 
    I have decoded a significant portion of the Goldline control protocol.  This is important because now I can control the actions of my pool from anywhere I want.  Sure there are systems out there that already do this; if you want to spend several hundred dollars and pay extremely expensive pool repair people to come to your house to install it.  Then after a year, when the warranty runs out, you get to pay them again and again.  I fully intend to control my pool to my own tastes, not work under the limits of some automation controller and system.  Besides, the only device that directly interfaces a computer to the pool controller, the AQ-CO-SERIAL is overpriced, and although simpler, still doesn't tell you something as simple as, the light is on, is a reasonable fashion.  I want to type 'l' and have the light turn on, or create a web page of my own design and push a button labeled "Light".
     The first control software that I developed is below.  I place it in the public domain for anyone to use and improve upon asking only that you update me if you discover anything that will make it work better or expand on the protocol description.  Naturally, it involves an arduino controller with support devices and will expand and (hopefully) improve over time, as will yours.
     Please understand, I have decoded a lot of the protocol, but there are portions that still escape me.  So things like comm buss addresses and some responses are not yet clear.  I may eventually decode some of these, but for now, control and monitoring are my immediate concerns.
   
GoldLine Protocol:

The protocol is obviously something that evolved rather than something that was designed fully capable and carefully deployed.  To understand why I claim this let me discuss a couple of the remotes and how they are supported.  There is one remote that has an LCD display that is 16 characters wide and two lines  tall; the controller sends the actual text that is displayed every couple of seconds properly formatted for this display.  There is a different remote that has a display that is 20 characters wide.  There's a specially formatted packet for this controller as well.  As you can see, there is a lot of traffic on the RS485 buss.  But just to make it even worse, the controller sends a packet that seems to be a keep-alive signal at sub-second intervals.  This packet doesn't seem to actually do anything but it sure fills up logs when you are recording the traffic.


10 02 01 01 00 14 10 03

     This is the keep-alive packet.  The first two bytes indicate the beginning and the last two indicate the end; I have no idea what the intermediate 01 01 do, but the 00 14 that precede the ending indicator is a checksum.  10 + 02 + 01 + 01 = 14 (all numbers are hexadecimal); they count the first two bytes (beginning indicator) in the checksum, but not the ending two bytes.  So, if you watch the protocol fly by you will see the actual text that is shown on the various kinds of displays.

01 03 50 6F 6F 6C 20 54 65 6D 70 20 20 38 34 DF 46 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 00 07 57 

     Above is an example that flew by while I was watching.  I left off the beginning 10 02 and ending 10 03 and captured the payload data.  The payload starts with a 01 03 that means it is intended to be displayed on the LCD screen and the formatting is for a 16 character display.  The text to be displayed follows and it ends with the checksum. This packet tells me  "Pool Temp  84 F".  There is a similar packet for every thing displayed on the remotes except the software revision that appears when you first turn it on and the "Updating Display" message.  Needless to say, with the plethora of display types available, there are a lot of this kind of message.  One of the difficulties is that the protocol actually changes when a new device signs on to the RS485 half duplex comm system.  For example when I turn on my wireless remote it sends a packet like:


10 02 01 02 0E 00 00 00 20 00 00 00 00 23 10 03

From that point on, until the remote has been off for around 20 seconds, there are packets formatted for a display of 2 lines of 20 characters added.  The status LEDs are another display and they come in a special packet specific to the various displays that has bit fields telling which LEDs should be on.  These packets look like:


01 02 0E 00 00 00 20 00 00 00 00 43
01 02 2E 00 00 00 20 00 00 00 00 63

     These two packets are especially interesting.  The 2E above shows that the filter is on, that's the 2 part, the E part means something else.  Notice that in the second packet the 2 is gone leaving only the E?  The first packet turns the light on and the second turns the light off.  That means the filter light is flashing as each packet is decoded.  The first 2E has a corresponding 20 a little further down the packet, that 20 means the first 2E is supposed to flash.  So they are supporting displays smart enough to see the second bit and flash the light themselves as well as displays that can't and need something else to flash the light for them.  So, if you want to decode this packet you have to handle the filter bit going on and off with the packets.  These are the bits that I have decoded.  There are two sets of 4 bytes where the first 4 directly correspond to the second with the second indicating that the corresponding LED is supposed to flash.

Byte
Bit
LED
Byte
Bit
LED
1
0
Heater1
2
0
Aux2
1
1
Valve3
2
1

1
2
Check System
2
2
Aux3
1
3
Pool
2
3
Aux4
1
4
Spa
2
4

1
5
Filter
2
5

1
6
Lights
2
6
Valve4
1
7
Aux1
2
7


     There are other packets that don't fit the description above.  Some of them appear to come from the variable speed motor I have and change when the motor changes speeds on its own.  There's also one packet that seems to be telling me the line voltage to the motor.  I have also seen packets that don't terminate with the 10 03 and just end with the 03.  These are display packets and could be for a display I'm not familiar with.  There is also a combination packet that has the bit pattern for the LEDs combined with the display text.  That's a cool packet but it disappears when the corresponding remote times out and shuts off so I don't use it.  Remember how I described how the protocol changed above?  This is an example.
     Now, the good part, the control packets.  They follow the 10 02 .......checksum 10 03 pattern and have bit fields in the middle.  The bit fields are different from the above and correspond in some fashion to the buttons on the remote.  I couldn't figure out the pattern, so I only have data for the devices I use, if you need others, use the source code below to dump the packets as they are sent by your remote and add code as needed.  00, 83 are the command bytes sent by the wireless controller, below are the bit patterns from the various buttons.  These are repeated twice in the message so 00 83 00 01 00 00 00 01 00 00 would be a light button.  These are the bit patterns I have figured out
       80 00 00 00   filter button
       20 00 00 00   plus sign  (minus sign doesn't send sometimes)
       40 00 00 00   pool button
       01 00 00 00   right arrow
       02 00 00 00   menu button
       04 00 00 00   left arrow
       08 00 00 00   System off button
       00 01 00 00   Light  
       00 02 00 00   Waterfall    (Aux 1)
       00 04 00 00   Fountain     (Aux 2)
       00 00 01 00   Solar Heater (Valve 3)
       00 00 02 00   button on bottom
       00 00 04 00   button in middle

A complete packet to turn on or off the light is:
10 02 00 83 01 00 01 00 00 00 01 00 00 00 00 98 10 03

     Sorry, there is no light on command, only a light toggle.  So, if it's already on, the command above will turn it off.  Think of it as a pushbutton to change the light's state.  This can be problematic with multispeed motors since each command will step the motor one event forward.  That's where reading the LED commands comes in handy.  Now, let's talk about timing and speeds.  This is RS485, and is supposed to handle higher speeds over long distances and the data is running at 19.2KB so, with the huge traffic load, a lot happens really fast and can outrun code if you're not somewhat careful.  Especially if you're using a PIC that runs at lower CPU speeds.  Additionally, decoding the packet could take enough time that, when you send it, you collide with some other packet flying by out there. RS485 doesn't have collision protection and is half duplex, that means you don't have any idea if some other device is sending at the same time you are.  The method I use is to wait for one of the keep-alive packets and as soon as it ends I send a command.  That works OK, but there are failures on occasion, so I have to resend if the command collides with some other device.  The first hundred or so techniques I tried took too long to format or something and the failure rate was very high.  
     So, you have to format your command, wait for a keep-alive to come in and send the command as soon as you can after the keep-alive ends.  Using half duplex you keep the receive line low until the packet flies by and then pull the line high, send and then pull the line back low.  Actually, it's not as bad as it sounds, but it does take some care.  I suspect there would be significant problems using a normal computer such as a laptop because the OS would schedule something at the wrong time or a disk swap would delay the send.  There's also some significant delays using USB communication ports when you first start them up.  Hence, the Arduino.  Besides, the Arduino could be put right inside the controller case and an XBee link set up to remote the device to a multipurpose machine in the house somewhere.  Right now, I use a laptop USB connected to the Arduino with a long wire running out the back door to the pool controller; obviously not the permanent solution.

Hardware


As I said, this is RS485 so a special adapter is needed to go from the serial TTL of the arduino board.  I used this little device the Futurelec Mini RS422 adapter; don't let the name confuse you, it easily switches to half-duplex RS485, and at less than $5, the price was right.

And, of course, an Arduino.  I specifically got one a version back from the latest one just in case I needed to change the chip at some point.  These are also a bit cheaper and easy to find.

This is the device in operation hooked to the usb port of my laptop.  Using the laptop I can send the letter 'l' to the arduino, it waits until the right time and then send a light on command to the pool controller.  The plan is to interface something else to the arduino making it fully remote, then install it near the controller so there are no difficulties with wiring.  Notice that besides power and ground, there are only three signal lines to the RS485 converter.  Other than the obvious receive and transmit there is a line to switch between transmit and receive modes.  


     Over the next few days I'll adapt this to work with an XBee radio and mount it in a water proof box for installation near the pool controller.  The XBee will allow remote monitoring and control of the system.  I'll then interface it with my Home Controller Arduino and I can have as many timers as I want and use the other sensors around the house to generate commands to the pool.  For example, I can now tell the pool to turn on the lights any time I turn on the porch light, or keep the light off during the daylight hours so someone can't mistakenly leave it on.


Pool Controller Software

     Below is the Arduino script I came up with that actually can control the pool.  The command interpreter is extremely primitive, so you can modify it any way you want to meet your own preferences.  However, the techniques I used may need a little explanation.
     Since it can take a couple of seconds to find a place in the protocol exchange that will accept a command and then for the pool controller to actually react to the command, one can't send and expect an immediate response.  To overcome this problem I use timers set at two seconds to check to see if the command worked.  So, I send a command, wait 2 seconds check the result.  If the command didn't work, which likely means a collision, I resend the command and wait again.  The command usually works on the first try but every fifth time or so, a retry is necessary.  On the rare occasion there will even be a third try.  However, this seems to work well and is easily adapted to. The code relies heavily on various flags that are set while decoding the protocol and then acting on them as a separate action.  This helps the timing of the commands being sent.  That means that with a few changes you could implement such commands  as "lights off" by simply looking to see if the light was on before sending a command.  Maximum versatility is available this way.

The Arduino Sketch

/*

Goldline ProLogic control software.

This took a couple of months research and testing to get this far.  The pool controller
protocol is not documented anywhere, but there are a few subtle clues in various places.  I
put a LOT of comments in here to show what I'm doing and how I'm controlling the pool.

It's very difficult to decode the protocol and I haven't completed doing so.  However, I have
discovered enough to control my pool and you should be able to expand on my efforts to get
what you need done.

I want to be able to set up timers to turn the pump on whenever I want, not just the built
in 2 timers they allow me.  Additionally, it would be nice to be able to turn the pool light
on when the sun goes down and then turn it off maybe an hour later.  I want to be able to do
things the controller just won't let me do.

Also, I don't want to shell out several hundred dollars for a RS232 interface that is as hard to
use as the actual controller such as the AQ-CO-SERIAL_DS.  Granted, the person that developed
that device put in a lot of work, but they had access to Goldlines documentation as well.
Additionally, the menu directed interface of the AQ-CO-SERIAL_DS is silly.

I have implemented a very simple input scheme of type an 'l' and the light turns on.  A 'f' will
turn on the fountain, etc.  The filter is an 'm' since the 'f' was already used.  The command is
sent to the pool controller and then the status is checked to see if it happened.  If it doesn't,
the code will send it again.  This operation is controlled by a timer since some of the items can
take as much as two seconds to happen.  So, not only do we have to allow for RS485 collisions,
we also have to account for the time it takes to do something.  Talk about reality programming.

There's much more description of the protocol and timing considerations on my web site at
  draythomp.blogspot.com

I place this code and my descriptions in the public domain and encourage people to expand on it;
I ask only that any discoveries you make be passed back to me for eventual addition to this work
*/

#include <MemoryFree.h>
#include <SoftwareSerial.h>
#include <Time.h>
#include <TimeAlarms.h>

SoftwareSerial poolSerial = SoftwareSerial(2,3);
uint8_t buffer[200];
uint8_t* bufptr;
boolean sendPending = false;
#define dirPin 4
// bits for various functions
#define filterOn 0x20
#define lowSpeed 0x20  // same bit different byte
#define solarOn 0x02
#define lightOn 0x40
#define waterfallOn 0x80
#define fountainOn 0x01
// where I'll hold the data to give on request
// this was originally a series of boolean flags, that turned out
// to be harder to handle than a bit field.  If you need more bits
// at some point, use a uint16_t; that should hold you a while
uint8_t poolStatusFlag = 0;  // most recent pool status
uint8_t newStatusFlag = 0;
#define filterBit         0x80
#define filterLowSpeedBit 0x40
#define solarBit          0x20
#define lightBit          0x10
#define waterfallBit      0x08
#define fountainBit       0x04
int poolTemp = 0;
int airTemp = 0;
// Command strings to send to the pool controller
// Yes, I could construct these on the fly and been much more elegant
// for the computer purists out there.  However, this is much clearer
// and easy to understand for most folk.  Heck, you can just look at it
// and see how the protocol works.  It was a pain calculating the
// checksum though.
// So if you create a new one, keep the data from reading it and reuse
// the checksum value
uint8_t lightData[] =     {0x10, 0x02, 0x00, 0x83, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x98, 0x10, 0x03};
uint8_t fountainData[] =  {0x10, 0x02, 0x00, 0x83, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x10, 0x03};
uint8_t filterData[] =    {0x10, 0x02, 0x00, 0x83, 0x01, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x96, 0x10, 0x03};
uint8_t waterfallData[] = {0x10, 0x02, 0x00, 0x83, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x10, 0x03};
uint8_t solarData[] =     {0x10, 0x02, 0x00, 0x83, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x10, 0x03};

void showMem(){
  Serial.print("Free Memory = ");
  Serial.println(freeMemory());
}

void setup(){
  Serial.begin(57600);
  Serial.println("Initializing..");
  poolSerial.begin(19200);
  pinMode(dirPin, INPUT);      // this will set the internal pull up resistor on the
  digitalWrite(dirPin, HIGH);  //digital output pin
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, LOW);   // to receive from rs485
  memset(buffer, 0, sizeof(buffer));
  bufptr = buffer;
  setTime(0,0,0,1,1,11);  // just so alarms work well, I don't really need the time.
  // the timealarm library is a nice way to schedule something in a few seconds or minutes
  // this can be used to send commands also.  I do this later in the code
  // to report pool status after a command is sent
  Alarm.timerRepeat(60, poolReport); //Show status periodically
  Serial.println("done");

}
#define waitForFrameStart1 1
#define waitForFrameStart2 2
#define gatherData 3
#define waitForFrameEnd 4
boolean okToSend = false;

int frameStatus = waitForFrameStart1;
boolean checksumOk = false;
uint8_t* commandPtr = 0;

boolean firsttime = true;

void loop(){
  char c;

  if(firsttime == true){  // the arduino has limited resouces, check them
    showMem();            // this helps keep me under the limits
    firsttime = false;
  }
  if(Serial.available()){  // extremely primitive command decoder
    c = Serial.read();
    newStatusFlag = poolStatusFlag;
    switch(c){
      case 'l':
        commandPtr = lightData;
        newStatusFlag ^= lightBit;  // I can't believe it!  I actually got to use ^ for real.
        break;
      case 'm':  // the filter has three states off, high, low
        commandPtr = filterData;
        if (poolStatusFlag & filterLowSpeedBit) // if low speed, the filter is on, next =  off
          newStatusFlag = poolStatusFlag & ~(filterBit | filterLowSpeedBit);
        else if (poolStatusFlag & filterBit) // filter is on, but not low speed, next = low speed
          newStatusFlag = poolStatusFlag | (filterBit + filterLowSpeedBit);
        else
          newStatusFlag = poolStatusFlag | filterBit;
        break;
      case 'f':
        commandPtr = fountainData;
        newStatusFlag ^= fountainBit;
        break;
      case 'w':
        commandPtr = waterfallData;
        newStatusFlag ^= waterfallBit;
        break;
      case 's':
        Serial.println("Solar is thermostat controlled...silly");
        break;
      case 'R':
        poolReport();
        commandPtr = 0;
        break;
      default:
        commandPtr = 0;
        break;
    }
    Serial.flush();
    if (commandPtr != 0)
      poolSendFlag();
  }

  Alarm.delay(0);  //just to make the alarms work
  // the protocol has a 0x10, 0x02, data, 2 byte checksum, 0x10, 0x03 form
  // that makes it hard to parse since there are two characters to mess with
  // to add insult to injury, there is one packet type that ends with just a
  // 0x03 apparently to support an older or different display.
  // let's complicate it even more, there are packets in there that don't even
  // come close to any of the above.  They look something like
  // "00 E0 18 80 00 E6 00 18 9E 00 E0 1E 80"  and are probably related to motor
  // control.  Since Hayward took over the company and added support for their latest
  // motors.
  if (poolSerial.available()){
    c = (uint8_t)poolSerial.read();
    switch( frameStatus ){
      case waitForFrameStart1:
        if(c != 0x10){
//          printByteData(c);   //this will print data outside the 10->03 frames
//          Serial.print(" ");
          break;
        }
        else {  // this is a status or command frame
          frameStatus = waitForFrameStart2;
        }
        break;
      case waitForFrameStart2:
        if (c != 0x02){                   // it's not really the start of a frame
          frameStatus = waitForFrameStart1;
          break;
        }
        else {
          frameStatus = gatherData;
        }
        break;
      case gatherData:
        if (c != 0x10){
          *bufptr++ = (char)c;  // capture the characters inside a frame
          break;
        }
        else {  // nearly end of frame, check the checksum
          int len = (int)(bufptr - buffer);
          int i = 0;
          unsigned int checksum = 0x12; // sum of 0x10 + 0x02
          for( i = 0; i < len - 2; i++){
            checksum += (unsigned int)buffer[i];
          }
          if (checksum == (unsigned int)buffer[i] * 256 + (unsigned int)buffer[i+1]){
            checksumOk = true;
          }
          else {
            checksumOk = false;
          }
          frameStatus = waitForFrameEnd;  // wait for the last 0x03
          break;
        }
        case waitForFrameEnd:
          if(c != 0x03)
            break;
          else {
            if(sendPending && okToSend){  //this send has to come as soon after the end of packet
                                          // as I can possibly code it.
              poolSend();
              Serial.println("Command Send **************************");
              // It can take a couple of seconds for something like the motor
              // command to make all the way through the devices so...
              // makes you wonder why they have to run at 19.2K and create
              // so much traffic, doesn't it?
              Alarm.timerOnce(2, poolActionCheck); // in 2 second see if it happened
              sendPending = false;
              okToSend == false;
            }
            frameStatus = waitForFrameStart1;
            int len = (int)(bufptr - buffer);
//            printFrameData(buffer,len);
            if(checksumOk)
              processPoolFrame(buffer, len);
            memset(buffer, 0, sizeof(buffer));
            bufptr = buffer;
            break;
          }
    }
  }
}

void processPoolFrame(uint8_t* buffer, int len){

//  printFrameData(buffer,len);
  if(buffer[0] == 0x01){  // Display command
    if(buffer[1] == 0x01){  // some kind of keep-alive - ignoring for now
      okToSend= true;
      return;
    }
    // handle this like an interrupt.  Only set flags and deal with them after
    // the packet has been decoded.  There is not enough time to do serial prints
    // for information.  It's ok, to use them for debugging
    if(buffer[1] == 0x02){ // led display command
      poolStatusFlag = (buffer[2] & filterOn) ? poolStatusFlag | filterBit :
                         poolStatusFlag & ~filterBit;
      // controller trying to blink filter led for low speed indication
      poolStatusFlag = (buffer[6] & lowSpeed) ? poolStatusFlag | (filterLowSpeedBit + filterBit) :
                          poolStatusFlag & ~filterLowSpeedBit;
      poolStatusFlag = (buffer[2] & solarOn)? poolStatusFlag | solarBit :
                         poolStatusFlag & ~solarBit;
      poolStatusFlag = (buffer[2] & lightOn)? poolStatusFlag | lightBit :
                         poolStatusFlag & ~lightBit;
      poolStatusFlag = (buffer[2] & waterfallOn)? poolStatusFlag | waterfallBit :
                         poolStatusFlag & ~waterfallBit;
      poolStatusFlag = (buffer[3] & fountainOn)? poolStatusFlag | fountainBit :
                         poolStatusFlag & ~fountainBit;
//      printFrameData(buffer, len);  // use this carefully, will affect the command send
    }
    if(buffer[1] == 0x03){ // Display update command
//      for ( int i = 0; i < 32; i++){  // use this to show text intended for display
//        Serial.print(buffer[i+2]);
//      }
//      Serial.println();
      if (strncmp((char *)buffer+2,"Pool Temp",9) == 0){
        poolTemp = atoi((char *)buffer+12);
      }
      if (strncmp((char *)buffer+2,"Air Temp",8) == 0){
        airTemp = atoi((char *)buffer+11);
      }
    }
  }
  else if (buffer[0] == 0x00 && buffer[1] == 0x83){
    /*
       0x00, 0x83 is the command string sent by the wireless controller
       below are the bit patterns from the various buttons.  These are repeated
       twice in the message so 00 83 00 01 00 00 00 01 00 00 would be a light button
       80 00 00 00   filter button
       20 00 00 00   plus sign  (- doesn't send sometimes)
       40 00 00 00   pool button
       01 00 00 00   right arrow
       02 00 00 00   menu button
       04 00 00 00   left arrow
       08 00 00 00   System off button
       00 01 00 00   Light
       00 02 00 00   Waterfall    (Aux 1)
       00 04 00 00   Fountain     (Aux 2)
       00 00 01 00   Solar Heater (Valve 3)
       00 00 02 00   Unused switch on bottom
       00 00 04 00   Unused switch in middle
    */
//    printFrameData(buffer, len); // this will print command buffers outgoing from remote
  }
}

void poolSendFlag(){  // this flag routine tells the send code to go ahead
  sendPending = true;
}

void poolActionCheck(){

  if ((poolStatusFlag | solarBit) != (newStatusFlag | solarBit)){// solar is thermostat controlled
    sendPending = true;                                          // don't check it
    // This will now loop around through the frame handling and resend
    // which will set another timer to come back here and check again.
    // and so forth until the action has completed
  }
  else {
    poolReport();
  }
}
 


void poolSend(){
// This is rs485 and there is no collision protection.  It doesn't seem like the protocol
// goldline uses has an addressing scheme to enable the various possible control panels either
// Therefore....I just send it a couple of times and hope one of them gets through.
// So far, this seems to work just fine.  However, the commands have to be sent as SOON as
// possible after the end of a packet.  They must be only accepting commands for a timed period
// because I don't get on, off, on, off, types of reactions.  Ten commands only results in one
// action if they happen close enough together.
  for (int count = 0; count < 2; count++){
    digitalWrite(dirPin, HIGH); // to send rs485
    for(int i = 0; i < sizeof(lightData); i++){
     poolSerial.write(commandPtr[i]);
    }
    digitalWrite(dirPin, LOW); // to receive from rs485
  }
}
// this routine is where things are reported if you need it.  Tailor this routine
// any way you want to support your project
void poolReport(){
  Serial.print("Pool, ");
  Serial.print("Filter ");
  Serial.print(poolStatusFlag & filterBit ? "On, " : "Off, ");
  Serial.print(poolStatusFlag & filterLowSpeedBit ? "Low" : "High");
  Serial.print(" Speed, ");
  Serial.print("Waterfall ");
  Serial.print(poolStatusFlag & waterfallBit ? "On, " : "Off, ");
  Serial.print("Light ");
  Serial.print(poolStatusFlag & lightBit ? "On, " : "Off, ");
  Serial.print("Fountain ");
  Serial.print(poolStatusFlag & fountainBit ? "On, " : "Off, ");
  Serial.print("Solar ");
  Serial.print(poolStatusFlag & solarBit ? "On, " : "Off, ");
  Serial.print("Pool Temp ");
  Serial.print(poolTemp);
  Serial.print(", ");
  Serial.print("Air Temp ");
  Serial.print(airTemp);
  Serial.println();
}

void printFrameData(uint8_t* buffer, int len){

  // there's lots of nulls in there, can't just print it
  // so I print the hex values then the ascii below
  // so you can see the text as it flys by
  int i = 0;
  while(i < len){
    printByteData(buffer[i++]);
    Serial.print(" ");
  }
  Serial.println();
  i = 0;
  while(i < len){
    Serial.print(" ");
    if (isprint(buffer[i]))
      Serial.print(buffer[i],BYTE);
    else
      Serial.print(" ");
    Serial.print(" ");
    i++;
  }
  Serial.println();
}
// routine to take binary numbers and show them as two bytes hex
void printByteData(uint8_t Byte){
  Serial.print((uint8_t)Byte >> 4, HEX);
  Serial.print((uint8_t)Byte & 0x0f, HEX);
}


Actual Installation (with XBee)

Here's my version of the controller.  Notice that I put a hole in the box to plug in a laptop to change the programming and there is an XBee on the bottom with the antenna pointing down.  This version is totally remote controlled and works well.  I get power from the USB plug right now; it is hooked to a wall wart mounted inside my pool controller.  I will change that to a couple of wires leading into the box like the two RS485 wires that are on the bottom right.  Then I will plug all the holes in the bottom to keep the bugs out.  Rain shouldn't be a problem since the holes are all on the bottom.  Actually, I will leave one hole open for venting and drying with a small piece of wire mesh for the bugs.  I'm also going to paint it white to keep the sun from rotting away the plastic over time and keep it as cool as possible in the desert sun.




Other thoughts

It has occurred to me that I can do even better than this.  The Goldline controller only allows me two choices of speed at a time, low and high.  I can set the speed of each of these settings, but only get to choose between them.  The motor has provisions for four different speeds as well as timers.  Perhaps when I get this current project running I'll look into greater flexibility.  I may have to decode the link to the motor, but I could also just use the control input to the motor itself and disconnect it from the Goldline altogether.


Pool Solar Heater
I've had a solar pool heater for a few years now and love it.  For me, a pool is most comfortable running a only a little below skin temperature.  Yes, that means over 90F.  I know there are people out there that will argue this with me forever, but it's my pool, I'll keep the temperature where I want it.  So there.

However, when I put in the really cool variable speed pump, the solar heating system stopped working well because there wasn't enough pressure in the line to close the vacuum break on the roof.  So, the system sucked air and bubbled it out into the pool.  The air running through the system caused a drop in efficiency and the pool wouldn't heat as well.  I called around and no one had a solution to this except to turn the pump up so the higher pressure would close the vacuum break.  That just didn't make sense to me at all.  Why have a low speed pump that I have to run at high speed during the peak billing period to support a solar heater that is supposed to save energy?

I ran across a web site that discusses low head pressure on solar systems.  These folks present a really good case for lower pressure and have nice animated displays to illustrate their point (look here).  I called them and they were extremely nice, but they didn't have a solution either.  So, I thought about it a while and decided that I would stop the air from entering the system through the vacuum break.  I couldn't just close off the break, that would cause serious problem because the system wouldn't drain when not in use.  That could cause freezing in the winter and some other problems along the way.  What to do?  Put a valve in.

I got a valve like the ones that control the various features of the pool, ran some wires and installed the valve on the roof between the vacuum break and the heater array.  The valve is normally open and closes when the solar heater valve is turned on.  That way the air is cut off during use and allowed to pass when the solar is turned off.  It can still drain and the valve is (at least) as reliable as the rest of the system.  Cool Huh?


This is a picture of the solar array on the roof, the valve is on the right (not visible)

This is the valve and vacuum break.  The vacuum break is at the end of the white pipe on the left.  The system has been in place for a couple of months now and works really well.  No problems with it sucking air or leaking at all.

Update August 2011:

Spoke waaaay too soon.  The pressure of the water blew the connection to the valve apart.  Seems I need a barb fitting.  This turned into a major project that is detailed in blog posts on the main page.  Links:
Part 1Part 2Part 3Part 4, Part 5.  This was a real pain and took quite a while to figure out and fix.


The graph above shows the temperature over the last few days.  When the pump is off I can't monitor temperature since there is no water flow across the temperature sensor.  So, to keep the graph somewhat within reason I cut the temperature display off at 10F.  This graph is almost real time.  A quick note on some of the temperature readings:  If it goes over 100, it's probably because the water flow is so low that the temperature sensor is heating up from the direct sun; if it drops mid-day, it's because I'm doing something and shut the pool motor off and the water isn't flowing at all.  There has been one instance of my devices sending a huge number just once.  I can't get that to reproduce, but I'll look into preventing it.....sigh.


Acid Injection Pump
A salt water pool with automatic chlorination suffers from 'pH creep'.  This is where the chemical reaction of the chlorine generator causes the pH to rise over time.  If you don't pay attention to the pH constantly, you will get an alkaline pool that has a calcium ring around it.  It also creates 'snow'.  Snow is a fine white powder that circulates around the pool collecting in the corners and generally makes the pool look weird.  I got tired of messing with it every single day and decided to get an acid pump and automate it.

And this is where the story gets complicated.  Below is my first few tries at making this work.  I failed.  The pump I specify just wasn't up to the job and I finally had to admit defeat and start searching for something else to try.  I'll update this page when I have another idea ready to try out, but I'm going to keep the documentation on my failures as an example for other folk on what NOT TO DO.  Notice also, that this project has been ongoing since August, 2011; it takes a lot of time and patience to get something like this to work.

Update July 14, 2012: I have a new solution to this problem.  I am now using a peristaltic pump that has several advantages over the Hanna and seems to be doing well.  It is all detailed in my post here.  I'm still using the same timer configuration that is controlled by the House Controller and the same bucket and float to indicate how much acid I have left.  Let's hope this set of devices works out better.

The failure is described in excruciating details below:

I chose the Hanna BL 7-1 Dosing pump over a peristaltic pump because the peristaltic pumps tend to leak when they fail.  If you Google peristaltic pumps you'll see that they have a little tube that rollers run across to move the chemical.  This tube will dry out and break over time in a harsh, hot, outside environment (like where I call home) allowing the acid to drip inside the pump head.  I wasn't real fond of the idea of acid dripping in my pump head.  However, I have to put up with the noise a diaphragm pump makes.  This kind of pump works off a solenoid and the solenoid isn't the quietest thing in the neighborhood, but I only have to run it a few minutes a day.
However (there's always a freaking 'however'), there aren't any timers out there that can run a few minutes a day with the kind of control one needs for something like this.  It needs to be able to survive a power outage, know the current day in case you have to switch to every other day, know if the pool pump is running and control 110V directly.

So I built one.


This little device is an Ardweeny, an Adafruit XBee adapter board, an XBee and a relay.  I used this configuration because I wanted it to fit in a duplex outlet box like the pool controller above.  It's programmed to grab the time from my House Clock and activate the relay whenever I want.  Here's the device mounted on the fence hooked up to work.


I put the Hanna pump in a plastic box and mounted it beside the timer.  


The box was a problem though.  The dimensions of the box were given for the greatest amount in all directions and when I tried to put the pump in it, the lid wouldn't close because it was curved.  So, I broke out my heat gun, forced the lid shut and heated the lid until it set down properly.  Distorted the lid a bit, but it doesn't look bad and works quite well.


I inject the acid directly into the pool plumbing after the filter and before the chlorine generator with a little plumbing concoction that me and a guy at the plumbing supply came up with.


This actually works quite nicely.  It raises the pH while the pump is on and helps to clean the chlorine generator, plus the high volume of water at this point helps mix the acid well with the pool water.  It will take me a couple of weeks of checking and adjusting to get the right amount of acid per day to offset the pH creep, but that's better than forgetting and having my pool run amok.

Over time I plan to sample the acid level in a bucket below the dosing pump and turn on a light I'll add to my House Controller.  This way I won't have to check the bucket very often to make sure there's still acid in it.  The timer already sends data via XBee to the controller telling me it's alive and whether it's running or not.  Since it doesn't run very often, I have to stand there and watch for it though.  I may do some work in that area as well, it would be nice to know the last time it ran for example.

But the cool thing about this is that this is another little computer.  I can have it do any darn thing I want it to and add sensors or controls to it as I see fit.  For example, I'm thinking about adding a temperature sensor to the device so I have the temperature on that side of the house.  I could also put a moisture sensor in that area to check for leaks and such.  Cool.

Update 11/28/2011:  The fittings on the acid pump are starting to melt from the acid.  This is NOT supposed to happen.  I checked the specs carefully and talked to the pump company about what I planned, and the pump should be able to handle this just fine.  It's important to note that the pump housing, pump head, tubing and other stuff are not having problems.  Just the fittings for the valves.  There's some kind of material problem here.  I have detailed this here and here with pictures.  The problem is not resolved, I'll update as I go along.

Update 12/9/2011:  I talked to the manufacturer of the Acid pump and received a replacement pump head. When I disassembled the pump to install the head, I came across the root cause of my problems and detailed it here.  This problem is not resolved yet, and after it runs for a while, I'll try some of the ideas out.

Update 2/2/2012: Had to send the pump back for replacement.  Acid leaked into the controls through the shaft of the potentiometer on the front of the device.  More details here.

Update 3/5/2012:  Got the replacement acid pump back.  Now I'm testing the ideas I have for fittings and valves.  Details here.

Update 3/29/2012: OK, it's back in service and running.  All the valves have been replaced with parts that won't dissolve in the acid.  The system has been tested at much higher pressures and there are clamps everywhere.  The final configuration is here.  I may come back and change this part of the blog to reflect the reality of this project more clearly.  This has been a long time project; it seemed simple, get a pump and hook it up, but nothing ever seems to work the way they advertise.  Just for the record, here is a picture of the final configuration, compare it to the way it started out above.

The key thing to know is what plastics to use.  For example, the nuts I originally received with the pump were acetate, this will dissolve in acids.  The same thing happens with Nylon; the various fitting you find at Home Depot, Lowe's and such are often Nylon, beware.  Plastics like PVC, Kynar (PVDE), high density polyethylene (HDPE) will tolerate acids really well.  Metals are forbidden, not only will they dissolve or oxidize, they leave residue behind and will destroy other things.  Metal screws and such that will not be exposed to acid are OK until a leak happens.  So allow for a leak and give the parts plenty of ventilation to remove the corrosive fumes.  In my installation the pipe fittings are PVC, the tubing is HDPE, the valves are Kynar and the clamps are acetal.  This means the clamps are a possible weak link.  Since they are outside the tubing, easy to replace, cheap, easy to inspect, and serve a secondary function to backup the seal, I'm not too worried.  However, if I ever find Kynar, PVC, or HDPE clamps they will get replaced.  A special mention on the valves.  They are diaphragm types that do not have a spring.  There are mainly two types of check valves: ball and diaphragm; ball valves require a spring and it is usually metal.  Unless you were to use an exotic metal (expensive and rare) this won't work.  The diaphragm in the valve I used is Viton, another material that doesn't react to the acid.  For the picky people reading this, there are several other types of check valves; plunger and hinge come to mind, but they have disadvantages in this kind of installation; stick to either ball or diaphragm.

When you decide exactly what you are going to try first, be careful ordering.  The tubing I have is expensive and stiff.  It also is an unusual size.  This means fittings were hard to guess and I finally had to resort to using a digital caliper to actually measure things (gasp!).  So, a 3/16 inch barb fitting works well, while a 1/4 inch barb would work with some serious effort, and probably risk.  Since compression fittings work around the outside of the tubing, I used 5/16 inch fittings.  These (as described in my various posts) are a tiny bit too small and I had to resort to a heat gun to soften the tubing to make them work.

Here's a list of the parts I ended up with.  Note that I tried many combinations of parts and pieces getting to this state so read the various posts above that detail the various failures along the way.

US Plastic Item #: 57152

.307" x .342" Snap Grip Clamps, these are acetyl and could dissolve so order extras and inspect occasionally. 
US Plastic Item #: 61277

Kynar Connector Tube And Hose Fitting 5/16" x 1/4".  These are all plastic, no metal at all.  The thread size is only 1/4" so that means some adapters are necessary.

US Plastic Item #: 26001

3/8" x 1/4" PVC Threaded Reducing Bushing.  This is PVC and fits the top and bottom of the pump head.  One of the compression fitting above can be threaded directly into this and you can run tubing from that point on.  I also used this to inject the acid into the 2" PVC pipe that leads to the pool.  Notice though that this fitting has 8 sides so a socket won't fit it.  That's OK though since most of us use a pair of pliers to install this stuff.

US Plastic Item #: 64108

3/16" Kynar® Standard Check Valves.  This is the key item.  The body is Kynar and the diaphragm is Viton so it won't dissolve.  The break pressure is real low and it can withstand reverse pressure way above the swimming pool levels.  Too bad it doesn't have threaded fittings.

You'll also need elbows and nipples to direct things.  These are much easier to find and may even be available locally.  Remember they need to be 1/4" pipe thread.

Acid Pump Level Indicator
Sept 14, 2011:  I finished my first attempt at reporting when the pump reservoir bucket is getting empty.  Abysmal failure.  I detailed it in this blog post here .  Ever notice how, no matter how much you research something, there are things that sneak up to bite you?

I have another idea already in progress.  I'll report on success or failure when the glue dries.

Update Sept 15, 2011:  Failures like the one above don't deter me for long.  I have a working level indicator that will allow me to walk by and check it as well as have it reported electronically.  What I did was get some PVC tubing that would telescope inside a piece of 3/4 inch tubing.  This gave me something that I could run out of the bucket and put a switch on.  Here's the lid of the bucket and the float assembly:


It's a piece of 1/2 CPVC with a toilet float attached to the bottom of it.  On the lid I glued a flange and a piece of 3/4 PVC so I could mount a magnetic read switch outside the bucket.  The tube on the float has a magnet in it to close the switch when the acid level gets low.  The tube serves two purposes: the first I already mentioned, to hold the magnetic switch.  The second is to keep the float straight up and down in the bucket so it doesn't try to wander around.  Learned that lesson from the attempt with string.  Should have known better, but live and learn.  The piece of CPVC that is running across the lid is for stiffening up the structure.  These buckets are made as cheaply as possible and have a lot of flex.  This cross member glued on helped that problem a lot.


Here's more detail on the float and tube.  Notice I pinned the float on the tube instead of gluing it.  I didn't think I could find a glue that would work in the hot acid environment.  The marks on the tube represent the level of the acid in the bucket.  So I can walk by it and take a look to see how full it is.  Here's the magnetic switch:


I simply tie wrapped it to the 3/4 inch tubing.  This isn't the perfect solution since tie wraps dry out and fall off in about 6 months in my weather, however it will work while I get some experience with the level indicator.  I'll use a couple of stainless hose clamps to fasten it on better when I'm comfortable with the way it's working.  The magnetic switch is water proof, as most of these things are, but it may rot in the weather over time.  I'll see about wrapping it with some metallic tape to protect it in a week or two.  Here is the device installed and working:


One nice thing is that this lid is white already.  I'm going to paint the entire thing with a plastic paint soon, but being white will make that a little easier.  Ace hardware carries the white buckets if you need one.  The top mark on the rod is the empty mark, the next one down shows one gallon and the next two, etc.  So right now I have almost two gallons of acid in the bucket.  Nice to be able to walk by it and just look to see how it's doing.



79 comments:

  1. As I said before, I love what you're doing with the house/power monitoring.

    That Goldline protocol looks like a dog's breakfast.

    ______
    Rob

    ReplyDelete
  2. Actually, the protocol looks like what comes after a dog's breakfast. I couldn't believe they change it based on what devices are attached and active. Plus, the idea of sending a message to turn a light on, then a message to turn it off??? Where did they come up with that? My latest swimming pool project is an acid injector. This project is taking forever though. Fittings problems, plumbers that don't have a clue what they are actually doing once they get out of their basic routine, etc....sigh.

    ReplyDelete
  3. I am trying to decode this protocol as well, I have not been successful with sending a command. I have the AQL-P4 with a wireless remote and I suspect I am having an issue with the half duplex. Would it be possible for you to publish your header files so I can give your code a try on my setup?

    Thanks.

    ReplyDelete
  4. The code above is all there is of it. Notice that the only header files are the normal system ones for the Arduino. I use the strings I constructed to do each of the commands. There's a finite number or commands I use, so this method if pretty effective for me.

    ReplyDelete
  5. I figured out what my problem was, Thanks for your help.

    FYI-

    Here is the strings that work for my controller, they were a little different then what you are using.


    Filter
    10 2 0 5 2 0 2 0 7F 0 9A 10 3 On
    10 2 0 5 0 2 0 2 7F 0 9A 10 3 Off

    Lights
    10 2 0 5 20 0 20 0 7F 0 D6 10 3 On
    10 2 0 5 0 20 0 20 7F 0 D6 10 3 Off

    Cleaner
    10 2 0 5 10 0 0 10 0 0 7F 0 B6 10 3 On
    10 2 0 5 0 10 0 0 10 0 7F 0 B6 10 3 off

    Waterfall
    10 2 0 5 8 0 8 0 7F 0 A6 10 3 On
    10 2 0 5 0 8 0 8 7F 0 A6 10 3 Off

    ReplyDelete
  6. Wow, you actually have on and off commands. That will make controlling the pool a lot easier.

    ReplyDelete
  7. Those came from the AQL2-SS-RF Wireless remote. My keypad in AQL-P-4 generates a single command for On/Off similar to what yours is doing. I am using the RF remote commands for the advantage of sending an on of off.

    ReplyDelete
  8. I am trying to do the same, but I am using an mbed (mbed.org). There are a few details I may have missed.

    The AQL-P4 has 4 pins for wired remotes, you have two wires, which of the 2 wires are hooked to the AQL's which pins?

    Also, I cannot tell from the picture, but it looks like you have T+ and T- connected, right? Not T+ R+, right?

    ReplyDelete
  9. I can't remember which two wires I hooked into on the P4, I'll have to open it up and look. I'll try to get to it tomorrow and I'll post here. And, yes, I'm using t+ and t- on the rs485 adapter. The protocol is half duplex and the board I chose was a full duplex capable board. So, when that happens, you just use half of it for the protocol. I know, it's wasteful, but what the heck, these things are cheap.

    ReplyDelete
  10. Dave, thanks. I have the same rs485 adapter, I want to try and do the same thing you are doing, using the mbed instead (instead of adruino) and write an iPhone/iPad app to control the P4 from there. I have an ethernet cable I hooked up to the P4, I hooked up 4 wires (to the 4 terminals) and I just need to figure out which of the 4 need to be hooked up. I tried 1,2 and 3,4 to T+/T- and neither worked (I got nothing through the rs485 adapter), but I may have done something wrong.

    Also, I don't quite understand these lines of your code:

      pinMode(dirPin, INPUT);      // this will set the internal pull up resistor on the
      digitalWrite(dirPin, HIGH);  //digital output pin
      pinMode(dirPin, OUTPUT);
      digitalWrite(dirPin, LOW);   // to receive from rs485

    You set the pin to input, then set it to high.....then you set the pin to output? Why bother with the first step? Why do you want the internal pull up resistor on this pin? "High" is for send, right? SO when things are disconnected, you want it in send mode?

    Sorry for being dumb here...I am a programmer by profession, but haven't done anything embedded since college, so I am a little rusty on these intricacies..

    Thanks!

    ReplyDelete
  11. Here is my pinout.

    AQL P-4
    Red 1 is not Connected
    Blk 2 connects to T+/B on RS485
    YEL 3 connects to T-/A on RS485
    GRN 4 connects to Ground on RS485

    ReplyDelete
  12. Code Sample that I am using on linux with a USB - RS485 adaptor, it shows up as /dev/ttyUSB0 for me. I am sure you could make many improvements to this code.

    so once I compile that I can run it as ./a.out /dev/ttyUSB0


    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include


    int main(int argc,char** argv)
    {
    struct termios tio;
    struct termios stdio;
    int tty_fd,i;
    fd_set rdset;

    unsigned char input[128] = {0};
    unsigned char c='D';
    unsigned char l,pos;
    //10 2 0 5 0 20 0 20 7F 0 D6 10 3 Lights Off
    unsigned char lightsOff[] = {0x10,0x02,0x00,0x05,0x00,0x20,0x00,0x20,0x7F,0x00,0xD6,0x10,0x03};
    //10 2 0 5 20 0 20 0 7F 0 D6 10 3 Lights On
    unsigned char lightsOn[] = {0x10,0x02,0x00,0x05,0x20,0x00,0x20,0x00,0x7F,0x00,0xD6,0x10,0x03};

    // 10 2 0 5 2 0 2 0 7F 0 9A 10 3 Filter On
    unsigned char filterOn[]= {0x10,0x02,0x00,0x05,0x02,0x00,0x02,0x00,0x7F,0x00,0x9A,0x10,0x03};
    // 10 2 0 5 0 2 0 2 7F 0 9A 10 3 Filter Off
    unsigned char filterOff[]={0x10,0x02,0x00,0x05,0x00,0x02,0x00,0x02,0x7F,0x00,0x9A,0x10,0x03};

    // 10 2 0 5 10 0 0 10 0 0 7F 0 B6 10 3 Sweeper On
    unsigned char sweeperOn[]={0x10,0x02,0x00,0x05,0x10,0x00,0x00,0x10,0x00,0x00,0x7F,0x00,0xB6,0x10,0x03};
    // 10 2 0 5 0 10 0 0 10 0 7F 0 B6 10 3 Sweeper off
    unsigned char sweeperOff[]={0x10,0x02,0x00,0x05,0x00,0x10,0x00,0x00,0x10,0x00,0x7F,0x00,0xB6,0x10,0x03};

    // 10 2 0 5 8 0 8 0 7F 0 A6 10 3 Waterfall On
    unsigned char waterfallOn[]={0x10,0x02,0x00,0x05,0x08,0x00,0x08,0x00,0x7F,0x00,0xA6,0x10,0x03};
    // 10 2 0 5 0 8 0 8 7F 0 A6 10 3 Waterfall Off
    unsigned char waterfallOff[]={0x10,0x02,0x00,0x05,0x00,0x08,0x00,0x08,0x7F,0x00,0xA6,0x10,0x03};




    FILE *fp,*pooltemp,*poolsalt;
    fp=fopen("/tmp/pool-serial.out", "a+");
    //setlogmask (LOG_UPTO (LOG_NOTICE));
    openlog ("pool-lighs-on", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);

    //printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
    memset(&stdio,0,sizeof(stdio));
    stdio.c_iflag=0;
    stdio.c_oflag=0;
    stdio.c_cflag=0;
    stdio.c_lflag=0;
    stdio.c_cc[VMIN]=1;
    stdio.c_cc[VTIME]=0;
    tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
    tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking




    memset(&tio,0,sizeof(tio));
    tio.c_iflag=0;
    tio.c_oflag=0;
    tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
    tio.c_lflag=0;
    tio.c_cc[VMIN]=1;
    tio.c_cc[VTIME]=5;

    tty_fd=open(argv[1], O_RDWR | O_NONBLOCK);
    cfsetospeed(&tio,B19200); // 115200 baud
    cfsetispeed(&tio,B19200); // 115200 baud

    tcsetattr(tty_fd,TCSANOW,&tio);
    i=0;
    pos=0;
    while (c!='q')
    {
    if (read(tty_fd,&c,1)>0){ // if new data is available on the serial port, print it out
    //fprintf(stdout," %x", c, pos); // print out data as it arrived
    if ( l == 16 && c == 3) { // end of command ready for sending
    // insert your own logic here
    write(tty_fd,&filterOff,sizeof(filterOff));
    c='q';
    }
    }
    l=c;
    }
    fclose(fp);
    close(tty_fd);
    closelog ();
    }

    ReplyDelete
  13. Awesome, thanks! I tried pin 1&2, and pin 3&4, but not 2&3...Interesting that you are grounding p4.

    ReplyDelete
  14. Here are my stats for my Pool http://mccoy-racing.com/wq/ I am using CO2 injection based on my PH. I am using a PH probe and ORP probe from Phidgets with their boar that converts to voltage. I am using a DS2450 on my One Wire bus using OWFS to convert the Voltage from the Phidgets board to PH. Seems to be working quite well with the controls sent to the AQL-P4. I am also using a Hitachi X200 VFD to drive a 3 phase motor connected to my old WisperFlow WFE-3. I ordered a 355201S from www.thepoolguystore.com for $151.32 a bargain compared to the VFD pump from Pentair. I have not setup the ModBus stuf for the Hitachi X200 yet but I am driving the dry contacts from the Parallel port and its working great all day long @ about 20 HZ.

    ReplyDelete
  15. I also do not ground it. I have the same pins otherwise. Middle two connected the two outside pins left open.

    You can tell why I used an Arduino, the board and its 485 converter both fit in a duplex outlet box. Makes it easier to place on the wall. These little arduinos boot in a couple of seconds so a watchdog timer to reboot when it has trouble doesn't present a problem.

    I'm starting work on an acid injector. My thinking is that acid is easy to get and an injection pump is simple to maintain over time. I expect to put a ph probe in the mix in a couple of months, but I've got about three other projects in front of it.

    pinMode(dirPin, INPUT);
    digitalWrite(dirPin, HIGH);

    The lines above are solely to enable the internal pull-up resistor on the digital pin. You set it to input, then set it high and it enables a pull up resistor.

    pinMode(dirPin, OUTPUT);
    digitalWrite(dirPin, LOW);

    This is the control for the pin itself. The dirPin (Direction Pin) switches between rx and tx on the half-duplex 485 board. In this case I'm setting it to receive.

    I took a different tactic on the pool. Instead of controlling it directly from the internet, I control another box that in turn, controls the pool. The other box also has controls for the A/C, and other stuff. I use that box to update Pachube and it has a display to tell me what's going on when I'm in the house. This way I can put timers on the second box to turn on the pool lights and such without worrying about how much memory I've used up on the little arduino.

    ReplyDelete
  16. I am having no luck. Two strange issues (note, I have no problem communicating to other device using my micro controller and serial)...

    1) I am getting nothing. I have things configured like you do (19200 baud, etc). I have wired the direction pin to ground, for now, I am only receiving, not sending. I have the RS485 board you have configured the same way you do in your above picture (the picture that also shows the Adruino).

    Next step, I will try going to my PC serial directly to see if I see anything, I suspect I will not

    2) When I have pin 2 and pin 3 connected to the RS485 board, and that board connected to my micro controller, which is then connected to my computer, via USB, I am getting a slight shock when touching the metal on my computer. Very strange...(not, the USB is powering the microconroller, thus the RS485 board).

    ReplyDelete
  17. That's weird. You're using the plug on the upper left of the P4 correct? That plug has an AC voltage on it of something or other to power some of the add on devices, but you shouldn't be getting anything from the two middle pins like you are experiencing.

    The way I tested the setup was to run a wire pair about 60 feet from the pool controller through my back door to the Arduino on my kitchen table. I was set up this way for a couple of weeks trying things. I had completely different luck, I only had to reverse the wires in the very beginning and I started getting data. Once I tried a few different baud rates I got data I could read and went from there.

    I'm actually set up exactly like the picture. I power the 485 board from the arduino and power the arduino from a 5V wall wart I picked up on eBay. I do not use pins 0 & 1 on the arduino, those are hooked to an XBee I have in the box for RF control. When I was testing it I used the usb connection to see the data.

    I'm at a loss on what could be causing your problem with the little shock.

    ReplyDelete
  18. I'm trying to work out the protocol of my Pentair Inteliflow VS pump while connected directly to an RS-485 shield of an Arduino, but I don't see any messages at all over the serial port. I suspect that my pump needs to be actively polled with a valid request before it will send anything.

    Does any of your other pool equipment have RS-485 ports, or is your Goldline controller the only device sending RS-485 communications?

    ReplyDelete
  19. I have the controller, motor and remote control sending commands. I'm using the Hayward motor and it has to be set to "Remote" for it to respond to the 485 port. I haven't tried to decode its protocol yet because the Goldline is doing it for me. I don't have a clue what the trick is to getting the Pentair to talk over the serial, but it may be the same kind of thing.

    ReplyDelete
  20. Ok, after further experimentation (my free time is limited), I am getting @12 Volts out of the RS232 TxRx pins, so my RS485 line driver must be misconfigured.

    I will have to look at the documentation to see what the heck I am doing wrong.

    ReplyDelete
  21. Where the heck are you getting 12V from? When I was hooked to my laptop I most I had running around was a little under 5V from the USB port.

    ReplyDelete
  22. I am supplying 5 volts. The pins from the Goldline were not 12 volts (obviously they fluctuated, but one pin was like 3v, the other was -3v or something). The Mini RS422 board (same one you use, same configuration) was outputting 12V through RX/TX (what is meant to connect to my MCU). Something is messed up here, I have ordered another RS232 to RS486 converter (I assume the one I ordered isn't RS232 TTL, but I have board for that separately).

    ReplyDelete
  23. Nice write up, thanks. Did my residency in Phoenix and can relate to viewing the swimming pool as an essential home appliance. Dont know if this "Industrial Liquid Level Sensor" might help but its surplus and only $8:
    http://www.goldmine-elec-products.com/prodinfo.asp?number=G17844
    Sounds like it toggles off when full so it may be bass ackwards for your needs. Enjoy the winter!

    ReplyDelete
  24. That thing is cool. Thank you. I don't think it will work for the acid injector, but there's this water softener that I keep forgetting about out in the garage. For eight buck and a light I can see when I drive into the garage.....

    ReplyDelete
  25. Excellent work!

    Regarding the communications protocol, I believe these are the specifications that would have simplified your efforts: http://www.hayward-pool.com/pdf/manuals/Manual343.pdf

    I agree that it is a poor protocol, e.g. button presses and display scraping!

    Cheers,
    John

    ReplyDelete
  26. Thanks for the link. When I want to add something, I'll dig into it. For now, I got so fed up with the silly way it worked I decided any changes can wait a year or two.

    It's probably the most annoying protocol I've ever worked with.

    ReplyDelete
  27. i was under the impression that the prot in the hayward link was the hex that came out via 232 "after" it goes through the $200 hayward adapter... i thought that it had some microprocessor that simplified it...

    ReplyDelete
  28. I'm not really sure what the heck the Hayward adapter actually does. The protocol from the controller itself matches pretty closely the protocol from the adapter. So, that doesn't leave it much to do except maybe level conversions, timing correction or something.

    I'm not willing to pay their price to find out either.

    ReplyDelete
  29. Really enjoy your site. I am working on a much smaller project controlling my pool. Wondering if you could give some advise.
    Question: Do you have arduino turn off and on your pool pump. If so what kind of realy do you use?
    Kenny

    ReplyDelete
  30. I control a Goldline pool controller with a device I made that tells it what to do, so I don't directly control the pool motor. However, I have looked at doing this a lot and plan to in the future because I just don't like having something in the middle that doesn't let me do what I want to do.

    Regarding your question about which relay, it would depend. For example, if you have one of those new variable speed motors, you can use a small relay that carries as little as an amp. If you are controlling one of the single speed motors, you need a bigger one. There are a thousand (or more) possibilities, so what you do is check the current draw of the motor and the operating voltage. You'll need a relay that has contacts rated for that. Then, you need to decide what will power the relay itself. If you're going to use an arduino, it can only supply 30ma at 5V, so you will have to have something that can go between the arduino and the new relay. If you're going to do something different, drop a hint here and we can discuss it a bit to get you started.

    ReplyDelete
  31. hi, how you did install Ph Sensor into the pipe?

    ReplyDelete
    Replies
    1. I don't use a Ph sensor. When I went looking I couldn't find one that didn't need constant calibration and would last more than a year before having to be replaced. So, I know that it will take about three cups every two days in the winter and I set the acid pump up to supply that amount as the default. Then I check the pool every few days to see what the Ph is, and if it needs more acid, I just turn the pump on for an extra cycle.

      However, if I ever run across a sensor that will do the job, I'll put in a piece of 6 inch PVC and mount the sensor through the side of the new piece of pipe.

      Delete
    2. This comment has been removed by the author.

      Delete
  32. even such one need to replace every year?

    https://www.atlas-scientific.com/product_pages/kits/ph-kit.html

    ReplyDelete
    Replies
    1. Their sensor is the most likely to work that I ran across when I was looking. They specifically say that it can remain in solution indefinitely, which gave me some hope. However, they also have a data sheet where they specifically talk about the sensor aging. In the data sheet they describe how to test for aging and how to recondition the sensor. It seems even with reconditioning, the sensor can age out of range and have to be replaced.

      Since they don't cite any times and conditions to use as a guide for an aging sensor, I decided the expense wasn't worth the experiment.

      The various pool equipment manufacturers are building Ph automation equipment, and they may well come up with a way of doing measurements long term. If they do, I'll look into it again, but for now, I'll just walk out and check it every few days.

      Delete
  33. I've been looking at building a web interface to the Goldline equipment too. As part of my research I put my logic analyzer on the microcontroller side of the generator board RS-485 chip and recorded the Tx and Rx data streams as I sequentially pressed the buttons on the control panel. Links to these data dumps are at the end of this post.

    I haven't had time to look at the data in detail, but I have noticed a couple of interesting things. First, what you call the keep alive packet is generally transmitted every 100ms. It also appears to be the trigger for the control panel to send button data back.

    Second, there are packets with framing errors. I'm not sure if this a glitch in the code the analyzer uses to decode the serial data or actual bad data from the Goldline. I'm leaning toward the latter.

    When looking at the files in the links below, I pressed the buttons in this order:
    left arrow
    service
    menu
    right arrow
    down arrow (-)
    up arrow (+)
    pool/spa
    filter
    lights
    aux1
    aux2

    https://www.dropbox.com/s/blzq3wkuv5hufda/Sample%20Tx%20data%20stream.txt

    https://www.dropbox.com/s/4o53w3oag0v2m99/Sample%20Rx%20data%20stream.txt

    The entire 10 second logic analyzer capture is contained in the following file. You will need to install Saleae Logic 1.15 (www.saleae.com)to open it.

    https://www.dropbox.com/s/q7us48x0mp8b6ge/Goldline%20data%20dump.logicdata

    Hope this helps your effort,
    Colin

    ReplyDelete
    Replies
    1. Thanks Colin, I haven't got the time to look at it right now, so I'll copy the files for later. There are other folk out there that come by from time to time to figure out how to control these things as well, maybe they'll have a breakthrough and let us know.

      Delete
  34. Hi Dave,
    I wrote a quick test routine that talks reliably to the goldline: https://www.dropbox.com/s/ke5aqpp9dedubt6/RS485.cpp

    This code is for a netburner nano, but should be portable to other platforms. The button strings are extracted from an 11 button, 2x16 character display topside control.

    One thing to notice is the delay between receipt of the "keep alive" and the sending of button data. There needs to be at least 0.5ms or the controller doesn't recognize the data sent to it.

    ReplyDelete
  35. NICE JOB !! With the data you show it is now totally possible to completely control one of these remotely. Over the years I've had this thing I've become more and more disappointed with it. For the price, they could have done so much more with it, including a network interface complete with wifi interface. I guess the swimming pool industry will just lag behind the times...

    I suspect the reason for the delay being required is that it takes that long for the controller to switch from send to receive on their half duplex chip.

    Thanks a lot for sharing this.

    ReplyDelete
  36. Hi I was reading your thread in the Arduino forum and thought it might help with my project talking to my power-one inverter that uses rs485. I have a dfrobot rs485 shield so the programming will be different, but I need a base to start from so I have copied your sketch and will have a look at it. Thanks Chas.

    ReplyDelete
    Replies
    1. Don't let the complexity of the code scare you away. The problem I faced was that the controller sends a constant stream of data at 19K. That means I can't actually do anything to it but gather data and then wait for a certain message to fly by and then shove the data out as fast as I can. That means I get characters one at a time, save a buffer, process it, etc ... really a painful way to do it.

      But it works. So, steal anything you want and use it for an example. Hope it helps.

      Delete
  37. Thanks Dave, I am trying to find all the bits of sketches to understand Arduino programming hopefully this will help me on the way. Programming is not my strong point but once I understand how it works I modify to my needs. :-)

    ReplyDelete
  38. Hi ,
    My name is Chris from Monteal and I have a question for you .
    I have a SwimPurePlus salute chlorination system and I wan to know if it possible to send commands on the 485 protocol to change the "function" ,ex: from OFF to AUTO or FROM OFF to super chlorination.
    Thanks ,
    Chris

    ReplyDelete
    Replies
    1. I suspect it's possible to control it in some fashion, but I've never experimented with one of them. Give it a try and see if you can catch any packets going to it.

      Delete
  39. I would love to get a swimming pool soon. I think it would be nice if we could go outside on a hot day and jump in the pool. I have a real problem with the summer months. How much money does it take to get one of these started? http://dolphin-pools.com/pages/pools/

    ReplyDelete
    Replies
    1. I'm going to assume that this isn't spam and actually answer it. The answer is "it depends." Pool prices vary by region and by what you want in it. Is it square? potato shaped? etc. These things all contribute to the price. However, go for a pool with the very basic timer controller, not a big fancy thing, Do not get a salt pool with chlorinator on it. Only pay for basic valves.

      All that cool stuff can be added at 1/10 the cost they'll quote you. Chlorinators don't work worth a crap, If you wan the nice feel of a salt pool, simply add salt, it doesn't hurt anything. Get a simple filter you can back flush, you'll thank me later.

      Spend a little as you can on the fancy upgrades and add them yourself over time. That will save you at least 5K on cost. Yes, this includes solar heating. Take the advice of someone that has already been through the mill.

      Delete
    2. We R WhoThe Manuf Call.January 30, 2017 at 9:36 PM

      " Chlorinators don't work worth a crap, If you wan the nice feel of a salt pool, simply add salt, it doesn't hurt anything"

      I beg to differ.1. Salt is not what changes "the nice feel". The difference, is the type of oxidizer you are using to sanitize your pool.Chlorine is need in much higher concentrations than what a salt cell produces. Which is sodium hypochlorite. That is much gentler on your skin,hair clothes.ect... It does not leave that dried out, sticky feel that CL does. The salt is only there in a very low concentration(3500 ppm)to facilitate electrochlorination. It also has a much lower ph level. 2. And is easier to maintain and stabilize. Maximum ph is 7.8. of course there are pros and cons. But they are more than just a useless up sale. I am a technician in central Florida that specializes in warranty work for Pentair, Hayward and Jandy/Zodiac. We go to continued education classes for all 3 + some, on a reg. basis We specialise in Automation, wireless,remote apps. salt systems variable speed pumps, gas heaters, gas fire features,Water features, colored light, sophisticated on site fabrication/migration, and dabble in chemistry as needed to perform our job efficiently etc..
      I would be happy to answer any questions I can, or offer help/opinions based on my job experience. We are also one of the largest solar companies, for pool heat, DHW, and PVR. Have a blessed night guys.
      Steve

      Delete
    3. We R WhoThe Manuf CallJanuary 30, 2017 at 9:46 PM

      Sorry if this was off topic.
      Steve

      Delete
    4. Steve, thanks for the comment, but for people using well water in limestone rich areas, they totally are a useless up-sale. And, the slinky feel of the salt water is totally due to added chemicals like ... salt.

      Otherwise, the ocean wouldn't feel nice. There's no electrical chlorinator at the beach. The very fact that folk have to call you out to fix their chlorinator is a bit of a testimony to the reliability of the devices as well. I had to replace the chlorinator head every three years because it wore out. That's $500 bucks all by itself. Cartridge filters that plugged up with the white calcium build up created on the plates ran almost $400 a year.

      Jut using a simple float in the pool with some chlorine tablets from Walmart costs me about $75 a year, and no troubles from the side-effects of the chlorinator to fight.

      Electrical chlorinators may be really good for your business, but not for my back yard.

      Delete
  40. Hi Dave thanks for the awesome write up on your trials and tribulations. I saw that in 2012 you mention the desire to design your own system from the ground up and remove the Goldline controller.I have a pool that is about six months old and was installed with only electrical and mechanical controls, no automation whatsoever. A friend of mine and I like to tinker, Have some electronics electrical and programming ability and were thinking about designing an Arduino based pool controller.we were then talking about integrating it with the home automation system that already has Wi-Fi Bluetooth and smart phone GUIs for the interface. I was wondering if you were familiar with anyone who has done anything like that or had any resources in your vault for that type of thing?we will of course share our plans and ideas to help anyone else who wants to make some changes.
    Happy tinkering!
    Antonio

    ReplyDelete
  41. I've thought about this a lot and think I can come up with a nice way to do it. My one remaining problem is finding the right transformer to supply power that doesn't cost as much as everything else in the project combined.

    Take a look at the 'about me' link on the right and send me an email so I can tell you my thoughts directly. It would get too long to do in a reply.

    ReplyDelete
  42. Watson ! This is OUTSTANDING

    ReplyDelete
  43. This is an excellent write up! I am looking to control my Aqualogic PS-4 using Smartthings instead. Playing around with the Photon and then the arduino on a ST shield. The code is very helpful and if there are change, I will let you know. By the way, which connector on the PCB did you use to connect to the RS422? The green terminals or the JST connectors onboard? Thanks!

    ReplyDelete
    Replies
    1. I just screwed down a couple of wires to the green terminals. I'm lazy like that.

      Delete
  44. Hi Dave,

    Thanks for your work on the hayward pool controller over the years. I just stumbled on this page as I intend to control my system from pc/phone through either an arduino / r-pi. While reading to the comments, many people shared some sample code which was used to improve protocol decoding over the years. Many of these links to dropbox pages don't work anymore. I felt like your arduino sketch predated the more in depth protocol analysis. Do you happen to have a more recent version you are willing to share?

    ReplyDelete
  45. Great work! I plan to decipher the protocol and I am glad you and a few others have done it already! I live in Phoenix, AZ as well so I understand the importance and fun of home automation.

    In fact I've done wifi thermostat and power meters as well based on ESP8266 and MQTT. My next step is to build a RS485-Wifi bridge with ESP8266 in order to control my Goldline controller remotely. It would be nice to chat with you in person when you get a chance.

    Cheers,

    ReplyDelete
    Replies
    1. Look over on the right in the 'about me' area. My email address is cleverly disguised there.

      When I first started this project wifi was expensive and horribly unreliable. I tried it and just gave up. I have wired devices and a ton of XBee things running and I've had really good success with them. I seriously doubt if I'll go to wifi as a normal thing anytime soon; my internet connection goes down too often. Plus, I've had problems with the Wemo switches I have around the house because they disconnect and do strange things from time to time.

      Zwave is a real possibility though.

      Might I suggest that you seriously about just replacing the goldline with a device of your own. The silly thing just doesn't offer enough for the huge price they ask for it. I know, you've already spent the money, and want to get some value out of it. I'm in exactly the same boat.

      Delete
  46. Thanks for relying Dave... I agree XBee or Zwave are both good alternatives ... in fact my SRP power meter is ZigBee capable but SRP hasn't turned it on. PG&E customers California do have the ability to communicate with their meters if they purchase a receiver... SRP will probably open it up soon.

    Now the only reason I chose Wifi and ESP8266 is its price point relative to its function -- 1.5 bucks and you get a SOC programmable with Arduino IDE. It did serve me will but I also found its limitations -- I made a board that intercepts my Honeywell thermostat control signals and I put it in the attic. The board has a temp sensor and I found as soon as the attic temp reaches 120F the board shuts off. It has been very predictable. Later I was forced to relocated it beside the thermostat and it works fine.

    I also agree with you on replacing Goldline all together. It was inherited from the last pool owner and has been working reasonably well, except the board malfunctions when the temperature drops close to freezing. The pump would keep running and the buttons stop responding. IF Goldline can't stand the cold here, it will definitely do poorly in other states.

    One question for you is about the above mentioned P4 RS485 socket. I found a 4-pin male wireless socket and 2 4-pin male COMM socket on Goldline board. The wireless socket connects to the Hayward RF base "AQL2 Base RF" with RED, ORANGE, YELLOW and PURPLE wires. Any idea what these wires are? I plan to build a RS485 - Wifi bridge with ESP8266 and it seems there is a power wire in them that I can use to power ESP8266 as well.

    Also I plan to connect the base with a PC through a 485-USB adapter and analyze the protocol with a PC just in case Hayward has changed it since you did the deciphering.

    Cheers,

    ReplyDelete
    Replies
    1. I have the RF adapter that plugs into the port you mention; it isn't wifi, it's some radio transmitter I haven't looked into. It communicates with a proprietary remote control that I have in the house. Seldom us it anymore, but just in case... They probably use wifi now; I haven't looked in a while.

      I don't know what the pin outrs485 is, but I'v been told that it's also rs485. I don't believe that.

      The protocol has not changed, but it has been extended to support more motors and heaters and such. Hayward (after they bought goldline) added their stuff into the mix. That means it's even more messy than it was back in the day.

      I've lost the board entirely once, had the power supply solder points fail twice (I didn't fix it good enough the first time), but it seems solid for the temperature range out here. I also talked Hayward into reprogramming the board for me when I installed the new variable speed motor.

      I like the idea of a USB to 485 adapter, but I went with the arduino because it was what I had around. My goal was to eventually gut the P4 and only save the power supply and use a little computer in place of the big complex board they put in there. Since then, I've pretty much given up on that idea in favor of a smaller control system I actually control with a tablet of some kind.

      Delete
    2. The RF adapter is exactly what I am trying to replace with an wifi bridge with. If the interface is indeed rs485 that'd be great! Replacing P4's board while keeping its PSU, relays and terminal blocks is a good idea. I will have to test the weather tolerance of my Wifi board before implementing it.

      Another alternative to control P4 that I can imagine is to use its wireless remote and directly toggle its keys inside with GPIOs from a MCU. Have you tried that? It would totally eliminate the need to understand the protocol and be future-proof.

      BTW which ZigBee module are you using for the project? My understanding is that it is a mesh network so you have to configure the (potentially multiple) senders and receivers? Also I try to be compatible with the meter's protocol for future connectivity. Here is the link to it:
      https://www.pge.com/en/myhome/addservices/moreservices/streammydata/faq/index.page

      Delete
    3. I use series 2 or 2.5 XBees because I have a bunch of them from projects over the years. There's a new version that should be better out now, but I haven't tried it yet. The power company uses pretty good security in their transmissions that requires the device you use to talk to it be included in their records. I don't know all the details, but you might have to get a device that they approve and then translate the data from there to your own device for analysis and such.

      There's been mixed results setting up an XBee network, I have no trouble at all and many others have done it. Then there's the folk that just can't seem to make it work. Basically, you get 50 feet or two walls from the little wire antenna ones, and if you need a relay to get greater distance, just hook another XBee to a wall wart and you're done.

      Initially when I only had a couple of them I had to make a relay to get the XBee farthest away to the controller I was working on. It took me about 15 minutes to make one. I have enough now that it's no problem at all. The XBee handles all that without intervention.

      I have not tried to simulate the buttons on the controller, but it should be reasonably easy to do. My objection is simply that the controller is limited and I can do better if I finally get off my butt and actually do it instead of procrastinating.

      Delete
  47. 2nd year trying to get this to work and re-started the project with the exact same parts using Arduino Uno and RS-485 described here. I can read successfully from the controller once I figure out that my command code is 8C and not 83 as in the original code. I have tried for days and unsuccessful at writing a command back out. I changed dirPin from 9 to 13 so that I can see it blink and nadda. I h ave tried delayMicroseconds(500) as someone has suggested and still nothing. I am wondering if anyone here might be able to shed some light? I went as far as ordering another RS-485 to test and same result. Thanks!

    ReplyDelete
    Replies
    1. I had this problem when I first started trying to talk to the controller. I did what you did, I tried new parts to see if it was a hardware problem. Then I realized that I had enough hardware to set up a monitor and watch what I was sending (if anything) and what the pool was sending at the same time.

      So, I put an arduino and 485 together and watched the wires with it. It couldn't send, it could only receive and shove what it saw out the serial port so I could watch the activity. Then I brought up a terminal program (putty) to watch that arduino and started poking data from the other one using the arduino development software.

      I only had one laptop to do the development with so this meant I had to hook up a usb hub to plug everything into. My kitchen table was covered with two arduinos, the laptop, the hub, power supplies for all this stuff. Trailing off it was an extension cord to the wall and a set of wires leading out the door, across the yard, and up to the pool controller.

      But it helped me monitor what the heck was happening. Now that you have the hardware, give it a try.

      Delete
    2. This comment has been removed by the author.

      Delete
  48. Hi,
    Has anyone tried to decode the protocol between the Hayward controller and a Hayward Goldline Aqua rite? I have been trying to figure out but the frames between both seems to be very different. I am using a OnCommand that is connected to the Aqua Rite. So far I have not been able to get a reply from the chlorinator with the frames I have capture.
    Cheers,
    Fred

    ReplyDelete
    Replies
    1. Sounds like you have something set up to monitor it; if so, do you see the frames for controlling the motor? If you see those you should be able to pick out some of the frames sent to the chlorinator. It really doesn't matter if they're very different, just that you can see them. I started out not knowing anything about the interaction and with some judicious button pushing and watching managed to get a lot of it decoded.

      Don't give up.

      Delete
  49. Hi,
    I think I found the frames going to the Aquarite. What I do not understand is that they keep changing. It looks like they do not follow at all the 1002 start and 1003 end.

    So I disconnect the Oncommand and only keep the USB RS485 attached to the Aquarite but I have not been able to get any response back from it. I also tried to only unpower the Oncommand (to keep it on the RS485 bus as when I attached the scope to it I found that the RS485 voltage from my adapter was higher probably because there was not end of line resistor). I have ordered another RS485 adaptor so I can bridge them to be sure what is the source for each stream that I capture. Will get in on Monday.

    I also tried to capture the packets when Chlorinator is disconnected from power source to see the difference and I see that the packets that I suspect to be addressed to the Chlorinator are shorter.

    Here is what I have captured when Chlorinator is connected to OnCommand and I poweron the Oncommand until I see the "externally controlled" led on the chlorinator. To make it easier I disconnected the LCD of the OnCommand on the RS485 bus so I get less data.

    If you have any idea it would be great! I just don't undestand that I am not getting any reply from it when trying to emulate the communications. I am thiking that maybe I should try to write something to send the stream automatically and see if it's going to work.

    10 02 02
    09 00 1d 10 03
    10 02 01 01
    00 14 10 03
    0
    c1 18
    80 00 99 00 18 9e 00 c1 1e 00 00 81 18 80 00 06 80 00
    00 1e 60 00 60 00 10 02 01 02 04 00 00 00 00 00
    00 00 00 19 10 03 10 02 01 03 20 20 20 20 20 20 44 65 66 61 …
    20 20 20 20 20 20 20 20 20 20 20 20 4d 65 6e 75 20 20 20 20 …
    10 03 10 02 01 01 00 14 10 03
    10 02 01 02 00 00 00 00 00 00 00 00 00 15 10
    3
    10
    02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10
    02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10
    02 01 01 00 14 10 03
    10 02 04 07 00 1d 10 03
    10 02 01 02 00 00 00 00 00 00 00 00 00 15 10 03 10 02 01 03 …
    20 44 65 66 61 75 6c 74 20 20 20 20 20 20 20 20 20 20 20 20 …
    20 20 20 20 20 20 20 00 08 10 00 10 03
    10 02 01 01 00 14 10 03
    0
    e0 18
    80 00 e6 06 e0 fe 80 18 e0 00 81 1e 80 00 60 0c c0 00
    18 60 00 06 00 60 9e 00 c1 1e 80 10 02 01 02 28 00 00
    00 00 00 00 00 00 3d 10 03
    10 02 01 01 00 14 10 03
    10 02
    01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02
    01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    0
    e0 18
    80 00 d9 06 03 fe 80 18 e0 00 c1 1e 00 00 60 0e c0 00
    18 03 00 06 00 60 9e 00 60 0f c0
    10 02 01 01 00 14 10 03
    10 02
    01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02
    01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02
    01 01 00 14 10 03
    10 02 01 02 28 00 00
    00 00 00 00 00 00 3d 10 03 10 02 01 03 20 20 20 20 20 20 44 …
    20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 4d 65 6e 75 20 …
    08 10 00 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02
    01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03

    ReplyDelete
  50. And this is the capture with the Chlorinator disconnected (power on the Oncommand while Chlorinator disconnected).

    So I was under the impression that the data to chlorinator was

    Capture
    10 02 02 09 00 1d 10 03
    10 02 01 01 00 14 10 03
    00 e0 18
    80 00 99 00 18 9e 00 e0 1e 00
    10 02 01 02 04 00 00
    00 00 00 00 00 00 19 10 03 10 02 01 03 20 20 20 20 20 20 44 …
    20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 4d 65 6e 75 20 …
    08 10 00 10 03 10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10
    02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10
    3
    10 02 01 01 00 14 10 03
    10 02 04 07 00 1d 10 03
    10 02 01 02 04 00 00 00 00 00 00 00 00 19 10 03 10 02 01 03 …
    20 44 65 66 61 75 6c 74 20 20 20 20 20 20 20 20 20 20 20 20 …
    20 20 20 20 20 20 20 00 08 10 00 10 03
    10 02 01 01 00 14 10 03
    10 02 01 02 2c 00 00 00 00 00 00 00 00 41 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10
    02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10
    02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    0
    81 18 80 00
    e6 00 18 9c 00 c1 1e 80
    10 02 01 01 00 14 10 03
    10 02 01 01
    00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01
    00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01
    00 14 10 03
    10 02 01 02 2c 00 00 00 00
    00 00 00 00 41 10 03 10 02 01 03 20 20 20 20 20 20 44 65 66 …
    20 20 20 20 20 20 20 20 20 20 20 20 20 4d 65 6e 75 20 20 20 …
    00 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01
    00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01
    00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    0
    e0 18
    80 00
    cd 00 18 bc 00 81 1e 80
    10 02 01 01 00 14 10 03
    10 02 01 01
    00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00
    14 10 03
    10 02 01 01 00 14 10 03
    10 02 01 01 00 14 10 03

    ReplyDelete
    Replies
    1. I see what you mean. I'd try to see what is causing the line breaks in the 10 02 ... 10 03 packets, then I'd filter them out to get them off the page to condense the data I have to look at. I also see the 'Default', 'Menu' going out over and over again, so you can probably discount that.

      You've obviously got some bit patterns going on with the changes from 80 to c0 and such, that may give you a clue if you change some settings and see what happens to the data.

      Your problem with replaying the packets may be timing. There's a window after the 10 02 01 01 ... 10 03 packet where things don't listen. I judged it to be about 50 milliseconds or so back when I messing with it. You might put some code together to wait after the packet for 50 milliseconds and then send the replay. If that doesn't work, fudge it one way or the other to see what happens. There is some timing there since this isn't full duplex and you'll have to fit your stuff in there somewhere.

      One other thing that might be worth trying is to pull the controller off so only you are connected to it and just send some of the recorded packets to see what happens. It can get really confusing when the controller is constantly sending things down the wire to mess up what you're trying to look at. An awful lot of these devices wait for the controller to do something before they do anything themselves. The idea is that the controller has to be active or they just shut down and do nothing. The variable speed motors are that way.

      Delete
  51. Hi,

    For the timing thing do you know any software that I should use to capture things with timings? That would help a lot. I am using Monitor device righ now and found also a aquadisplay.py. Both looks the same. I also capture rax data with minicom, used xxd to convert it and some awk & sed to display it better. Only thing I see that seems to be only there when Aquarite is enabled is the frames that are not starting with 10 02 and ending with 10 03. I get this from all the software I used (windows or on the PI).

    I am going to get an extra RS485 adaptor and will try the bridge mode. That way it should be clear what's coming from OnCommand and Aquarite.

    I have tried to disconnect the LCD display with buttons (which is RS485) to have less messages. Strange thing is that I still get the default menu.

    I have tried to send many of the commands directly (PC to Aquarite without Oncommand and with Oncommand but Oncommand un powered). I never get a single frame back from Aquarite. T

    he only thing I see on the line is what I am sending. Will see with the other adapter shortly.

    Here is the capture of the data between Oncommand and Aquarite without the LCD panell connected at the Poweron of the Oncommand.

    Cheeers
    Fred

    00001239 2016-09-18 12:18:15.2516389 +0.0000085 IRP_MJ_READ UP 0x00000000 10 02 01 01 00 14 10 03 ........
    00001250 2016-09-18 12:18:15.2663260 +0.0000055 IRP_MJ_READ UP 0x00000000 00 e0 18 ...
    00001274 2016-09-18 12:18:15.2806630 +0.0000073 IRP_MJ_READ UP 0x00000000 80 00 d9 00 18 9e 00 c1 1e 00 00 c1 18 80 00 06 80 .................
    00001290 2016-09-18 12:18:15.2965166 +0.0000026 IRP_MJ_READ UP 0x00000000 00 00 1e 60 00 60 00 10 02 01 02 04 00 00 00 00 ...`.`..........
    00001303 2016-09-18 12:18:15.3125345 +0.0000021 IRP_MJ_READ UP 0x00000000 00 00 00 00 19 10 03 10 02 01 03 20 20 20 20 20 20 44 65 66 … ........... Def…
    00001311 2016-09-18 12:18:15.3285217 +0.0000017 IRP_MJ_READ UP 0x00000000 20 20 20 20 20 20 20 20 20 20 20 20 20 4d 65 6e 75 20 20 20 … Menu …
    00001319 2016-09-18 12:18:15.3445277 +0.0000022 IRP_MJ_READ UP 0x00000000 00 10 03 10 02 01 01 00 14 10 03 ...........
    00001327 2016-09-18 12:18:15.3765182 +0.0000025 IRP_MJ_READ UP 0x00000000 10 02 01 02 00 00 00 00 00 00 00 00 00 15 ..............
    00001335 2016-09-18 12:18:15.3926298 +0.0000022 IRP_MJ_READ UP 0x00000000 10 03 ..

    ReplyDelete
    Replies
    1. Actually, I do, sort of ...

      https://docs.influxdata.com/influxdb/v1.0/

      I haven't used this yet, but it come HIGHLY recommended for grabbing time series data and then looking at it to see what the heck is going on.

      I fully plan on installing this on something I have around here and using it to look at things like the Acurite weather station, some Zigbee devices I want to beat into submission and such. There is also a graphing tool that fits right together with it and can give you information in a chart form that could possibly help called Grafana.

      http://play.grafana.org/

      Like I said, these look like the perfect solution to some of the things I want to look into over time, and I'll definitely be prowling around in them.

      My thanks for this to one of my readers who doesn't like the idea of spreading his name all over the internet. I understand that; I had a bit of trouble with the idea myself back when I started this.

      Delete
  52. Hummm got it... Weird product this thing! The whole bus is running at 19200 BUT when it goes to the chlorinator it sends at 9600!!! So no wonder why it looked so weird! When I was setting at 9600 I had just junk or almost. At 19200 it's working well but the packet for the Chlorinator and from the Chlorinator made no sense and I was not able to send them back...

    I just tried to put my laptop in the middle with two USB RS485 adaptors. At 19200 there was just stuff from the Oncommand. I decided to bridge at 9600 and then voila I got couple of packets out of all garbage that made sense and I could see the chlorinator replying! Who could believe they just decided to use two different speeds for the same bus!

    Set at 15% (to chlorinator) 10 02 50 11 0f 82 10 03
    Reply from chlorinator 10 02 00 12 40 00 64 10 03
    So the 12 byte (0f) is the percentage directly converted...

    20%
    10 02 50 11 14 87 10 03
    10 02 00 12 40 00 64 10 03

    Superchlorinate:
    10 02 50 11 65 d8 10 03
    10 02 00 12 40 00 64 10 03

    Now I need to see where is the ppm coming back

    ReplyDelete
    Replies
    1. Serendipity ! I think you may have found something that will explain a bunch of problems that folk have been having decoding some of the devices out there. My question is: How the heck do they know when to change baud rates?

      Do they send to the chlorinator at 9600, then wait for a response before switching back to 19.2K? That's the only method I can think of. That also means they can't support unexpected error messages from the chlorinator, so they have to poll it somehow to check the status.

      I'm willing to bet they did that to hide parts of the protocol.

      Delete
    2. They send everything at 19200 and then changes the speed to 9600, sends the frame to the chlorinator which replies almost immediately and then continue at 19200.

      The only thing the oncommand gets back from the chlorinator is the salinity.

      For the chlorintator it seems that the Oncommand sends a kind of ping 10 02 50 00 62 10 03 and then the chlorinator responds with this 10 02 00 01 00 00 13 10 10 03. Not much use as even if I disconnect the chlorinator and reconnect it I can send the command to set the output directly without sending the ping.


      So each time I set the output I get the same reply: 10 02 00 12 42 00 66 10 03. The only two things that are changing are the 42 (which is the hex value for the salt that must be multiplied by 50 and that explaination was on the other site). and the checksum. If I stop the pump (and then the no flow light turns on) I still get the same reply. So it looks like I am not able to get any status other than the water salinity.



      There is one exception is if I remove the power from the chlorinator it sends this one or two times before it dies 10 02 00 12 40 20 84 10 03. I am surprised that I am not getting anything else like the amps, voltage, temp, etc. Maybe there is some other commands to send to retrieve those but the Oncommand was not fetching it. So will check on the other forum in case I find something.


      One interesting thing is the 10 02 50 11 ff 72 10 03 frame that comes from chlorinator when the pump is disabled.

      Delete
    3. There is one more thing. Yesterday I was not able to get any reply back from chlorinator when only my pc was connected. It was ok previous day and then when testing I found that I was connected on the gnd, tx+, tx- and the previous day the gnd and power was still connected to the oncommand.

      So for the chlorinator to listen and work with rs485 it needs to be fed +10.7v between the power and gdn! Strange that it needs to be fed with power but then it works!

      Delete
    4. I'm not sure I understand. rs485 is differential and the ground is to act as a shield of sorts. How are you feeding it 10.7 volts?

      Delete
    5. looks like my reply didn't work.

      the chlorinator rs485 has 4 connections rd485a, rs485b, gnd and power. my rs485 is connected to gnd and rs485a and rs485b. I need to connect power between gnd and power. without it nothing gets through! maybe the power feeds a resistor to raise a bias on the line I have not check. but it works

      Delete
  53. Has anyone thought of using Blynk http://www.blynk.cc/ to control a wifi enabled arduino like a wemos D1 mini https://www.wemos.cc/product/d1-mini.html? You could then control the pool and monitor it from your phone very easily.

    ReplyDelete
    Replies
    1. I've been asked to look into Blynk a couple of times and always give up on it after a bit of reading the documentation. First, I object to cloud services that I have to store data on. I want my data at home. Next, they're always missing some piece that I use around the house.

      Blynk is a cool idea and I wish them luck, but it's just not for me.

      Delete