Introduction: Pool Pump and Light IoT

My solar pool heater controller died. Whilst I want to get back to the stage of being able to have it work automatically depending on pool temperature, roof temperature and desired temperature we are currently just turning it on manually. It is a pain walking down to the filter box to turn the pump on and off though. So I thought I would try my hand at my first IoT project and set it up so that the family could turn the solar heating pump and pool lights on and off from a webpage.

Step 1: Parts and Tools

1x Raspberry Pi Model B (any version) (Model A should be ok as well)

1x WiFi dongle

1x dual channel 10A relay

1x 5V 2A power supply

2x flush mounted 240v sockets

Miscellaneous wire and jumper cables

1x enclosure to put it all in

Screwdriver

Drill or Dremel

Wire strippers

Hot glue

Step 2: Hardware

This is a fairly straight forward build HOWEVER you are going to be wiring up high voltage plugs so if you don't know what you are doing then DO NOT attempt this. Best case you will burn your house down worst case you will get electrocuted.

OK having said that the low voltage side is straight forward. Whilst there are various posts suggesting the need to wire up the Raspberry Pi to the relay via a transistor arrangement I found a post which suggested this was not necessary and you can wire a GPIO straight to the trigger pin. This is what I did. However I did choose to supply 5V to the relay directly from the supply rather than through the Pi.

You will see a schematic above which shows how I wired the whole thing up.

Once I tested it all I put in a box by hot gluing either brackets or spacers to the box and then screwing the components to those spacers.

The Raspberry Pi has no modifications. In terms of software it is pretty much as per out of the box except for a couple of Python modules which need to be installed which you will work out from the following pages.

Step 3: Software Pt 1

This was not straight forward. At least for me. I searched high and low and there are a lot of different ways to solve this problem. I was looking for a method which would use a webpage to call a Python script to turn the respective GPIO pin on or off. As far as I could tell using the RPi.GPIO library was no good as you had to elevate the www-data user to super-user status which is a security risk. I was then pushed off to using another library called gpiozero which does not need need su status to work but I could not work out how to use it such that the pin would stay HIGH when the script ended.

In the end I found a post about Flask which allows for a dynamically generated webpage to be created and is run via Python thus creating the GPIO control and webpage in one!

My python code ended up as

import requests
import re
import os
import RPi.GPIO as GPIO
from flask import Flask, render_template, request

app = Flask(__name__)
GPIO.setmode(GPIO.BCM)

# Create a dictionary called pins to store the pin number, name, and pin state:
pins = {
   17 : {'name' : 'Pool Heater Pump', 'state' : GPIO.LOW},
   21 : {'name' : 'Pool Light', 'state' : GPIO.LOW}
   }

# Set each pin as an output and make it high:
for pin in pins:
   GPIO.setup(pin, GPIO.OUT)
   GPIO.output(pin, GPIO.HIGH)

@app.route("/")
def main():
   # For each pin, read the pin state and store it in the pins dictionary:
   message2 = "CPU Temperature: " + os.popen('vcgencmd measure_temp').readline().replace("temp=","").replace("'C\n","")
   page = requests.get('http://www.bom.gov.au/products/IDQ60801/IDQ60801.94575.shtml')
   dtg = re.search('t1-datetime">\d{1,2}\/(\d\d:\d\d[ap]m)<\/td>[\s].*t1-tmp">(\d{1,2}.\d)',page.text)
   message3 = "At " + dtg.group(1)  + " the temperature at Archerfield was " + dtg.group(2)

  for pin in pins:
      pins[pin]['state'] = GPIO.input(pin)
   # Put the pin dictionary into the template data dictionary:
      templateData = {
      'message2' : message2,
      'message3' : message3,
      'pins' : pins
      }

   # Pass the template data into the template main.html and return it to the user
   return render_template('main.html', **templateData)

# The function below is executed when someone requests a URL with the pin number and action in it:
@app.route("//")
def action(changePin, action):
   message = ""
   message2 = "CPU Temperature: " + os.popen('vcgencmd measure_temp').readline().replace("temp=","").replace("'C\n","")
   page = requests.get('http://www.bom.gov.au/products/IDQ60801/IDQ60801.94575.shtml')
   dtg = re.search('t1-datetime">\d{1,2}\/(\d\d:\d\d[ap]m)<\/td>[\s].*t1-tmp">(\d{1,2}.\d)',page.text)
   message3 = "At " + dtg.group(1)  + " the temperature at Archerfield was " + dtg.group(2)

   # Convert the pin from the URL into an integer:
   changePin = int(changePin)

   # Get the device name for the pin being changed:
   deviceName = pins[changePin]['name']

   # If the action part of the URL is "on," execute the code indented below:
   if action == "off":
      # Set the pin high:
      GPIO.output(changePin, GPIO.HIGH)
   if action == "on":
      GPIO.output(changePin, GPIO.LOW)
   if action == "toggle": 
     # Read the pin and set it to whatever it isn't (that is, toggle it):
      GPIO.output(changePin, not GPIO.input(changePin))
      message = "Toggled " + deviceName + "."

# For each pin, read the pin state and store it in the pins dictionary:
   for pin in pins:
      pins[pin]['state'] = GPIO.input(pin)

   # Along with the pin dictionary, put the message into the template data dictionary:
   templateData = {
      'message' : message,
      'message2' : message2,
      'message3' : message3,
      'pins' : pins
   }

   return render_template('main.html', **templateData)

if __name__ == "__main__":
   app.run(host='0.0.0.0', port=810, debug=True)

Step 4: Software Pt 2

You need two directories under the working directory (in my case /var/www/html ). One to be called static which contains any pictures you want to use and the other called templates which has the HTML template that is used to create the webpage that will appear in the browser. My template file ended up like in the picture. (I can't work out how to post HTML in here!)

Step 5: Finished Product

So here it is. It works perfectly. I used my 3D printer to make up the various little brackets you can see in blue. My next step is to work out how to connect the existing roof and pool temp sensors to the pi (That bit of Rainbow cable is this work in progress) and use those to make the system even more intelligent. Expect an update to this Instructable soon!