Pentair Compool Hacking

The Discovery

One weekend in the very late summer my family and I went in our
backyard pool to enjoy one of the last chances of the season to splash
around in the backyard. The water was a little cooler than expected
and upon investigating we found that the solar heating had not been
working and that there was a mysterious "ERR 1" displayed on our pool
control panel in our house.

Given that this was a relatively new controller purchased this
millennium, I was a little disappointed by the cryptic error message,
but also hopeful that I would be able to find out something about it
online. Sure enought, I found
the Compool Cp3800
manual on the Pentair
website. It explained that "Err 1" was a problem with the water
temperature sensor, which was a plausible reason why the solar heat
was not turning on.

I learned a lot of other things from the manual than just how to
diagnose error codes. For example, there was support for a wired
spa-side remote as well as a telephone interface. One frustrating
thing about our current pool was that when we remodeled the pool, the
designer omitted a spa-side remote, something we used to have and
use. We did not realize this ommision until it was too hard to easily
correct. They suggested the workaround was to replace our brand new
and expensive pool control with an even more expensive model that
would support a wireless controler. Not wanting to spend more money
with this frustrating vendor who had not thought out the use cases
very well, we just left the system as it was, even though it meant
occasionally walking though the house wet to access the control panel
to turn the spa on.

With all
the Pentair
Compool information available, I was able to confirm that a new
controller would be required for the wireless controller. However, it
occured to me that whatever they were using to connect the spa side
remote or the telephone interface could be interfaces for a remote of
my own creation. Indeed, the manual included a wiring diagram showing
how the spa remote's switches could be made to control the users
choice of any four of 9 total options as well as a tenth spa-side
remote specific "heat boost" option not found on the main control
panel which had more precise temperature controls. There was separate
documentation on
the MOD-TELSPA
telephone remote control, which allows a user to call to their home
phone and dial SPA or HTR to turn on the spa or heater
respectively. The telephone module seemed a more restrictive interface
with a less documented connector to the power center circuit
board. However, alongside the documentation was information on another
extension module for the Compool Cp3800 called
the MOD-RS485.

The MOD-RS485 consisted of a RS-232 to RS-485 converter and Softcp
Windows software that provided a virtual version of the Compool
control
panel. RS-485 was
the communication bus being used to connect the main control panel in
our house to power center circuit board. The module plugged into a
second port on the back of the indoor control panel allowing a
computer to be plugged into the RS-232 (aka serial) port. While the
MOD-RS485 module cost hundreds of dollars, I could imagine that it
might not be too hard to reverse engineer the protocol. Since this
would be the same protocol used between the main control panel and the
power center circuit board, a program using this would have full
access to the system including not just control, but also status such
as temperature as well error reports. Given a computer interface, I
could easily build a web interface to control the pool from a phone
browser or from one of my Wi-Fi phones connected to
my Asterisk home PBX system.

Not wanting to reinvent the wheel, I searched to see if someone else
had already documented the Cp3800 protocol. I quickly found a thread
entitled Compool
Driver - PERL question referring not only to Perl code for talking
to a Compool controller, but also a specification for the Compool
interface written by a Visual Basic programmer. Looking to see if I
could find the Perl code online myself, I
discovered MisterHouse,
an open source home automation system for Windows or Unix written in
Perl. Sure enough,
MisterHouse's feature
list mentioned Compool pool equipment, with the FAQ noting that
support was added back
in May
2000 and ComPool updates as recently
as
January
2003. I downloaded
the latest MisterHouse source code to confirm there ComPool support
would work with my particular ComPool Cp3800 model. The Compool
module, which is
found
lib/Compool.pm, did in fact mention a serial interface, referenced
LX3xxx and a model 3830 controller, had the Perl code mentioned in the
forum thread I had found and the header comment matching the top of
protocol specification (local cleaned up
copy) provided by the Visual Basic programmer on that
thread. Seemed like a pretty solid match for my Cp3800.

I pulled my Cp3800 control panel off the wall and confirmed that there
was a
free RJ25
jack to connect an an RS-485 to RS-232 convertor. These converters
could be found for less than $10 online including shipping, so after
confirming I could not get one locally at someplace
like Fry's
or Halted, I ordered one and waited
for it to arrive.

First Contact

After the RS-485 to RS-232 adapter arrived, I needed to figure out the
right RJ25 pinout to connect the ComPool control panel to the
adapter. Unlike RS-232 which has a number of well defined connectors
including DB-25
and DE-9 (aka DB-9), there are no standard connectors or pinouts
for RS-485. However, the wiring is much simpler consisting of a
positive and negative signal on two wires plus an optional ground.

