Here is the complete program which runs my pool and controls the heat. It has a couple of sensors for daylight and pump pressure.
#! /usr/bin/env python3
import os
import cayenne.client
import time
import datetime
import sys
import glob
import logging
import gpiozero
import busio
import board
from RPLCD.i2c import CharLCD
from gpiozero import Button, OutputDevice
from signal import pause
# import adafruit_ads1x15.ads1015 as ADS
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
# Temperature check. Start Heater if temp < HEATER_ON
HEATER_ON_TEMP = 86
# Temperature check. Shut down over HEATER_OFF
HEATER_OFF_TEMP = 88
#msg_HeaterControl = "Loading..."
# *************************************************************************
lcd = CharLCD('PCF8574', 0x27)
# Cayenne Connection Information
MQTT_USERNAME = " "
MQTT_PASSWORD = " "
MQTT_CLIENT_ID = " "
# Initialize the GPIO Pins
os.system('modprobe w1-gpio') # Turns on the GPIO module
os.system('modprobe w1-therm') # Turns on the Temperature module
# Finds the correct device file that holds the temperature data
base_dir = '/sys/bus/w1/devices/'
device_folder_pool = glob.glob(base_dir + '28-01162136d3ee')[0]
device_folder_heater = glob.glob(base_dir + '28-011623b89cee')[0]
device_folder_air = glob.glob(base_dir + '28-02161de554ee')[0]
device_file_pool = device_folder_pool + '/w1_slave'
device_file_heater = device_folder_heater + '/w1_slave'
device_file_air = device_folder_air + '/w1_slave'
PumpRelayPin = 17 # Originally 17
HeaterRelayPin = 22
LightRelayPin = 23 # Originally 23
PumpRelay = gpiozero.OutputDevice(PumpRelayPin, active_high=True, initial_value=True)
HeaterRelay = gpiozero.OutputDevice(HeaterRelayPin, active_high=False, initial_value=False)
LightRelay = gpiozero.OutputDevice(LightRelayPin, active_high=False, initial_value=False)
#********* LED Button GPIO Setup *******************
BlueButton=Button(18) # Declaring Blue button GPIO 18
RedButton=Button(27) # Declaring Red button GPIO 27
# Get what action. If you manually turning on/off the heater
action = sys.argv.pop()
# The callback for when a message is received from Cayenne.
def on_message(message):
print("message received: " + str(message))
msg_list = ast.literal_eval(str(message))
msg_value = msg_list['value']
msg_channel = msg_list['channel']
print("value is " + msg_value)
print("channel is %s" % msg_channel)
# Initialize the client
client = cayenne.client.CayenneMQTTClient()
client.on_message = on_message
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)
# Create the I2C bus
i2c = busio.I2C(board.SCL, board.SDA)
# Create the ADS object
# ads = ADS.ADS1015(i2c)
ads0 = ADS.ADS1115(i2c)
ads1 = ADS.ADS1115(i2c)
# Create a sinlge ended channel on Pin 0
# Max counts for ADS1015 = 2047
# ADS1115 = 32767
chan0 = AnalogIn(ads0, ADS.P0) # Pressure
chan1 = AnalogIn(ads1, ADS.P1) # Light
# The ADS1015 and ADS1115 both have the same gain options.
#
# GAIN RANGE (V)
# ---- ---------
# 2/3 +/- 6.144
# 1 +/- 4.096
# 2 +/- 2.048
# 4 +/- 1.024
# 8 +/- 0.512
# 16 +/- 0.256
#
gain0 = (2 / 3)
gain1 = (1)
# A function that reads the sensors data
def read_temp_raw():
f = open(device_file_pool, 'r') # Opens the temperature device file
lines = f.readlines() # Returns the text
f.close()
return lines
def read_Heater_Output_temp_raw():
f = open(device_file_heater, 'r') # Opens the temperature device file
lines = f.readlines() # Returns the text
f.close()
return lines
def read_Air_temp_raw():
f = open(device_file_air, 'r') # Opens the temperature device file
lines = f.readlines() # Returns the text
f.close()
return lines
# Convert the value of the sensor into a temperature
def read_pool_temp():
lines = read_temp_raw() # Read the temperature 'device file'
# While the first line does not contain 'YES', wait for 0.2s
# and then read the device file again.
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
# Look for the position of the '=' in the second line of the
# device file.
equals_pos = lines[1].find('t=')
# If the '=' is found, convert the rest of the line after the
# '=' into degrees Celsius, then degrees Fahrenheit
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_f
def read_Heater_Output_temp():
lines = read_Heater_Output_temp_raw() # Read the temperature 'device file'
# While the first line does not contain 'YES', wait for 0.2s
# and then read the device file again.
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_Heater_Output_temp_raw()
# Look for the position of the '=' in the second line of the
# device file.
equals_pos = lines[1].find('t=')
# If the '=' is found, convert the rest of the line after the
# '=' into degrees Celsius, then degrees Fahrenheit
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_f
def read_Air_temp():
lines = read_Air_temp_raw() # Read the temperature 'device file'
# While the first line does not contain 'YES', wait for 0.2s
# and then read the device file again.
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_Air_temp_raw_raw()
# Look for the position of the '=' in the second line of the
# device file.
equals_pos = lines[1].find('t=')
# If the '=' is found, convert the rest of the line after the
# '=' into degrees Celsius, then degrees Fahrenheit
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_f
def Pump_on():
print("Pump On")
PumpRelay.on()
def Pump_off():
print("Pump and Heater Off")
HeaterRelay.off()
time.sleep(10)
PumpRelay.off()
def Heater_on():
print("Heater On")
HeaterRelay.on()
client.virtualWrite(18, 1, "digital_sensor")
def Heater_off():
print("Heater Off")
HeaterRelay.off()
client.virtualWrite(18, 0, "digital_sensor")
def PoolLight_on():
print("Light On")
LightRelay.on()
client.virtualWrite(20, 1, "digital_sensor")
def PoolLight_off():
print("Light Off")
LightRelay.off()
client.virtualWrite(20, 0, "digital_sensor")
# def check_heater(pin):
# GPIOsetup()
# return GPIO.input(pin)
def run_Heater():
#log file information
logging.basicConfig(filename='/home/pi/HydroPi/HeaterRelay.log',level=logging.INFO,format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
current_date = datetime.datetime.now()
global temp_pool
temp_pool = read_pool_temp()
temp_HeaterOutput = read_Heater_Output_temp()
temp_AirTemp = read_Air_temp()
global msg_HeaterControl
print('Temperature' +str(temp_pool))
client.virtualWrite(1, temp_pool, "analog_sensor")
client.virtualWrite(2, temp_HeaterOutput, "analog_sensor")
client.virtualWrite(25, temp_AirTemp, "analog_sensor")
if float(temp_pool) <= HEATER_ON_TEMP:
if RedButton.is_pressed:
print ('Requesting Heater but Switch is Pressed')
msg_HeaterControl = "Button Override"
#time.sleep(10)
elif PumpRelay.value == 0: # Pump relay uses inverted logic
print ('Requesting Heater but Pump is Off')
msg_HeaterControl = "Pump Off Override"
#time.sleep(10)
else:
print('Heater ON')
logging.info("HEATER ON")
msg_HeaterControl = "Heating"
Heater_on()
#time.sleep(10)
elif float(temp_pool) >= HEATER_OFF_TEMP:
print('Turning OFF Heater')
logging.info("Turning off Heater")
msg_HeaterControl = "Heater Off"
Heater_off()
#time.sleep(10)
# return 1 # exit script. The pi has cooled down
else:
print('Pool is operating under normal temperatures.')
logging.info("Pool is operating under normal temperatures.")
msg_HeaterControl = "Normal Temperature"
#Heater_off()
#time.sleep(10)
def PoolPressure():
global psi
ads0.gain = gain0
volts = chan0.value / 32767.0 * 6.144
psi = 7.5 * volts - 3.75
#Print PSI
print("\n{0:0.2f} psi ".format(psi))
client.virtualWrite(4, psi, "analog_sensor")
def DaylightSensor():
#Print Light Value
print('LDR raw value: ' + str(chan1.value))
#if value < 6000: it is now dark, turn LED on
if chan1.value < 6000:
print ("Its Sunny")
PoolLight_off()
lightsensor = "Sunny"
else:
print ("Its Dark")
PoolLight_on()
lightsensor = "Dark"
client.virtualWrite(15, chan1.value, "analog_sensor")
def LCD_Display():
lcdTemp = read_pool_temp
#heater = msg_HeaterControl
lcd.clear()
lcd.cursor_pos = (0, 0)
lcd.write_string(msg_HeaterControl)
lcd.cursor_pos = (1, 0)
lcd.write_string("Temp:{0:0.0f}".format(temp_pool) + " PSI:{0:0.1f}".format(psi))
BlueButton.when_pressed = Pump_off
BlueButton.when_released = Pump_on
RedButton.when_pressed = Heater_off
RedButton.when_released = Heater_on
while True:
if BlueButton.is_pressed:
PumpRelay.off()
time.sleep(5)
lcd.clear()
print ('Blue Button Pressed')
lcd.write_string("Pump Off")
client.virtualWrite(16, 0, "digital_sensor")
else:
client.loop()
client.virtualWrite(16, 1, "digital_sensor")
run_Heater()
PoolPressure()
DaylightSensor()
LCD_Display()
time.sleep(10)
# Cayenne Connection
# Publish the change of state of the Sunday1 button which is on dashboard channel 4
# Cayenne.virtualWrite(1, "[2,1,3]", "accel", "g");
time.sleep(5)
# except KeyboardInterrupt:
# # # here you put any code you want to run before the program
# # # exits when you press CTRL+C
# logging.warning("Keyboard Interupted")
# except SystemExit:
# # # here you put any code you want to run before the program
# # # exits when you press CTRL+C
# logging.warning("System Error")
# lcd.clear()
# lcd.write_string("*** SYSTEM ERROR ***")
# finally:
# # #GPIO.cleanup() # this ensures a clean exit
# logging.info("Program Exit")