Would a set of these be considered safe:
SSR-25DA
I tried to put a link to a page that describes one, but none of the links work. A google for the above term will yield what I'm describing
Would a set of these be considered safe:
SSR-25DA
I tried to put a link to a page that describes one, but none of the links work. A google for the above term will yield what I'm describing
Last edited by Craigjw; 26-08-17 at 06:20 PM. Reason: invalid link
M_C (28-08-17)
Maybe this link will work
Last edited by M_C; 28-08-17 at 12:00 AM.
M_C (28-08-17)
Regarding the fans and pump, they are both 12v DC, I believe that the relay board I have would be fine for such applications.
M_C (28-08-17)
I did some research of the activation current required to trip the relays, for the 4 channel 5v relay, it maybe 75ma, but I can't find any hard facts on this. For the SSR's, these are 17.4ma. A single channel on the GPIO ports of the raspberry pi can support 17ma, with a total of 50ma across all channels. I'm making an educated guess, but I think that the raspberry pi will become fried after prolonged use of either relays. I've also read a few posts about this and it seems to be a reasonably common thing that the GPIO channels on the pi are being fried from activating the 4 channel relays.
I am thinking about how to make a driver circuit for the relays, a relay for the relays if you like using a separate 5v power supply. I'm not sure exactly how to go about this, but I think it involves a bunch of mosfets and resistors. The power supply to the pi is rated at 3A. According to the pi datasheet, the pi uses much less than this, therefore, I'm considering using the pi supply to power the relays as well as the pi itself.
Please feel free to comment on my suggestions, as any guidance and assistance is appreciated.
I've made some other progress too, which I'll document in posts below.
M_C (28-08-17)
lazor_ears (18-09-17), M_C (28-08-17)
I've knocked up some code to control the lights, including the LED & CFL, the fans and pump. I have yet to write code to add in the code to control the GPIO ports, monitor the temperature/humidity, log data and also write code to safeguard against exception errors.
I had issues with using "time.after(DELAY, function)" as it just wouldn't sleep for the delay time, so made it using threads instead. I also had trouble with pickle; it wouldn't let me write to a file in text mode, only binary, this isn't too much of an issue, as it's not meant to be modified with via the settings file, but still annoying that it wouldn't work.
Code:from tkinter import Tk from tkinter import * import time import pickle import os import threading class MiniCabGui: def __init__(self, master): self.master = master self.settings = Settings() self.LED = False self.CFL = False self.Pump = False self.Fans = False self.Temp = 29 self.LoadSettings() self.InitGui(master) self.ClockThread() self.CheckTimeThread() self.CheckPumpThread() def InitGui(self, master): master.title("Mini-Cab Monitor") self.master.geometry("300x400") self.label = Label(text = "")#label for the clock self.label.pack() self.close_button = Button(master, text="Close", command=master.quit) self.close_button.pack() self.timeFrame = Frame(borderwidth = 5, relief = RAISED) self.timeFrame.pack(side = TOP) self.timeInputFrame = Frame(self.timeFrame)# for time input frame self.timeInputFrame.pack() self.LightOn = StringVar() # time loaded from on time from text field self.LightOn.set(self.settings.lights.GetOnTime()) # add the loaded time to text field self.LightOnLabel = Label(self.timeInputFrame, text="Lights On") self.LightOnLabel.pack() self.LightOnTb = Entry(self.timeInputFrame, textvariable=self.LightOn, bd =5) self.LightOnTb.pack() self.LightOff = StringVar() # time loaded from off time from text field self.LightOff.set(self.settings.lights.GetOffTime()) # add the loaded time to text field self.LightOffLabel = Label(self.timeInputFrame, text="Lights Off") self.LightOffLabel.pack() self.LightOffTb = Entry(self.timeInputFrame, textvariable=self.LightOff, bd =5) self.LightOffTb.pack() self.enableCflButtonVar = IntVar() self.enableCflButtonVar.set(self.settings.lights.enableCFL) self.enableCflButton = Checkbutton(self.timeInputFrame, text="Enable CFL ", variable=self.enableCflButtonVar, command=self.LightControl ) self.enableCflButton.pack() self.pumpFrame = Frame(borderwidth = 5, relief = RAISED) self.pumpFrame.pack(side = TOP) self.pumpOnLabel = Label(self.pumpFrame, text="Water Pump Times") self.pumpOnLabel.pack() self.pumpInputFrame = Frame(self.pumpFrame) self.pumpInputFrame.pack() self.pumpOn1 = StringVar() self.pumpOn1.set(self.settings.pump.GetOnTime(0)) self.pumpOn2 = StringVar() self.pumpOn2.set(self.settings.pump.GetOnTime(1)) self.pumpPeriod1 = StringVar() self.pumpPeriod1.set(self.settings.pump.PeriodList[0]) self.pumpPeriod2 = StringVar() self.pumpPeriod2.set(self.settings.pump.PeriodList[1]) self.pumpLabel1 = Label(self.pumpInputFrame, text="Pump On").grid(row=0, column=0) self.pumpLabel2 = Label(self.pumpInputFrame, text="Pump Period (S)").grid(row=0, column=1) self.PumpOnEntry1 = Entry(self.pumpInputFrame, bd=5, textvariable=self.pumpOn1).grid(row=1, column=0) self.PumpPeriodEntry1 = Entry(self.pumpInputFrame, bd=5, textvariable=self.pumpPeriod1).grid(row=1, column=1) self.PumpOnEntry2 = Entry(self.pumpInputFrame, bd=5, textvariable=self.pumpOn2).grid(row=2, column=0) self.PumpPeriodEntry2 = Entry(self.pumpInputFrame, bd=5, textvariable=self.pumpPeriod2).grid(row=2, column=1) self.apply_button = Button(text='Apply', command =self.ApplyChanges) self.apply_button.pack() def ClockThread(self): t = threading.Thread(target=self.UpdateClock, args = ()) t.daemon = True t.start() def CheckTimeThread(self): t = threading.Thread(target=self.CheckTime, args = ()) t.daemon = True t.start() def CheckPumpThread(self): t = threading.Thread(target=self.PumpCheck, args = ()) t.daemon = True t.start() def CheckTime(self): now = time.strftime("%H:%M") self.LightCheck(now) time.sleep(1) self.CheckTime() def LightCheck(self, now): if (now >= self.settings.lights.GetOnTime()) and (now < self.settings.lights.GetOffTime()): if(self.Fans != True): self.SwitchOnFans(True) if(self.LED != True): self.SwitchOnLed(True) if(self.settings.lights.enableCFL == True and self.CFL != True and self.Temp < 28 ): self.SwitchOnCfl(True) else: if(self.LED == True): self.SwitchOnLed(False) if(self.CFL == True): self.SwitchOnCfl(False) if(self.Fans == True): self.SwitchOnFans(False) def PumpCheck(self): pump = self.settings.pump now = time.strftime("%H:%M") print(now + " checking Pump") self.PumpScheduleCheck(pump.GetOnTime(0), int(pump.PeriodList[0]), now) self.PumpScheduleCheck(pump.GetOnTime(1), int(pump.PeriodList[1]), now) print("Waiting for 29s") time.sleep(29) print("Finished pumpCheck") self.PumpCheck() def PumpScheduleCheck(self, activationTime, period, timeNow): if (timeNow == activationTime): print(timeNow + " pump time") while(period > 0): if(period <= 10): print("Activating pump for: " + str(period)) self.Pump = True time.sleep(period) self.Pump = False print("Finished final pump phase") else: print("Activating pump for 10") self.Pump = True time.sleep(10) self.Pump = False print("finished intermediate pump phase") print("Pausing for 15") time.sleep(15) period = period - 10 print("finished pumping") time.sleep(35) def SwitchOnLed(self, enable): print("LED " + str(enable)) self.LED = enable self.settings.lights.LEDState = enable def SwitchOnCfl(self, enable): print ("CFL " + str(enable)) self.CFL = enable self.settings.lights.CFLState = enable def SwitchOnPump(self, duration): print ( "Pump ON (" + str(duration) + ")") self.Pump = True time.sleep(duration) self.Pump = False print( "Pump OF") def SwitchOnFans(self, enable): print ("Fans " + str(enable)) self.Fans = enable self.settings.fans.State = enable def UpdateClock(self): now = time.strftime("%H:%M:%S") self.label.configure(text = now) time.sleep(1) self.UpdateClock() def LoadSettings(self): if os.path.isfile("Settings.txt")== True: with open("Settings.txt", "rb") as f: self.settings = pickle.load(f) self.LightOnTb = self.settings.lights.GetOnTime() self.LightOffTb = self.settings.lights.GetOffTime() self.LED = self.settings.lights.LEDState self.CFL = self.settings.lights.CFLState self.Pump = self.settings.pump.State self.Fans = self.settings.fans.State def ApplyChanges(self): print("Applying changes") self.settings.lights.SetOnTime(self.LightOnTb.get()) self.settings.lights.SetOffTime(self.LightOffTb.get()) self.settings.pump.SetTimes(self.pumpOn1.get(), self.pumpPeriod1.get(), 0) self.settings.pump.SetTimes(self.pumpOn2.get(), self.pumpPeriod2.get(), 1) print("Pump On: " + self.settings.pump.GetOnTime(0) + " - " + self.settings.pump.PeriodList[0] ) print("Pump On: " + self.settings.pump.GetOnTime(1) + " - " + self.settings.pump.PeriodList[1] ) with open("Settings.txt", "wb") as f: pickle.dump(self.settings, f) def LightControl(self): if self.enableCflButtonVar.get() == 1: self.settings.lights.enableCFL = True else: self.settings.lights.enableCFL = False class SimpleDevice(): def __init__(self): self.OnTime = time.strptime("08:00", "%H:%M") self.OffTime = time.strptime("02:00", "%H:%M") def GetOnTime(self): return time.strftime("%H:%M", self.OnTime) def GetOffTime(self): return time.strftime("%H:%M", self.OffTime) def SetOnTime(self, timeStr): self.OnTime = time.strptime(timeStr, "%H:%M") def SetOffTime(self, timeStr): self.OffTime = time.strptime(timeStr, "%H:%M") class Lights(SimpleDevice): LEDState = True CFLState = False def __init__(self): self.enableCFL = True self.OnTime = time.strptime("08:00", "%H:%M") self.OffTime = time.strptime("02:00", "%H:%M") self.LEDState = True self.CFLState = False class Fans(SimpleDevice): State = True def __init__(self): self.State = True class Settings(): def __init__(self): self.lights = Lights() self.fans = Fans() self.pump = Pump() class Pump(): State = False def __init__(self): self.OnTimeList = [] self.PeriodList = [] self.AppendTimes("04:00", 20) self.AppendTimes("09:00", 15) self.State = False def AppendTimes(self, timeStr, period): t = time.strptime(timeStr, "%H:%M") self.OnTimeList.append(t) self.PeriodList.append(period) def SetTimes(self, timeStr, period, index): t = time.strptime(timeStr, "%H:%M") self.OnTimeList[index] = t self.PeriodList[index] = period def GetOnTime(self, index): return time.strftime("%H:%M", self.OnTimeList[index]) root = Tk() myGui = MiniCabGui(root) root.mainloop()
M_C (28-08-17)
Did some more wiring of the box, attaching fan leads and temperature/humidity sensor leads. Also made a lead for the sensor with 3-pin din and epoxied the sensor onto the wire.
Did a circuit test and everything seems to be ok. Sensor also reads correctly when the pi is connected to the internal connection via the 3-pin din.
JamesJoyce (14-09-17), M_C (28-08-17)
I'm pretty close to finishing the code to run this Pi. I'm currently testing it on the Pi using a mocked GPIO interface, so that it doesn't actually use any of the GPIO. It's been running now for about 12 hours with no fault.
M_C (05-09-17)
The software has been running in test mode for about 5 days now without error.
I have yet to receive the Solid State Relays, these are due for delivery late next week.
I have moved on to Live testing of the circulation fans and water pump and temperature sensor, these are all plugged in and being controlled by the raspberry pi box.
lazor_ears (18-09-17), M_C (09-09-17)
Here is the latest iteration of the code that I have developed using Python 3
Here I've listed some features:
-It will switch off the CFL if the temperature is above 28, and switch it on if it below 27 and will switch off all lights if above 33 as there is likely to be an issue
-Fans will always switch on if the lights are on
-manual overrides available for lights and fans, with a timeout, so they will switch on after a few minutes
-Three scheduled times for water pump activation & manual pumping
-Logging of info, errors and debug
-Some exception handling if things break, any exception will be logged as an error
-Settings are saved with apply, auto loads on boot
-Timers are 24h compatible, ie, if on time is 6am and off time is 2am, it'll still work correctly
-Pump will pause for a short time during pumping to allow the water to drain, so that the feed does not overflow over the rim.
-Auto shut off for the lights and pump, while the fan will auto switch on if the application crashes
I have ordered a water flow meter, I intend make a dosing system, so that a more accurate measure of water can be fed to the plant.
Screenshot:
Python code:
Code:import tkinter as tk from tkinter import * from tkinter import messagebox import threading import time from datetime import datetime, timedelta import os import sys import traceback from random import randint import pickle import logging from logging.handlers import RotatingFileHandler #Raspberry pi GPIO use, remove the # for use with Raspberry Pi #''' import RPi.GPIO as GPIO import Adafruit_DHT ''' #Mock classes & variables to simulate GPIO under windows environment #Add # at the end for use on Windows class GPIO: BCM = "BCM" OUT = "OUT" LOW = "LOW" HIGH = "HIGH" def setmode(self, param): pass def setup(self, DEVICE, action): pass def output(self, DEVICE, action): pass def cleanup(self): print("GPIO Cleanup") class Adafruit_DHT: def read_retry(self, sensor, pin): sensor pin temp = randint(24, 30) hum = randint(50, 90) return (hum, temp) Adafruit_DHT.DHT11 = "Adafruit_DHT.DHT11" GPIO = GPIO() Adafruit_DHT = Adafruit_DHT() ''' class CabGui(tk.Tk): def __init__(self): super().__init__() print("Initialising Cab Gui") logger.debug("Initialising Cab Gui") self.running = True self.threads = [] self.auto_lights_timer = threading.Timer self.auto_fans_timer = threading.Timer self.override_lights = False self.override_fans = False self.manual_pump_switch = False self.Init_Devices() self.Init_Gui() self.LoadSettings() self.InfoThread() self.ClockThread() self.PumpThread() self.DHTThread() def Init_Gui(self): try: self.title("Mini-Cab Monitor") self.geometry("320x690") '''Clock''' self.clock_label = Label(text = "", font=(None, 15))#label for the clock self.clock_label.pack() '''Temperature/Humidity''' self.tempFrame = Frame(borderwidth = 5, relief = RAISED) self.tempFrame.pack(side = TOP) '''Temperature''' self.temperature_var = StringVar() # temp loaded from devices self.temperature_var.set(str(self.temperature.Get()) + " \u00b0C") # add the loaded temperature to text field self.temperature_label = Label(self.tempFrame, font=(None, 10), text="Temperature:").grid(row=0, column=0) self.temperature_value_label = Label(self.tempFrame, font="Helvetica 13 bold", textvariable=self.temperature_var).grid(row=0, column=1) self.tempSpacerLabel = Label(self.tempFrame, text=" ").grid(row=0, column=2) '''Humidity''' self.humidity_var = StringVar() # temp loaded from devices self.humidity_var.set(str(self.humidity.Get()) + "%") # add the loaded temperature to text field self.humidity_label = Label(self.tempFrame, font=(None, 10), text="Humidity:").grid(row=0, column=3) self.humidity_value_Label = Label(self.tempFrame, font="Helvetica 13 bold", textvariable=self.humidity_var).grid(row=0, column=4) '''Lights''' self.lights_title_label = Label(text="LIGHTS", font="Helvetica 14") self.lights_title_label.pack() self.lights_frame = Frame(borderwidth = 5, relief = RAISED) self.lights_frame.pack(side = TOP) self.lights_input_frame = Frame(self.lights_frame) self.lights_input_frame.pack(side = TOP) '''Lights On''' self.lights_on_var = StringVar() # time loaded from on time from text field self.lights_on_var.set(self.lights.GetOnTime()) # add the loaded time to text field self.light_on_label = Label(self.lights_input_frame, text="Lights On").grid(row=0, column=0) self.lights_on_entry = Entry(self.lights_input_frame, textvariable=self.lights_on_var, bd =5).grid(row=1, column=0) '''Lights Off''' self.lights_off_var = StringVar() # time loaded from off time from text field self.lights_off_var.set(self.lights.GetOffTime()) # add the loaded time to text field self.light_off_label = Label(self.lights_input_frame, text="Lights Off").grid(row=0, column=1) self.light_off_entry = Entry(self.lights_input_frame, textvariable=self.lights_off_var, bd =5).grid(row=1, column=1) '''LED Check checkbox''' self.led_on_var = IntVar() self.led_on_var.set(self.lights.LED.state) self.LED_checkbutton = Checkbutton(self.lights_frame, font="Helvetica 12", text="LED Light On", variable=self.led_on_var, command= self.LED_On_checkbutton_click, state=DISABLED) self.LED_checkbutton.pack(fill=BOTH) '''CFL Check checkbox''' self.cfl_on_var = IntVar() self.cfl_on_var.set(self.lights.CFL.state) self.CFL_checkbutton = Checkbutton(self.lights_frame, font="Helvetica 12", text="CFL Light On", variable=self.cfl_on_var, command=self.CFL_On_checkbutton_click, state=DISABLED) self.CFL_checkbutton.pack(fill=BOTH) '''CFL Enabled checkbox''' self.cfl_enable_var = IntVar() self.cfl_enable_var.set(self.lights.CFL.CFLEnabled) self.CFL_enable_checkbutton = Checkbutton(self.lights_frame, font="Helvetica 12", text="Enable CFL", variable=self.cfl_enable_var, command=self.CFL_Enable_checkbutton_click ) self.CFL_enable_checkbutton.pack(fill=BOTH) 'Override Lights button' self.override_lights_text = StringVar() self.override_lights_text.set("Manual Override") self.override_lights_button = Button(self.lights_frame, textvariable=self.override_lights_text, command=self.OverrideLights, width=25, bg="light grey") self.override_lights_button.pack() '''Fans''' self.fans_title_label = Label(text="FANS", font="Helvetica 14") self.fans_title_label.pack() self.fans_frame = Frame(borderwidth = 5, relief = RAISED) self.fans_frame.pack(side = TOP) self.fans_input_frame = Frame(self.fans_frame) self.fans_input_frame.pack(side = TOP) '''Fans On''' self.fans_on_var = StringVar() # time loaded from on time from text field self.fans_on_var.set(self.fans.GetOnTime()) # add the loaded time to text field self.fans_on_label = Label(self.fans_input_frame, text="Fans On").grid(row=0, column=0) self.fans_on_entry = Entry(self.fans_input_frame, textvariable=self.fans_on_var, bd =5).grid(row=1, column=0) '''Fans Off''' self.fans_off_var = StringVar() # time loaded from off time from text field self.fans_off_var.set(self.fans.GetOffTime()) # add the loaded time to text field self.fans_off_label = Label(self.fans_input_frame, text="Fans Off").grid(row=0, column=1) self.fans_off_entry = Entry(self.fans_input_frame, textvariable=self.fans_off_var, bd =5).grid(row=1, column=1) '''Fans checkbox''' self.fans_on_check_var = IntVar() self.fans_on_check_var.set(self.fans.state) self.fans_on_checkbutton = Checkbutton(self.fans_frame, font="Helvetica 12", text="Fans On", variable=self.fans_on_check_var, command=self.Fans_On_checkbutton_click, state=DISABLED) self.fans_on_checkbutton.pack(fill=BOTH) 'Override Fans button' self.override_fans_text = StringVar() self.override_fans_text.set("Manual Override") self.override_fans_button = Button(self.fans_frame, textvariable=self.override_fans_text, command=self.OverrideFans, width=25, bg="light grey") self.override_fans_button.pack() '''Pump Times''' self.pump_title_label = Label(text="PUMP", font="Helvetica 14") self.pump_title_label.pack() self.pump_frame = Frame(borderwidth = 5, relief = RAISED) self.pump_frame.pack(side=TOP) self.pump_input_frame = Frame(self.pump_frame) self.pump_input_frame.pack(side = TOP) self.pumpOnLabel = Label(self.pump_input_frame, text="Water Pump Times") self.pump_time_on_var1 = StringVar() self.pump_time_on_var1.set(self.pump.GetOnTime(0)) self.pump_time_on_var2 = StringVar() self.pump_time_on_var2.set(self.pump.GetOnTime(1)) self.pump_time_on_var3 = StringVar() self.pump_time_on_var3.set(self.pump.GetOnTime(2)) self.pump_period_var1 = StringVar() self.pump_period_var1.set(self.pump.PeriodList[0]) self.pump_period_var2 = StringVar() self.pump_period_var2.set(self.pump.PeriodList[1]) self.pump_period_var3 = StringVar() self.pump_period_var3.set(self.pump.PeriodList[2]) self.pumpLabel1 = Label(self.pump_input_frame, text="Pump On").grid(row=0, column=0) self.pumpLabel2 = Label(self.pump_input_frame, text="Pump Period (S)").grid(row=0, column=1) self.PumpOnEntry1 = Entry(self.pump_input_frame, bd=5, textvariable=self.pump_time_on_var1).grid(row=1, column=0) self.PumpPeriodEntry1 = Entry(self.pump_input_frame, bd=5, textvariable=self.pump_period_var1).grid(row=1, column=1) self.PumpOnEntry2 = Entry(self.pump_input_frame, bd=5, textvariable=self.pump_time_on_var2).grid(row=2, column=0) self.PumpPeriodEntry2 = Entry(self.pump_input_frame, bd=5, textvariable=self.pump_period_var2).grid(row=2, column=1) self.PumpOnEntry3 = Entry(self.pump_input_frame, bd=5, textvariable=self.pump_time_on_var3).grid(row=3, column=0) self.PumpPeriodEntry3 = Entry(self.pump_input_frame, bd=5, textvariable=self.pump_period_var3).grid(row=3, column=1) '''Pump Checkbox''' self.pump_on_var = IntVar() self.pump_on_var.set(self.pump.state) self.pump_on_checkbutton = Checkbutton(self.pump_frame, font="Helvetica 12", text="Pump On", variable=self.pump_on_var) self.pump_on_checkbutton.pack(fill=BOTH) '''Manual Pump''' self.manual_pump = Button(self.pump_frame, text="Manual Pump", command=self.ManualPump, width=25, bg="light grey") self.manual_pump.pack() '''Update button''' self.apply_title_label = Label(text="") self.apply_title_label.pack() self.application_operation = Frame(borderwidth = 5, relief = RAISED) self.application_operation.pack(side = BOTTOM) self.apply_button = Button(self.application_operation, text='Apply', command =self.ApplyChanges, width=20, bg="light grey").grid(row=0) self.close_button = Button(self.application_operation, text="Close", command=self.CloseApp, width=20, bg="light grey").grid(row=1) except Exception as e: logger.error("Error initialising Gui: : " + str(e)) raise e def Init_Devices(self): try: self.devices = GPIODevices() self.lights = Lights(self, self.devices) self.fans = Fans(self, self.devices) self.pump = Pump(self, self.devices) self.temperature = Temperature(self, self.devices) self.humidity = Humidity(self, self.devices) except Exception as e: logger.error("Failed to Init_Devices: " + str(e)) raise e def CloseApp(self): logger.info("Closing App") try: self.running = False self.destroy() except Exception as e: logger.critical("Failed to CloseApp: " + str(e)) raise e def OverrideLights(self): try: if(self.override_lights == False): self.DisableAutoLights() self.auto_lights_timer = threading.Timer(180, self.OverrideLightsAutoReset) self.auto_lights_timer.start() else: self.auto_lights_timer.cancel() self.EnableAutoLights() except Exception as e: logger.error("Failed to Override: " + str(e)) raise e def EnableAutoLights(self): self.LED_checkbutton.config(state=DISABLED) self.CFL_checkbutton.config(state=DISABLED) self.override_lights_button.config(bg = "light grey") self.override_lights = False self.override_lights_text.set("Manual Override") def DisableAutoLights(self): self.override_lights_button.config(bg = "red") self.LED_checkbutton.config(state=NORMAL) self.CFL_checkbutton.config(state=NORMAL) self.override_lights = True self.override_lights_text.set("Auto") self.lights.LED.Off() self.lights.CFL.Off() def OverrideFans(self): if(self.override_fans == False): self.DisableAutoFans() self.auto_fans_timer = threading.Timer(180, self.OverrideFansAutoReset) self.auto_fans_timer.start() else: self.auto_fans_timer.cancel() self.EnableAutoFans() def EnableAutoFans(self): self.override_fans_button.config(bg="light grey") self.fans_on_checkbutton.config(state=DISABLED) self.override_fans = False self.override_fans_text.set("Manual Override") def DisableAutoFans(self): self.override_fans_button.config(bg="red") self.fans_on_checkbutton.config(state=NORMAL) self.override_fans = True self.override_fans_text.set("Auto") def OverrideLightsAutoReset(self): self.EnableAutoLights() def OverrideFansAutoReset(self): self.EnableAutoFans() def ManualPump(self): if(not self.manual_pump_switch): self.manual_pump_switch = True self.pump.On() else: self.manual_pump_switch = False self.pump.Off() def ClockThread(self): try: t = threading.Thread(target=self.UpdateClock, args = (), name="ClockThread") self.threads.append(t) t.daemon = True t.start() except Exception as e: logger.error("Create ClockThread: " + str(e)) raise e def PumpThread(self): try: t = threading.Thread(target=self.PumpCheck, args=(), name="PumpThread") self.threads.append(t) t.daemon = True t.start() except Exception as e: logger.error("Create PumpThread: " + str(e)) raise e def DHTThread(self): try: t = threading.Thread(target=self.DHTCheck, args=(), name="DHTThread") self.threads.append(t) t.daemon = True t.start() except Exception as e: logger.error("Create DHTThread: " + str(e)) raise e def InfoThread(self): try: t = threading.Thread(target=self.Info, args=(), name="InfoThread") self.threads.append(t) t.daemon = True t.start() except Exception as e: logger.error("Create InfoThread: " + str(e)) raise e def Info(self): try: while(self.running == True): now = time.strftime("%H:%M:%S") temp = self.temperature.Get() hum = self.humidity.Get() msg = now + ": Temp: " + str(temp) + " \u00b0C, Hum: " + str(hum) + " %" print(msg) logger.info(msg) time.sleep(180) except Exception as e: logger.error("Info error: " + str(e)) def UpdateClock(self): try: with threading.Lock(): while(self.running==True): now = time.strftime("%H:%M:%S") self.clock_label.configure(text = now) self.LightCheck(now) self.FanCheck(now) time.sleep(1) except Exception as e: logger.error("UpdateClock: " + str(e)) raise e #Time schedule check works for any time def TimeScheduleCheck(self, onTime, offTime, now): if(onTime < offTime): if (now >= onTime) and (now < offTime): return True else: if(now >= onTime) or (now < offTime): return True return False def LightCheck(self, now): try: if(self.override_lights == False): onTime = self.lights.GetOnTime() offTime = self.lights.GetOffTime() if(self.temperature.Get() > 33): self.lights.LED.Off() self.lights.CFL.Off() messagebox.showerror("Temperature Warning", " Temperature is above 33\u00b0C") else: if(self.TimeScheduleCheck(onTime, offTime, now)): if(self.lights.LED.state != True): self.lights.LED.On() if(self.lights.CFL.CFLEnabled == True and self.lights.CFL.state == False and self.temperature.Get() < 27): self.lights.CFL.On() if(self.lights.CFL.state == True and self.temperature.Get() > 28): self.lights.CFL.Off() else: if(self.lights.LED.state == True): self.lights.LED.Off() if(self.lights.CFL.state == True): self.lights.CFL.Off() except Exception as e: logger.error("LightCheck: " + str(e)) raise e def FanCheck(self, now): try: if(self.override_fans == False): if(self.fans.state == False and (self.lights.LED.state == True or self.lights.CFL.state == True)): self.fans.On() else: onTime = self.fans.GetOnTime() offTime = self.fans.GetOffTime() if(self.TimeScheduleCheck(onTime, offTime, now)): if(self.fans.state == False): self.fans.On() else: if(self.fans.state == True and self.lights.LED.state == False and self.lights.CFL.state == False): self.fans.Off() except Exception as e: logger.error("FanCheck: " + str(e)) raise e def PumpCheck(self): try: with threading.Lock(): while(self.running == True): now = time.strftime("%H:%M") self.PumpScheduleCheck(self.pump.GetOnTime(0), int(self.pump.PeriodList[0]), now) self.PumpScheduleCheck(self.pump.GetOnTime(1), int(self.pump.PeriodList[1]), now) self.PumpScheduleCheck(self.pump.GetOnTime(2), int(self.pump.PeriodList[2]), now) time.sleep(15) except Exception as e: logger.error("PumpCheck: " + str(e)) raise e def PumpScheduleCheck(self, activationTime, duration, timeNow): max_duration = 15 interval = 10 if (timeNow == activationTime): logger.info("Pump On: " + str(duration)) while(duration > 0): if(duration <= interval): self.SwitchPumpOn(duration) else: self.SwitchPumpOn(max_duration) time.sleep(5) duration = duration - max_duration time.sleep(60) def DHTCheck(self): try: with threading.Lock(): while(self.running == True): self.devices.Read_DHT() self.SetTemperature(self.temperature.Get()) self.SetHumidity(self.humidity.Get()) time.sleep(120) except Exception as e: logger.error("DHTCheck: " + str(e)) raise e def SetTemperature(self, temperature): temp = str(temperature) + "\u00b0C" self.temperature_var.set(temp) def SetHumidity(self, humidity): hum = str(humidity) + "%" self.humidity_var.set(hum) def SwitchPumpOn(self, duration): logger.info("Pump On: " + str(duration)) self.pump.On() time.sleep(duration) self.pump.Off() def LED_On_checkbutton_click(self): try: if(self.led_on_var.get()==False): self.lights.LED.Off() else: self.lights.LED.On() except Exception as e: logger.error("LED On Checkbutton: " + str(e)) raise e def CFL_On_checkbutton_click(self): try: if(self.cfl_on_var.get()==False): self.lights.CFL.Off() else: self.lights.CFL.On() except Exception as e: logger.error("CFL On Checkbutton: " + str(e)) raise e def CFL_Enable_checkbutton_click(self): try: if(self.cfl_enable_var.get()==False): self.lights.CFL.CFLEnabled = False else: self.lights.CFL.CFLEnabled = True except Exception as e: logger.error("CFL Enable Checkbutton: " + str(e)) raise e def Fans_On_checkbutton_click(self): try: if(self.fans_on_check_var.get()==False): self.fans.Off() else: self.fans.On() except Exception as e: logger.error("Fans On Checkbutton: " + str(e)) raise e def ApplyChanges(self): try: self.lights.SetOnTime(self.lights_on_var.get()) self.lights.SetOffTime(self.lights_off_var.get()) self.lights.CFL.CFLEnabled = self.cfl_enable_var.get() self.pump.SetTimes(self.pump_time_on_var1.get(), self.pump_period_var1.get(), 0) self.pump.SetTimes(self.pump_time_on_var2.get(), self.pump_period_var2.get(), 1) self.pump.SetTimes(self.pump_time_on_var3.get(), self.pump_period_var3.get(), 2) self.fans.SetOnTime(self.fans_on_var.get()) self.fans.SetOffTime(self.fans_off_var.get()) settings = Settings(self.lights, self.pump, self.fans) except Exception as e: logger.error("Apply Changes gui update: " + str(e)) raise e try: with open("Settings.txt", "wb") as f: try: pickle.dump(settings, f) except Exception as e: logger.error("Failed to pickle Settings file") raise e except IOError: logger.error("Could not read Settings file") raise def LoadSettings(self): try: if os.path.isfile("Settings.txt")== True: with open("Settings.txt", "rb") as f: settings = pickle.load(f) self.lights.SetOnTime(settings.lights_on_var) self.lights_on_var.set(self.lights.GetOnTime()) self.lights.SetOffTime(settings.lights_off_var) self.lights_off_var.set(self.lights.GetOffTime()) self.lights.LED.SetState(settings.led_on_var) self.led_on_var.set(self.lights.LED.state) self.lights.CFL.SetState(settings.cfl_on_var) self.cfl_on_var.set(self.lights.CFL.state) self.lights.CFL.CFLEnabled = settings.cfl_enable_var self.cfl_enable_var.set(self.lights.CFL.CFLEnabled) self.pump.SetTimes(settings.pump_time_on_var1, settings.pump_period_var1, 0) self.pump_time_on_var1.set(self.pump.GetOnTime(0)) self.pump_period_var1.set(self.pump.PeriodList[0]) self.pump.SetTimes(settings.pump_time_on_var2, settings.pump_period_var2, 1) self.pump_time_on_var2.set(self.pump.GetOnTime(1)) self.pump_period_var2.set(self.pump.PeriodList[1]) self.pump.SetTimes(settings.pump_time_on_var3, settings.pump_period_var3, 2) self.pump_time_on_var3.set(self.pump.GetOnTime(2)) self.pump_period_var3.set(self.pump.PeriodList[2]) self.fans.SetOnTime(settings.fans_on_var) self.fans_on_var.set(self.fans.GetOnTime()) self.fans.SetOffTime(settings.fans_off_var) self.fans_off_var.set(self.fans.GetOffTime()) except Exception as e: logger.error("Failed to un-pickle Settings file: " + str(e)) raise e class SimpleDevice(): def __init__(self): self.OnTime self.OffTime def GetOnTime(self): return time.strftime("%H:%M", self.OnTime) def GetOffTime(self): return time.strftime("%H:%M", self.OffTime) def SetOnTime(self, timeStr): self.OnTime = time.strptime(timeStr, "%H:%M") def SetOffTime(self, timeStr): self.OffTime = time.strptime(timeStr, "%H:%M") class Lights(SimpleDevice): def __init__(self, gui, devices): try: self.devices = devices self.LED = self.LED(gui, devices) self.CFL = self.CFL(gui, devices) '''Debug auto set on/off time +1/+2 mins''' min1 = datetime.now() + timedelta(minutes=1) min2 = datetime.now() + timedelta(minutes=2) onTime = min1.time().strftime("%H:%M") offTime = min2.time().strftime("%H:%M") self.OnTime = time.strptime(onTime, "%H:%M") self.OffTime = time.strptime(offTime, "%H:%M") except Exception as e: logger.error("Lights initialisation: " + str(e)) raise e class LED(): def __init__(self, gui, devices): try: self.devices = devices self.state = False self.gui = gui except Exception as e: logger.error("LED initialisation: " + str(e)) raise e def GetState(self): return self.state def SetState(self, state): if(state): self.On() else: self.Off() def On(self): now = time.strftime("%H:%M:%S") logger.info(now + " LED on") try: self.state = True self.gui.led_on_var.set(True) self.devices.LEDOn() except Exception as e: logger.error("LED On: " + str(e)) raise e def Off(self): now = time.strftime("%H:%M:%S") logger.info(now + " LED off") try: self.state = False self.gui.led_on_var.set(False) self.devices.LEDOff() except Exception as e: logger.error("LED Off: " + str(e)) raise e class CFL(object): def __init__(self, gui, devices): try: self.devices = devices self.state = False self.CFLEnabled = True self.gui = gui except Exception as e: logger.error("CFL initialisation: " + str(e)) raise e class CFLEnabled(): def __init__(self, state = True): self._state = state def GetState(self): return self._state def SetState(self, state): self._state = state def GetState(self): return self.state def SetState(self, state): if(state): self.On() else: self.Off() def On(self): now = time.strftime("%H:%M:%S") logger.info(now + " CFL on (" + str(self.gui.temperature_var.get()) + " C)") try: self.state = True self.gui.cfl_on_var.set(True) self.devices.CFLOn() except Exception as e: logger.error("CFL On: " + str(e)) raise e def Off(self): now = time.strftime("%H:%M:%S") logger.info(now + " CFL off (" + str(self.gui.temperature_var.get()) + " C)") try: self.state = False self.gui.cfl_on_var.set(False) self.devices.CFLOff() except Exception as e: logger.error("CFL Off: " + str(e)) raise e class Fans(SimpleDevice): def __init__(self, gui, devices): try: self.devices = devices self.state = False self.gui = gui min1 = datetime.now() + timedelta(minutes=1) min2 = datetime.now() + timedelta(minutes=2) onTime = min1.time().strftime("%H:%M") offTime = min2.time().strftime("%H:%M") self.OnTime = time.strptime(onTime, "%H:%M") self.OffTime = time.strptime(offTime, "%H:%M") except Exception as e: logger.error("Fans initialisation: " + str(e)) raise e def GetState(self): return self.state def SetState(self, state): if(state): self.On() else: self.Off() def On(self): now = time.strftime("%H:%M:%S") logger.info(now + " Fans On") try: self.devices.FansOn() self.state = True self.gui.fans_on_check_var.set(True) except Exception as e: logger.error("Fans On: " + str(e)) raise e def Off(self): now = time.strftime("%H:%M:%S") logger.info(now + " Fans Off") try: self.devices.FansOff() self.state = False self.gui.fans_on_check_var.set(False) except Exception as e: logger.error("Fans Off: " + str(e)) raise e class Pump(): def __init__(self, gui, devices): try: self.devices = devices self.OnTimeList = [] self.PeriodList = [] #self.AppendTimes("04:00", 20) #self.AppendTimes("09:00", 15) self.state = False self.gui = gui '''Debug auto set on/off time +1/+2 mins''' min1 = datetime.now() + timedelta(minutes=1) min2 = datetime.now() + timedelta(minutes=2) min3 = datetime.now() + timedelta(minutes=3) onTime1 = min1.time().strftime("%H:%M") onTime2 = min2.time().strftime("%H:%M") onTime3 = min3.time().strftime("%H:%M") self.AppendTimes(onTime1, 5) self.AppendTimes(onTime2, 25) self.AppendTimes(onTime3, 5) except Exception as e: logger.error("Pump initialisation: " + str(e)) raise e def GetState(self): return self._state def On(self): now = time.strftime("%H:%M:%S") logger.info(now + " Pump On") try: self.devices.PumpOn() self.state = True self.gui.pump_on_var.set(True) except Exception as e: logger.error("Pump On: " + str(e)) raise e def Off(self): now = time.strftime("%H:%M:%S") logger.info(now + " Pump On") try: self.devices.PumpOff() self.state = False self.gui.pump_on_var.set(False) except Exception as e: logger.error("Pump Off: " + str(e)) raise e def AppendTimes(self, timeStr, period): try: t = time.strptime(timeStr, "%H:%M") self.OnTimeList.append(t) self.PeriodList.append(period) except Exception as e: logger.error("Pump AppendTimes: " + str(e)) raise e def SetTimes(self, timeStr, period, index): try: t = time.strptime(timeStr, "%H:%M") self.OnTimeList[index] = t self.PeriodList[index] = period except Exception as e: logger.error("Pump SetTimes: " + str(e)) raise e def GetOnTime(self, index): try: return time.strftime("%H:%M", self.OnTimeList[index]) except Exception as e: logger.error("Pump GetOnTime: " + str(e)) raise e class Temperature(): def __init__(self, gui, devices): self.gui = gui self.dht = devices.dht def Get(self): temp = self.dht.temperature self.gui.SetTemperature(temp) return temp class Humidity(): def __init__(self, gui, devices): self.gui = gui self.dht = devices.dht def Get(self): hum = self.dht.humidity self.gui.SetHumidity(hum) return hum class Settings: def __init__(self, lights, pump, fans): try: self.lights_on_var = lights.GetOnTime() self.lights_off_var = lights.GetOffTime() self.led_on_var = lights.LED.state self.cfl_on_var = lights.CFL.state self.cfl_enable_var = lights.CFL.CFLEnabled self.pump_time_on_var1 = pump.GetOnTime(0) self.pump_time_on_var2 = pump.GetOnTime(1) self.pump_time_on_var3 = pump.GetOnTime(2) self.pump_period_var1 = pump.PeriodList[0] self.pump_period_var2 = pump.PeriodList[1] self.pump_period_var3 = pump.PeriodList[2] self.fans_on_var = fans.GetOnTime() self.fans_off_var = fans.GetOffTime() except Exception as e: logger.error("Settings initialisation: " + str(e)) raise e class GPIODevices: def __init__(self): try: GPIO.setmode(GPIO.BCM) #set relay pins as output GPIO.setup(DEVICE.LED, GPIO.OUT) GPIO.setup(DEVICE.CFL, GPIO.OUT) GPIO.setup(DEVICE.FANS, GPIO.OUT) GPIO.setup(DEVICE.PUMP, GPIO.OUT) #Auto set default device config (LED = OFF, CFL = OFF, PUMP = OFF, FANS = ON) GPIO.output(DEVICE.LED, GPIO.LOW) GPIO.output(DEVICE.CFL, GPIO.LOW) GPIO.output(DEVICE.FANS, GPIO.HIGH) GPIO.output(DEVICE.PUMP, GPIO.HIGH) self.dht = self.DHT() except Exception as e: logger.error("GPIODevices initialisation: " + str(e)) raise e class DHT: def __init__(self): try: self.humidity = 0 self.temperature = 0 self.Read() except Exception as e: logger.error("DHT initialisation: " + str(e)) raise e def Read(self): try: self.humidity, self.temperature = Adafruit_DHT.read_retry(DEVICE.SENSOR, DEVICE.DHT) except Exception as e: logger.error("DHT Read: " + str(e)) raise e def LEDOn(self): try: GPIO.output(DEVICE.LED, GPIO.HIGH) except Exception as e: logger.error("GPIO LEDOn: " + str(e)) raise e def LEDOff(self): try: GPIO.output(DEVICE.LED, GPIO.LOW) except Exception as e: logger.error("GPIO LEDOff: " + str(e)) raise e def CFLOn(self): try: GPIO.output(DEVICE.CFL, GPIO.HIGH) except Exception as e: logger.error("GPIO CFLOn: " + str(e)) raise e def CFLOff(self): try: GPIO.output(DEVICE.CFL, GPIO.LOW) except Exception as e: logger.error("GPIO CFLOff: " + str(e)) raise e def FansOn(self): try: GPIO.output(DEVICE.FANS, GPIO.HIGH) except Exception as e: logger.error("GPIO FansOn: " + str(e)) raise e def FansOff(self): try: GPIO.output(DEVICE.FANS, GPIO.LOW) except Exception as e: logger.error("GPIO FansOff: " + str(e)) raise e def PumpOn(self): try: GPIO.output(DEVICE.PUMP, GPIO.LOW) except Exception as e: logger.error("GPIO PumpOn: " + str(e)) raise e def PumpOff(self): try: GPIO.output(DEVICE.PUMP, GPIO.HIGH) except Exception as e: logger.error("GPIO PumpOff: " + str(e)) raise e def Read_DHT(self): self.dht.Read() class DEVICE(enumerate): LED = 2 CFL = 3 FANS = 4 PUMP = 22 DHT = 14 SENSOR = Adafruit_DHT.DHT11 class LogFilter(object): def __init__(self, level): self.__level=level def filter(self, logRecord): return logRecord.levelno <= self.__level ''' if __name__ == "__main__": root = CabGui() root.mainloop() ''' if(not os.path.exists("logs")): try: os.makedirs("logs") except OSError as e: print.error("Log directors does not exist and can't create it.") raise logger = logging.getLogger("debug") logger.setLevel(logging.DEBUG) infoHandler = RotatingFileHandler("logs/info.log", maxBytes=500000, backupCount=5) infoHandler.setLevel(logging.INFO) debugHandler = RotatingFileHandler("logs/debug.log", maxBytes=500000, backupCount=5) debugHandler.setLevel(logging.DEBUG) errorHandler = RotatingFileHandler("logs/Error.log", maxBytes=500000, backupCount=5) errorHandler.setLevel(logging.ERROR) streamHandler = logging.StreamHandler() streamHandler.setLevel(logging.WARNING) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') infoFormatter = logging.Formatter('%(message)s') infoHandler.setFormatter(infoFormatter) debugHandler.setFormatter(formatter) streamHandler.setFormatter(formatter) errorHandler.setFormatter(formatter) infoHandler.addFilter(LogFilter(logging.INFO)) logger.addHandler(infoHandler) logger.addHandler(debugHandler) logger.addHandler(errorHandler) logger.addHandler(streamHandler) if __name__ == "__main__": try: root = CabGui() root.resizable(False, False) root.mainloop() except KeyboardInterrupt: print("CTRL-C Exit") except BaseException as e: print("Other error or exception: " + str(e)) traceback.print_tb(sys.exc_info()[2]) finally: #Default conditions, (LED = OFF, CFL = OFF, PUMP = OFF, FANS = ON) GPIO.output(DEVICE.LED, GPIO.LOW) GPIO.output(DEVICE.CFL, GPIO.LOW) GPIO.output(DEVICE.FANS, GPIO.HIGH) GPIO.output(DEVICE.PUMP, GPIO.HIGH) GPIO.cleanup() #ensure clean exit, freeing up GPIO pins os._exit(0)
JamesJoyce (14-09-17), M_C (10-09-17)
THCtalk.com Disclaimer - You must be over 18 years old to view/use this site .THCtalk.com does not encourage growing Cannabis or possessing Cannabis. Learning how to grow Cannabis instructions should be for educational purposes only. All Information contained in this web site is for: Historical reference, Scientific reference and Educational purposes only. Visitors to this website are advised against breaking the law as It is illegal to smoke, grow, or possess cannabis in the UK and some US States
Bookmarks