Monday, July 28, 2014

Controlling the Hayward Ecostar Pump

Quite some time ago I got fed up with the huge amount of power a pool pump uses and got one of those cool permanent magnet, variable speed pumps.  It's really is cool, it can run from a few RPM up to way over 3000.  All of the speeds use less power than a conventional motor and you can actually circulate water with 200 watts of power usage.  This is what they look like:

There's three pieces to these things, the controller, the actual motor and the filter-impeller.  Hayward calls the controller the 'drive'; I don't have any idea why except maybe because they make pool controllers and they don't want customers to get confused.  The drive is this part here:

Yes, I stole the image off the web.  It was too hot to go out and take my own picture.  The drive can be separated from the motor and remotely set up.  This makes it convenient for ease of use, and nice if you have the rest of the stuff inside an enclosure.

The drive has its own controls, but it can also be controlled by my Goldline P4 controller.  The problem is that the darn controller only supports two speeds: low and high.  Sure, I can set the speed for each of them to anything I want, but I only have two speeds for my variable speed motor.  That has always ticked me off.  Hayward decided that I only get two speeds for the motor that are easily done.  To do anything else I have to futz around with settings each time.  Really ??

A few weeks ago one of my readers asked if I had ever pursued breaking the protocol between my controller and the drive.  I hadn't, but it sounded like a cool project to take on.  So, armed with my motor, his motor, his skills, my lack of skills, we embarked upon a project to get control of this motor.  Naturally, there is zero documentation on the protocol, but we had some hints.

It's RS485 half duplex because it works on the same line as the other controls for the P4.  It's 19.2Kbaud for the same reason.  That meant that we could set up monitors and code to listen to the conversations between the devices as we changed things and might stand a chance to get a hint on how to control it.

Guess what?  After a few false starts, we beat it.  We can now control the motor and change the speed to anything we want to.  It turns out the protocol is relatively simple; you send a command to the motor periodically telling it the speed you want it to run.  If you stop sending, the motor stops.  If you send a speed of zero, the motor stops.  If you send a specific speed, the motor runs at that speed.

The motor protocol works in percentage.  If you send 100%, it will run at the top speed.  If you send 0%, it stops.  You can choose any percentage in between and the motor will go to that speed.  You can't send 1000 RPM, you have to send a percentage instead.  Still, it works quite nicely.  The protocol looks like this:

Off     0x10, 0x02, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x03

100% 0x10, 0x02, 0x0C, 0x01, 0x00, 0x64, 0x00, 0x83, 0x10, 0x03

45%   0x10, 0x02, 0x0C, 0x01, 0x00, 0x2D, 0x00, 0x4C, 0x10, 0x03

The 0x10, 0x02 is the start of packet indicator.  The 0x0C, 0x01 means from device 1 to device 12.  The 0x00 is just a zero, never saw it become anything else.  the 0x00 or 0x64 or 0x2D is the percentage in hex (0, 100, 45) the next two bytes are the checksum and the 0x10, 0x03 is the end of packet indicator.  So, to change the speed, change the percentage, recalculate the checksum and send it.  The motor will change speed.  You have to send this at half second intervals to keep the motor running.  Actually, I've gone up to a second and a half and still had the motor run, but better safe than sorry.

The checksum is a matter of adding the byte values and sticking them in place.  In the first packet above, 10 + 2 + C + 1 + zeros = 1F.  Remember, it's hexadecimal and the checksum is two bytes long, so it's 0x00, 0x1F.  Similarly, the 100% packet is 10 + 2 + C + 1 + 0 + 64 = 0x00, 0x83.  The last two bytes, 0x10, 0x03 are not used in the checksum.

Each of these control packets is responded to immediately by the drive unit with something like:

0x10 0x02 0x00 0x0C 0x00 0x00 0x2D 0x02 0x36 0x00 0x83 0x10 0x03

It starts off with the begin packet bytes of 0x01, 0x02.  Then 0x00 , 0x0c which would mean, from device 12 to device 0.  Strange that it would reply to device zero when device 1 sent the command, but ??  Byte 6 of the packet is the speed, in the packet above it is byte 6 counting from the first byte being index [0].  Bytes 7 & 8 are the power and they threw me for a loop. They’re in nibble form of the actual speed if you read it out loud. For example:

0x10 0x02 0x00 0x0C 0x00 0x00 0x62 0x17 0x81 0x01 0x18 0x10 0x03

Byte 6 is 0x62, for 98 percent and bytes 7 & 8 are 0x17 0x81, this reads as one, seven, eight, one or a power reading of 1,781 watts. Is that weird or what?   I tried big endian, little endian, hex, some obscure rotations I’ve seen in the past and other stuff until I just happened to read it out loud and then look at the motor. Shocked is probably the correct term for my reaction.

Edit: I had a face-slap moment on this a couple of months after I posted here. The number is simple binary coded decimal; the reason I missed it is because I haven't seen BCD used since the late '70s of last century. I gues it's still used somewhat, but I completely missed it.

