Replace Your Pool and Spa Controller With Raspberry Pi, Arduino, Node Red




Introduction: Replace Your Pool and Spa Controller With Raspberry Pi, Arduino, Node Red

In this Instructable I will describe how to build a pool and spa controller that controls a pump motor, multiple electric valve actuators, lights, a cleaner, air blower, and heater. It also measures the water and air temperatures. I built this to replace an old Compool pool controller which broke. The Compool model I had is obsolete and replacing it with a new controller and associated parts would cost around $800. I built this replacement for about $75 (using some parts I already had - buying all new will run about $100).

This pool controller uses Node Red on a Raspberry Pi to provide a web interface for controlling the various devices and displaying the temperatures. The Raspberry Pi has the high level logic to do things like determine whether to turn on the heater based on a temperature setting and the current water temperature and ensure that only valid combinations of devices can be operated at the same time. An Arduino Nano has the low level logic to turn on and off a set of relays which in turn control various motors and valves. The Arduino also reads the temperature sensors. The Raspberry Pi is inside my house and the Arduino is outside by the pool equipment; they communicate over a USB cable.

Rather than provide just a step by step listing of how I built this controller, I will also explain how the various controlled devices work. With that knowledge, you could easily build a controller for a brand new system rather than replace the controller for an existing system like mine.

This project requires some knowledge of electronics because you will assemble and solder various components together to build the controller. It will be helpful to understand the basics of reading a schematic because I provide two, one that describes the whole device and another that describes the power supplies. They are very helpful in understanding the controller as well as fixing any issues that might arise.

Let's get started!

Step 1: How Motors, Actuators and Heater Work

Each controlled device has its own method of operating. They require different voltages, some are AC and some are DC, etc. All of the devices connected to my controller fall into four categories: motors and lights, valve actuators, heater, thermistors.

Motors and Lights

My system has a single 240V, 2HP electric motor. It is turned on by switching a heavy duty double pole relay which switches both lines of the 240V. The blower motor and lights operate on 120V electricity and use the same type of relay to operate (see picture). The relay is labeled "24VDC". I tested it and it requires only about 12-13VDC to activate and will stay activated until the applied voltage drops below about 3VDC. These are expensive relays, about $80 each, so I reused them. Feel free to substitute a different, cheaper brand if you are starting from scratch.

Valve Actuators

My pool has three valve actuators, i.e., electric motors that turn valves to make the water flow through different pipes. One is for the intake water - intake from pool or intake from spa. Another is for the return water - return to pool and spa or return to spa only. The third is for the automatic cleaner which operates with pressurized water diverted from the pump's output.

Valve actuators operate on 24VAC. They have three wires, typically black, red and white. Black is connected to the first leg of the 24VAC. To operate the actuator in one direction, you apply the second 24VAC leg to the red wire; to operate the actuator in the other direction, you apply the second 24VAC leg to the white wire. There are switches inside the actuator that stop it once it has reached its limit, i.e., you do not have to disconnect the power, you can just apply the power for the direction you want it to turn and leave it applied rather than having to somehow figure when it's gone far enough and cut the power. Also, the actuators have a three position switch (see picture of bottom of actuator). It turns the actuator off in the middle position, the other positions choose which direction it will turn - if you have it in one position, then applying power to red will operate it clockwise and applying power to white will operate it counterclockwise. If you have it in the other position, then applying power to red will operate it counterclockwise and applying power to white will operate it clockwise. This means that if you wire red and white backwards, all you have to do is flip this switch to the other direction to make it work properly. Sometimes you get lucky and mistakes don't matter!


My heater is a Hayward and it has a lot of complicated electronics inside as well as a ton of safety features that prevent it from running if water is not flowing, the temperature gets too hot, the gas supply falls below pressure and more. It sounds complicated, but the good news is that you don't have to worry about any of that. All it requires is two wires that either have 24VAC or 0VAC. It turns on when at 0VAC, off at 24VAC.

