ESPHome Pool Controller: Controlling Nidec Neptune / Waterway Pumps & Stenner Dosing

Hi everyone,

If you’ve ever tried to automate a Waterway Power Defender variable speed pool pump, you already know the frustration. While the community has mature integrations for Pentair and Hayward systems, documentation for Waterway is almost non-existent. I saw several threads where people ultimately gave up trying to talk to these pumps.

After a few days of reverse-engineering and trial-and-error, I finally cracked the protocol and wanted to share a drop-in ESPHome reference architecture to control these units safely.

The Protocol Trap: Limited X17 Modbus

The Waterway Power Defender series (like my PD140) is powered by the Nidec Neptune (NPTQ270) motor engine. While it is fundamentally based on the industry-standard X17 Modbus protocol, Nidec uses a scaled-down, limited implementation. If you try to pass many standard X17 initialization or command structures, the drive simply ignores them.

My configuration has been running for about a week now and has been solid.


The Hardware Stack

I designed this configuration around a single, highly integrated industrial board to serve as a complete pool-pad controller:

  • Controller: Waveshare Industrial ESP32-S3-Relay-6CH (utilizing the onboard RS-485 transceiver, piezo buzzer, and WS2812 status pixel)
  • Circulation Pump: Waterway Power Defender 140 (PD140) wired directly to the RS-485 bus
  • Chlorine Dosing: Stenner 7.5-Gallon Tank & Peristaltic Pump (driven via the high-voltage isolated Relay 1)

Core Subsystem Features

1. Split-Surface Pump Command Control

To protect the high-voltage hardware, the configuration completely decouples user/operator intent from low-level execution.

  • Public-facing Home Assistant sliders let you request a target speed.
  • ESPHome intercepts this intent locally, sanitizing and clamping it against rigid hardware RPM guardrails (600–3450 RPM) and active service overrides (like backwashing or vacuuming) before writing the hex code to the pump.
  • Includes an embedded C++ multi-point linear interpolation array that derives continuous, real-time GPM (Gallons Per Minute) flow estimation from filter psi mapping across the pump's torque curve.

2. Safety-Gated Liquid Chlorine Dosing

When you are dealing with high-concentration liquid chlorine, safety is important. The Stenner dosing pump cannot simply be turned on by a timer. Dosing runs through an asynchronous script that requires five strict safety gates to clear before Relay 1 closes:

  1. Valid calibration data present.
  2. An active, non-zero volumetric request.
  3. Maintenance lockouts/physical overrides are turned off.
  4. Active Modbus telemetry loop confirmation (proving ESPHome is successfully talking to the pump).
  5. Confirmed high-velocity water movement.

The Fail-Safe: A continuous background diagnostic loop monitors pump velocity and Modbus communication. If the pool pump unexpectedly loses power, drops offline, or drops below safe RPMs, the system instantly triggers an emergency fallback script to kill Relay 1—completely mitigating the risk of dumping raw chlorine into stagnant PVC plumbing. It also includes pre- and post-run delays to ensure water is flowing before and after chemical injection.

3. Localized Telemetry

  • 7-Day Rolling History: Uses shifting arrays to persist and track pump runtime, energy metrics (Wh), total volume throughput (gallons), and chlorine consumption directly inside local flash storage.

Repository

The complete, sanitized YAML configuration in the repository below. To make it as easy as possible for anyone grabbing this configuration, I structured the code to pull all hardware pins, Modbus settings, relay labels, thresholds, and pool parameters into a Substitutions block right at the top of the file. You can customize the entire system for your specific pad equipment without needing to dig into or modify the underlying C++ or execution logic.

5 of the 6 relays on the Waveshare board remain completely open for future pad expansions (pool lights, heater loops, etc.).

:backhand_index_pointing_right: GitHub Repository: GitHub - ccpk1/esphome-nidec-neptune-pool-controller: ESPHome configuration for the Nidec Neptune (NPTQ270) Modbus protocol, native to Waterway Power Defender (PD) variable speed pumps. Features robust split-surface intent architecture, adaptive RPM guardrails, safety-locked liquid chlorine dosing injection, and 7-day rolling historical telemetry tracking. · GitHub