So, to calculate the speed: Serial.print(((long)3450 * buffer[6]) / 100); seems to work just fine. It’s a tiny bit off from the actual motor reading on its LCD sometimes, but I think that’s because of the calculations on the two devices being a little different. The power is right on for every instance I have tried.

The code for something like this was relatively simple to put together, but it gets really complex when you add in whatever method you use to control it.  I have an XBee network that I send commands through, but most folk out there want wireless ethernet or wires.  It can be controlled from a board as simple as an Arduino (like me and my colleague), or any other device that can either provide RS485 or handle an adapter to convert TTL serial.  My setup is described here <link>, I just added code to it to handle the motor separately and turned off control of the motor in the Goldline P4 I have.

The physical connection is with two wires from your RS485 device to the motor drive unit on the communications port.  You may have to use shielded cable and connect the ground up as well; these motors are extremely noisy on both the power line and RF near the unit.  So, grab some of that shielded CAT5 cable and go for it.

I cut this right out of the installation manual for the Ecostar motor.  Pin 7 is the plus (+) side of the RS485 link and they clearly label the comm connection.  This image also shows how the connection is made to a pool controller like my P4.

If you do this to control your motor, there is something that will help you.  When you send something to the motor that it can't understand, it locks up the drive unit.  I sent many a packet that was constructed incorrectly and the drive would go nuts and not respond after that.  You have to actually power down the motor and then turn it back on to continue.  Not the most robust software in the world.

There is another protocol here that I will research in more depth later.  Not only is the 'drive' controlled by the pool controller, the motor itself is controlled by the 'drive'.  Yes, the motor itself has a protocol all it's own that the drive supplies.  That's why you can separate the drive from the motor and mount it somewhere else with some wires running between.  This is also RS485 and it runs at 1200 baud.  It has a different checksum scheme and there are bits in there that have to be figured out.  We haven't made much progress on this protocol, but we can make the motor turn on without the drive unit even being there.  This may come in handy at some point in the future when the drive dies and the warranty has expired.  Those drives cost almost as much as the entire assembly ... jerks.

There you go folk, you now have control of that expensive motor Hayward has been keeping secret. Plus, for people like me, you can monitor the power usage real time to keep energy costs down.  You won't be limited by some arrangement of relays or the two speeds Hayward saw fit to allow.

