diff options
Diffstat (limited to 'klippy/extras/bltouch.py')
-rw-r--r-- | klippy/extras/bltouch.py | 212 |
1 files changed, 126 insertions, 86 deletions
diff --git a/klippy/extras/bltouch.py b/klippy/extras/bltouch.py index 2bcb9cc1..76823a25 100644 --- a/klippy/extras/bltouch.py +++ b/klippy/extras/bltouch.py @@ -9,49 +9,54 @@ from . import probe SIGNAL_PERIOD = 0.020 MIN_CMD_TIME = 5 * SIGNAL_PERIOD -TEST_TIME = 5 * 60. -RETRY_RESET_TIME = 1. -ENDSTOP_REST_TIME = .001 -ENDSTOP_SAMPLE_TIME = .000015 +TEST_TIME = 5 * 60.0 +RETRY_RESET_TIME = 1.0 +ENDSTOP_REST_TIME = 0.001 +ENDSTOP_SAMPLE_TIME = 0.000015 ENDSTOP_SAMPLE_COUNT = 4 Commands = { - 'pin_down': 0.000650, 'touch_mode': 0.001165, - 'pin_up': 0.001475, 'self_test': 0.001780, 'reset': 0.002190, - 'set_5V_output_mode' : 0.001988, 'set_OD_output_mode' : 0.002091, - 'output_mode_store' : 0.001884, + "pin_down": 0.000650, + "touch_mode": 0.001165, + "pin_up": 0.001475, + "self_test": 0.001780, + "reset": 0.002190, + "set_5V_output_mode": 0.001988, + "set_OD_output_mode": 0.002091, + "output_mode_store": 0.001884, } + # BLTouch "endstop" wrapper class BLTouchProbe: def __init__(self, config): self.printer = config.get_printer() - self.position_endstop = config.getfloat('z_offset', minval=0.) - self.stow_on_each_sample = config.getboolean('stow_on_each_sample', - True) - self.probe_touch_mode = config.getboolean('probe_with_touch_mode', - False) + self.position_endstop = config.getfloat("z_offset", minval=0.0) + self.stow_on_each_sample = config.getboolean("stow_on_each_sample", True) + self.probe_touch_mode = config.getboolean("probe_with_touch_mode", False) # Create a pwm object to handle the control pin - ppins = self.printer.lookup_object('pins') - self.mcu_pwm = ppins.setup_pin('pwm', config.get('control_pin')) - self.mcu_pwm.setup_max_duration(0.) + ppins = self.printer.lookup_object("pins") + self.mcu_pwm = ppins.setup_pin("pwm", config.get("control_pin")) + self.mcu_pwm.setup_max_duration(0.0) self.mcu_pwm.setup_cycle_time(SIGNAL_PERIOD) # Command timing - self.next_cmd_time = self.action_end_time = 0. + self.next_cmd_time = self.action_end_time = 0.0 self.finish_home_complete = self.wait_trigger_complete = None # Create an "endstop" object to handle the sensor pin - self.mcu_endstop = ppins.setup_pin('endstop', config.get('sensor_pin')) + self.mcu_endstop = ppins.setup_pin("endstop", config.get("sensor_pin")) # output mode - omodes = ['5V', 'OD', None] - self.output_mode = config.getchoice('set_output_mode', omodes, None) + omodes = ["5V", "OD", None] + self.output_mode = config.getchoice("set_output_mode", omodes, None) # Setup for sensor test - self.next_test_time = 0. + self.next_test_time = 0.0 self.pin_up_not_triggered = config.getboolean( - 'pin_up_reports_not_triggered', True) + "pin_up_reports_not_triggered", True + ) self.pin_up_touch_triggered = config.getboolean( - 'pin_up_touch_mode_reports_triggered', True) + "pin_up_touch_mode_reports_triggered", True + ) # Calculate pin move time - self.pin_move_time = config.getfloat('pin_move_time', 0.680, above=0.) + self.pin_move_time = config.getfloat("pin_move_time", 0.680, above=0.0) # Wrappers self.get_mcu = self.mcu_endstop.get_mcu self.add_stepper = self.mcu_endstop.add_stepper @@ -59,33 +64,40 @@ class BLTouchProbe: self.home_wait = self.mcu_endstop.home_wait self.query_endstop = self.mcu_endstop.query_endstop # multi probes state - self.multi = 'OFF' + self.multi = "OFF" # Common probe implementation helpers self.cmd_helper = probe.ProbeCommandHelper( - config, self, self.mcu_endstop.query_endstop) + config, self, self.mcu_endstop.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 + ) # Register BLTOUCH_DEBUG command - self.gcode = self.printer.lookup_object('gcode') - self.gcode.register_command("BLTOUCH_DEBUG", self.cmd_BLTOUCH_DEBUG, - desc=self.cmd_BLTOUCH_DEBUG_help) - self.gcode.register_command("BLTOUCH_STORE", self.cmd_BLTOUCH_STORE, - desc=self.cmd_BLTOUCH_STORE_help) + self.gcode = self.printer.lookup_object("gcode") + self.gcode.register_command( + "BLTOUCH_DEBUG", self.cmd_BLTOUCH_DEBUG, desc=self.cmd_BLTOUCH_DEBUG_help + ) + self.gcode.register_command( + "BLTOUCH_STORE", self.cmd_BLTOUCH_STORE, desc=self.cmd_BLTOUCH_STORE_help + ) # Register events - self.printer.register_event_handler("klippy:connect", - self.handle_connect) + self.printer.register_event_handler("klippy:connect", self.handle_connect) + 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 handle_connect(self): self.sync_mcu_print_time() self.next_cmd_time += 0.200 @@ -95,17 +107,20 @@ class BLTouchProbe: self.verify_raise_probe() except self.printer.command_error as e: logging.warning("BLTouch raise probe error: %s", str(e)) + def sync_mcu_print_time(self): curtime = self.printer.get_reactor().monotonic() est_time = self.mcu_pwm.get_mcu().estimated_print_time(curtime) self.next_cmd_time = max(self.next_cmd_time, est_time + MIN_CMD_TIME) + def sync_print_time(self): - toolhead = self.printer.lookup_object('toolhead') + toolhead = self.printer.lookup_object("toolhead") print_time = toolhead.get_last_move_time() if self.next_cmd_time > print_time: toolhead.dwell(self.next_cmd_time - print_time) else: self.next_cmd_time = print_time + def send_cmd(self, cmd, duration=MIN_CMD_TIME): # Translate duration to ticks to avoid any secondary mcu clock skew mcu = self.mcu_pwm.get_mcu() @@ -115,26 +130,32 @@ class BLTouchProbe: end_time = mcu.clock_to_print_time(cmd_clock) # Schedule command followed by PWM disable self.mcu_pwm.set_pwm(self.next_cmd_time, Commands[cmd] / SIGNAL_PERIOD) - self.mcu_pwm.set_pwm(end_time, 0.) + self.mcu_pwm.set_pwm(end_time, 0.0) # Update time tracking self.action_end_time = self.next_cmd_time + duration self.next_cmd_time = max(self.action_end_time, end_time + MIN_CMD_TIME) + def verify_state(self, triggered): # Perform endstop check to verify bltouch reports desired state - self.mcu_endstop.home_start(self.action_end_time, ENDSTOP_SAMPLE_TIME, - ENDSTOP_SAMPLE_COUNT, ENDSTOP_REST_TIME, - triggered=triggered) + self.mcu_endstop.home_start( + self.action_end_time, + ENDSTOP_SAMPLE_TIME, + ENDSTOP_SAMPLE_COUNT, + ENDSTOP_REST_TIME, + triggered=triggered, + ) try: - trigger_time = self.mcu_endstop.home_wait( - self.action_end_time + 0.100) + trigger_time = self.mcu_endstop.home_wait(self.action_end_time + 0.100) except self.printer.command_error as e: return False - return trigger_time > 0. + return trigger_time > 0.0 + def raise_probe(self): self.sync_mcu_print_time() if not self.pin_up_not_triggered: - self.send_cmd('reset') - self.send_cmd('pin_up', duration=self.pin_move_time) + self.send_cmd("reset") + self.send_cmd("pin_up", duration=self.pin_move_time) + def verify_raise_probe(self): if not self.pin_up_not_triggered: # No way to verify raise attempt @@ -145,24 +166,25 @@ class BLTouchProbe: # The "probe raised" test completed successfully break if retry >= 2: - raise self.printer.command_error( - "BLTouch failed to raise probe") + raise self.printer.command_error("BLTouch failed to raise probe") msg = "Failed to verify BLTouch probe is raised; retrying." self.gcode.respond_info(msg) self.sync_mcu_print_time() - self.send_cmd('reset', duration=RETRY_RESET_TIME) - self.send_cmd('pin_up', duration=self.pin_move_time) + self.send_cmd("reset", duration=RETRY_RESET_TIME) + self.send_cmd("pin_up", duration=self.pin_move_time) + def lower_probe(self): self.test_sensor() self.sync_print_time() - self.send_cmd('pin_down', duration=self.pin_move_time) + self.send_cmd("pin_down", duration=self.pin_move_time) if self.probe_touch_mode: - self.send_cmd('touch_mode') + self.send_cmd("touch_mode") + def test_sensor(self): if not self.pin_up_touch_triggered: # Nothing to test return - toolhead = self.printer.lookup_object('toolhead') + toolhead = self.printer.lookup_object("toolhead") print_time = toolhead.get_last_move_time() if print_time < self.next_test_time: self.next_test_time = print_time + TEST_TIME @@ -170,8 +192,8 @@ class BLTouchProbe: # Raise the bltouch probe and test if probe is raised self.sync_print_time() for retry in range(3): - self.send_cmd('pin_up', duration=self.pin_move_time) - self.send_cmd('touch_mode') + self.send_cmd("pin_up", duration=self.pin_move_time) + self.send_cmd("touch_mode") success = self.verify_state(True) self.sync_print_time() if success: @@ -181,12 +203,14 @@ class BLTouchProbe: msg = "BLTouch failed to verify sensor state" if retry >= 2: raise self.printer.command_error(msg) - self.gcode.respond_info(msg + '; retrying.') - self.send_cmd('reset', duration=RETRY_RESET_TIME) + self.gcode.respond_info(msg + "; retrying.") + self.send_cmd("reset", duration=RETRY_RESET_TIME) + def multi_probe_begin(self): if self.stow_on_each_sample: return - self.multi = 'FIRST' + self.multi = "FIRST" + def multi_probe_end(self): if self.stow_on_each_sample: return @@ -194,35 +218,43 @@ class BLTouchProbe: self.raise_probe() self.verify_raise_probe() self.sync_print_time() - self.multi = 'OFF' + self.multi = "OFF" + def probe_prepare(self, hmove): - if self.multi == 'OFF' or self.multi == 'FIRST': + if self.multi == "OFF" or self.multi == "FIRST": self.lower_probe() - if self.multi == 'FIRST': - self.multi = 'ON' + if self.multi == "FIRST": + self.multi = "ON" self.sync_print_time() - def home_start(self, print_time, sample_time, sample_count, rest_time, - triggered=True): + + def home_start( + self, print_time, sample_time, sample_count, rest_time, triggered=True + ): rest_time = min(rest_time, ENDSTOP_REST_TIME) self.finish_home_complete = self.mcu_endstop.home_start( - print_time, sample_time, sample_count, rest_time, triggered) + print_time, sample_time, sample_count, rest_time, triggered + ) # Schedule wait_for_trigger callback r = self.printer.get_reactor() self.wait_trigger_complete = r.register_callback(self.wait_for_trigger) return self.finish_home_complete + def wait_for_trigger(self, eventtime): self.finish_home_complete.wait() - if self.multi == 'OFF': + if self.multi == "OFF": self.raise_probe() + def probe_finish(self, hmove): self.wait_trigger_complete.wait() - if self.multi == 'OFF': + if self.multi == "OFF": self.verify_raise_probe() self.sync_print_time() if hmove.check_no_movement() is not None: raise self.printer.command_error("BLTouch failed to deploy") + def get_position_endstop(self): return self.position_endstop + def set_output_mode(self, mode): # If this is inadvertently/purposely issued for a # BLTOUCH pre V3.0 and clones: @@ -233,10 +265,11 @@ class BLTouchProbe: return logging.info("BLTouch set output mode: %s", mode) self.sync_mcu_print_time() - if mode == '5V': - self.send_cmd('set_5V_output_mode') - if mode == 'OD': - self.send_cmd('set_OD_output_mode') + if mode == "5V": + self.send_cmd("set_5V_output_mode") + if mode == "OD": + self.send_cmd("set_OD_output_mode") + def store_output_mode(self, mode): # If this command is inadvertently/purposely issued for a # BLTOUCH pre V3.0 and clones: @@ -249,32 +282,38 @@ class BLTouchProbe: # The pin-up is not needed but does not hurt logging.info("BLTouch store output mode: %s", mode) self.sync_print_time() - self.send_cmd('pin_down') - if mode == '5V': - self.send_cmd('set_5V_output_mode') + self.send_cmd("pin_down") + if mode == "5V": + self.send_cmd("set_5V_output_mode") else: - self.send_cmd('set_OD_output_mode') - self.send_cmd('output_mode_store') - if mode == '5V': - self.send_cmd('set_5V_output_mode') + self.send_cmd("set_OD_output_mode") + self.send_cmd("output_mode_store") + if mode == "5V": + self.send_cmd("set_5V_output_mode") else: - self.send_cmd('set_OD_output_mode') - self.send_cmd('pin_up') + self.send_cmd("set_OD_output_mode") + self.send_cmd("pin_up") + cmd_BLTOUCH_DEBUG_help = "Send a command to the bltouch for debugging" + def cmd_BLTOUCH_DEBUG(self, gcmd): - cmd = gcmd.get('COMMAND', None) + cmd = gcmd.get("COMMAND", None) if cmd is None or cmd not in Commands: - gcmd.respond_info("BLTouch commands: %s" % ( - ", ".join(sorted([c for c in Commands if c is not None])))) + gcmd.respond_info( + "BLTouch commands: %s" + % (", ".join(sorted([c for c in Commands if c is not None]))) + ) return gcmd.respond_info("Sending BLTOUCH_DEBUG COMMAND=%s" % (cmd,)) self.sync_print_time() self.send_cmd(cmd, duration=self.pin_move_time) self.sync_print_time() + cmd_BLTOUCH_STORE_help = "Store an output mode in the BLTouch EEPROM" + def cmd_BLTOUCH_STORE(self, gcmd): - cmd = gcmd.get('MODE', None) - if cmd is None or cmd not in ['5V', 'OD']: + cmd = gcmd.get("MODE", None) + if cmd is None or cmd not in ["5V", "OD"]: gcmd.respond_info("BLTouch output modes: 5V, OD") return gcmd.respond_info("Storing BLTouch output mode: %s" % (cmd,)) @@ -282,7 +321,8 @@ class BLTouchProbe: self.store_output_mode(cmd) self.sync_print_time() + def load_config(config): blt = BLTouchProbe(config) - config.get_printer().add_object('probe', blt) + config.get_printer().add_object("probe", blt) return blt |