For those of you with a swimming pool and a solar heating system — this project is for you. If you have neither of these then hopefully after reading this article you will be inspired to start your own Raspberry Pi project. Let’s begin.
I recently completed a Raspberry Pi project that uses Spring Boot and Java, Python and Angular to control the toggling on and off of a pool pump that heats my swimming pool. The idea came to me when I realised that I need to be more power-conscious, not only to help the environment but also to save a few bucks on electricity bills.
I wanted a solar heating system that would only be on when needed. Some might say a timer from your local hardware store would suffice. Just set it to turn on at 6 AM and turn off at 6 PM. I on the other hand am an over-thinker (it’s both a curse and a blessing). What if it rains during these times? Not only will the pool pump be running unnecessarily, but you allow the pool temperature to drop, losing heat already in the water. No no no! A timer is old fashioned. Why not make it temperature controlled? This way I can save the heat of the water and save even more on my electricity bill.
So the premise is this. To build a toggler that will turn on or off my pool pump based on the temperature I give it. It needs to get temperature from some kind of sensor which needs to be placed close to the solar panels responsible for heating the water. Simple right? On the contrary. As I plan on getting more involved with IoT projects, I didn’t want to start my first project off with having to build an interface for every new IoT project, so I opted to create a control hub that will manage all my smart devices. Whoa, that was a mouthful, let me break it up into sections. Let's start with the temperature sensor.
The NTC Thermistor was the temperature sensor I opted to use for this project. A Negative Temperature Coefficient (NTC) thermistor is a resistor (an element that limits current) that decreases its resistance as it gets hotter. By measuring the voltage of the thermistor (which has a direct relationship with its resistance) and converting that resistance to a degrees Celsius value we can determine what the temperature of the thermistor is.
To measure the voltage of the thermistor we use a principle called voltage divider — voltage gets divided between components of a circuit. The circuit used was one comprised of the thermistor and a resistor.
By placing multi-meter probes between the 2 leads of the thermistor and setting it to measure voltage we can find the voltage applied to the thermistor (the remaining voltage will be across the resistor of known resistance).
Again this sounds simple but one caveat is that the heart and soul of this system is a Raspberry Pi. Why is this a problem? Well unlike Arduino’s that have a built-in analog to digital converts, at the time of writing the Raspberry Pi doesn’t (it's a digital-only micro-controller). The voltage of the thermistor is an analog reading, meaning the value can be anything between a set of voltages (for example 0V and 5V) whereas our digital device (the Raspberry Pi) understands only finite values (depending on the accuracy of the digital device, can be anything between 0 and a power of 2). See the article by Sparkfun for more on analog vs digital readings. So we are tasked with mapping our analog voltage to a digital voltage. This is the job of an Analog to Digital Converter (ADC), more specifically, the MCP3002 ADC.
The MCP3002 is a 10-bit converter meaning our thermistor’s digital voltage will lie between the values 0 and 1023.
Now the question is, how do we use this chip to convert our analog voltage to digital voltage? By using the relationship:
Substituting in the 5V analog sensor circuit voltage that will be used and the ADC resolution of 1024, we get the equation defining the digital voltage.
As an example, say we measure the thermistor voltage to be 2.12V from our voltage divider circuit. The digital voltage equivalent using this equation will be 434.
The MCP3002 ADC has 6 pins. 2 of its pins are used to read in the analog voltage (either pin can be used), the remaining 4 pins are used for SPI communication. Via SPI we are able to send the analog voltage from the temperature sensor to the Raspberry Pi in its digital format.
The Serial Peripheral Interface (SPI) communication protocol is used for synchronous communication (only 1 physical connection carries all the data). Both the MCP3002 ADC chip and the Raspberry Pi have SPI interfaces to perform to facilitate the SPI protocol. The 4 pins and their use are explained below
SCLK (Clock) — signal sent from master (which for this project is the Raspberry Pi) to slave (the temperature sensor) to synchronise data sent and data received
MOSI (Master Out Slave In)— to send data from the master device to the slave device
MISO (Master In Slave Out)— to send data from the slave device to the master device
SS (Slave Select) — used to wake-up the slave device telling it that communication is about to take place
For more on how the SPI communication protocol works see Circuit Basics blog on the subject.
Now that you know how communication within the system takes place we can understand how to translate digital voltage to degrees Celsius using the modified Steinhart equation.
Modified Steinhart Equation
Typically a temperature table is provided from the manufacturer of the thermistor. Such a table is shown in the image below
From this table we can easily match thermistor resistance to temperature values. We could simply program the manufacturer provided temperature table in our program and Bob would be my uncle, but of course, my Uncle is not Bob. The thermistor manufacturer I went with did not provide such a table. I was only supplied with a beta value.
With the beta constant, we can use an equation known as the modified Steinhart Equation to obtain temperature readings from our thermistor.
Where T0 and R0 are temperature and resistance of the thermistor at room temperature respectively, B is the beta value and T is the temperature in Kelvin. By rearranging the equation to make T the subject and converting Kelvin to degrees Celsius we get the following equation.
A brilliant article by Adafruit dives deeper into the Modified Steinhart and Steinhart equations and even provide in-depth discussions on how to improve the accuracy of the measured temperature.
Now that we have our temperature sensor sub-system defined, it's time to turn our attention to the system responsible for turning on the pool pump. The relay circuit.
The relay module used is the Keyes SR1y relay module. It exposes 3 pins, the signal pin (marked with an S), the positive pin (+) and the negative pin (-). In addition, it has 3 screw terminals, COM (Common), NC (Normally Closed) and NO (Normally Open). 5V power is supplied to the positive and negative pins from the Raspberry Pi. This power is used to electromagnetically close the connection between the COM and NO screw terminals or open the connection between the COM and NC screw terminals.
The live wire connection of the pool pump connects to the COM and NO terminals (connecting it to the NO terminal means the pump will be off initially). Any of the logic pins on the Raspberry Pi connects to the S pin and is used to tell the relay circuit to toggle on or off. In my case, I chose to use pin GPIO_03 (pin 15 on the Raspberry Pi). By setting this pin to HIGH we are able to toggle the pump on. Its state is LOW at the startup of the Raspberry Pi and is the reason I went with this pin (we don’t want the pump to turn on and off during the startup of the system).
If you would like to choose another pin to use, consult the BroadCom BCM2835 ARM Peripherals Manual page 102 to view which pins have LOW and HIGH turn-on states.
This part of the project was supposed to be the easiest, however, I spent most of my time debugging issues with the relay not toggling. Turns out my ground connection was not truly grounded.
Raspberry Pi Grounds
The Raspberry Pi Zero has 7 ground pins that I could have chosen from to ground the relay module. I arbitrarily chose pin 34 as ground and connected the relay module’s (-) terminal to it. Sending a test signal from the Raspberry Pi I couldn’t hear the satisfying click of the relay. Next, I grabbed my trusty multimeter and measured the voltage between the (+) and (-) terminals of the relay module — 3.5V . That was not right. I expected to measure close to 5V. I leaned back and gave one big sigh (because that always works). Turns out that the ground connection was not truly 0V.
I changed the ground and finally, I could hear the relay clicking away. So be warned. There may be some noise on Raspberry Pi ground connections. To check this, simply set a multimeter to measure voltage, connect 1 probe to a ground connection and use the other probe probing away at all other grounds. You should measure 0V for each of the connections you test. Stay away from any ground that measures anything other than 0V.
Now, putting it all together — the circuit layout
All the connections in the schematic above were done according to the explanation given in the previous sections. The (Bill of Materials) BOM follows.
Now it's time to turn that bark into a bite. All of the construction shown below closely followed the component layout discussed previously.
The thermistor subsystem comprised the 2 core 5-meter long cable, a 3 pin female connector, the 2.7K Ohm resistor and the thermistor. The resistor was soldered to one pin of the female connector. The female connector was soldered to one end of the 2 core cable and the other end to the thermistor.
The connecting of the Raspberry Pi Zero, MCP3002 and relay followed. A trick when soldering something to a Veroboard is to stick the components through the holes, bending the leads to keep them in place and then using Prestik to keep the components as close as possible to the board for neatness before soldering. Once the MCP3002 chip and connectors were soldered to the Veroboard I turned my attention to cutting holes into the enclosure. Holes for the pump connection and thermistor were drilled and holes to bolt the relay module and Raspberry Pi to the enclosure lid were made. The most satisfying feeling is to see how everything just fits together!
Next, I needed something to close up the thermistor and hold it to the solar panels for an accurate temperature reading. This was the week I bought a 3D printer. Guess what my first print was? (No, not the famous first print benchy).
Finally, I laid the wire from the solar panels to the pump and bolted the pump controller to the pump housing where I connected the pump to the relay screw terminals.
That does it for the brawn of the project (hardware), now for the brains (software). The system's layout follows
There are 2 Raspberry Pi’s used in this project. The first is the control-hub and the second is the pump-controller.
As mentioned in the introduction, the control-hub is responsible for servicing end users of the pump-controller. Users can set the turn on temperature (the temperature at which the pump must be turned on) and the override status of the pump (whether the pump must be on, off or run autonomously). Together these 2 attributes form the pump configuration.
The front end will also display the most recent temperature measured by the pump controller, the determining temperature for turning on or off the pool pump and the toggle status (on or off) of the pool pump.
Having an understanding of the systems in the project, let's move on to the software architecture.
The architecture is simple. At its core it uses the publish/subscribe architectural pattern and the observer design pattern.
Let's start with the pub/sub pattern. It works like this:
- A publisher or producer sends messages to a queue.
- A subscriber or consumer then subscribes to that queue to receive messages.
- The producer and consumer only know about the queue they send or receive messages to or from.
- A broker (which for this application is the RabbitMQ message broker) accepts and forwards messages to and from queues.
For more on how RabbitMQ messaging works, follow their tutorial on their website.
The need for the pub/sub pattern is for the control-hub to communicate with the pump-controller when the pump configuration has changed and also for when the pump-controller sends the ambient temperature and pump toggle status to the control hub.
The observer pattern is used in the control-hub to notify components of the received ambient temperature reading.
The pump-controller uses the pattern to notify the togglers of the update and whether the manual toggler must be used or the automatic toggler needs to adjust itself.
Together, the publish and subscribe pattern and the observer patterns are what makes the magic of this system happen!
The code of this project is available on GitHub. Follow the instructions laid out in the README to reproduce this project. If you don’t have a swimming pool or a pool pump, add an additional step to get yourself those first. (Or share this project with a friend who does have one)