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>
This commit is contained in:
parent
b549c3927e
commit
5208fc38ed
|
@ -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
|
||||
|
|
|
@ -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
|
||||
================
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue