From 72b9b995c3cb2e1c7863276136298db7f0504d73 Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 12 Oct 2023 19:18:35 -0400 Subject: [PATCH] good sensorless (#65) * real sensorless v1 * flake * tests and docs * refactor current again to not wipe overrides * add min homing dist behavior * Remove unecessary logs * use stepper name instead * readme --------- Co-authored-by: Rogerio Goncalves --- .gitignore | 1 + README.md | 6 +++ docs/Config_Reference.md | 23 ++++++++- klippy/extras/homing.py | 102 ++++++++++++++++++++++++++++++++++----- klippy/extras/tmc.py | 41 +++++++++++++--- klippy/extras/tmc2130.py | 33 +++++++++++-- klippy/extras/tmc2240.py | 41 +++++++++++++--- klippy/extras/tmc2660.py | 24 ++++++++- klippy/extras/tmc5160.py | 33 +++++++++++-- klippy/stepper.py | 22 +++++++++ klippy/toolhead.py | 11 +++++ test/klippy/tmc.cfg | 4 +- 12 files changed, 301 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index 45735517a..2bc23f69f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ klippy/.version .DS_Store ci_build/ ci_cache/ +_test_.* diff --git a/README.md b/README.md index d5a50fbc0..d2036295c 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,12 @@ Features merged into the master branch: - [core: danger_options](https://github.com/DangerKlippers/danger-klipper/pull/67) +- [stepper: home_current](https://github.com/DangerKlippers/danger-klipper/pull/65) + +- [homing: post-home retract](https://github.com/DangerKlippers/danger-klipper/pull/65) + +- [homing: sensorless minimum home distance](https://github.com/DangerKlippers/danger-klipper/pull/65) + "Dangerous Klipper for dangerous users" Klipper is a 3d-Printer firmware. It combines the power of a general diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index db2fd576f..814ca3294 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -204,7 +204,9 @@ position_max: # is 5mm/s. #homing_retract_dist: 5.0 # Distance to backoff (in mm) before homing a second time during -# homing. Set this to zero to disable the second home. The default +# homing. If `use_sensorless_homing` is false, this setting can be set +# to zero to disable the second home. If `use_sensorless_homing` is +# true, this setting can be > 0 to backoff after homing. The default # is 5mm. #homing_retract_speed: # Speed to use on the retract move after homing in case this should @@ -219,6 +221,9 @@ position_max: # better to use the default than to specify this parameter. The # default is true if position_endstop is near position_max and false # if near position_min. +#use_sensorless_homing: +# If true, disables the second home action if homing_retract_dist > 0. +# The default is true if endstop_pin is configured to use virtual_endstop ``` ### Cartesian Kinematics @@ -3399,6 +3404,9 @@ run_current: # when the stepper is not moving. Setting a hold_current is not # recommended (see TMC_Drivers.md for details). The default is to # not reduce the current. +#home_current: +# The amount of current (in amps RMS) to configure the driver to use +# during homing procedures. The default is to not reduce the current. #sense_resistor: 0.110 # The resistance (in ohms) of the motor sense resistor. The default # is 0.110 ohms. @@ -3492,6 +3500,9 @@ run_current: # when the stepper is not moving. Setting a hold_current is not # recommended (see TMC_Drivers.md for details). The default is to # not reduce the current. +#home_current: +# The amount of current (in amps RMS) to configure the driver to use +# during homing procedures. The default is to not reduce the current. #sense_resistor: 0.110 # The resistance (in ohms) of the motor sense resistor. The default # is 0.110 ohms. @@ -3535,6 +3546,7 @@ uart_pin: #interpolate: True run_current: #hold_current: +#home_current: #sense_resistor: 0.110 #stealthchop_threshold: 0 # See the "tmc2208" section for the definition of these parameters. @@ -3603,6 +3615,9 @@ cs_pin: run_current: # The amount of current (in amps RMS) used by the driver during # stepper movement. This parameter must be provided. +#home_current: +# The amount of current (in amps RMS) to configure the driver to use +# during homing procedures. The default is to not reduce the current. #sense_resistor: # The resistance (in ohms) of the motor sense resistor. This # parameter must be provided. @@ -3680,6 +3695,9 @@ run_current: # when the stepper is not moving. Setting a hold_current is not # recommended (see TMC_Drivers.md for details). The default is to # not reduce the current. +#home_current: +# The amount of current (in amps RMS) to configure the driver to use +# during homing procedures. The default is to not reduce the current. #rref: 12000 # The resistance (in ohms) of the resistor between IREF and GND. The # default is 12000. @@ -3801,6 +3819,9 @@ run_current: # when the stepper is not moving. Setting a hold_current is not # recommended (see TMC_Drivers.md for details). The default is to # not reduce the current. +#home_current: +# The amount of current (in amps RMS) to configure the driver to use +# during homing procedures. The default is to not reduce the current. #sense_resistor: 0.075 # The resistance (in ohms) of the motor sense resistor. The default # is 0.075 ohms. diff --git a/klippy/extras/homing.py b/klippy/extras/homing.py index a0add5f93..12decd06d 100644 --- a/klippy/extras/homing.py +++ b/klippy/extras/homing.py @@ -4,11 +4,13 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import math +import logging HOMING_START_DELAY = 0.001 ENDSTOP_SAMPLE_TIME = 0.000015 ENDSTOP_SAMPLE_COUNT = 4 + # Return a completion that completes when all completions in a list complete def multi_complete(printer, completions): if len(completions) == 1: @@ -47,6 +49,7 @@ def __init__(self, printer, endstops, toolhead=None): toolhead = printer.lookup_object("toolhead") self.toolhead = toolhead self.stepper_positions = [] + self.distance_elapsed = [] def get_mcu_endstops(self): return [es for es, name in self.endstops] @@ -116,6 +119,7 @@ def homing_move( ) endstop_triggers.append(wait) all_endstop_trigger = multi_complete(self.printer, endstop_triggers) + self.toolhead.dwell(HOMING_START_DELAY) # Issue move error = None @@ -157,6 +161,16 @@ def homing_move( sp.stepper_name: sp.halt_pos - sp.trig_pos for sp in self.stepper_positions } + steps_moved = { + sp.stepper_name: (sp.halt_pos - sp.start_pos) + * sp.stepper.get_step_dist() + for sp in self.stepper_positions + } + filled_steps_moved = { + sname: steps_moved.get(sname, 0) + for sname in [s.get_name() for s in kin.get_steppers()] + } + self.distance_elapsed = kin.calc_position(filled_steps_moved) if any(over_steps.values()): self.toolhead.set_position(movepos) halt_kin_spos = { @@ -216,10 +230,38 @@ def _fill_coord(self, coord): def set_homed_position(self, pos): self.toolhead.set_position(self._fill_coord(pos)) + def _set_current_homing(self, homing_axes): + print_time = self.toolhead.get_last_move_time() + affected_rails = set() + for axis in homing_axes: + axis_name = "xyz"[axis] # only works for cartesian + partial_rails = self.toolhead.get_active_rails_for_axis(axis_name) + affected_rails = affected_rails | set(partial_rails) + + for rail in affected_rails: + ch = rail.get_tmc_current_helper() + if ch is not None: + ch.set_current_for_homing(print_time) + self.toolhead.dwell(0.5) + + def _set_current_post_homing(self, homing_axes): + print_time = self.toolhead.get_last_move_time() + affected_rails = set() + for axis in homing_axes: + axis_name = "xyz"[axis] # only works for cartesian + partial_rails = self.toolhead.get_active_rails_for_axis(axis_name) + affected_rails = affected_rails | set(partial_rails) + + for rail in affected_rails: + ch = rail.get_tmc_current_helper() + if ch is not None: + ch.set_current_for_normal(print_time) + self.toolhead.dwell(0.5) + def home_rails(self, rails, forcepos, movepos): # Notify of upcoming homing operation self.printer.send_event("homing:home_rails_begin", self, rails) - # Alter kinematics class to think printer is at forcepos + # Alter kinematics class to think printer is at forcepo homing_axes = [axis for axis in range(3) if forcepos[axis] is not None] startpos = self._fill_coord(forcepos) homepos = self._fill_coord(movepos) @@ -228,9 +270,24 @@ def home_rails(self, rails, forcepos, movepos): endstops = [es for rail in rails for es in rail.get_endstops()] hi = rails[0].get_homing_info() hmove = HomingMove(self.printer, endstops) + + self._set_current_homing(homing_axes) + hmove.homing_move(homepos, hi.speed) + + homing_axis_distances = [ + dist + for i, dist in enumerate(hmove.distance_elapsed) + if i in homing_axes + ] + # Perform second home if hi.retract_dist: + needs_rehome = False + if any([dist < hi.retract_dist for dist in homing_axis_distances]): + needs_rehome = True + + logging.info("needs rehome: %s", needs_rehome) # Retract startpos = self._fill_coord(forcepos) homepos = self._fill_coord(movepos) @@ -241,18 +298,37 @@ def home_rails(self, rails, forcepos, movepos): hp - ad * retract_r for hp, ad in zip(homepos, axes_d) ] self.toolhead.move(retractpos, hi.retract_speed) - # Home again - startpos = [ - rp - ad * retract_r for rp, ad in zip(retractpos, axes_d) - ] - self.toolhead.set_position(startpos) - hmove = HomingMove(self.printer, endstops) - hmove.homing_move(homepos, hi.second_homing_speed) - if hmove.check_no_movement() is not None: - raise self.printer.command_error( - "Endstop %s still triggered after retract" - % (hmove.check_no_movement(),) - ) + if not hi.use_sensorless_homing or needs_rehome: + self.toolhead.dwell(0.5) + # Home again + startpos = [ + rp - ad * retract_r for rp, ad in zip(retractpos, axes_d) + ] + self.toolhead.set_position(startpos) + print_time = self.toolhead.get_last_move_time() + for endstop in endstops: + # re-querying a tmc endstop seems to reset the state + # otherwise it triggers almost immediately upon second home + endstop[0].query_endstop(print_time) + hmove = HomingMove(self.printer, endstops) + hmove.homing_move(homepos, hi.second_homing_speed) + if hmove.check_no_movement() is not None: + raise self.printer.command_error( + "Endstop %s still triggered after retract" + % (hmove.check_no_movement(),) + ) + + # Retract (again) + startpos = self._fill_coord(forcepos) + homepos = self._fill_coord(movepos) + axes_d = [hp - sp for hp, sp in zip(homepos, startpos)] + move_d = math.sqrt(sum([d * d for d in axes_d[:3]])) + retract_r = min(1.0, hi.retract_dist / move_d) + retractpos = [ + hp - ad * retract_r for hp, ad in zip(homepos, axes_d) + ] + self.toolhead.move(retractpos, hi.retract_speed) + self._set_current_post_homing(homing_axes) # Signal home operation complete self.toolhead.flush_step_generation() self.trigger_mcu_pos = { diff --git a/klippy/extras/tmc.py b/klippy/extras/tmc.py index 28b4ea130..cb8f4662c 100644 --- a/klippy/extras/tmc.py +++ b/klippy/extras/tmc.py @@ -11,6 +11,7 @@ # Field helpers ###################################################################### + # Return the position of the first bit set in a mask def ffs(mask): return (mask & -mask).bit_length() - 1 @@ -345,29 +346,53 @@ def cmd_SET_TMC_FIELD(self, gcmd): def cmd_SET_TMC_CURRENT(self, gcmd): ch = self.current_helper - prev_cur, prev_hold_cur, req_hold_cur, max_cur = ch.get_current() + ( + prev_cur, + prev_hold_cur, + req_hold_cur, + max_cur, + prev_home_cur, + ) = ch.get_current() run_current = gcmd.get_float( "CURRENT", None, minval=0.0, maxval=max_cur ) hold_current = gcmd.get_float( "HOLDCURRENT", None, above=0.0, maxval=max_cur ) - if run_current is not None or hold_current is not None: + home_current = gcmd.get_float( + "HOMECURRENT", None, above=0.0, maxval=max_cur + ) + if ( + run_current is not None + or hold_current is not None + or home_current is not None + ): if run_current is None: run_current = prev_cur if hold_current is None: hold_current = req_hold_cur + if home_current is not None: + ch.set_home_current(home_current) toolhead = self.printer.lookup_object("toolhead") print_time = toolhead.get_last_move_time() ch.set_current(run_current, hold_current, print_time) - prev_cur, prev_hold_cur, req_hold_cur, max_cur = ch.get_current() + ( + prev_cur, + prev_hold_cur, + req_hold_cur, + max_cur, + prev_home_cur, + ) = ch.get_current() # Report values if prev_hold_cur is None: - gcmd.respond_info("Run Current: %0.2fA" % (prev_cur,)) + gcmd.respond_info( + "Run Current: %0.2fA Home Current: %0.2fA" + % (prev_cur, prev_home_cur) + ) else: gcmd.respond_info( - "Run Current: %0.2fA Hold Current: %0.2fA" - % (prev_cur, prev_hold_cur) + "Run Current: %0.2fA Hold Current: %0.2fA Home Current: %0.2fA" + % (prev_cur, prev_hold_cur, prev_home_cur) ) # Stepper phase tracking @@ -451,6 +476,8 @@ def _handle_mcu_identify(self): # Lookup stepper object force_move = self.printer.lookup_object("force_move") self.stepper = force_move.lookup_stepper(self.stepper_name) + self.stepper.set_tmc_current_helper(self.current_helper) + # Note pulse duration and step_both_edge optimizations available self.stepper.setup_default_pulse_duration(0.000000100, True) @@ -551,6 +578,7 @@ def cmd_DUMP_TMC(self, gcmd): # TMC virtual pins ###################################################################### + # Helper class for "sensorless homing" class TMCVirtualPinHelper: def __init__(self, config, mcu_tmc): @@ -636,6 +664,7 @@ def handle_homing_move_end(self, hmove): # Config reading helpers ###################################################################### + # Helper to initialize the wave table from config or defaults def TMCWaveTableHelper(config, mcu_tmc): set_config_field = mcu_tmc.get_fields().set_config_field diff --git a/klippy/extras/tmc2130.py b/klippy/extras/tmc2130.py index c7325b8dc..374a53608 100644 --- a/klippy/extras/tmc2130.py +++ b/klippy/extras/tmc2130.py @@ -203,21 +203,30 @@ def __init__(self, config, mcu_tmc): self.name = config.get_name().split()[-1] self.mcu_tmc = mcu_tmc self.fields = mcu_tmc.get_fields() - run_current = config.getfloat( + self.run_current = config.getfloat( "run_current", above=0.0, maxval=MAX_CURRENT ) - hold_current = config.getfloat( + self.hold_current = config.getfloat( "hold_current", MAX_CURRENT, above=0.0, maxval=MAX_CURRENT ) - self.req_hold_current = hold_current + self._home_current = config.getfloat( + "home_current", self.run_current, above=0.0, maxval=MAX_CURRENT + ) + self.prev_current = self.run_current + self.req_hold_current = self.hold_current self.sense_resistor = config.getfloat( "sense_resistor", 0.110, above=0.0 ) - vsense, irun, ihold = self._calc_current(run_current, hold_current) + vsense, irun, ihold = self._calc_current( + self.run_current, self.hold_current + ) self.fields.set_field("vsense", vsense) self.fields.set_field("ihold", ihold) self.fields.set_field("irun", irun) + def set_home_current(self, new_home_current): + self._home_current = min(MAX_CURRENT, new_home_current) + def _calc_current_bits(self, current, vsense): sense_resistor = self.sense_resistor + 0.020 vref = 0.32 @@ -256,7 +265,13 @@ def get_current(self): vsense = self.fields.get_field("vsense") run_current = self._calc_current_from_bits(irun, vsense) hold_current = self._calc_current_from_bits(ihold, vsense) - return run_current, hold_current, self.req_hold_current, MAX_CURRENT + return ( + run_current, + hold_current, + self.req_hold_current, + MAX_CURRENT, + self._home_current, + ) def set_current(self, run_current, hold_current, print_time): self.req_hold_current = hold_current @@ -268,6 +283,14 @@ def set_current(self, run_current, hold_current, print_time): val = self.fields.set_field("irun", irun) self.mcu_tmc.set_register("IHOLD_IRUN", val, print_time) + def set_current_for_homing(self, print_time): + prev_run_cur, _, _, _, _ = self.get_current() + self._prev_current = prev_run_cur + self.set_current(self._home_current, self.hold_current, print_time) + + def set_current_for_normal(self, print_time): + self.set_current(self._prev_current, self.hold_current, print_time) + ###################################################################### # TMC2130 SPI diff --git a/klippy/extras/tmc2240.py b/klippy/extras/tmc2240.py index f75edf369..14ba8fa67 100644 --- a/klippy/extras/tmc2240.py +++ b/klippy/extras/tmc2240.py @@ -271,19 +271,30 @@ def __init__(self, config, mcu_tmc): self.Rref = config.getfloat( "rref", 12000.0, minval=12000.0, maxval=60000.0 ) - max_cur = self._get_ifs_rms(3) - run_current = config.getfloat("run_current", above=0.0, maxval=max_cur) - hold_current = config.getfloat( - "hold_current", max_cur, above=0.0, maxval=max_cur + self.max_cur = self._get_ifs_rms(3) + self.run_current = config.getfloat( + "run_current", above=0.0, maxval=self.max_cur ) - self.req_hold_current = hold_current - current_range = self._calc_current_range(run_current) + self.hold_current = config.getfloat( + "hold_current", self.max_cur, above=0.0, maxval=self.max_cur + ) + self._home_current = config.getfloat( + "home_current", self.run_current, above=0.0, maxval=self.max_cur + ) + self.prev_current = self.run_current + self.req_hold_current = self.hold_current + current_range = self._calc_current_range(self.run_current) self.fields.set_field("current_range", current_range) - gscaler, irun, ihold = self._calc_current(run_current, hold_current) + gscaler, irun, ihold = self._calc_current( + self.run_current, self.hold_current + ) self.fields.set_field("globalscaler", gscaler) self.fields.set_field("ihold", ihold) self.fields.set_field("irun", irun) + def set_home_current(self, new_home_current): + self._home_current = min(self.max_cur, new_home_current) + def _get_ifs_rms(self, current_range=None): if current_range is None: current_range = self.fields.get_field("current_range") @@ -331,7 +342,13 @@ def get_current(self): ifs_rms = self._get_ifs_rms() run_current = self._calc_current_from_field("irun") hold_current = self._calc_current_from_field("ihold") - return (run_current, hold_current, self.req_hold_current, ifs_rms) + return ( + run_current, + hold_current, + self.req_hold_current, + ifs_rms, + self._home_current, + ) def set_current(self, run_current, hold_current, print_time): self.req_hold_current = hold_current @@ -342,6 +359,14 @@ def set_current(self, run_current, hold_current, print_time): val = self.fields.set_field("irun", irun) self.mcu_tmc.set_register("IHOLD_IRUN", val, print_time) + def set_current_for_homing(self, print_time): + prev_run_cur, _, _, _, _ = self.get_current() + self._prev_current = prev_run_cur + self.set_current(self._home_current, self.hold_current, print_time) + + def set_current_for_normal(self, print_time): + self.set_current(self._prev_current, self.hold_current, print_time) + ###################################################################### # TMC2240 printer object diff --git a/klippy/extras/tmc2660.py b/klippy/extras/tmc2660.py index d6eb0fbec..85a891969 100644 --- a/klippy/extras/tmc2660.py +++ b/klippy/extras/tmc2660.py @@ -123,6 +123,10 @@ def __init__(self, config, mcu_tmc): self.current = config.getfloat( "run_current", minval=0.1, maxval=MAX_CURRENT ) + self._home_current = config.getfloat( + "home_current", self.current, above=0.0, maxval=MAX_CURRENT + ) + self._prev_current = self.current self.sense_resistor = config.getfloat("sense_resistor") vsense, cs = self._calc_current(self.current) self.fields.set_field("cs", cs) @@ -140,6 +144,9 @@ def __init__(self, config, mcu_tmc): "idle_timeout:ready", self._handle_ready ) + def set_home_current(self, new_home_current): + self._home_current = min(MAX_CURRENT, new_home_current) + def _calc_current_bits(self, current, vsense): vref = 0.165 if vsense else 0.310 sr = self.sense_resistor @@ -185,17 +192,32 @@ def _update_current(self, current, print_time): self.mcu_tmc.set_register("DRVCONF", val, print_time) def get_current(self): - return self.current, None, None, MAX_CURRENT + return ( + self.current, + None, + None, + MAX_CURRENT, + self._home_current, + ) def set_current(self, run_current, hold_current, print_time): self.current = run_current self._update_current(run_current, print_time) + def set_current_for_homing(self, print_time): + prev_run_cur, _, _, _, _ = self.get_current() + self._prev_current = prev_run_cur + self.set_current(self._home_current, None, print_time) + + def set_current_for_normal(self, print_time): + self.set_current(self._prev_current, None, print_time) + ###################################################################### # TMC2660 SPI ###################################################################### + # Helper code for working with TMC2660 devices via SPI class MCU_TMC2660_SPI: def __init__(self, config, name_to_reg, fields): diff --git a/klippy/extras/tmc5160.py b/klippy/extras/tmc5160.py index 80e1b3f6c..ecf8d3ac8 100644 --- a/klippy/extras/tmc5160.py +++ b/klippy/extras/tmc5160.py @@ -256,21 +256,30 @@ def __init__(self, config, mcu_tmc): self.name = config.get_name().split()[-1] self.mcu_tmc = mcu_tmc self.fields = mcu_tmc.get_fields() - run_current = config.getfloat( + self.run_current = config.getfloat( "run_current", above=0.0, maxval=MAX_CURRENT ) - hold_current = config.getfloat( + self.hold_current = config.getfloat( "hold_current", MAX_CURRENT, above=0.0, maxval=MAX_CURRENT ) - self.req_hold_current = hold_current + self._home_current = config.getfloat( + "home_current", self.run_current, above=0.0, maxval=MAX_CURRENT + ) + self._prev_current = self.run_current + self.req_hold_current = self.hold_current self.sense_resistor = config.getfloat( "sense_resistor", 0.075, above=0.0 ) - gscaler, irun, ihold = self._calc_current(run_current, hold_current) + gscaler, irun, ihold = self._calc_current( + self.run_current, self.hold_current + ) self.fields.set_field("globalscaler", gscaler) self.fields.set_field("ihold", ihold) self.fields.set_field("irun", irun) + def set_home_current(self, new_home_current): + self._home_current = min(MAX_CURRENT, new_home_current) + def _calc_globalscaler(self, current): globalscaler = int( (current * 256.0 * math.sqrt(2.0) * self.sense_resistor / VREF) @@ -313,7 +322,13 @@ def _calc_current_from_field(self, field_name): def get_current(self): run_current = self._calc_current_from_field("irun") hold_current = self._calc_current_from_field("ihold") - return run_current, hold_current, self.req_hold_current, MAX_CURRENT + return ( + run_current, + hold_current, + self.req_hold_current, + MAX_CURRENT, + self._home_current, + ) def set_current(self, run_current, hold_current, print_time): self.req_hold_current = hold_current @@ -324,6 +339,14 @@ def set_current(self, run_current, hold_current, print_time): val = self.fields.set_field("irun", irun) self.mcu_tmc.set_register("IHOLD_IRUN", val, print_time) + def set_current_for_homing(self, print_time): + prev_run_cur, _, _, _, _ = self.get_current() + self._prev_current = prev_run_cur + self.set_current(self._home_current, self.hold_current, print_time) + + def set_current_for_normal(self, print_time): + self.set_current(self._prev_current, self.hold_current, print_time) + ###################################################################### # TMC5160 printer object diff --git a/klippy/stepper.py b/klippy/stepper.py index eafab950b..77f3b26c5 100644 --- a/klippy/stepper.py +++ b/klippy/stepper.py @@ -18,6 +18,7 @@ class error(Exception): MIN_BOTH_EDGE_DURATION = 0.000000200 + # Interface to low-level mcu and chelper code class MCU_stepper: def __init__( @@ -64,6 +65,13 @@ def __init__( self._mcu.get_printer().register_event_handler( "klippy:connect", self._query_mcu_position ) + self._tmc_current_helper = None + + def get_tmc_current_helper(self): + return self._tmc_current_helper + + def set_tmc_current_helper(self, tmc_current_helper): + self._tmc_current_helper = tmc_current_helper def get_mcu(self): return self._mcu @@ -374,6 +382,7 @@ def parse_step_distance(config, units_in_radians=None, note_valid=False): # Stepper controlled rails ###################################################################### + # A motor control "rail" with one (or more) steppers and one (or more) # endstops. class PrinterRail: @@ -394,6 +403,7 @@ def __init__( self.get_name = mcu_stepper.get_name self.get_commanded_position = mcu_stepper.get_commanded_position self.calc_position_from_coord = mcu_stepper.calc_position_from_coord + self.get_tmc_current_helper = mcu_stepper.get_tmc_current_helper # Primary endstop position mcu_endstop = self.endstops[0][0] if hasattr(mcu_endstop, "get_position_endstop"): @@ -404,6 +414,12 @@ def __init__( self.position_endstop = config.getfloat( "position_endstop", default_position_endstop ) + endstop_pin = config.get("endstop_pin") + # check for ":virtual_endstop" to make sure we don't detect ":z_virtual_endstop" + endstop_is_virtual = ( + endstop_pin is not None and ":virtual_endstop" in endstop_pin + ) + # Axis range if need_position_minmax: self.position_min = config.getfloat("position_min", 0.0) @@ -435,6 +451,10 @@ def __init__( self.homing_positive_dir = config.getboolean( "homing_positive_dir", None ) + self.use_sensorless_homing = config.getboolean( + "use_sensorless_homing", endstop_is_virtual + ) + if self.homing_positive_dir is None: axis_len = self.position_max - self.position_min if self.position_endstop <= self.position_min + axis_len / 4.0: @@ -472,6 +492,7 @@ def get_homing_info(self): "retract_dist", "positive_dir", "second_homing_speed", + "use_sensorless_homing", ], )( self.homing_speed, @@ -480,6 +501,7 @@ def get_homing_info(self): self.homing_retract_dist, self.homing_positive_dir, self.second_homing_speed, + self.use_sensorless_homing, ) return homing_info diff --git a/klippy/toolhead.py b/klippy/toolhead.py index 7f38a6969..4b30f3c23 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -334,6 +334,17 @@ def __init__(self, config): for module_name in modules: self.printer.load_object(config, module_name) + def get_active_rails_for_axis(self, axis): + # axis is 'x,y,z' + active_rails = [] + rails = self.kin.rails + for rail in rails: + for stepper in rail.get_steppers(): + if stepper.is_active_axis(axis): + active_rails.append(rail) + break + return active_rails + # Print time tracking def _update_move_time(self, next_print_time): batch_time = MOVE_BATCH_TIME diff --git a/test/klippy/tmc.cfg b/test/klippy/tmc.cfg index 4ae85f440..560691d73 100644 --- a/test/klippy/tmc.cfg +++ b/test/klippy/tmc.cfg @@ -37,10 +37,12 @@ rotation_distance: 40 endstop_pin: tmc5160_stepper_y:virtual_endstop position_endstop: 0 position_max: 210 +use_sensorless_homing: true [tmc5160 stepper_y] cs_pin: PG2 -run_current: .5 +run_current: .7 +home_current: .5 sense_resistor: 0.220 diag1_pin: !PK7