Pool pump speed control - easy way?

Looking for some advice.

I’d like to control my variable speed pool pump using something like esp8266/esp32.

I can turn on the chlorinator and pump using a smart GPO, but can’t amend the speed. I’ve got a Viron P320xt pump and e25 chlorinator.

Generally speaking, the chlorinator/control just comes on using its own timer, but I will probably set this to manual and put a smart GPO on it to turn on and off using HA. Pump comes on using last state (low power).

When I need the pump to run on fast (high power) for things like running vacuum/extra filtering, I’ve got no way of altering except going to the pump and pressing the appropriate speed. If it gets forgotten, it stays on this speed

Wondering if anyone has found a way to interface with the pumps or alternative way of changing speed easily? As a crude way, I could get 3x switchbots to physically press the buttons, but that seems a bad way.

1 Like

Does this help?

4 Likes

Wow!! Thanks for this! And referencing my other topic. I’m going to try this asap.

I have to be VLink controller that already acts as a master on the Modbus line. It sends out pump demand and status requests every few seconds, so it would compete if I sent different demand requests also. The pump’s speed would change to my requested speed and then back to the original VLink requested speed, etc. That’s why I wanted to intercept and filter out the VLink requests under certain conditions, mostly while my solar valve was “On”.

A big part of my problem so far is the fact that the pump uses a nonstandard Modbus protocol, as you alluded to. That meant having to parse incoming raw UART bytes and outputting custom Modbus commands. I also have no CPP or Python skills.

Does your code take into account the pump’s command time-out (default is 60 s)? If the pump doesn’t receive any requests from the master after this interval, the pump shuts itself off.

I may well have to ditch the VLink interface and set up schedules, etc. all within HA.

Do you have any insights into the other protocols/DIP switch settings? My previous pump was a Hayward EcoStar and my main pool control board is a Hayward Aqualogic that I have interfaced into HA. If I could control the new pump via the Aqualogic that might be the best way to go.

Thanks again. Following.

Yes, you only want one master on a modbus bus.

I set the sensor update interval so that it prevents the pump from reverting to the control panel values.

There is a setting that controls the timeout for automation interfaces but I didn’t force that because I like to fail safe so if my little RS485 device fails then at least the pump will just stop.

I’ve been running this firmware for a couple of weeks now and it seems to be very reliable … I’m using it to reduce rpm overnight or when we are socialising near the plant room to cut the noise down and also to boost the speed when I do a vac!

Let me know how you get on, happy to make mods or add code to help the community.

Also, we could probably set your pump to respond to Hayward commands when DIP #1 is in the OFF pos. Let me take a look and see if we can create an ESP button for that!

