aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/extras/tmc.py
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2021-02-20 20:18:40 -0500
committerKevin O'Connor <kevin@koconnor.net>2021-02-27 10:39:47 -0500
commitf035de264f7469127dbc6f7abf6f173f2618e1ca (patch)
treeea00c9286c0d97ceb2aa516a6bf4b0ec41f1495d /klippy/extras/tmc.py
parent53b10d3ae7e4bdbcb82f20971600f56b9e01dfeb (diff)
downloadkutter-f035de264f7469127dbc6f7abf6f173f2618e1ca.tar.gz
kutter-f035de264f7469127dbc6f7abf6f173f2618e1ca.tar.xz
kutter-f035de264f7469127dbc6f7abf6f173f2618e1ca.zip
tmc: Add support for periodic checking of driver status
Check the status of all Trinamic stepper motor drivers once a second. If the driver reports an error then invoke a shutdown. Also log any serious warnings. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/extras/tmc.py')
-rw-r--r--klippy/extras/tmc.py77
1 files changed, 76 insertions, 1 deletions
diff --git a/klippy/extras/tmc.py b/klippy/extras/tmc.py
index 3dd46432..6d6e765b 100644
--- a/klippy/extras/tmc.py
+++ b/klippy/extras/tmc.py
@@ -77,16 +77,89 @@ class FieldHelper:
######################################################################
+# Periodic error checking
+######################################################################
+
+class TMCErrorCheck:
+ def __init__(self, config, mcu_tmc, clear_gstat=True):
+ self.printer = config.get_printer()
+ self.stepper_name = ' '.join(config.get_name().split()[1:])
+ self.mcu_tmc = mcu_tmc
+ self.fields = mcu_tmc.get_fields()
+ self.check_timer = None
+ # Setup for GSTAT query
+ self.clear_gstat = clear_gstat
+ reg_name = self.fields.lookup_register("drv_err")
+ if reg_name is not None:
+ self.gstat_reg_info = [0, reg_name, 0xffffffff, 0xffffffff]
+ else:
+ self.gstat_reg_info = None
+ # Setup for DRV_STATUS query
+ reg_name = self.fields.lookup_register("ot")
+ mask = err_mask = 0
+ err_fields = ["ot", "s2ga", "s2gb", "s2vsa", "s2vsb"]
+ warn_fields = ["otpw", "t120", "t143", "t150", "t157"]
+ for f in err_fields + warn_fields:
+ if f in self.fields.all_fields[reg_name]:
+ mask |= self.fields.all_fields[reg_name][f]
+ if f in err_fields:
+ err_mask |= self.fields.all_fields[reg_name][f]
+ self.drv_status_reg_info = [0, reg_name, mask, err_mask]
+ def _query_register(self, reg_info, try_clear=False):
+ last_value, reg_name, mask, err_mask = reg_info
+ count = 0
+ while 1:
+ val = self.mcu_tmc.get_register(reg_name)
+ if val & mask != last_value & mask:
+ fmt = self.fields.pretty_format(reg_name, val)
+ logging.info("TMC '%s' reports %s", self.stepper_name, fmt)
+ reg_info[0] = last_value = val
+ if not val & err_mask:
+ break
+ count += 1
+ if count >= 3:
+ fmt = self.fields.pretty_format(reg_name, val)
+ raise self.printer.command_error("TMC '%s' reports error: %s"
+ % (self.stepper_name, fmt))
+ if try_clear:
+ try_clear = False
+ self.mcu_tmc.set_register(reg_name, val & err_mask)
+ def _do_periodic_check(self, eventtime, try_clear=False):
+ try:
+ self._query_register(self.drv_status_reg_info)
+ if self.gstat_reg_info is not None:
+ self._query_register(self.gstat_reg_info, try_clear=try_clear)
+ except self.printer.command_error as e:
+ self.printer.invoke_shutdown(str(e))
+ return self.printer.get_reactor().NEVER
+ return eventtime + 1.
+ def stop_checks(self):
+ if self.check_timer is None:
+ return
+ self.printer.get_reactor().unregister_timer(self.check_timer)
+ self.check_timer = None
+ def start_checks(self):
+ if self.check_timer is not None:
+ self.stop_checks()
+ self._do_periodic_check(0., try_clear=self.clear_gstat)
+ reactor = self.printer.get_reactor()
+ curtime = reactor.monotonic()
+ self.check_timer = reactor.register_timer(self._do_periodic_check,
+ curtime + 1.)
+
+
+######################################################################
# G-Code command helpers
######################################################################
class TMCCommandHelper:
- def __init__(self, config, mcu_tmc, current_helper):
+ def __init__(self, config, mcu_tmc, current_helper, clear_gstat=True):
self.printer = config.get_printer()
self.stepper_name = ' '.join(config.get_name().split()[1:])
self.name = config.get_name().split()[-1]
self.mcu_tmc = mcu_tmc
self.current_helper = current_helper
+ self.echeck_helper = TMCErrorCheck(config, mcu_tmc, clear_gstat)
self.fields = mcu_tmc.get_fields()
self.read_registers = self.read_translate = None
self.toff = None
@@ -153,6 +226,7 @@ class TMCCommandHelper:
# Shared enable via comms handling
val = self.fields.set_field("toff", self.toff)
self._init_registers(print_time)
+ self.echeck_helper.start_checks()
except self.printer.command_error as e:
self.printer.invoke_shutdown(str(e))
def _do_disable(self, print_time):
@@ -161,6 +235,7 @@ class TMCCommandHelper:
val = self.fields.set_field("toff", 0)
reg_name = self.fields.lookup_register("toff")
self.mcu_tmc.set_register(reg_name, val, print_time)
+ self.echeck_helper.stop_checks()
except self.printer.command_error as e:
self.printer.invoke_shutdown(str(e))
def handle_stepper_enable(self, print_time, is_enable):