Hopefully, this saves the next person from spending days staring at a serial monitor trying to get these proprietary pumps talking. Let me know if you have any questions about the register mapping or the safety logic!

My old Pentair Challenger pump's single speed 1.5 HP motor died. Based on the energy savings I replaced it with the Nidec Neptune NPTQ270. It was a bolt on replacement for the old motor and smaller, lighter and quieter. I ordered the Waveshare and don't have a chlorine doser on my pool. I'm look forward to adapting your code and getting it into home assistant. It looks very well put together.

Let me know how it goes or if you have questions. Happy to help. Also, chlorine doser should be fine left as is or could easily strip that out.

Also happy to share some of the dashboard and automations I built out for it, but didn’t want to spend a lot of time on that part until I found there was interest.

Ya, i have some flipping questions!?!? I keep signing up to reserve your pool on different weekends and it keeps sending me offensive messages back like "The pool insurance doesn't cover beached wales and we cant afford you being stranded out of the water" or "Sorry, we've had a history of people that look like you stealing water from our pool but, we have a complementary garden hose out front that you can play in but, we dont accept reservations in days that end in the letter "Y"...........

Whats the deal with your pool system being a jerk to me??? Im starting to think me and my man thong swim suit arent welcome there now and idk how thats even possible!! Who wouldn't want me over by the pool tanning my beautiful amd hairy back cheeks in the sun, even if i do steal a little pool water from time to time!!

I better get an apology or at least some complimentary free hours with the garden hose sprinkler out front so i can at least run and jump through it while screaming "YYEeeee"!

Im so dissapointment......

; )

Haha, I guess these ESPs are a lot smarter than we give them credit for! I didn't realize it had achieved full sentience and a bad attitude. I promise the ‘beached whale’ notice and 'man-thong' ban will be in the next release notes!

Oh ya! Id say yours has become self aware and thinks its a dang comedian! Hey, everyone else has been worried about a Terminator scenario but, it seems that was worst case and instead we got rude a-hole consciousness and now we can all be mocked and put down equally!! It might become the magical thing that makes us all equal after all and now hopefully governments will quit jacking up taxes because of the same goal!!

Lol you're a good sport, thanks!

@ccpk1 Hey got everything hooked up. Made all the ESPHome changes. I have flashed the code to the waveshare.com-esp32-s3-relay-6ch. It is avaiable in my homeassistant. I can also access the webserver on the waveshare. I cannot seem to get any valid RS-485 communication. I just used a 3 conductors off a 5 foot - cat6 cable. I also tried reversing + and - for the RS-485. Have tried putting it in remote mode and get nothing. The response I see in the webserver looks like this:

12:07:36[W] [modbus:063] Stop waiting for response from 240 272ms after last send 12:07:36 [W] [modbus:063] Stop waiting for response from 240 272ms after last send 12:07:36 [W] [modbus:063] .....

Any idea what I'm missing?

Figured it out. I forgot to set the Nidec Neptune (NPTQ270) to the Waterway RS-485. On the Nidec Neptune (NPTQ270) motherboard (located under the motor's canopy or rear wiring cover), there is a small bank of physical DIP switches. According to Nidec's manual, to enable the RS-485 Modbus controller, you must physically toggle DIP Switch #3 to ON (the rest are usually OFF). If DIP Switch #3 is currently OFF, the pump is in analog/local-override mode and will keep its RS-485 transceiver completely disabled or ignored, resulting in a 100% silent timeout! Now things are working as expected.

That is great to hear! I’m out of town for a few days, but let me know if you have interest in the dashboard and automations I’m using to control it and I could bundle them up for you to check out. Let me know if that interests you or if you already have an approach to handle that.

I'd appreciate the bundle when you get a chance. I did set up my summer and winter schedules - using the custom scheduler card (too take advantage of my SRP TOU energy plan). Things are working great. My next thing is to mount everything in the pool electrical panel and mount the antenna. Thanks for the great idea to control the pool pump (and other things with the relays).

So here are the pictures of my Arizona pool pump motor and control upgrade. Yes the power was off at the breaker the entire time - be careful out there.

Pool Pump - Pentair Challenger 2 - 355460 CHII-N1-11/2FE - 34-543
Pump motor upgrade:
A.O. Smith Century Centurion single speed 1.5 HP - 177-451-03
US Motors NEPTUNE variable speed NIDEC 2.7 HP - NPTQ270

I repurposed the old mechanical timer electrical box to DIN rail mount the 12 VDC power supply, waveshare and external wifi antenna. Used CAT6 inside flexible conduit for all the RS-485 communication. Love the ability to see all kinds of great things in Home Assistant and follow schedules.

After:



During:




Before:




Real happy with the way it worked out.

That looks great! Thanks for posting the details. I know it helps make these kinds of projects seem more accessible to users who might feel like it's too complicated at first glance.

Love seeing successful installs like this—hopefully, it inspires others to share their builds and join the conversation!


Hello, I stumbled my way here after searching on a way to control my PD140 after my clean button, pushed through the panel. I am not familiar with home assistant…yet.
My question is once programmed using home assistant, does the Waveshare ESP32-S3-relay-6ch device work on it’s own, or does home assistant need to continue to operated in the background? Thank you for any help.

Yes it will run without home assistant. There is a web interface you can connect to that allows you to see all the sensors and use the controls. The way I set the package up, I have home assistant control the schedule, but you could add scheduling into the config too if you wanted.

Also, sorry to hear about the button failure, that’s frustrating. Since is doesn’t sound like you are familiar with home assistant or esphome, I thought I’d also mention that with esphome it would be straightforward to add physical buttons on a keypad of sorts. This would allow you to simulate the functionality of the current buttons on your pump if you’d prefer that over accessing via a web browser for normal use as I mentioned. Similarly, if you keep home assistant in the mix, you could add numerous different wireless buttons or other triggers to start cycles or change speeds. Pretty much anything you can think up. Good luck and happy to help answer questions along the way if you get stuck.

Thanks for so much for your advise. I have ordered the ESP32-S3-relay-6ch. I also learned after posting, I can run the ESPHome software on my windows PC without HA. Yes, my plan is to add 6 physical buttons to an enclosure using all the devises relays. Will I be able to accomplish the button programming using ESPHome or will I still need HA?

Yes, you can just run esphome without HA to get the device setup. Once the device is working, it can be completely standalone without even esphome. Physical buttons can be direct wired to the device as well, so they will also work fine without any other external system too.

Awesome. I will update when I’m up and running. Thank you!!

Now that I have the device and trying to set it up, I see I would need to spend countless hours learning how to write code. I thought it would be a more user friendly process, like clicking a few boxes here and there…from what I see, that is not the case.
For me, I think a new pump will be money well spent. Thanks anyway. :slightly_smiling_face:

It certainly does take more than just clicking a few buttons, but I also wouldn’t say it’s countless hours writing code. The ESPHome is more configuration and the template configurations I built for this only require a small number of settings for basic web page access / control and using some tools like ChatGPT or Gemini can make most required adjustments or feature changes copy / paste.

Of course only use can decide if you want to spend time on it, but I’ll leave this for others or in case you decide you want to play around with it.

  1. Install ESPHome - ESPHome - Smart Home Made Simple in Home Assistant or standalone in Windows or Linux.
  2. Access the ESPHome administration interface
  3. Copy the esphome-nidec-neptune-pool-controller/pool-controller.yaml at main · ccpk1/esphome-nidec-neptune-pool-controller into a new device.
  4. Create a secrets file in ESPHome or alternatively you can manually look for the “!secret” placeholders in the configuration file to add in things like your wifi ssid and and wifi password. (Using a secrets file is the recommended approach for security reasons)
  5. Connect the device to your computer via USB cable and install that configuration on the device.
  6. DISCONNECT POWER OR TRIP BREAKER for your pool pump.
  7. Connect 2 wires from the rs-485 port on the waveshare device to the rs-485 connection block on your pool pump.
  8. Connect power to the Waveshare device and reconnect power to pool pump
  9. Go into the pool pump menu settings and enable it for remote control. (Be sure to press enter or otherwise set that remote control mode per your pump instructions. Sometimes it looks like you put it in that remote mode, but it was really just showing the menu option)
  10. Use a web browser to navigate to the Waveshare device and confirm everything is working as expected.

As mentioned in my earlier posts, I have not created any internal schedules or physical button triggers, but that could all be added fairly easily with some AI help. Good Luck!