Thanks again!
Flashed it last night using the yaml in your Readme. Pretty much worked first try! I’m still hooked up to the VLink interface so there’s some Master-Master competition going on, I think. Every couple of minutes the pump will go to 0 RPM then restart. Maybe I need to change the Sensor Update Interval you mentioned. Where is that located? Just to clarify, you don’t have the Century control panel hooked up at all now, just your ESPHome node, right?
Also, I found this a while back (https://github.com/wbwallace/Vgreen-automation) which might be use. I also saw that today someone on this forum had asked a question about custom modbus protocols (Testing modbus integration), so I referred him to your GitHub repository.
I’ll be following.

Yeah, I think the vlink box will be getting confused, it’s going to see the replies from the pump to you HA control device. I’d temporarily disconnect that to make sure that is the cause of going to zero rpm.

I do still have the panel on the top of the pump connected, but this is ignored if the device gets data on its Modbus interface … well for one minute anyway. The update frequency is set in __init.py__ on the line .extend(cv.polling_component_schema("10s")).

Thanks. I’ll try that.

Ok, first off, I can’t thank gazoodle enough for publishing this repository and readme about how to get HA to talk to my V-Green variable pump motor. I have now removed the V-link cloud device and can control the pump locally with HA and the ESP32 device shown in the photos. After some tinkering and a ton of research about ESPHome, etc., I purchased the ESP32 device shown in the github link and got everything working.
Albeit except for 1 issue; I have the 2.7HP regal motor that also has a relay on the control board next to the RS485. I use this to fire up a booster pump. The protocol document from Regal references auxiliary relays and the configuration commands to set it to close at certain RPMs, but I have no idea how to send a command to do that or to manually close and open the relay. Everything else works perfectly – pump on/off and RPM setting. Any idea where to start? I have no scripting skills, but can piece together with sample code and make changes.

I can abandon the integrated relay and just toss in a Shelly relay to control the booster pump, but I did like how the pump had a failsafe to not allow the relay to close without the pump running, etc.

Thanks again!

Have you figured out how to read the power consumption from the pump?

I had originally build a system using the relay inputs, and was going to use a CT sensor to read power.

Power would be useful for energy monitoring and give an indication of pump issues, such as broken impeller, the pump would spin faster under no load and theoretically be a lower power than usual, aiding in diagnostics.

Edit: reviewing your code, am I reading correctly, that sending the read sensor command should get the pump to reply back with ALL the sensor data and you just have to look for the 0x01 Motor current byte address, using this as an example:

- platform: centuryvspump
    name: Pool Pump Controller Demand
    address: 3
    page: 0
    scale: 4
    type: custom
    unit_of_measurement: RPM

But instead of pulling RPM, I’d like to get current, so would that be a matter of adding this to the yaml you made, so the code above to modify and add would be

- platform: centuryvspump
    name: Pool Pump Controller Current
    address: 1
    page: 0
    scale: 1000        ## 1000 per Gen 3 EPC modbus Comm Protocol
    type: custom
    unit_of_measurement: Amps

Then AC Input Voltage would be

- platform: centuryvspump
    name: Pool Pump Voltage
    address: 31       ## or 2 Mains Voltage RMS
    page: 1              ## or 3 for Mains Voltage RMS
    scale: 230          ## NA per manual
    type: custom
    unit_of_measurement: Volts

It’s more elegant than I thought, but just want to make sure before I run it.
Thank you

VGreen pump is enroute. Ordered the ATOM RS-485 module. Can’t wait to try this out. Thanks, @gazoodle! This will be replacing / augmenting my current ESPHome relay based solution. I might have to redesign it as one fully integrated solution instead of two. I assume it’s possible to use your “centuryvspump” code with separate RS-485 Modbus controller shown in this wiki page?

I have no experience with these RS-485 controllers, though - so I would at a loss at understanding what I would need (configuration wise) to use this other board with a separate ESP32 and your code.

Did you get this config to work? Can you monitor motor speed, current, and voltage using your YAML additions, above?

I’ve been busy. I need to put it together and try it out.

@gazoodle Did you ever look at the wiki that I linked to, from ESPHome? It looks like there is a LOT more modbus configuration that can be done - and I’m not sure how much of it (if any) is needed. The ATOM unit was working out for a little while when I had it inside the pump motor housing - but now it seems to be flakey and unreliable - probably because the WiFi signal is being attenuated by the metal box. I temporarily moved it inside of my main, plastic pool controller box - but it seems redundant, as I already have another ESP32 device in there, running the light and the water features. Is any of that configuration for the “standalone” modbus module needed? or just the RX pin, TX pin, and baud rate that you have in your original ESPHome sketch?

This code was working fine but stopped working for me after some ESPHome update.
Any idea what it might be?

Same here. It’s throwing an error during compiling when I try to flash an update.

strange - I was able to compile and flash - but it is not working
RS485 configuration seems changed in ESPHome since that repo was created

I finally built it. It works, using an ES8266, a RS485 converter modem, and a DC-DC buck boost converter to take the 12 VDC and drop it down to 5VDC regulated. Logging has to be disabled as the UART logging stops the modbus comms, per the ESPhome website

It worked for a bit, then it stopped working. Question, how have you handled loss of power on the pump, or loss of wifi? Did you build an automation to allow the controller to continue running the original schedule on return of power, or on loss of wifi, carry on with original schedule?

I think I have to get an ESP32 with external antenna, as my wifi doesn’t reach all the way to the back corner of the yard, with -85 dbi.

Also, referring back to my previous post, it appears my examples on retrieving current and voltage from what I read in the Regal Modbus document don’t work. I think its that Current is a Union data type, and Voltage is a Unsigned Byte. @gazoodle What would need to change in your YAML to read those?

So looking at your CenturyVSpump.cpp file, I see the lines describing reading a sensor

CenturyPumpCommand CenturyPumpCommand::create_read_sensor_command(CenturyVSPump *pump, uint8_t page, uint8_t address, uint16_t scale, std::function<void(CenturyVSPump *pump, uint16_t value)> on_value_func)
        {
            CenturyPumpCommand cmd = {};
            cmd.pump_ = pump;
            cmd.function_ = 0x45; // Read sensor
            cmd.payload_.push_back(page);
            cmd.payload_.push_back(address);
            cmd.on_data_func_ = [=](CenturyVSPump *pump, const std::vector<uint8_t> data)
            {
                // Always going to have at least 1 byte of sensor data
                uint16_t value = (uint16_t)data[2];
                if (data.size() == 4)
                {
                    // But sometimes, we get two bytes
                    value |= (uint16_t)data[3] << 8;
                }
                // Scale the value
                value /= scale;
                ESP_LOGD(TAG, "Read value %d from page %d, addr %d", value, page, address);
                on_value_func(pump, value);
            };
            return cmd;
        }

I think in how you wrote it to look at only 1 or 2 bytes, which works, but say for motor current, page 0, address 01,scaling 1000, it would have to be union data type, looking at 2 bytes. The same for Inverter input power, page 0, address 05, scaling n/a. Not sure how to implement that yet.