That's two of their secret protocols I've put on the web now <link>; maybe I should think about hiding for a while...


  1. Thanks for your analysis! I have a Hayward pool heater -- do you know the protocol for that or where I can find it?

    1. No, sorry I don't have a solar heater on my pool and never played with the Hayward heater. However, it should follow the protocol for the motor to some degree.

  2. Hi Dave, did you ever figure out the 1200 baud 'drive' protocol? -CL

    1. Not completely, I got off onto other things and haven't gotten back to this. I did get a mail from a person that beat the checksum and had figured out some control commands though. I'll have to dig that out and post it sometime.

  3. Thanks much for your work. I would love to hear any updates you may have in the future.

    1. I'm actually going to be digging into this again this year. The problem is that when I post about it it will show up in the most current position. You might check back every couple of months to see if I've added anything about the motor.

  4. Thanks for your work! Did you get anywhere with the drive protocol? I have it hooked up and have started to look at getting the protocol but if you have any pointers they would be great.

    1. You know, I have gathered a bunch of information on that protocol, but I've lost track of it. When I have some time, I'll hunt it down.

  5. Thanks would appreciate if you could ... I can also share what I find out ...

  6. Fyi. They call it a drive because it's properly known as a variable frequency drive

  7. Would you be able to helpme with that ?
    I'm not able to receive any proper signal from the pump.. I only see a bunch of 0x00 every seconds from the pump when I set the baud rate at 19200... What I tried was to attach the setup as follow :

    Pump RS485 port----Rs485to-TTL (thats a module called SH-U12)--------USB-to-TTL (module name CP2102)-----PC running Termite Com5/19200/8N1

    I also get the exact same results if I skip the RS485-to-TTL as follow :

    Pump RS485 port----USB-to-TTL (module name CP2102)-----PC running Termite Com5/19200/8N1

    So I'm receiving something, I can see the RX led flashing every seconds on the usb-to-TTL but it's just not what is expected..

    If I lower the baud rate, (to 1200) I see a repeating signal but nothing as described on Desert-Home web site :
    01 01 00 00 6b 0d 0a 01 40 00 00 00 00 00 00 00 ....k...@.......
    10 00 00 00 00 00 71 0d 0a ......q..
    01 01 00 00 6b 0d 0a 01 40 00 00 00 00 00 00 00 ....k...@.......
    10 00 00 00 00 00 71 0d 0a ......q..
    01 01 00 00 6b 0d 0a 01 40 00 00 00 00 00 00 00 ....k...@.......
    10 00 00 00 00 00 71 0d 0a ......q..

    I've attached RS485 A,B and ground in parallel to the cables coming from the interface to the board next to AC current input on the pump. The pump being a SP2603VSP.

    Only the dipswitch 1 is on. (I tried putting other ones also on without success :(

    1. You're looking at noise, not the data. The baud rate is 1200 and it really is rs485.

  8. I'm (more than a little) bit confused about a couple of things. When I first got my Hayward Super Pump VS (the label on the side of the pump) I thought it was going to be a great idea being able to run the pump slower during periods of higher electricity rates, but quickly discovered that the lower pump speeds don't produce enough pressure to allow the gas heater to run, so after a day of the pump saving electricity, you come home to a cold pool, which takes hours to heat up. The solution seemed simple: use an arduino to monitor the water temperature and if it gets too low, speed up the pump and turn on the heater. I figured I could tackle this in the couple of weeks before pool season starts.
    It turns out it's a lot more confusing that I thought it was going to be.

    Thanks for your insights; they've been a big help up to a point.

    So here's what I'm facing:

    First off, my pump has and identity crisis. The label on the outside says one thing, but the label on the controller's motherboard says it's a Tristar VS.
    To make matters more fun, the label on the outside has "SP2600ZLV" written on it, but there is no such model of pump. There is, of course, the SP2600 but the photos in the manual show a different pump motor (one with cooling vanes) and a very different control head. The closest I can find is the SP2603VSP which at least looks the same.

    In all three cases, the manuals show the terminals as you've posted them on this web page: namely, the connector labelled "Wall Mount Display" on the controller board, is shown in all cases as having 8 pins while mine only has 6.

    I'm really not impressed with Hayward at this point.

    As an experiment, I tried connecting pins 5 and 6 to my USB->RS485 interface but there was no communication on them at either 1200 or 19200 baud (or, really, anything in between).

    So this leaves me with trying to sniff the commands on the RS485 port on the motor (the one that has the short cable leading to the controller. At 1200 Baud, as expected, I can see data there, consistently formatted, which changes as I change the motor speed via the control panel. So at least that much is successful.

    Now, after that long-winded preamble, for my points of confusion:

    Using your examples, I've tried injecting a stop (0x10, 0x02, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x03) initially by copying and pasting what you wrote, but then realizing that to 0x and commas are probably for human readability, so I sent 10 02 0C 01 00 00 00 1F, hoping it would stop the motor, but that would have been too easy. I'm using a terminal program in Linux that allows me to send hex strings and not ASCII text but I also realize, but didn't test last night, that maybe it wants it as one continuous string of hex (no spaces). ie: 10020C010000001F but I suspect that won't work either because as I write this today, it's dawning on me that by injecting my hex commands into the controller-motor data link, I'm really just introducing another bus master and anything I write will just be overwritten by the motor's controller anyway.

    So now, I'm thinking I'll need an Arduino Mega with it's multiple serial ports to connect one port via an RS485 adapter to the controller and the other port via an RS485 adapter to the motor. Communication from the motor to the controller would be sent strait through the Mega but commands from the controller to the motor would be intercepted and my own commands injected instead.

    You've successfully worked with Hayward's RS485 protocols before: in your opinion, am I over-thinking this?

    Frankly, at this point the inelegant 3-relay control method is looking so much easier although it renders the motor's control panel useless.

    Any thoughts/advice would be appreciated. I've never worked with RS485 before and I suspect I'm either overcomplicating it or biting off more than I can chew.

    1. Actually, the additional port to handle the conversation is a nifty idea and will give you flexibility It would also give you the ability to show the conversation interaction on the console so you can debug it.

      Back when I was doing this the Mega was much more expensive and I didn't have a spare one to try out. That would have helped a lot. Megas are cheaper now and the clones work pretty well.

      I'd try it.

  9. Hello Dave,
    I would like to ask you if you can help me adapting and using the ps goldline control. Do you have the possiblity to get in touch with me by email?
    Thank you

    1. It's been so long that I've probably forgotten most of it. However, I'm certainly willing to help if I can. You can get my email address out of the profile link up the page a bit. Drop me a note.

  10. Thanks would appreciate you effort... with the help of your collected data, I am able to control Start STOP and Run at defended percentage - it working perfectly

    only 1 thing left -- if I want to change RS485 Address of VSP what is the command required - did you got any chance to work on it type of command

    Thanks You

    1. When I looked at the addressing, Hayward said that it couldn't be changed. I never tested to see if that was actually true though. Net, I don't have an answer for that.

    2. ohk Thanks for you response

      but in Same RS485 path, if we want to control more the one VSP --- it will not work if Address is same

  11. what we can do multiple VSP is in same RS485 bus --- so any option is there to change VSP RS485 address,

    I saw some DIP switch, can we configure RS485 address with the help of DIP switch and what is the address with respect to DIP switch

  12. To be clear, the protocol is at 1200 baud, not 19200 as mentioned above in the article?