My RS-485 to RS-485 adapter in
the Hexin
HXSP-485B. The also have two other models 485A and 485C, but all
that changes is wiring block attached to DE-9 connector on the RS-485
side. The 485B seems to be the most compact and seems to be the most
common on eBay. The 4 wire connections are labeled from left to right:

Label

Actual

User Manual

D+/A

D-/A

Data-

D-/B

D+/B

Data+

GND

GND

GND

9V

9V

+5~+12V

The GND and 9V are for supplying power to the adapter, although in
typical operation the adapter can get its power from the RS-232 port.

The D+/A and D-/B are the positive and negative data pins. The A/B
naming seems to be backward from the standard, which is
a common
mistaken apparently. (It turned out I found out the hard way that
the A/B labels were correct and the D+/D- labels were what was
backwards. The
HXSP-485 User Manual does seem to imply the correct order, although the
HXSP-485B Data Sheet does not have any pinout and in fact cannot
even spell data correctly.)

The wiring on the ComPool side was a little less clear. In the wall
behind the ComPool control panel was a RJ25 wiring box labeled "iS10
WIRING". I had seen the name iS10 on the Pentair web site along side
the other automation documentation so I went back and found
the iS10
Spa-Side Remote, which provides a spa-side remote with more
advanced temperature controls for InterTouch pool control systems, but
also with an "adapter" box for the Cp3800.

The iS10 spa-side remote documenation provided the following mapping
into RJ25 colors

iS10

Cp3800

RED

YEL

YEL

RED

GRN

GRN

BLK

WHT

Pulling this all together, it seemed like the RJ25 6P6C connector on the
back of the Cp3800 could be mapped as follows:

Pin

Old colors

Twisted pair colors

Signal

1

white

white/green

GND

2

black

white/orange

unused

3

red

blue

+DATA

4

green

white/blue

-DATA

5

yellow

orange

+15 VDC

6

blue

green

unused

Later I noticed that I worked harder than I had too because the
protocol description already had a similar,
although slightly different, pin out:

Pin

Color

Signal

1

white

GND

2

black

+10 VDC (~100ma max)

3

red

+DATA

4

green

-DATA

5

yellow

+10 VDC (~100ma max)

6

blue

GND

Since for my for my first test I was only going to try and use the
+DATA -DATA signals without a ground, I took an old RJ14 cable I used
in testing jacks when setting up my Asterisk home
PBX system and wired the red and green wires to the matching D+
and D- pins on HXSP-485B adapter (Note that as I discovered later red
needed to go to D-/A and green to D+/B). The next step was to take my
old Dell Inspiron 8200
laptop which had an actual serial port on it and connect up the
HXSP-485B and see if I could see anything with a terminal program such
as Microsoft Windows HyperTerminal (or in my
case Van Dyke
Software'sSecureCRT,
which just added a dumb terminal type to version 6.6 at my request
after I found that it didn't support that for this type of
debugging). The MisterHouse ComPool::init method (in file
lib/Compool.pm) suggested using serial port settings of 9600 baud with
8 data bits, no parity, and 1 stop bit. I connected and saw chunks of
data arrive every 2.5 seconds as noted in
the protocol description, with a common
23-byte chunk repeating frequently:

00 a9 95 c9 fb df f3 d9 ff bf 9f 6d bf ff ff e7 39 b8 ff 1f ea 43 fe

Looking again at ComPool::init, it seems that the protocol was in fact
binary with a basic acknowledgement packets being 24 bytes long. The
protocol description agreed. so something seemed wrong with my
data. Interestingly, the basic acknowledgement packet should start
with "ff", not "00". Perhaps the data wire polarity was reversed?

After switching the data wires, I now see a 24-byte pattern starting
with the expected "ff aa 0f" sequence:

Created a Windows Scheduled Task with Control Panel to startup
C:\misterhouse\run.bat on boot so it would automatically come up
after Windows Update reboots, etc.

Pretty Pictures

One of the features of bdc_compool_test.pl is that on every
$New_Minute it checks the pool status which is logged to a CSV file.
A perl script on my home Linux box runs every
minute via cron using rsync to pull the data, ploticus to generate the
graphs, and another rsync to upload the results to
my public pool temperature page.

A Kindler, Gentler Web Interface

