aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-03-11 00:22:44 -0500
committerKevin O'Connor <kevin@koconnor.net>2018-03-11 00:49:11 -0500
commit5208fc38edc7e62958bfc51de7918351b888b408 (patch)
tree78837f8929048a871af75f23d1837afac535175b
parentb549c3927e292a33188b46d22fc67ab48b6b790a (diff)
downloadkutter-5208fc38edc7e62958bfc51de7918351b888b408.tar.gz
kutter-5208fc38edc7e62958bfc51de7918351b888b408.tar.xz
kutter-5208fc38edc7e62958bfc51de7918351b888b408.zip
verify_heater: Add initial support for verifying heaters and sensors
Add runtime checks to heaters and temperature sensors to check for possible hardware faults. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--config/example-extras.cfg22
-rw-r--r--docs/Todo.md4
-rw-r--r--klippy/extras/verify_heater.py67
-rw-r--r--klippy/heater.py2
4 files changed, 91 insertions, 4 deletions
diff --git a/config/example-extras.cfg b/config/example-extras.cfg
index 33b67178..fa48e780 100644
--- a/config/example-extras.cfg
+++ b/config/example-extras.cfg
@@ -122,6 +122,28 @@
# See the example.cfg for the definition of the above parameters.
+# Heater and temperature sensor verification. Heater verification is
+# automatically enabled for each heater that is configured on the
+# printer. Use verify_heater sections to change the default settings.
+#[verify_heater heater_config_name]
+#heating_gain: 2
+# The minimum temperature (in Celsius) that the heater must increase
+# by when approaching a new target temperature. The default is 2.
+#check_gain_time:
+# The amount of time (in seconds) that the heating_gain must be met
+# in before an error is raised. The default is 20 seconds for
+# extruders and 60 seconds for heater_bed.
+#hysteresis: 4
+# The difference between the target temperature and the current
+# temperature for the heater to be considered within range of the
+# target temperature. The default is 4.
+#check_time: 10
+# The amount of time (in seconds) a heater that has reached the
+# target temperature (as defined by the hysteresis field) may fall
+# outside the target temperature range before an error is
+# raised. The default is 10.
+
+
# Multi-stepper axes. On a cartesian style printer, the stepper
# controlling a given axis may have additional config blocks defining
# steppers that should be stepped in concert with the primary
diff --git a/docs/Todo.md b/docs/Todo.md
index adf4c8c1..2c9be3c5 100644
--- a/docs/Todo.md
+++ b/docs/Todo.md
@@ -44,10 +44,6 @@ Safety features
endstop detection is a good idea because of spurious signals caused
by electrical noise.)
-* Support validating that heaters are heating at expected rates. This
- can be useful to detect a sensor failure (eg, thermistor short) that
- could otherwise cause the PID to command excessive heating.
-
Testing features
================
diff --git a/klippy/extras/verify_heater.py b/klippy/extras/verify_heater.py
new file mode 100644
index 00000000..f7b750eb
--- /dev/null
+++ b/klippy/extras/verify_heater.py
@@ -0,0 +1,67 @@
+# Heater/sensor verification code
+#
+# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
+#
+# This file may be distributed under the terms of the GNU GPLv3 license.
+import logging
+import extruder
+
+class HeaterCheck:
+ def __init__(self, config):
+ self.printer = config.get_printer()
+ self.heater_name = config.get_name().split()[1]
+ self.heater = None
+ self.hysteresis = config.getfloat('hysteresis', 4., above=0.)
+ self.check_time = config.getfloat('check_time', 10., minval=1.)
+ self.heating_gain = config.getfloat('heating_gain', 2., above=0.)
+ default_gain_time = 20.
+ if self.heater_name == 'heater_bed':
+ default_gain_time = 60.
+ self.check_gain_time = config.getfloat(
+ 'check_gain_time', default_gain_time, minval=1.)
+ self.met_target = False
+ self.last_target = self.goal_temp = 0.
+ self.fault_systime = self.printer.get_reactor().NEVER
+ def printer_state(self, state):
+ if state == 'connect':
+ self.heater = extruder.get_printer_heater(
+ self.printer, self.heater_name)
+ logging.info("Starting heater checks for %s", self.heater_name)
+ reactor = self.printer.get_reactor()
+ reactor.register_timer(self.check_event, reactor.NOW)
+ def check_event(self, eventtime):
+ temp, target = self.heater.get_temp(eventtime)
+ if temp >= target - self.hysteresis:
+ # Temperature near target - reset checks
+ if not self.met_target:
+ logging.info("Heater %s within range of %.3f",
+ self.heater_name, target)
+ self.met_target = True
+ self.fault_systime = eventtime + self.check_time
+ elif self.met_target:
+ if target != self.last_target:
+ # Target changed - reset checks
+ logging.info("Heater %s approaching new target of %.3f",
+ self.heater_name, target)
+ self.met_target = False
+ self.goal_temp = temp + self.heating_gain
+ self.fault_systime = eventtime + self.check_gain_time
+ elif eventtime >= self.fault_systime:
+ # Failure due to inability to maintain target temperature
+ return self.heater_fault()
+ elif temp >= self.goal_temp:
+ # Temperature approaching target - reset checks
+ self.goal_temp = temp + self.heating_gain
+ self.fault_systime = eventtime + self.check_gain_time
+ elif eventtime >= self.fault_systime:
+ # Failure due to inability to approach target temperature
+ return self.heater_fault()
+ self.last_target = target
+ return eventtime + 1.
+ def heater_fault(self):
+ logging.error("Heater %s not heating at expected rate", self.heater_name)
+ self.printer.invoke_shutdown("Heater %s failsafe" % (self.heater_name,))
+ return self.printer.get_reactor().NEVER
+
+def load_config_prefix(config):
+ return HeaterCheck(config)
diff --git a/klippy/heater.py b/klippy/heater.py
index d3315a52..0e854db7 100644
--- a/klippy/heater.py
+++ b/klippy/heater.py
@@ -141,6 +141,8 @@ class PrinterHeater:
# pwm caching
self.next_pwm_time = 0.
self.last_pwm_value = 0.
+ # Load verify_heater module
+ printer.try_load_module(config, "verify_heater %s" % (self.name,))
def set_pwm(self, read_time, value):
if self.target_temp <= 0.:
value = 0.