Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

good sensorless #65

Merged
merged 8 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ klippy/.version
.DS_Store
ci_build/
ci_cache/
_test_.*
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 22 additions & 1 deletion docs/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
102 changes: 89 additions & 13 deletions klippy/extras/homing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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 = {
Expand Down
41 changes: 35 additions & 6 deletions klippy/extras/tmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand Down
Loading