Although MisterHouse has a web interface, it was not something I
wanted to family to have to use poolside on a small phone
screen. Fortunately, the MisterHouse web interface did automatically
expose controls for my bdc_compool_test.pl code, including checking
the current status of pool equipment, sensors, etc. So I put together
this simple old-school Perl CGI script to
provide a minimal interface, dropping it into a http://pool virtual
host for convenience.

Moving from Windows to Unix

With everything basically working, I wanted to move off the Windows
laptop which I used for the proof of concept to the home Linux box I
planned to use for the long term. Most of this involved pulling wire
from the Linux box to the pool controller, but I'll document the Linux
setup here.

Created C:/misterhouse/code, and ~/misterhouse/data,
~/misterhouse/data/logs, ~/misterhouse/run,
~/misterhouse/data/code_select.txt,
~/misterhouse/code/bdc_compool_test.pl along the lines of the Windows
versions above. I did not use a mh.private.ini on Linux since it
could not handle expanding ~/misterhouse paths and I did not want
to hardwire my home directory into the configuration file. So
instead I supplied the options on my ~/misterhouse/run script like
this:

Unfortunately, it misterhouse would not let me supply the
Compool_serial_port on the command line, presumably because it was
not found in mh/bin/mh.ini, so I keep that in the
~/misterhouse/mh.private.ini like so:

Compool_serial_port=/dev/ttyS0

Migrated my historical data from the old Windows box to the new Linux box:

Minimally ComPool.pm to avoid using Win32::SerialPort specific
code, instead using the portable Device::SerialPort subset. The
full file is here, but the change was pretty small, basically
removing use of is_handshake, changing is_status to status, and
collapsing read_bg/read_done into a simple read call. Here is
the diff:

Setup misterhouse to automatically start at boot time. I used the
instructions from
the StarterScripts
page of MisterHouse Wiki, not the
ghastly
version from the FAQ. I tweaked the /etc/init.d/mh script to
run as my personal user, not mh, and out of my ~/misterhouse, not
/opt/misterhouse. I also fixed a bug in the mh.pid path, which is
actually located in misterhouse/mh/data/mh.pid, not
misterhouse/data/mh.pid. I also changed their mh.sh script by
locating it in ~/misterhouse/mh.sh and had it invoke my
~/misterhouse/run script instead of misterhouse/mh/bin/mh
directly. I used "rcconf --on mh" to make sure it started on next
boot.

UPDATED: now on Ubuntu 10.04 Lucid Lynx I'm using an
Upstart script in /etc/init/mh.conf.

Based on warning in the ~/misterhouse/data/mh.log, ran
~/misterhouse/mh/bin/set_password to setup a misterhouse password.

MisterHouse Issues

I have to say that MisterHouse is not very cleanly architected. Here
are some things I found suprising or frustrating:

The code appear to be plain perl at first glance but are actually
parsed to differentiate code that runs only at startup (such as
object creation) while the rest is left to run in an event loop.

Like asterisk distributions, a whole lot of sample things are
turned on out of the box to show you how the powerful the system
is. Unfortunately it was not very clear how to disable things to
go to a more minimal configuration because things like the Tk UI
were also enabled as part of the same extension
mechanism. Clever perhaps, but it meant experimenting to turn
off unneeded features.

It is good that they encourage the user in the documentation
with startup warnings that users should maintain their own code
and data directories. However, their own use of the directories
is confusing because they both contain a mixture of maintained
and generated files. I'm not talking about the fact that config
files can be editted by hand with a text editor versus through
the Tk and web interfaces. I'm talking about the fact that
derived files such as items.mhp are stored alongside their
sources such as items.mht. Or that generated code such as
organizer_events.pl and organizer_tasks.pl are dumped in code
because organizer.pl by default. As a new user of the system, I
like to look over the configuration files and having all these
extraneous files in my code and data directories as opposed to
some "/var" like area was confusing.

"parm" should not be an abbreviation for "parameter"...

Bugs to report:

"indpendent" misspelled in "How are the X10 and Serial Items implemented, indpendent of the platform?"

Need to replace "get_device_now" with "get_device" in Compool code and lib

Need to replace "HomeBase" with "Compool" in mh/code/public/Compool_test.pl

Reference to unknown "Compool::set_device_with_timer" found in mh/code/public/Compool.pl

mh/lib/Compool.pm has Win32::SerialPort specific calls. For
example, "is_handshake" is used which is similar to commented
out code in mh/lib/Xantect.pm. Similarly, the Win32 specific
"is_status" is used instead of "status" and "read_bg/read_done"
instead of "read".

wrapper script recommendation should suggest using "call mh" not just "mh" and perhaps change directory after