diff options
Diffstat (limited to 'klippy/extras/smart_effector.py')
-rw-r--r-- | klippy/extras/smart_effector.py | 110 |
1 files changed, 66 insertions, 44 deletions
diff --git a/klippy/extras/smart_effector.py b/klippy/extras/smart_effector.py index 3caa4e6b..2ddee5e9 100644 --- a/klippy/extras/smart_effector.py +++ b/klippy/extras/smart_effector.py @@ -9,28 +9,33 @@ from . import probe # SmartEffector communication protocol implemented here originates from # https://github.com/Duet3D/SmartEffectorFirmware -BITS_PER_SECOND = 1000. +BITS_PER_SECOND = 1000.0 + class ControlPinHelper: def __init__(self, pin_params): - self._mcu = pin_params['chip'] - self._pin = pin_params['pin'] - self._start_value = self._invert = pin_params['invert'] + self._mcu = pin_params["chip"] + self._pin = pin_params["pin"] + self._start_value = self._invert = pin_params["invert"] self._oid = None self._set_cmd = None self._mcu.register_config_callback(self._build_config) + def _build_config(self): self._mcu.request_move_queue_slot() self._oid = self._mcu.create_oid() self._mcu.add_config_cmd( "config_digital_out oid=%d pin=%s value=%d default_value=%d" - " max_duration=%d" % (self._oid, self._pin, self._start_value, - self._start_value, 0)) + " max_duration=%d" + % (self._oid, self._pin, self._start_value, self._start_value, 0) + ) cmd_queue = self._mcu.alloc_command_queue() self._set_cmd = self._mcu.lookup_command( - "queue_digital_out oid=%c clock=%u on_ticks=%u", cq=cmd_queue) + "queue_digital_out oid=%c clock=%u on_ticks=%u", cq=cmd_queue + ) + def write_bits(self, start_time, bit_stream): - bit_step = 1. / BITS_PER_SECOND + bit_step = 1.0 / BITS_PER_SECOND last_value = self._start_value bit_time = start_time for b in bit_stream: @@ -48,12 +53,13 @@ class ControlPinHelper: bit_time += bit_step return bit_time + class SmartEffectorProbe: def __init__(self, config): self.printer = config.get_printer() - self.gcode = self.printer.lookup_object('gcode') - self.probe_accel = config.getfloat('probe_accel', 0., minval=0.) - self.recovery_time = config.getfloat('recovery_time', 0.4, minval=0.) + self.gcode = self.printer.lookup_object("gcode") + self.probe_accel = config.getfloat("probe_accel", 0.0, minval=0.0) + self.recovery_time = config.getfloat("recovery_time", 0.4, minval=0.0) self.probe_wrapper = probe.ProbeEndstopWrapper(config) # Wrappers self.get_mcu = self.probe_wrapper.get_mcu @@ -67,51 +73,61 @@ class SmartEffectorProbe: self.get_position_endstop = self.probe_wrapper.get_position_endstop # Common probe implementation helpers self.cmd_helper = probe.ProbeCommandHelper( - config, self, self.probe_wrapper.query_endstop) + config, self, self.probe_wrapper.query_endstop + ) self.probe_offsets = probe.ProbeOffsetsHelper(config) self.param_helper = probe.ProbeParameterHelper(config) - self.homing_helper = probe.HomingViaProbeHelper(config, self, - self.param_helper) + self.homing_helper = probe.HomingViaProbeHelper(config, self, self.param_helper) self.probe_session = probe.ProbeSessionHelper( - config, self.param_helper, self.homing_helper.start_probe_session) + config, self.param_helper, self.homing_helper.start_probe_session + ) # SmartEffector control - control_pin = config.get('control_pin', None) + control_pin = config.get("control_pin", None) if control_pin: - ppins = self.printer.lookup_object('pins') + ppins = self.printer.lookup_object("pins") pin_params = ppins.lookup_pin(control_pin, can_invert=True) self.control_pin = ControlPinHelper(pin_params) - self.gcode.register_command("RESET_SMART_EFFECTOR", - self.cmd_RESET_SMART_EFFECTOR, - desc=self.cmd_RESET_SMART_EFFECTOR_help) + self.gcode.register_command( + "RESET_SMART_EFFECTOR", + self.cmd_RESET_SMART_EFFECTOR, + desc=self.cmd_RESET_SMART_EFFECTOR_help, + ) else: self.control_pin = None - self.gcode.register_command("SET_SMART_EFFECTOR", - self.cmd_SET_SMART_EFFECTOR, - desc=self.cmd_SET_SMART_EFFECTOR_help) + self.gcode.register_command( + "SET_SMART_EFFECTOR", + self.cmd_SET_SMART_EFFECTOR, + desc=self.cmd_SET_SMART_EFFECTOR_help, + ) + def get_probe_params(self, gcmd=None): return self.param_helper.get_probe_params(gcmd) + def get_offsets(self): return self.probe_offsets.get_offsets() + def get_status(self, eventtime): return self.cmd_helper.get_status(eventtime) + def start_probe_session(self, gcmd): return self.probe_session.start_probe_session(gcmd) + def probe_prepare(self, hmove): - toolhead = self.printer.lookup_object('toolhead') + toolhead = self.printer.lookup_object("toolhead") self.probe_wrapper.probe_prepare(hmove) if self.probe_accel: systime = self.printer.get_reactor().monotonic() toolhead_info = toolhead.get_status(systime) - self.old_max_accel = toolhead_info['max_accel'] - self.gcode.run_script_from_command( - "M204 S%.3f" % (self.probe_accel,)) + self.old_max_accel = toolhead_info["max_accel"] + self.gcode.run_script_from_command("M204 S%.3f" % (self.probe_accel,)) if self.recovery_time: toolhead.dwell(self.recovery_time) + def probe_finish(self, hmove): if self.probe_accel: - self.gcode.run_script_from_command( - "M204 S%.3f" % (self.old_max_accel,)) + self.gcode.run_script_from_command("M204 S%.3f" % (self.old_max_accel,)) self.probe_wrapper.probe_finish(hmove) + def _send_command(self, buf): # Each byte is sent to the SmartEffector as # [0 0 1 0 b7 b6 b5 b4 !b4 b3 b2 b1 b0 !b0] @@ -124,7 +140,7 @@ class SmartEffectorProbe: bit_stream.extend([b & 0x08, b & 0x04, b & 0x02, b & 0x01]) bit_stream.append((~b) & 0x01) # Wait for previous actions to finish - toolhead = self.printer.lookup_object('toolhead') + toolhead = self.printer.lookup_object("toolhead") toolhead.wait_moves() start_time = toolhead.get_last_move_time() # Write generated bits to the control pin @@ -133,9 +149,11 @@ class SmartEffectorProbe: # with the SmartEffector programming toolhead.dwell(end_time - start_time) toolhead.wait_moves() - cmd_SET_SMART_EFFECTOR_help = 'Set SmartEffector parameters' + + cmd_SET_SMART_EFFECTOR_help = "Set SmartEffector parameters" + def cmd_SET_SMART_EFFECTOR(self, gcmd): - sensitivity = gcmd.get_int('SENSITIVITY', None, minval=0, maxval=255) + sensitivity = gcmd.get_int("SENSITIVITY", None, minval=0, maxval=255) respond_info = [] if sensitivity is not None: if self.control_pin is not None: @@ -143,29 +161,33 @@ class SmartEffectorProbe: self._send_command(buf) respond_info.append("sensitivity: %d" % (sensitivity,)) else: - raise gcmd.error("control_pin must be set in [smart_effector] " - "for sensitivity programming") - self.probe_accel = gcmd.get_float('ACCEL', self.probe_accel, minval=0.) - self.recovery_time = gcmd.get_float('RECOVERY_TIME', self.recovery_time, - minval=0.) + raise gcmd.error( + "control_pin must be set in [smart_effector] " + "for sensitivity programming" + ) + self.probe_accel = gcmd.get_float("ACCEL", self.probe_accel, minval=0.0) + self.recovery_time = gcmd.get_float( + "RECOVERY_TIME", self.recovery_time, minval=0.0 + ) if self.probe_accel: - respond_info.append( - "probing accelartion: %.3f" % (self.probe_accel,)) + respond_info.append("probing accelartion: %.3f" % (self.probe_accel,)) else: respond_info.append("probing acceleration control disabled") if self.recovery_time: - respond_info.append( - "probe recovery time: %.3f" % (self.recovery_time,)) + respond_info.append("probe recovery time: %.3f" % (self.recovery_time,)) else: respond_info.append("probe recovery time disabled") gcmd.respond_info("SmartEffector:\n" + "\n".join(respond_info)) - cmd_RESET_SMART_EFFECTOR_help = 'Reset SmartEffector settings (sensitivity)' + + cmd_RESET_SMART_EFFECTOR_help = "Reset SmartEffector settings (sensitivity)" + def cmd_RESET_SMART_EFFECTOR(self, gcmd): buf = [131, 131] self._send_command(buf) - gcmd.respond_info('SmartEffector sensitivity was reset') + gcmd.respond_info("SmartEffector sensitivity was reset") + def load_config(config): smart_effector = SmartEffectorProbe(config) - config.get_printer().add_object('probe', smart_effector) + config.get_printer().add_object("probe", smart_effector) return smart_effector |