A heater will typically have two electrical connections, one for high voltage (120 or 240VAC) power and one for low voltage control power (24VAC). On my Hayward heater, both the low and high voltage could be connected on either the left or right side of the heater. There is a small panel on each side you can remove to get access to the connections. If you are replacing a controller, the high voltage line should not require any changes. The Hayward heater that I have can use either a two or three wire remote. A three wire remote just tells the heater whether to operate in pool or spa mode and the heater itself determines when to turn on and off based on its temperature settings for the pool and spa temperature (which are set on the heater's control panel). A two wire remote is basically just an on/off switch; whatever it is connected to determines when to turn the heater on or off. In this project, we are using the Raspberry Pi to check the temperature of the water and the pool and spa settings and turn on the heater if necessary, so we are using a two wire remote. This allows us to set the pool and spa temperature in the web interface rather than having to set those on the heater. The two connections used are the ones labeled POOL and 24V.


Thermistors are the devices that measure temperature. They are resistors whose resistance varies with temperature. Their resistance is about 10K. One of the thermistors I bought was made for pool use with a base and rubber O-ring so that it could be mounted in a hole drilled in a pipe carrying water to measure the water temperature. The other was a generic thermistor that I used for the air temperature; I bought a pack of five for less than ten dollars and that gave me extras to use for testing.

Step 2: Controller Design

I will describe how the controller works conceptually before we dive into how each of the pieces works.

A web interface has user controls to choose between everything off, pool or spa mode. It has switches to turn on the pool cleaner, lights, air blower for the spa, and to enable the heater. It has temperature gauges for the water and it allows you to set the temperature of the pool and spa so that when they are on, the heater will bring the water up to temperature and then turn off. It has a second temperature gauge for the outside air temperature.

The web interface is written in Node Red and runs on a Raspberry Pi which is inside my house. There is an Arduino Nano which is outside the house near the pool equipment. The Raspberry Pi monitors all the user controls and temperature settings and periodically communicates with the Arduino over a USB cable to tell it what to do with each of the various devices that the controller controls. The Arduino also measures the water and air temperature and sends that information back to the Raspberry Pi.

The Arduino controls the devices via a set of relays that switch various voltages either on and off, or from one connection to another to operate them. There are three small power supplies that provide three different DC voltages for various purposes.

The schematic shows the Arduino, relay board and power supplies. Even if you don't have much experience with schematics, It will be well worth your while to take some time to understand it - it does not have a lot of electronics mumbo-jumbo and is basically just a picture of how things fit together.

Step 3: Lexan Base

I used a piece of Lexan plastic as the base to mount all the circuitry for this controller. There were several different components (Arduino, relay board, etc.) and by mounting them all on one board, you can assemble it inside and mount it as a unit in the box outside next to the pool equipment. If you make sure every connection to something on that board is detachable, then you can remove it as needed to do repairs and upgrades.

I used 4-40 spacers, nuts and bolts to mount the various components to the Lexan and I used 8-32 machine screws to mount the Lexan base to the metal cabinet outside that used to house the old controller.

Step 4: Power

Above I mentioned that you need 24VAC for the heater and valve actuators as well as DC voltage of at least 12-13 volts for the heavy duty relays. My Compool controller had a transformer that provided 24VAC, 18VAC and 10VAC. I used the 24VAC directly for the valve actuators and heater. Later, you will see that in addition to DC power for the 24VDC relays, you also need 9VDC to power the Arduino and 5VDC to power the relay board. To create these three DC voltages, you need to build three little power supplies, all identical but set to the different voltages.

Take a look at the power supply circuit. It is a full wave bridge rectifier feeding into a smoothing capacitor which in turn feeds into a buck converter. The type I used is called the XM1584, it can handle input voltages up to 28VDC and will output up to 3A. See the attached pictures of a bare XM1584 next to a paper clip, which shows how tiny it is, and the completed circuit board with three power supplies. There is a small screw that you turn to set the output voltage. The output voltage must be less than the input voltage, so I set the three to 5VDC, 9VDC and 20VDC for the "24VDC" relays that actually require less than 24VDC to operate. The XM1584 buck converters are less than a dollar each from China and because they are switching power supplies, they do not get hot (unlike linear regulators). There are other models, e.g., LM2596, than would probably work just as well. I used a 1mF (1000 microfarad) electrolytic capacitor on the 5VDC and 9VDC power supplies and a 2.2mF capacitor for the 20VDC power supply.

I soldered all three power supplies on a single circuit board that is located near the top of unit because that is where the existing transformer leads are located. See the picture for the finished set of power supplies.

Step 5: The Relay Board

There are three motors and lights, three valve actuators and a heater. That is seven devices that need to be operated by routing power appropriately. This controller uses a relay board with eight relays. Each relay has one normally open contact and one normally closed. When looking at the relay, there is a little diagram that shows the center connection in contact with one of the other connections. That is the normally closed connection; the other is the normally open connection. The center pin will be connected to one or the other of the other two connections.

Each relay is operated by 5VDC which happens to be the output voltage of an Arduino pin. A nice feature of these boards is that the Arduino connections are isolated from the relay coil power, so there is essentially no possibility that voltage spikes from the relays will harm the Arduino. In order to take advantage of that, use a 5VDC power supply that is not connected to the Arduino (this is the purpose of the 5VDC power supply described in the prior step).

There are two headers on the relay board, a ten pin header and a three pin header. The three pin header is for the relay coil power (i.e., the 5VDC mentioned above). Make sure to remove the jumper and connect positive to the JD-VCC pin and negative to the GND pin. The ten pin header controls the relays. Connect the VCC connection to the 5V pin on the Arduino and the GND connection to the GND pin on the Arduino that is next to pin D2. The other eight pins control the eight relays. The relay is off when the pin is high (5V) and the relay is on when the pin is low (0V).

In order to connect the actuators, heater and other relays to the relay board, I salvaged the various connectors from the old controller board and soldered them to a small circuit board which I then connected to the relays on the relay board.

The first three relays on the relay board are used to turn on the heavy duty relays for the pump, lights and blower respectively. Each of those requires 20VDC, so wire the positive connection of the 20VDC power supply to the center connection and run a wire from the normally open connection to either wire of the heavy duty relay. Connect the negative connection of the 20VDC power supply to the other connection of the heavy duty relay.

The next three relays on the relay board are used to make the actuators go in one direction or another. Connect one leg of 24VAC to the black wire of each actuator. Connect the other leg of 24VAC to the center connection of the three relays. Connect the normally closed connection of the relay to the red wire of the actuator and connect the normally open connection of the relay to the white wire of the actuator (remember, it's not critical, but just being systematic here).

The seventh relay is used for the heater. The heater requires 24VAC to be off and 0VAC to be on. Connect the first leg of 24VAC to one wire of the heater and to the normally open connection of the relay. Connect the second leg of the 24VAC to the normally closed connection of the relay. Connect the second wire of the heater to the center connection of the relay. This means the when the relay is off, one wire of the heater is connected to the first leg of the 24VAc and the other wire is connected to the second leg of the 24VAC, so the heater gets 24VAC. When the relay is on, both wires of the heater are connected to the first leg of the 24VAC, so the heater sees a 0VAC potential difference and turns on.

Step 6: Arduino and Thermistors

Solder an IC socket to a small circuit board so you can easily remove the Arduino for programming. Solder headers to the circuit board and connect them to the pins of the IC socket so you can use jumper wires to make connections to the relay board and other places. Use a ribbon cable with header connectors on the ends to connect the Arduino to the relay board. Connect pin D11 on the Arduino to relay IN1, pin D10 to relay IN2, etc.

Get or make two wires that have a female header connector at one end and bare wires on the other end. Solder them to the positive and negative connections of the 9VDC power supply and connect the header connectors to the Arduino VIN and GND pins.

Create the voltage dividers with the thermistors. Connect 5VDC from the Arduino to one end of a resistor. Connect GND from the Arduino to one wire of the thermistor. You now have one unattached wire of the thermistor and one unattached end of the resistor. Connect these together along with a connection to an analog pin on the Arduino (pin A0 for the water temperature thermistor and pin A1 for the air temperature thermistor). As you can see in the picture of the full controller, I used a separate circuit board for the thermistor connectors, but if you can fit them on the same circuit board as the Arduino, that would be better.

The Arduino communicates with the Raspberry over a serial connection, i.e., a USB cable plugged into the USB connector. The Arduino writes the values of the water and air temperature to the serial port and it reads the desired state of the relays from the serial port. The attached sketch implements that. Setting the relay pins is just a digitalWrite() function call, while reading the temperature involves reading the raw voltage and then applying a standard formula (which you can find on Wikipedia) to convert that to degrees Fahrenheit (simple change to make it Celsius).

If you have never programmed an Arduino before, It is not difficult. There are many sources that describe how to do it, like this Instructables class. Upload the attached sketch to your Arduino. Then plug it into the IC socket on the circuit board - make sure the pins are lined up properly!

The Arduino has to do two things: respond to commands from the Raspberry Pi to set the relays, and read the water and air temperatures and send them to the Raspberry Pi. It uses serial communication for this.

When a serial message is received on the serial port, the function serialEvent() is called. The format of the relay setting is a single byte where each of the eight bits in the byte corresponds to one of the eight relays. Having the entire message in one byte means there is no need to worry about where the message starts and ends - every byte is a complete message. The byte is decomposed and the bits used to set the relays. It does this every time for all bits, even if the state of the bit has not changed. This is very simple and reliable; there is very little logic in the Arduino code which minimizes the chances of a bug in that code.

The main loop() function of the Arduino calls the function getTemp() twice - once to get the water temperature and once to get the air temperature. The function itself implements a formula you can find on Wikipedia or other places which converts the resistance of the thermistor to a temperature. The temperatures are sent in strings to the Raspberry Pi. Future upgrades (the subject of a future Instructable!) will likely require more than one byte of data, so in this case a string is used with a keyword for the type of data followed by the data itself. The loop has a delay of 2 seconds (2000 milliseconds) because there is no need to send the temperature any more frequently.

That's all the Arduino has to do, set relays and read temperatures. The Raspberry Pi handles everything else.

Step 7: Raspberry Pi and Node Red

The pool controller logic is implemented in Node Red on a Raspberry Pi. Node Red is a system that allows you to create logic flows graphically. The graphical representation makes it easy to understand the flow. You have to do a bit of programming in the nodes but that is not hard.

The UI is implemented with a set of Node Red nodes called the Node Red Dashboard. These nodes provide the dropdown that lets you choose pool, spa or off, the switches to turn on the cleaner, blower, lights and heater, the gauges to show water and air temperature, and the numeric input that lets you set the pool and spa temperatures. It automatically formats the various controls so it looks nice and works properly on a desktop computer web browser or on a smartphone browser.

The model for this flow is that inputs that come in via the serial port from the Arduino and from the various Node Red Dashboard controls set the state of the system. Periodically, a separate process reads the current state of the system, figures out what needs to be set on the Arduino and sends the appropriate commands as a serial message to the Arduino.

For example, there is a switch in the UI called Cleaner. When that switch is turned on, it sets a variable called CleanerSetting to true. There is a node called PoolControlHearbeat that reads the value of CleanerSetting. If it is true, it sends a message to the Arduino to turn on the relay for the cleaner.

If you have not used a Raspberry Pi before, there are many sources that describe how to get one up and running, like this Instructables class. You need to install Raspbian with the desktop so that you can perform the following steps and you will need to connect it to a monitor, keyboard and mouse to set this up, but after it is all set up you will not need the monitor, keyboard or mouse. You probably also want to set it to have a static IP so that you can access it from other devices in your home easily, and if you are going to run it headless, i.e., without monitor, keyboard or mouse, then you will need to enable ssh access (select Raspberry Pi config from the main menu to find these options) so you can access it if you ever need to power it down cleanly (it's not a good idea to just pull the power plug on a Raspberry Pi). For security reasons, I set mine up so that it is only accessible from my home intranet (not from the outside internet). Also, use Raspberry Pi config to ensure logins over the serial port are disabled (for two reasons: you will be using it to communicate with the Arduino so you do not want it to be sending login prompts to the serial port, and so that someone cannot unplug the USB cable and login to it from outside your house).

Lastly, install the Chromium browser and use that for Node Red; as of this writing, Chromium works best with Node Red. After you have set everything up and are logged in, check the main menu - Node Red should be an option on the Programming menu. Select that and let it start to make sure it works. You will need to perform a step to make Node Red start when the Raspberry Pi is booted (so you will not need to start it from the menu every time you restart the Raspberry Pi). Execute the following command in a Terminal window:

sudo systemctl enable node-red.service

Then, reboot. (Note: you need to start it as a service before you import the flow below, otherwise it will not find the flow you imported, so enable it as a service as just described before continuing.) Open the Chromium browser and connect to the address http://localhost:1880. That will open the Node Red workspace in your browser. Check if Node Red Dashboard is installed because it might not be installed by default. Open the menu (hamburger icon at the upper right), then select Manage Palette. Under Nodes, search for node-red-dashboard. If it is not there, go to Install, search for and install it. Once it is installed, you will see a set of nodes under the category dashboard with names like button, switch, gauge, chart.

You can now import the entire flow shown graphically in the attached picture by importing the file attached to this Instructable is called PoolControlFlow.txt. Download it and put it on a USB drive that you insert into your Raspberry Pi. Go to the Node Red menu on the browser page and choose Import. Navigate to the PoolControlFlow.txt file and select it. That will import the entire flow that runs this pool controller, so you don't have to program it all yourself.

Test that you can access the UI is accessible from the browser, too. Open the URL http://localhost:1880/ui. If you set a static IP, try accessing the UI from another computer or smartphone by substituting the IP address for the word localhost in the URL. If you have an Arduino on a breadboard for testing as described earlier, then you can connect it with a USB cable and try the various controls to see the LEDs go on and off (note that and LED on corresponds to the relay being off, and vice versa - that's how the relay board works). You can also connect a couple of spare thermistors for testing that the temperature gauges work.

Node Red Flow Description

If all is working, then you don't need to read this section, but if you are interested, this explains how the various parts of the Node Red flow work.

The ArduinoSerialGet node listens on the serial port for messages from the Arduino. Those messages have a keyword, one of H2O or AIR, followed by a colon and a number that is the value. The SerialMsgRouter node routes the message to one of two nodes corresponding to the keyword. The string is converted to a value that is sent to a gauge on the UI and a node that sets the value of a variable, H2OTemp or AIRTemp.

There are two nodes that set the default temperature settings for the pool, DefaultPoolTemperature (set in the node to 82) and DefaultSpaTemperature (set in the node to 100). Those values feed into the numeric controls on the UI so they have an initial value and also into the PoolTempSetter and the SpaTempSetter which set variables with the values. These are like thermostat settings, they are the temperature you want the pool water to be, while the H2OTemp is the temperature that the pool water is. The RelaySetter (described below) uses these to decide when to turn on the heater.

The Light switch turns the lights in the pool and spa on or off. The can be turned on whether the pool or spa is running or not.

The HeaterEnable switch does not directly turn on the heater. If it is off, then heater will not turn on in any situation. If it is on, then the heater will turn on if needed (see below). This allows you to maintain your temperature settings but not heat the pool until you decide to enable the heater.

The Cleaner switch turns on the automatic cleaner which is driven by a water line from the pump. That is controlled by a valve actuator.

The Blower switch turns on the air blower which adds bubbles to the spa. The blower is an electric motor.

The dropdown Off/Pool/Spa can be set to one of three values: Off, Pool or Spa. This sets a variable, PoolSpaMode to one of those values. This mode is also part of what is used in the RelaySetter to determine when to turn on the heater. The mode also enables or disables certain controls. If the pool is on, then you do not want the air blower for the spa to be turned on. Conversely, if the spa is on, then you do not want the cleaner to be turned on. So, whenever the pool is turned on, it turns off the blower switch and disables it, and also enables the cleaner switch. Whenever the spa is turned on, it turns off the cleaner and disables it, and also enables the air blower. Whenever the Off setting is chosen, it turns off both the cleaner and blower.

The PoolControlHeartbeat periodically sends a message to the RelaySetter which triggers it to check the settings of the cleaner, blower, lights and send the corresponding relay settings to the Arduino. The RelaySetter turns on the pump relay if the mode is Pool or Spa and turns it off if the mode is Off. The RelaySetter also turns on the heater if necessary. It does this by first checking to see if the HeaterSetting is on, i.e., if the heater is enabled. If the heater is enabled, then it determines what is the appropriate temperature setting - if the mode is Pool, then it uses the PoolTempSetting value; if the mode is Spa, then it uses the SpaTempSetting value. It compares that value to the H2OTemp value, i.e., the current water temperature. If the current water temperature is below the setting, then it turns on the relay for the heater, otherwise it turns it off. Lastly, the RelaySetter sets the intake and return valve actuator relays to off if the mode is Pool and on if the mode is Spa.

Once all relay values are known, a single byte is created where each bit corresponds to a relay and where the bit is set (value 1) to turn on the relay and the bit is unset (value 0) to turn off the relay. This byte is sent as a serial message to the Arduino by the ArduinoSerialSet node.

Step 8: Put All the Pieces Together

At this point, you have power supplies, a relay board, a curcuit board with a socket for the Arduino and the thermistors, and a circuit board with sockets for the devices controlled by the relays. Now you need to put all those pieces together. The pictures show two views without some of the cables so you can see how I laid out the components and another with the cables so you can see how it looks completely assembled. Refer to the schematic in the Controller Design section as well.

Drill holes on the Lexan backer to mount the relay board and other circuit boards. Use 4-40 spacers to mount the boards.

The positive output from the 24VDC power supply goes to the middle terminal of each of the relays #1, 2, 3. Daisy chain the connections, i.e., use one wire from the 24VDC power supply to the first relay, then a short piece of wire from the first relay to the second, and again to the third. The normally open (NO) terminals of those relays go to the corresponding connector for the heavy duty relays. The negative output from the 24VDC power supply goes to the second connection for each of the heavy duty relays. There is no connection to the normally closed (NC) terminals of the first three relays.

The positive output from the 9VDC power supply goes to the VIN pin of the Arduino and the negative output from the 9VDC power supply goes to the GND pin of the Arduino. The easiest way to make the wires you need is to get two jumpers with a female header connector on one end and cut off whatever is on the other end and strip the wire.

The 5VDC power supply must only be used for relay board power to achieve the isolation of the inputs from the switched relay connections. Remove the jumper on the three pin header. Connect the positive output to the JD-VCC pin and the negative output to the GND pin.

Connect leg one of 24VAC to the middle terminal of relays #4, 5, 6. Connect the NC terminal to the red wire of each valve actuator and the NO terminal to the white wire of each valve actuator. Connect leg two of 24VAC to the black wire of each valve actuator.

Connect leg one of 24VAC to the NC terminal of relay #7. Connect leg two of 24VAC to the NO terminal of the relay and one side of the heater connection. Connect the middle terminal of relay #7 to the other side of the heater connection. This ensures it is never floating, it is at 24VAC when the relay is off and at 0VAC when the relay is on.

Jumper wires often come in strips of multiple wires fastened together. If you have some like this, peel off a set of ten. Connect one end to the ten pin header on the relay board. Connect the other end of the GND wire to the Arduino Nano GND at the pin next to the RST pin. The other end of the VCC wire has to be connected to the 5V pin on the Arduino, but that is also required for the thermistors, so solder to the same board as the thermistors or add a header pin to that board and plug in the jumper.

Connect the first seven relay inputs to pins D11 through D5 on the Arduino (relay #8 is not used, so I deliberately left it unconnected so it cannot activate the relay).

I salvaged a number of two and three pin PCB headers and corresponding plugs from the old controller by desoldering them. You can do that or buy similar connectors and a crimping tool to make your own. Or, you can buy terminal blocks that you can solder to the circuit boards so all you have to do is strip the wires to be connected. The key thing is that while it is fine to solder connections between circuit boards on the Lexan backer, you want everything that connects something external to the Lexan backer to be a plug and socket so you can easily remove the Lexan backer with all of the circuit boards, relay board and power supplies and work on it in a more convenient location if necessary. I made a couple of mistakes where I had to rewire and resolder certain parts and it was easy since I could just remove the whole panel and bring it to where I had the solder iron and other tools. Label the various plugs and sockets to make it easier to reconnect everything. Put all the two and three pin headers on a separate circuit board next to the outputs of the relays since that is where they all need to be connected.

Add a power connector for the power supply input. I also salvaged that from the old controller so that it would fit the plug that was already fitted to the transformer output.

Step 9: Optional: Test Setup

It is handy to test the controller without having to connect it to the actual pool equipment. You can do this with a breadboard, two spare thermistors, two 10K resistors, seven LEDs, seven 100 or 220 ohm resistors and some jumpers. Create a voltage divider just like the main unit with the thermistors and and 10K resistors and connect the midpoint to pins A0 and A1. Connect each of the pins D5-D11 to one end of a 100 or 220 ohm resistor, then connect the other end of the resistor to the positive lead of the LED, then connect the negative lead of the LED to the ground bus. Connect the power and ground buses to the 5V and GND pins of the Arduino. Connect the USB connector to the Raspberry Pi and boot up the Raspberry Pi. It will power the Arduino via the USB cable.

In the Off setting of the interface, all of the LEDs should light (counterintuitive, yes, but recall that the relays are off when their inputs are high and on when low). As you try the different settings of pool, spa, blower, cleaner and heater, the LEDs should turn on and off appropriately.

The Node Red interface should show the air and water temperatures which you can test by dunking in hot or cold water.

You can test the heater by setting the pool or spa temperature above and below the water temperature shown on the gauge and watching the heater relay LED (pin D5) turn on when the settting is below the water temperature and turn off when the setting is above the water temperature.

Step 10: Install

Now that you have completed the controller unit, you need to mount it by your pool.

Note: the voltages involved with pools include 24VAC, 120VAC and 240VAC, easily enough to kill you if you touch the wrong wires or wire something incorrectly. If you are not experienced with electrical work like this, get an expert to set that up and do just the low voltage part yourself.

Drill holes for 8-32 machine screws in the enclosure that has the power and transformers supplying AC and mount the Lexan to it. Or, if not replacing a unit like I was, create an enclosure with appropriate power supplies. (If you are starting from scratch, you don't have to have three different AC inputs, you can pick whatever is available and cheap for the transformer, as long as it can supply 24VAC and the three DC power supplies.)

Run a USB cable from the enclosure at the pool into your house for the Arduino to Raspberry Pi connection. If you are replacing a controller, there will already be a cable routed between the two locations. Attach the USB cable to that and pull it through. NB: You might ask why not just put the Raspberry Pi outside the house in the pool enclosure as well? That would certainly work and avoid running cables into your house, but keep in mind that the Raspberry Pi has a direct connection to your home network via wifi, including the wifi password, so if it is outside, anyone can get to it and gain physical access to your home network.

The water temperature thermistor needs to be mounted in the water pipe. My old controller's thermistor was mounted in the PVC pipe just downstream of the pump. The new thermistor was slightly larger, so I had to drill the hole out a bit. Run the wire into the enclosure and put the appropriate connector on the end for attachment to the connector on the circuit board. The generic thermistors I bought already had a two pin connector, so it fit into a two pin connector that I salvaged. Place the generic thermistor inside the enclosure with the controller board, that will be the air temperature it measures.

Mount the Raspberry Pi somehow and run power to it. I initially intended to run 5VDC from the controller to the Raspberry Pi so that I would not need a separate power cord, but after reading more about it, decided it was better to power it the normal way, i.e., with a 5VDC power supply inside the house connected to the micro USB connector.

Connect all the controlled devices first, then the USB cable to the Raspberry Pi, then connect power to the unit and turn on the circuit breaker. Nothing should happen except a light glowing on the Arduino since the default is for everything to be off. Start the Raspberry Pi (which should automatically start Node Red if you followed the earlier instructions). Bring up the interface on a web browser and turn on the pool. Check the water and air temperature gauges to make sure they make sense. Test all the other functions to ensure they work. Check that the valve actuators turn in the proper direction; if not, just set the switch on the actuator to its opposite setting.

After you test that all is working, you can run the Raspberry Pi in headless mode. Power it down, disconnect the display and keyboard, then power it back up and test you can still access the web interface and can ssh to the Raspberry Pi.

You're done! Enjoy your pool and spa!

Step 11: Troubleshooting

Note: the voltages involved with pools include 24VAC, 120VAC and 240VAC, easily enough to kill you if you touch the wrong wires or wire something incorrectly. Many of the steps below require the main power to be on so that you can check for proper voltage at the controlled devices. If you are not experienced with electrical work like this, get an expert to help with the troubleshooting.

The relay board has a red LED for each relay that turns on when the relay is activated. If some device is supposed to be on, check that the red LED is on. If the LED for the wrong relay is lit, then check that the jumpers are wired correctly from the pins D5-D11 onthe Arduino to IN1-IN8 on the relay board. If the proper red LED is lit, use a multimeter to determine where in the chain from power supply to the device it is failing. If there is the appropriate voltage at the device, then check the device itself.

The thermistors should have 5VDC applied between the end of the resistor that is connected to the 5VDC connection on the Arduino and the wire of the thermistor that is connected to GND. Check that first, then if it is okay, check that the voltage at the three way connection (other end of the resistor, other wire of the thermistor, wire to pin A0 or A1 of the Arduino) is at some voltage roughly midway between 0 and 5VDC. Make sure the jumper is connected properly to pin A0 or A1.

If the problem is on the Raspberry Pi end, power it down over ssh and restart with a display and keyboard attached. Open Node Red in a browser. The serial interface nodes should show that it is connected to the Arduino. You can add a Debug node to the same output that sends the serial message to the Arduino so that you can see the value of the serial bytes in the Debug window in Node Red. You can add Debug nodes anywhere else to check what is happening. Remember to redeploy after adding or changing any nodes.

The service and installation manuals for heaters, valve actuators, pumps, etc. are often available online. If your device is not like the ones described here, it might be well worth your while to find the manual and see what it says about how it works and how to use it. For example, the manual for my Hayward heater describes in detail the electrical connections and the difference between two and three wire remotes (though it didn't mention that 0VAC is on and 24VAC is off; that I discovered by trial and error!).

Step 12: Parts List

This is a list of the parts used. Prices are for buying from US sources like Amazon. You can save a fair amount by buying electronics from China, e.g., from AliExpress, if you are willing to wait a little for the shipping. Buy things like Arduinos and buck converters and protoboard in multiples of three or five or ten, then you'll have some extra for future projects!

Raspberry Pi - about $35 plus power supply, case - I used a model 3 which has built in wifi but any model that can run Node Red and can connect to your home network. I'm planning to try a Pi Zero W ($10).

Arduino Nano - about $8 for one from local sources or $3 each in multiples of 5-10 from AliExpress or other similar sites - other models would also work but you might have to change the sketch to accommodate different pin layouts. You need one with at least seven digital outputs (for the relays) and two analog inputs (for the thermistors).

Lexan - about $5 for an 8.5x11 sheet from Lowe's or Home Depot

Water thermistor - about $25 - Pentair 520272 from Amazon

Air thermistor - about $2 each in a pack of 5 - OCR 10K-5

USB cable to connect Raspberry Pi and Arduino Nano - about $8 - $10 depending on the length - Cable Matters Gold Plated Hi-Speed USB 2.0 Type A to Mini-B Cable

Relay board - about $7 each in a pack of two - Huayao 2pcs 8 Channel DC 5V Relay Module with Optocoupler for Arduino

Buck converter - about $1.20 each in a pack of 10 (you need 3 for this project) - LIGHTHINKING 10PCS XM1584

Circuit boards (a.k.a., protoboard) - about $6 each, get two - Busboard Protot SB400

Capacitors: 1000uF or 2200uF (not critical) - about $6 for a pack of 10 - Nichicon 2200uF, Nichicon 1000uF. You can use 1000uF or 2200uF for all three, I just happened to have two 1000uF and one 2200uF.

Resistors: 10K ohm - $4 for 100 - 100 Uxcell 10K resistors

Wire and solder


Screws and spacers for circuit board mounting

Optional: breadboard, resistors and LEDs for the test setup

Tools: soldering iron, multimeter, drill

Total cost for parts is about $100 including extras as mentioned above. If you are like me and already have Arduino Nanos, capacitors, buck converters and other items sitting around waiting to be used in projects like this, it will cost less. A lot of electronic parts, like resistors and capactors, are much cheaper if you buy them in assortments that include a number of different sizes and several of each size.

Step 13: Update: Schedule Mode and Pi Zero W

Since I wrote the original Instructable, I made a few changes to NodeRed flow. I added a schedule mode so I can set a schedule for when the pool, spa and cleaner are on. I also added a freeze mode which monitors the air temperature and turns on the pool if the temperature falls below 37 degrees Fahrenheit. This updated flow is attached as PoolControlFlowWithSchedule.txt. Import it into NodeRed and modify the times to suit your needs.

All of the times are grouped together at the top of the flow so that you shouldn't have to dig to deep into the code just to get it to work. The times are in 24 hour format, so [ 8, 0 ] means 08:00 in the morning, [ 21, 30 ] means 9:30 in the evening (21:30), and 15 minutes after midnight is [ 0, 15 ]. You can set the pool schedule, spa schedule and cleaner schedule. The schedule controls the pump and the various actuator valves. It's essentially doing the same thing in code as someone selecting Pool, Spa and Cleaner Enable from the Dashboard, but does it in code. For example, suppose you have the following schedule.

const spaSchedule = {
start: [ 8, 0 ], end: [ 8, 15 ] };
const poolSchedule = {
    start: [ 8, 15 ],
    end: [ 20, 0 ]
const cleanerSchedule = {
    start: [ 8, 20 ],
    end: [ 11, 30 ]

This starts the pump and sets the actuator valves to spa mode at 08:00, then at 08:15 switches the actuator valves to pool mode, then at 08:20 it turns on the cleaner. At 11:30, it turns off the cleaner, then at 20:00 (8:00 in the evening), it turns off everything.

Once you've set the times and imported the flow, the dropdown that formerly provided the options Off/Pool/Spa will have the options Off/Pool/Spa/Schedule. Select Schedule to run the schedule you set or choose Pool or Spa to override the schedule and run the pool or spa as you wish.

The freeze mode runs the pool and spa alternately for 15 minutes at a time. It accomplishes this by simply checking the current time and calculating which quarter of the hour it is in. The code runs one for the first 15 minutes of the hour, the other for the next 15 minutes, etc.

Usually, just ensuring the water is flowing will keep it from freezing. If it is cold enough, however, the water could still freeze (this happened once in 14 winters at my home, during the winter prior to this project). To prevent that, you can enable the heater on the Dashboard and set the pool and spa temperatures to some value just above freezing, e.g., 34 degrees so that it will turn on before the water actually freezes. This will work in Schedule mode. Of course, it will only work if you have not winterized the heater and thus disabled it!

Another update was using a Raspberry Pi Zero W which is cheaper than a full Raspberry Pi 3 ($10 vs. $35). I simply replaced the Pi 3 with the Pi Zero W and inserted the same MicroSD card. The card is interchangeable between the devices, so I find it convenient when making changes to shut down the Pi Zero W, transfer the card to a Pi 3, make the changes, transfer the card back to the Pi Zero W and boot. It works great!

Fix It! Contest

Runner Up in the
Fix It! Contest

Be the First to Share


    • Make it Glow Contest

      Make it Glow Contest
    • First Time Author Contest

      First Time Author Contest
    • PCB Challenge

      PCB Challenge

    139 Discussions


    Question 1 year ago

    Hi and thank you for an outstanding project and documentation. I am just preparing to cobble this together and noticed your comment on freeze protection. Did you ever solve the 37 degree issue? Would you be willing to share your new flow?


    Answer 1 year ago

    I have not implemented it yet (because it got warmer!). The basic idea is to turn on at 36 and turn off at 38, so as it gets colder and possibly fluctuates between 36 and 37, it will turn on and stay on, then as it gets warmer and fluctuates between 37 and 38, it will turn off and stay off.


    Reply 5 weeks ago

    I know this thread is old ... but I had a related issue this morning. The air temperature was fluctuating between 36 and 37 degrees F. With my freeze temp trigger set at 37, the pump was flipping on for 15 seconds, and then flipping off again. Obviously, not good for the pump to turn on and off so often. So I first thought about creating a delay, which was a bad idea (delays are not good in Node-red). Then I read this post and implemented exactly what you suggested. Here's the basics of what I did ...
    1. Create a flow variable called FreezeStatus. Set that status to 0 on startup using the same injector that activates the HeaterEnabled setting.
    2. In the RelaySetter function, define a new variable called "freezetrigger" that has a value equal to the airFreezeSetting constant.
    3. If the system is set to "Schedule". the first thing to check is the FreezeStatus flow variable. If it is "on", then update the "freezetrigger" variable to be the airFreezeSetting + 2 degrees. If the FreezeStatus is "off", then update the freezetrigger variable to be the airFreezeSetting.
    4. Then test the air temperature against the new "freezetrigger". If it is less than the trigger, then set the FreezeStatus flow variable to "on" and proceed with the pump/pool/spa settings as currently exist.
    5. If the air temperature is equal to or greater than the "freezetrigger", then set the FreezeStatus flow variable to "off" and proceed with the scheduled times.

    Using some numbers helps ... If I have the airFreezeSetting at 37 F, then once I drop below that value, the FreezeStatus variable is set to "on" and the new airFreezeSetting is 39 F. That means the pump won't turn off until the air temperature reaches 39 F. Once the temperature hits 39 F, the FreezeStatus variable is set to "off", and the trigger temperature is set back to 37 F. Thus the pump won't cycle on/off/on/off by a temperature fluctuating between 36 and 37 degrees. Here's a snippet of my code:

    if (freeze == 1) {
    freezetrigger = airFreezeSetting + 2;
    } else {
    freezetrigger = airFreezeSetting;
    if (airtemp < freezetrigger) {
    flow.set("FreezeStatus", 1);
    var m = d.getMinutes();
    var q = Math.floor(m/15);
    var b = q%2;
    // Run cleaner while running pool so it doesn't freeze.
    if (b) {
    pumpmode = "Pool";
    cleanermode = true;
    } else {
    pumpmode = "Spa";
    cleanermode = false;
    } else {
    if (inSpaSchedulePeriod(d)) {
    pumpmode = "Spa";
    cleanermode = false;
    } else {
    if (inPoolSchedulePeriod(d)) {
    pumpmode = "Pool";
    // Only run cleaner if pool is running.
    if (inCleanerSchedulePeriod(d)) {
    cleanermode = true;
    } else {
    cleanermode = false;
    } else {
    pumpmode = "Off";


    Reply 5 weeks ago

    Thanks for sharing this. I implemented my idea a while ago but it did not work properly. When I saw your code, I realized my mistake - I was setting the freeze state in a local variable instead of a flow variable (like your "FreezeStatus"). I fixed that this morning and now it's working!


    Question 7 weeks ago

    Thank you very much for this write-up! I am in the middle of setting it up to convert my pool from two mechanical timers to this system at the fraction of the cost of buying a fully automated system. So thank you for putting this together!

    I am trying to understand a bit of code in the node-red flow that you provided. The relevant code is:

    1 const setBit = (num, position) => {
    2 let mask = 1 << position;
    3 return num | mask;
    4 };

    There is similar code for clearing the Bit ... I understand that "num" is a value of 0 or 1 for the bit and "position" is the specific bit that will be assigned. Obviously, the above function will set a Bit to 1 (and clearBit will set it to 0). But I don't follow the logic here. What does the second and third lines do? Can you help explain what this code is doing?
    Thanks in advance!


    Answer 6 weeks ago

    Hi, I'm glad you're building this project!

    The "num" argument is a byte (8 bits) and the "position" argument is the position of a bit you want to set. An important point is if "num" already has some bits set, the setBit function will not alter any bits except it will set the one at "position". On to the code: the number 1 is a byte with the rightmost bit set. The expression "1 << position" shifts that bit "position" places to the left, then it is assigned to the variable "mask". At this point you have a byte ("mask") with the bit at "position" set and the rest of the bits unset. The next step is to create a byte that has every bit in "num" set plus the bit at "position" set. That is what the expression "num | mask" does. The function clearBit is analogous, it clears just the bit desired without affecting any other bits. Does that help?


    Reply 5 weeks ago

    Thanks for sharing. Yes, that makes sense now. I'm not familiar with bits and bytes in programming, so this one was confusing. Your explanation makes a lot of sense. now.

    I finally installed my system yesterday and it is working flawlessly. I'll admit that I only have 2 items connected (main pump and booster pump for cleaner) right now, but I may be adding the other items as needed in the future (my system was completely manual until I installed this system).

    I also updated the code a bit to add a status portion to the controller. I updated the Arduino code to send back the status of each pin along with the air and water temperatures. Then I converted those status values into "LEDs" on the status screen (see image). The code for Node-RED is below. The Arduino code that I added is after that.

    Node-RED code:
    [{"id":"2c4e0270.1eb2ce","type":"serial in","z":"146c2038.8db98","name":"ArduinoSerialGet","serial":"2df3db69.684484","x":114,"y":56,"wires":[["d6acf235.b072f"]]},{"id":"3e7e7c0d.7a0614","type":"ui_gauge","z":"146c2038.8db98","name":"","group":"9be6d274.9dd69","order":0,"width":0,"height":0,"gtype":"gage","title":"","label":"F","format":"{{value}}","min":0,"max":"120","colors":["#ca3838","#e6e600","#00b500"],"seg1":"34","seg2":"70","x":573,"y":87,"wires":[]},{"id":"f21167c0.500ff8","type":"ui_gauge","z":"146c2038.8db98","name":"AirTemp","group":"a85a0c1d.bc66f","order":0,"width":0,"height":0,"gtype":"gage","title":"","label":"F","format":"{{value}}","min":0,"max":"120","colors":["#ca3838","#e6e600","#00b500"],"seg1":"36","seg2":"70","x":579,"y":181,"wires":[]},{"id":"d6acf235.b072f","type":"switch","z":"146c2038.8db98","name":"SerialMsgRouter","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"H2O","vt":"str"},{"t":"cont","v":"AIR","vt":"str"},{"t":"cont","v":"PUMP","vt":"str"},{"t":"cont","v":"LIGHT","vt":"str"},{"t":"cont","v":"BLOWER","vt":"str"},{"t":"cont","v":"INTAKE","vt":"str"},{"t":"cont","v":"RETURN","vt":"str"},{"t":"cont","v":"CLEANER","vt":"str"},{"t":"cont","v":"HEATER","vt":"str"},{"t":"cont","v":"UNUSED7","vt":"str"}],"checkall":"false","repair":false,"outputs":10,"x":150,"y":200,"wires":[["be23e135.7ea97"],["77746840.7f2a38"],["5351852c.dfb88c"],["19d92653.25743a"],["c3fa91e8.aff79"],["cd01891.8661278"],["b07f0743.b280e8"],["9e2c0710.33b9d8"],["44be005d.ba0a7"],[]]},{"id":"be23e135.7ea97","type":"change","z":"146c2038.8db98","name":"H2Ovalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"H2O:([0-9]+)","fromt":"re","to":"$1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":80,"wires":[["3e7e7c0d.7a0614","b7837816.e6e138"]]},{"id":"77746840.7f2a38","type":"change","z":"146c2038.8db98","name":"AIRvalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"AIR:","fromt":"str","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":120,"wires":[["f21167c0.500ff8","3f64d670.304bba"]]},{"id":"b7837816.e6e138","type":"function","z":"146c2038.8db98","name":"H2OTempSetter","func":"flow.set(\"H2OTemp\", parseInt(msg.payload, 10));\nreturn msg;","outputs":1,"noerr":0,"x":594.9999389648438,"y":51.44444274902344,"wires":[[]]},{"id":"3f64d670.304bba","type":"function","z":"146c2038.8db98","name":"AIRTempSetter","func":"flow.set(\"AIRTemp\", parseInt(msg.payload, 10));\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":595.6666259765625,"y":145.11109924316406,"wires":[[]]},{"id":"5351852c.dfb88c","type":"change","z":"146c2038.8db98","name":"Pumpvalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"PUMP:","fromt":"re","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":160,"wires":[["6ff50b8c.9e0f34"]]},{"id":"6ff50b8c.9e0f34","type":"function","z":"146c2038.8db98","name":"LEDSetter","func":"//flow.set(\"PumpStatus\", parseInt(msg.payload, 10));\nmsg.color = (parseInt(msg.payload, 10) === 1)?\"red\":\"lime\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":220,"wires":[["1f4fc3a4.ce8e4c"]]},{"id":"1f4fc3a4.ce8e4c","type":"ui_text","z":"146c2038.8db98","group":"5c2c4c03.b5a294","order":1,"width":0,"height":0,"name":"PumpLED","label":"Pump ","format":"","layout":"row-spread","x":790,"y":220,"wires":[]},{"id":"19d92653.25743a","type":"change","z":"146c2038.8db98","name":"Lightvalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"LIGHT:","fromt":"re","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":200,"wires":[["1b93a14c.e9ff8f"]]},{"id":"1b93a14c.e9ff8f","type":"function","z":"146c2038.8db98","name":"LEDSetter","func":"//flow.set(\"PumpStatus\", parseInt(msg.payload, 10));\nmsg.color = (parseInt(msg.payload, 10) === 1)?\"red\":\"lime\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":260,"wires":[["2c50d25d.0857ee"]]},{"id":"2c50d25d.0857ee","type":"ui_text","z":"146c2038.8db98","group":"5c2c4c03.b5a294","order":5,"width":0,"height":0,"name":"LightLED","label":"Light","format":"","layout":"row-spread","x":780,"y":260,"wires":[]},{"id":"c3fa91e8.aff79","type":"change","z":"146c2038.8db98","name":"Blowervalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"BLOWER:","fromt":"re","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":240,"wires":[["54239f77.bf32a"]]},{"id":"54239f77.bf32a","type":"function","z":"146c2038.8db98","name":"LEDSetter","func":"//flow.set(\"PumpStatus\", parseInt(msg.payload, 10));\nmsg.color = (parseInt(msg.payload, 10) === 1)?\"red\":\"lime\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":300,"wires":[["10ba3d0f.b63693"]]},{"id":"10ba3d0f.b63693","type":"ui_text","z":"146c2038.8db98","group":"5c2c4c03.b5a294","order":4,"width":0,"height":0,"name":"BlowerLED","label":"Blower","format":"","layout":"row-spread","x":790,"y":300,"wires":[]},{"id":"cd01891.8661278","type":"change","z":"146c2038.8db98","name":"Intakevalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"INTAKE:","fromt":"re","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":280,"wires":[["2b09626f.9b8a1e"]]},{"id":"2b09626f.9b8a1e","type":"function","z":"146c2038.8db98","name":"LEDSetter","func":"//flow.set(\"PumpStatus\", parseInt(msg.payload, 10));\nmsg.payload = (parseInt(msg.payload, 10) === 1)?\"Pool\":\"Spa\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":340,"wires":[["3ac7123b.022f2e"]]},{"id":"3ac7123b.022f2e","type":"ui_text","z":"146c2038.8db98","group":"5c2c4c03.b5a294","order":7,"width":0,"height":0,"name":"IntakeStatus","label":"Intake","format":"{{msg.payload}}","layout":"row-spread","x":790,"y":340,"wires":[]},{"id":"b07f0743.b280e8","type":"change","z":"146c2038.8db98","name":"Returnvalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"RETURN:","fromt":"re","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":320,"wires":[["b9067667.c34658"]]},{"id":"b9067667.c34658","type":"function","z":"146c2038.8db98","name":"LEDSetter","func":"//flow.set(\"PumpStatus\", parseInt(msg.payload, 10));\nmsg.payload = (parseInt(msg.payload, 10) === 1)?\"Pool\":\"Spa\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":380,"wires":[["a0c28f53.d7333"]]},{"id":"a0c28f53.d7333","type":"ui_text","z":"146c2038.8db98","group":"5c2c4c03.b5a294","order":6,"width":0,"height":0,"name":"ReturnStatus","label":"Return","format":"{{msg.payload}}","layout":"row-spread","x":790,"y":380,"wires":[]},{"id":"9e2c0710.33b9d8","type":"change","z":"146c2038.8db98","name":"Cleanervalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"CLEANER:","fromt":"re","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":360,"wires":[["4ef31ce0.ec24b4"]]},{"id":"4ef31ce0.ec24b4","type":"function","z":"146c2038.8db98","name":"LEDSetter","func":"//flow.set(\"PumpStatus\", parseInt(msg.payload, 10));\nmsg.color = (parseInt(msg.payload, 10) === 1)?\"red\":\"lime\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":420,"wires":[["24324dea.b64aa2"]]},{"id":"24324dea.b64aa2","type":"ui_text","z":"146c2038.8db98","group":"5c2c4c03.b5a294","order":2,"width":0,"height":0,"name":"CleanerLED","label":"Cleaner","format":"","layout":"row-spread","x":790,"y":420,"wires":[]},{"id":"44be005d.ba0a7","type":"change","z":"146c2038.8db98","name":"Heatervalue","rules":[{"t":"change","p":"payload","pt":"msg","from":"HEATER:","fromt":"re","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":400,"wires":[["f1ab9f22.5e19e"]]},{"id":"f1ab9f22.5e19e","type":"function","z":"146c2038.8db98","name":"LEDSetter","func":"//flow.set(\"PumpStatus\", parseInt(msg.payload, 10));\nmsg.color = (parseInt(msg.payload, 10) === 1)?\"red\":\"lime\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":460,"wires":[["9c7897cc.eb3928"]]},{"id":"9c7897cc.eb3928","type":"ui_text","z":"146c2038.8db98","group":"5c2c4c03.b5a294","order":3,"width":0,"height":0,"name":"HeaterLED","label":"Heater","format":"","layout":"row-spread","x":790,"y":460,"wires":[]},{"id":"ab01bcd1.c410e","type":"inject","z":"146c2038.8db98","name":"shutdown!","props":[{"p":"payload","v":"","vt":"date"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"","once":false,"topic":"","payload":"","payloadType":"date","x":880,"y":60,"wires":[["8f9f1fe.3f891e"]]},{"id":"8f9f1fe.3f891e","type":"exec","z":"146c2038.8db98","command":"sudo poweroff #","addpay":false,"append":"","useSpawn":"","timer":"","name":"turn off Pi","x":1054,"y":59,"wires":[[],[],[]]},{"id":"bd867dee.48345","type":"ui_button","z":"146c2038.8db98","name":"Shutdownbutton","group":"5c2c4c03.b5a294","order":8,"width":0,"height":0,"passthru":false,"label":"Shut Down Pool Pi","tooltip":"","color":"","bgcolor":"blue","icon":"fa-warning","payload":"","payloadType":"str","topic":"","x":910,"y":160,"wires":[["8f9f1fe.3f891e"]]},{"id":"2df3db69.684484","type":"serial-port","serialport":"/dev/ttyUSB0","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false,"responsetimeout":"10000"},{"id":"9be6d274.9dd69","type":"ui_group","name":"Water Temperature","tab":"fb3422ea.1e1b6","order":2,"disp":true,"width":"6","collapse":false},{"id":"a85a0c1d.bc66f","type":"ui_group","name":"Air Temperature","tab":"fb3422ea.1e1b6","order":3,"disp":true,"width":"6","collapse":false},{"id":"5c2c4c03.b5a294","type":"ui_group","name":"Status","tab":"fb3422ea.1e1b6","order":4,"disp":true,"width":"6","collapse":false},{"id":"fb3422ea.1e1b6","type":"ui_tab","name":"Nathan's Pool Control","icon":"dashboard","disabled":false,"hidden":false}]

    Arduino code:
    void loop() {
    // Read water temp and air temp in turn and write status
    // of each to serial port.
    int8_t val;
    val = getTemp(P_H2O);
    val = getTemp(P_AIR);
    val = digitalRead(P_PUMP);
    val = digitalRead(P_LIGHT);
    val = digitalRead(P_BLOWER);
    val = digitalRead(P_INTAKE);
    val = digitalRead(P_RETURN);
    val = digitalRead(P_CLEANER);
    val = digitalRead(P_HEATER);
    val = digitalRead(P_UNUSED7);


    Reply 5 weeks ago

    That status indicator is a nice enhancement. And it's great you have it up and running!


    Question 5 months ago

    Hi again! You've been so helpful in the past and I'm finally at the last leg of my project - hooking up my heater to my raspberry pi using a serial connection. Would you by chance know WHERE to hook up the wires using the USB RS485 serial connection? I can't for the life of me figure this part of it out. My pentair heater is a three wire system (model 472592) but my serial USB adapter is two wires. And then I don't see how this connection could even set the temps. Or maybe I'm just totally not understanding how this works. This part of the project I haven't been able to find many resources. Any feedback would be appreciated!
    The manual:
    The serial connector:


    Reply 5 months ago

    I looked at the manual for your Pentair pool heater. It (and many others) have two basic modes of operation. The first basic mode is you can set a pool temperature and a spa temperature at the heater, then turn on pool or spa mode and the heater will handle measuring the temperature and heating until it reaches the preset temperature. Your heater lets you get into that mode either via the pool or spa buttons on the heater, or remotely with the three wire mode. The second basic mode is where a remote device handles measuring the temperature and deciding when to turn on and off the heater. That mode for your heater is called two-wire mode. This second mode is what my article described. That's why my setup included thermistors and a Node Red interface to set the temperatures, and also why the connection to the heater was a simple 24VAC two wire connection. If you've set up your system similar to my article, then you want to use two wire mode on your heater. From looking at the manual for your heater, it appears that instead of supplying 24VAC, you just need to close the circuit. You could do that by connecting two wires from the Fireman's Switch connections on your heater to the relay (using the two connections which connect when the relay closes). You can test it beforehand by connecting a jumper across the two Fireman's Switch connections. If the heater turns on after a bit, then that's how it works. At least, that's how I read the manual, you need to make sure you understand how it works to avoid frying your heater, or getting a shock, or worse! Note that you do need a relay because the current will be too much for direct connection to a Raspberry Pi. I don't think you need or can use the USB RS485 adapter at all.


    Reply 5 months ago

    OK yeah, that make a ton more sense than what I was trying to square up in my head. I have one big key difference in my project that throws a wrench in things- for some reason the heater and main pump are wired to use the same 240v line. I assumed this was a safety decision so that the heater could never turn on without the pump being on. (Then you just have to worry about turning the heater off and allow the pump to pump cold water through the heater). Then you can just control the on/off and temp settings of the heater using a COM-like line. That's what I thought the nodeJS project did. I thought it reverse engineered the pentair's computer/buttons. I've already programmed the pumps and lights and water features and actuators etc using my own code...

    So I really like the idea of controlling the on/off with the two wire system, and eventually I will end up doing this... but I'd have a lot more homework/work to do. I'd have to wire in a new 240v line, install therms, and probably use some of that nodeJS project. I was really thinking I could just control the heater like I would pressing the buttons on the panel using the setup I have. That would make everything so much easier. I'm almost tempted to use servos to physically press the buttons or hijack the membrane pad connection wires to trigger the buttons!

    I think I still have a shot at making this work using the setup I have, by using the three wire system - but I'd need the ability to turn the heater off without cutting the power (like pressing the heater off button on the panel does). So we have the "pool" and "spa" presets - those both turn the heater on and off using the onboard temp controls... The manual hints at that if neither mode is selected the heater will be off....

    Use at least 2 relays per heater, to allow for an “OFF setting” on each heater mode. Select relays that can handle logic level switching. DO NOT apply line voltage to control board terminals
    What is "logic level switching"? Doesn't that just mean if I connect Pool to Common it will enable pool mode, spa to common for spa mode, and if nothing is selected, it will stay off? That's what I'm hoping anyways, and this seems like a super easy thing to test. Thanks again for your help and reading my (hopefully coherent) ramblings!


    Reply 5 months ago

    I do not think you would need to install another 240V line for any configuration. When the pump is on, 240V is also supplied to the heater, but the heater will not turn on until there is an explicit action taken to turn it on via the keypad, or the two or three wire connections.

    If you want to control the heater like pressing buttons on the panel, then you will use the three wire mode and you won't need thermistors and all that. It also means you will not need the temperature measuring or setting in the interface because you will not use those, you will use the panel on the heater to set the temperature.

    Logic level switching means a relatively low voltage, like 5V or 3.3V (Raspberry Pi is 3.3V, Arduino Nano like I used is 5V) and it's either low (zero volts) or high (5 or 3.3V). See if you can find a mention of a low voltage like this in the manual. If it's 3.3V then you could literally control it directly from a Raspberry Pi pin. If it's 5V, then you can use a logic level converter.

    It's possible that as you suggest, connecting Pool or Spa to Common would turn it on, but it could be the opposite (Common is off and High is on). See if you can find a mention of which way it is in the manual, too.


    Reply 5 months ago

    but the heater will not turn on until there is an explicit action taken
    to turn it on via the keypad, or the two or three wire connections.
    You would think so, but there must be a CMOS in the heater because if you have the heater on when you cut the power, it will automatically turn back on when you give it power. At least I think so. But I never let that happen because I'm careful to turn the heater off before I cut the power.

    I just wish there were three modes since I heat the pool to a specific number, but then the jacuzzi I have a "low" temp preference for the kids (97), and a "high" temp preference for adults and my back issues (103) haha. So I'll still have to crawl back to my equipment to set the temp every once in a while I guess.. for now.

    Looking forward to trying the three wire approach. I think that will totally work for now, I will report back. Dude. Thanks again. This page has by far been the most valuable research for me.


    Reply 5 months ago

    I'd test the heater by cutting power, setting the jumper for three wire mode, not connecting anything to the pool and spa connection, then giving it power. I expect it will not turn on. Check the voltage between Pool and Common and between Spa and Common, I expect it to be a low voltage like 3.3V or 5V. My guess is you turn on the heater by pulling either Pool or Spa to the same level as Common. If that is true, then a jumper between Pool and Common on the three wire connector should make the LEDs on the keypad show something and the heater go on (if the water temp is below the Pool temp setting). Same with Spa and Common. I'm not sure, though. Also, caution: there's high voltage in there, so be careful!


    Reply 5 months ago

    Wow, so check this out... I went to change the jumper and... I finally had to take a high res picture of the board because holding my head upside down inside the unit was giving me a neck ache trying to find this thing. After scouring the photo at 500% zoom, the closest thing to JMP3 I found was JMP1 which appears to just be 3 empty solder pads. Tomorrow I'm planning on unscrewing the panel and seeing if the jumpers are on the other side of the board... which would be... interesting. Have you ever seen anything like this? I'm guessing it's going to be impossible to pull the actual tech schematics for this board, so if the jumpers aren't on the opposite side of the board, I'm going to be completely at the mercy of Pentair to help me figure out how to enable the 3 wire remote control mode. I can't imagine Pentair requiring pool techs to solder tiny patch cables Unless you can see some glaring obvious jumper that I'm incapable of seeing somehow. Here's the high res pics on imgur in case instructables tries to compress them:
    EDIT: So TIL about solder jumper pads. Which I'm thinking what might be happening here. The online manual looks an awful lot like jumper pins, but the schematics here look like solder jumpers. I'm assuming JMP1 refers to pin 1 of the three pin jumper pad set? JMP3 would be pin 3? What I don't get is that shouldn't there be a connection between pins 2 and 3 already? I'm not totally nervous about soldering here - I have some good practice under my belt now... but... I'm still in a bit of shock that I would have to solder my heater board and why isn't there already a connection between pins 2 and 3... Have any thoughts? I obviously wouldn't solder anything until I was 100% sure what I was doing (I wonder how helpful Pentair phone support is!?)

    EDIT2: Found this on the web... Now I'm wondering if soldering the pads is even going to work since Pentair told this guy it wouldn't. And he said he soldered the "two circular pads" which I'm reading as pins 2 and 3 which would disable the toggle. Usually the square pin is 1? Sheeeeeesh. What do you think?


    Reply 5 months ago

    The numbering usually is for the whole component, so JMP1 would be one jumper with several pins, JMP2 another jumper somewhere else on the board, JMP3 yet another. Not pin numbers. I have serious doubts that JMP1 is the jumper you need but I do not see JMP3 where expected on the board. A long shot: since the jumper is to disable the keypad, maybe they moved it there? Can you get at the circuit board for the keypad easily?

    Also, what are the labels on the six pin header labeled J8? That header is not on the diagrams.


    Reply 5 months ago

    I checked my board again and there's definitely no jmp3. I'm pretty sure they just updated the board and not the documentation. See this thread with a few people having the same issues:
    In this thread, there's a picture of a board with a revision number slightly older than mine has the jumper pins are in the exact place as mine are, and are labeled JMP1, but they have the actual header pins / jumper. I will definitely call Pentair at this point. One comment even said you can just use the 3 wire system without the jumpers at all. But if that's the case, I'm worried I won't be able to turn the heater off using the 3 wire system (if there's no spa or pool mode with a completed circuit, I was assuming the heater would stay off)

    So right now I'm leaning towards hopefully being able to solder pins 2 and 3 together, and then using the 3 wire system to turn the heater on, set to pool or spa mode, or if neither is selected, the heater is off.... crossing my fingers.


    Reply 5 months ago

    I share your concern that if you don't disable the keypad then you might not be able to turn off the heater, but you could test it. Set the pool temp to above the current temp, then turn on pool heat with the membrane keypad. It should go on. Then turn off the pool heat with the membrane keypad (while the water temp is still below the setting). That just ensures the settings are correct for the real test, which is to put a jumper across the Pool and Common terminals of the 3 pin connector. The pool heat should come on. Then remove the jumper and it should go off. There might be delays built in to the system, so don't expect things to turn on or off immediately, wait a couple of minutes to see if it has an effect. If that works, you don't need to solder anything, you just need to remember not to use the membrane keypad because you will effectively have dual controls where either the membrane keypad or your Raspberry Pi can turn it on and both have to be off for it to be off.


    Reply 5 months ago

    Just got off the phone with Pentair. They're sending me a new board. They removed the jumpers since they thought no one used the three wire system but then got a bunch of complaints. He also all but confirmed that if neither the pool nor spa is closed to common, the heater should turn off. So it looks like my project is almost back on task! Thanks as always for your input


    Reply 5 months ago

    Great! Good luck. You can work on setting up the relays and corresponding code to operate them while waiting. :-)