From 8061042ee5e89a0956c6bbf6413c256a8ec7b7c3 Mon Sep 17 00:00:00 2001 From: fishpepper Date: Wed, 13 Nov 2024 19:03:46 +0100 Subject: [PATCH] add emergency relais support, inspired by pr60 --- config.py | 18 +++++++++++------- emergency-off.py | 29 +++++++++++++++++++++++++++++ lib/init/kiln-controller.service | 1 + lib/oven.py | 23 +++++++++++++++++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) create mode 100755 emergency-off.py diff --git a/config.py b/config.py index c133e9c7..9ccbc3c4 100644 --- a/config.py +++ b/config.py @@ -79,17 +79,21 @@ ####################################### # Output to control the relay ####################################### -# A single GPIO pin is used to control a relay which controls the kiln. +# One GPIO pin is used to control a relay which controls the kiln. # I use GPIO pin 23. +# +# A second GPIO pin is used to control an emergency cutoff relay which +# stops the kiln even if the SSRs short out. try: import board - spi_sclk = board.D17 #spi clock - spi_miso = board.D27 #spi Microcomputer In Serial Out - spi_cs = board.D22 #spi Chip Select - spi_mosi = board.D10 #spi Microcomputer Out Serial In (not connected) - gpio_heat = board.D23 #output that controls relay - gpio_heat_invert = False #invert the output state + spi_sclk = board.D17 #spi clock + spi_miso = board.D27 #spi Microcomputer In Serial Out + spi_cs = board.D22 #spi Chip Select + spi_mosi = board.D10 #spi Microcomputer Out Serial In (not connected) + gpio_heat = board.D23 #output that controls relay + gpio_heat_invert = False #invert the output state + gpio_emergency = board.D26 #output that controls emergency relay except (NotImplementedError,AttributeError): print("not running on blinka recognized board, probably a simulation") diff --git a/emergency-off.py b/emergency-off.py new file mode 100755 index 00000000..c11fa5db --- /dev/null +++ b/emergency-off.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +import config +import digitalio +import time +import datetime + +try: + import board +except NotImplementedError: + print("not running a recognized blinka board, exiting...") + import sys + sys.exit() + +######################################################################## +# +# shut down the mergency relais + +# Edit config.py and set the following in that file to match your +# hardware setup: gpio_emergency +######################################################################## + +emergency = digitalio.DigitalInOut(config.gpio_emergency) +emergency.direction = digitalio.Direction.OUTPUT + +print("\nboard: %s" % (board.board_id)) +print("emergency configured as config.gpio_emergency = %s BCM pin\n" % (config.gpio_emergency)) + +print("\nsetting emergency IO low") +emergency.value = False diff --git a/lib/init/kiln-controller.service b/lib/init/kiln-controller.service index 318e4c05..d39141e6 100644 --- a/lib/init/kiln-controller.service +++ b/lib/init/kiln-controller.service @@ -3,6 +3,7 @@ Description=kiln-controller [Service] ExecStart=/home/pi/kiln-controller/venv/bin/python /home/pi/kiln-controller/kiln-controller.py +ExecStopPost=/home/pi/kiln-controller/venv/bin/python /home/pi/kiln-controller/emergency-off.py [Install] WantedBy=multi-user.target diff --git a/lib/oven.py b/lib/oven.py index 9eed5183..219a660c 100644 --- a/lib/oven.py +++ b/lib/oven.py @@ -37,14 +37,21 @@ class Output(object): inputs config.gpio_heat config.gpio_heat_invert + config.gpio_emergency ''' def __init__(self): self.active = False self.heater = digitalio.DigitalInOut(config.gpio_heat) self.heater.direction = digitalio.Direction.OUTPUT + self.emergency = digitalio.DigitalInOut(config.gpio_emergency) + self.emergency.direction = digitalio.Direction.OUTPUT self.off = config.gpio_heat_invert self.on = not self.off + def emergency_set(self,state): + log.info("emergency relais = %s" %(state)) + self.emergency.value = state + def heat(self,sleepfor): self.heater.value = self.on time.sleep(sleepfor) @@ -346,6 +353,7 @@ def reset(self): self.heat_rate_temps = [] self.pid = PID(ki=config.pid_ki, kd=config.pid_kd, kp=config.pid_kp) self.catching_up = False + self.emergency_trigger() @staticmethod def get_start_from_temperature(profile, temp): @@ -392,11 +400,13 @@ def run_profile(self, profile, startat=0, allow_seek=True): self.totaltime = profile.get_duration() self.state = "RUNNING" log.info("Running schedule %s starting at %d minutes" % (profile.name,startat)) + self.emergency_release() log.info("Starting") def abort_run(self): self.reset() self.save_automatic_restart_state() + self.emergency_trigger() def get_start_time(self): return datetime.datetime.now() - datetime.timedelta(milliseconds = self.runtime * 1000) @@ -676,6 +686,11 @@ def heat_then_cool(self): # a simulation, so sleep. time.sleep(self.time_step / self.speedup_factor) + def emergency_trigger(self): + log.info("emergency triggered -> heating disabled.") + + def emergency_release(self): + log.info("emergency released -> heating enabled.") class RealOven(Oven): @@ -729,6 +744,14 @@ def heat_then_cool(self): except KeyError: pass + def emergency_trigger(self): + log.info("emergency triggered -> heating disabled.") + self.output.emergency_set(0) + + def emergency_release(self): + log.info("emergency released -> heating enabled.") + self.output.emergency_set(1) + class Profile(): def __init__(self, json_data): obj = json.loads(json_data)