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

Support reversing extruder direction and more #5210

Merged
merged 4 commits into from
Feb 10, 2022
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
12 changes: 12 additions & 0 deletions docs/Config_Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ All dates in this document are approximate.

## Changes

20220210: The `SYNC_STEPPER_TO_EXTRUDER` command is deprecated; the
`SET_EXTRUDER_STEP_DISTANCE` command is deprecated; the
[extruder](Config_Reference.md#extruder) `shared_heater` config option
is deprecated. These features will be removed in the near future.
Replace `SET_EXTRUDER_STEP_DISTANCE` with
`SET_EXTRUDER_ROTATION_DISTANCE`. Replace `SYNC_STEPPER_TO_EXTRUDER`
with `SYNC_EXTRUDER_MOTION`. Replace extruder config sections using
`shared_heater` with
[extruder_stepper](Config_Reference.md#extruder_stepper) config
sections and update any activation macros to use
[SYNC_EXTRUDER_MOTION](G-Codes.md#sync_extruder_motion).

20220116: The tmc2130, tmc2208, tmc2209, and tmc2660 `run_current`
calculation code has changed. For some `run_current` settings the
drivers may now be configured differently. This new configuration
Expand Down
7 changes: 1 addition & 6 deletions docs/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1781,12 +1781,7 @@ for an example configuration.
# See the "extruder" section for available stepper and heater
# parameters.
#shared_heater:
# If this extruder uses the same heater already defined for another
# extruder then place the name of that extruder here. For example,
# should extruder3 and extruder4 share a heater then the extruder3
# config section should define the heater and the extruder4 section
# should specify "shared_heater: extruder3". The default is to not
# reuse an existing heater.
# This option is deprecated and should no longer be specified.
```

### [dual_carriage]
Expand Down
37 changes: 23 additions & 14 deletions docs/G-Codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,23 +300,32 @@ extruders this command is used to change the active extruder.
parameters. If EXTRUDER is not specified, it defaults to the active
extruder.

#### SET_EXTRUDER_STEP_DISTANCE
`SET_EXTRUDER_STEP_DISTANCE [EXTRUDER=<config_name>]
#### SET_EXTRUDER_ROTATION_DISTANCE
`SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=<config_name>
[DISTANCE=<distance>]`: Set a new value for the provided extruder's
"step distance". The "step distance" is
`rotation_distance/(full_steps_per_rotation*microsteps)`. Value is not
retained on Klipper reset. Use with caution, small changes can result
in excessive pressure between extruder and hot end. Do proper
calibration steps with filament before use. If 'DISTANCE' value is not
included command will return current step distance.
"rotation distance". If the rotation distance is a negative number
then the stepper motion will be inverted (relative to the stepper
direction specified in the config file). Changed settings are not
retained on Klipper reset. Use with caution as small changes can
result in excessive pressure between extruder and hot end. Do proper
calibration with filament before use. If 'DISTANCE' value is not
included command will return current rotation distance.

#### SYNC_EXTRUDER_MOTION
`SYNC_EXTRUDER_MOTION EXTRUDER=<name> MOTION_QUEUE=<name>`: This
command will cause the stepper specified by EXTRUDER (as defined in an
[extruder](Config_Reference#extruder) or
[extruder_stepper](Config_Reference#extruder_stepper) config section)
to become synchronized to the movement of an extruder specified by
MOTION_QUEUE (as defined in an [extruder](Config_Reference#extruder)
config section). If MOTION_QUEUE is an empty string then the stepper
will be desynchronized from all extruder movement.

#### SET_EXTRUDER_STEP_DISTANCE
This command is deprecated and will be removed in the near future.

#### SYNC_STEPPER_TO_EXTRUDER
`SYNC_STEPPER_TO_EXTRUDER STEPPER=<name> [EXTRUDER=<name>]`: This
command will cause the given extruder STEPPER (as specified in an
[extruder](Config_Reference#extruder) or
[extruder stepper](Config_Reference#extruder_stepper) config section)
to become synchronized to the given EXTRUDER. If EXTRUDER is an empty
string then the stepper will not be synchronized to an extruder.
This command is deprecated and will be removed in the near future.

### [fan_generic]

Expand Down
5 changes: 3 additions & 2 deletions klippy/chelper/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@

struct stepcompress *stepcompress_alloc(uint32_t oid);
void stepcompress_fill(struct stepcompress *sc, uint32_t max_error
, uint32_t invert_sdir, int32_t queue_step_msgtag
, int32_t set_next_step_dir_msgtag);
, int32_t queue_step_msgtag, int32_t set_next_step_dir_msgtag);
void stepcompress_set_invert_sdir(struct stepcompress *sc
, uint32_t invert_sdir);
void stepcompress_free(struct stepcompress *sc);
int stepcompress_reset(struct stepcompress *sc, uint64_t last_step_clock);
int stepcompress_set_last_position(struct stepcompress *sc
Expand Down
16 changes: 13 additions & 3 deletions klippy/chelper/stepcompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,25 @@ stepcompress_alloc(uint32_t oid)
// Fill message id information
void __visible
stepcompress_fill(struct stepcompress *sc, uint32_t max_error
, uint32_t invert_sdir, int32_t queue_step_msgtag
, int32_t set_next_step_dir_msgtag)
, int32_t queue_step_msgtag, int32_t set_next_step_dir_msgtag)
{
sc->max_error = max_error;
sc->invert_sdir = !!invert_sdir;
sc->queue_step_msgtag = queue_step_msgtag;
sc->set_next_step_dir_msgtag = set_next_step_dir_msgtag;
}

// Set the inverted stepper direction flag
void __visible
stepcompress_set_invert_sdir(struct stepcompress *sc, uint32_t invert_sdir)
{
invert_sdir = !!invert_sdir;
if (invert_sdir != sc->invert_sdir) {
sc->invert_sdir = invert_sdir;
if (sc->sdir >= 0)
sc->sdir ^= 1;
}
}

// Helper to free items from the history_list
static void
free_history(struct stepcompress *sc, uint64_t end_clock)
Expand Down
4 changes: 3 additions & 1 deletion klippy/chelper/stepcompress.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ struct pull_history_steps {

struct stepcompress *stepcompress_alloc(uint32_t oid);
void stepcompress_fill(struct stepcompress *sc, uint32_t max_error
, uint32_t invert_sdir, int32_t queue_step_msgtag
, int32_t queue_step_msgtag
, int32_t set_next_step_dir_msgtag);
void stepcompress_set_invert_sdir(struct stepcompress *sc
, uint32_t invert_sdir);
void stepcompress_free(struct stepcompress *sc);
uint32_t stepcompress_get_oid(struct stepcompress *sc);
int stepcompress_get_step_dir(struct stepcompress *sc);
Expand Down
3 changes: 2 additions & 1 deletion klippy/extras/endstop_phase.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def __init__(self, config):
self.name = config.get_name().split()[1]
# Obtain step_distance and microsteps from stepper config section
sconfig = config.getsection(self.name)
self.step_dist = stepper.parse_step_distance(sconfig)
rotation_dist, steps_per_rotation = stepper.parse_step_distance(sconfig)
self.step_dist = rotation_dist / steps_per_rotation
self.phases = sconfig.getint("microsteps", note_valid=False) * 4
self.phase_calc = PhaseCalc(self.printer, self.name, self.phases)
# Register event handlers
Expand Down
2 changes: 1 addition & 1 deletion klippy/extras/motion_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def _api_update(self, eventtime):
mcu_pos = first.start_position
start_position = self.mcu_stepper.mcu_to_commanded_position(mcu_pos)
step_dist = self.mcu_stepper.get_step_dist()
if self.mcu_stepper.is_dir_inverted():
if self.mcu_stepper.get_dir_inverted()[0]:
step_dist = -step_dist
d = [(s.interval, s.step_count, s.add) for s in data]
return {"data": d, "start_position": start_position,
Expand Down
9 changes: 6 additions & 3 deletions klippy/extras/tmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ def __init__(self, config, mcu_tmc, current_helper):
self.stepper_enable = self.printer.load_object(config, "stepper_enable")
self.printer.register_event_handler("stepper:sync_mcu_position",
self._handle_sync_mcu_pos)
self.printer.register_event_handler("stepper:set_sdir_inverted",
self._handle_sync_mcu_pos)
self.printer.register_event_handler("klippy:mcu_identify",
self._handle_mcu_identify)
self.printer.register_event_handler("klippy:connect",
Expand Down Expand Up @@ -306,7 +308,7 @@ def _handle_sync_mcu_pos(self, stepper):
if enable_line.is_motor_enabled():
raise
return
if not stepper.is_dir_inverted():
if not stepper.get_dir_inverted()[0]:
driver_phase = 1023 - driver_phase
phases = self._get_phases()
phase = int(float(driver_phase) / 1024 * phases + .5) % phases
Expand Down Expand Up @@ -520,8 +522,9 @@ def TMCStealthchopHelper(config, mcu_tmc, tmc_freq):
velocity = config.getfloat('stealthchop_threshold', 0., minval=0.)
if velocity:
stepper_name = " ".join(config.get_name().split()[1:])
stepper_config = config.getsection(stepper_name)
step_dist = stepper.parse_step_distance(stepper_config)
sconfig = config.getsection(stepper_name)
rotation_dist, steps_per_rotation = stepper.parse_step_distance(sconfig)
step_dist = rotation_dist / steps_per_rotation
step_dist_256 = step_dist / (1 << fields.get_field("mres"))
threshold = int(tmc_freq * step_dist_256 / velocity + .5)
fields.set_field("tpwmthrs", max(0, min(0xfffff, threshold)))
Expand Down
51 changes: 42 additions & 9 deletions klippy/kinematics/extruder.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ def __init__(self, config):
gcode.register_mux_command("SET_PRESSURE_ADVANCE", "EXTRUDER",
self.name, self.cmd_SET_PRESSURE_ADVANCE,
desc=self.cmd_SET_PRESSURE_ADVANCE_help)
gcode.register_mux_command("SET_EXTRUDER_ROTATION_DISTANCE", "EXTRUDER",
self.name, self.cmd_SET_E_ROTATION_DISTANCE,
desc=self.cmd_SET_E_ROTATION_DISTANCE_help)
gcode.register_mux_command("SYNC_EXTRUDER_MOTION", "EXTRUDER",
self.name, self.cmd_SYNC_EXTRUDER_MOTION,
desc=self.cmd_SYNC_EXTRUDER_MOTION_help)
gcode.register_mux_command("SET_EXTRUDER_STEP_DISTANCE", "EXTRUDER",
self.name, self.cmd_SET_E_STEP_DISTANCE,
desc=self.cmd_SET_E_STEP_DISTANCE_help)
Expand Down Expand Up @@ -86,19 +92,45 @@ def cmd_SET_PRESSURE_ADVANCE(self, gcmd):
% (pressure_advance, smooth_time))
self.printer.set_rollover_info(self.name, "%s: %s" % (self.name, msg))
gcmd.respond_info(msg, log=False)
cmd_SET_E_ROTATION_DISTANCE_help = "Set extruder rotation distance"
def cmd_SET_E_ROTATION_DISTANCE(self, gcmd):
rotation_dist = gcmd.get_float('DISTANCE', None)
if rotation_dist is not None:
if not rotation_dist:
raise gcmd.error("Rotation distance can not be zero")
invert_dir, orig_invert_dir = self.stepper.get_dir_inverted()
next_invert_dir = orig_invert_dir
if rotation_dist < 0.:
next_invert_dir = not orig_invert_dir
rotation_dist = -rotation_dist
toolhead = self.printer.lookup_object('toolhead')
toolhead.flush_step_generation()
self.stepper.set_rotation_distance(rotation_dist)
self.stepper.set_dir_inverted(next_invert_dir)
else:
rotation_dist, spr = self.stepper.get_rotation_distance()
invert_dir, orig_invert_dir = self.stepper.get_dir_inverted()
if invert_dir != orig_invert_dir:
rotation_dist = -rotation_dist
gcmd.respond_info("Extruder '%s' rotation distance set to %0.6f"
% (self.name, rotation_dist))
cmd_SYNC_EXTRUDER_MOTION_help = "Set extruder stepper motion queue"
def cmd_SYNC_EXTRUDER_MOTION(self, gcmd):
ename = gcmd.get('MOTION_QUEUE')
self.sync_to_extruder(ename)
gcmd.respond_info("Extruder stepper now syncing with '%s'" % (ename,))
cmd_SET_E_STEP_DISTANCE_help = "Set extruder step distance"
def cmd_SET_E_STEP_DISTANCE(self, gcmd):
toolhead = self.printer.lookup_object('toolhead')
dist = gcmd.get_float('DISTANCE', None, above=0.)
if dist is None:
step_dist = gcmd.get_float('DISTANCE', None, above=0.)
if step_dist is not None:
toolhead = self.printer.lookup_object('toolhead')
toolhead.flush_step_generation()
rd, steps_per_rotation = self.stepper.get_rotation_distance()
self.stepper.set_rotation_distance(step_dist * steps_per_rotation)
else:
step_dist = self.stepper.get_step_dist()
gcmd.respond_info("Extruder '%s' step distance is %0.6f"
% (self.name, step_dist))
return
toolhead.flush_step_generation()
self.stepper.set_step_dist(dist)
gcmd.respond_info("Extruder '%s' step distance set to %0.6f"
% (self.name, dist))
% (self.name, step_dist))
cmd_SYNC_STEPPER_TO_EXTRUDER_help = "Set extruder stepper"
def cmd_SYNC_STEPPER_TO_EXTRUDER(self, gcmd):
ename = gcmd.get('EXTRUDER')
Expand All @@ -118,6 +150,7 @@ def __init__(self, config, extruder_num):
if shared_heater is None:
self.heater = pheaters.setup_heater(config, gcode_id)
else:
config.deprecate('shared_heater')
self.heater = pheaters.lookup_heater(shared_heater)
# Setup kinematic checks
self.nozzle_diameter = config.getfloat('nozzle_diameter', above=0.)
Expand Down
39 changes: 28 additions & 11 deletions klippy/stepper.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ class error(Exception):

# Interface to low-level mcu and chelper code
class MCU_stepper:
def __init__(self, name, step_pin_params, dir_pin_params, step_dist,
def __init__(self, name, step_pin_params, dir_pin_params,
rotation_dist, steps_per_rotation,
step_pulse_duration=None, units_in_radians=False):
self._name = name
self._step_dist = step_dist
self._rotation_dist = rotation_dist
self._steps_per_rotation = steps_per_rotation
self._step_pulse_duration = step_pulse_duration
self._units_in_radians = units_in_radians
self._step_dist = rotation_dist / steps_per_rotation
self._mcu = step_pin_params['chip']
self._oid = oid = self._mcu.create_oid()
self._mcu.register_config_callback(self._build_config)
Expand All @@ -33,14 +36,15 @@ def __init__(self, name, step_pin_params, dir_pin_params, step_dist,
raise self._mcu.get_printer().config_error(
"Stepper dir pin must be on same mcu as step pin")
self._dir_pin = dir_pin_params['pin']
self._invert_dir = dir_pin_params['invert']
self._invert_dir = self._orig_invert_dir = dir_pin_params['invert']
self._step_both_edge = self._req_step_both_edge = False
self._mcu_position_offset = 0.
self._reset_cmd_tag = self._get_position_cmd = None
self._active_callbacks = []
ffi_main, ffi_lib = chelper.get_ffi()
self._stepqueue = ffi_main.gc(ffi_lib.stepcompress_alloc(oid),
ffi_lib.stepcompress_free)
ffi_lib.stepcompress_set_invert_sdir(self._stepqueue, self._invert_dir)
self._mcu.register_stepqueue(self._stepqueue)
self._stepper_kinematics = None
self._itersolve_generate_steps = ffi_lib.itersolve_generate_steps
Expand Down Expand Up @@ -98,18 +102,29 @@ def _build_config(self):
max_error_ticks = self._mcu.seconds_to_clock(max_error)
ffi_main, ffi_lib = chelper.get_ffi()
ffi_lib.stepcompress_fill(self._stepqueue, max_error_ticks,
self._invert_dir, step_cmd_tag, dir_cmd_tag)
step_cmd_tag, dir_cmd_tag)
def get_oid(self):
return self._oid
def get_step_dist(self):
return self._step_dist
def set_step_dist(self, dist):
def get_rotation_distance(self):
return self._rotation_dist, self._steps_per_rotation
def set_rotation_distance(self, rotation_dist):
mcu_pos = self.get_mcu_position()
self._step_dist = dist
self._rotation_dist = rotation_dist
self._step_dist = rotation_dist / self._steps_per_rotation
self.set_stepper_kinematics(self._stepper_kinematics)
self._set_mcu_position(mcu_pos)
def is_dir_inverted(self):
return self._invert_dir
def get_dir_inverted(self):
return self._invert_dir, self._orig_invert_dir
def set_dir_inverted(self, invert_dir):
invert_dir = not not invert_dir
if invert_dir == self._invert_dir:
return
self._invert_dir = invert_dir
ffi_main, ffi_lib = chelper.get_ffi()
ffi_lib.stepcompress_set_invert_sdir(self._stepqueue, invert_dir)
self._mcu.get_printer().send_event("stepper:set_dir_inverted", self)
def calc_position_from_coord(self, coord):
ffi_main, ffi_lib = chelper.get_ffi()
return ffi_lib.itersolve_calc_position_from_coord(
Expand Down Expand Up @@ -222,10 +237,12 @@ def PrinterStepper(config, units_in_radians=False):
step_pin_params = ppins.lookup_pin(step_pin, can_invert=True)
dir_pin = config.get('dir_pin')
dir_pin_params = ppins.lookup_pin(dir_pin, can_invert=True)
step_dist = parse_step_distance(config, units_in_radians, True)
rotation_dist, steps_per_rotation = parse_step_distance(
config, units_in_radians, True)
step_pulse_duration = config.getfloat('step_pulse_duration', None,
minval=0., maxval=.001)
mcu_stepper = MCU_stepper(name, step_pin_params, dir_pin_params, step_dist,
mcu_stepper = MCU_stepper(name, step_pin_params, dir_pin_params,
rotation_dist, steps_per_rotation,
step_pulse_duration, units_in_radians)
# Register with helper modules
for mname in ['stepper_enable', 'force_move', 'motion_report']:
Expand Down Expand Up @@ -263,7 +280,7 @@ def parse_step_distance(config, units_in_radians=None, note_valid=False):
raise config.error("full_steps_per_rotation invalid in section '%s'"
% (config.get_name(),))
gearing = parse_gear_ratio(config, note_valid)
return rotation_dist / (full_steps * microsteps * gearing)
return rotation_dist, full_steps * microsteps * gearing


######################################################################
Expand Down
16 changes: 10 additions & 6 deletions test/klippy/extruders.test
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,28 @@ G1 X20 Y20 Z1
G1 X25 Y25 E7.5

# Update step_distance
SET_EXTRUDER_STEP_DISTANCE EXTRUDER=extruder DISTANCE=.005
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=33.2
G1 X30 Y30 E8.0

# Reverse step_distance
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=-33.1
G1 X30 Y30 E8.2

# Disable extruder stepper motor
SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER=
SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=
G1 X35 Y35 E8.5

# Disable my_extra_stepper stepper motor
SYNC_STEPPER_TO_EXTRUDER STEPPER=my_extra_stepper EXTRUDER=
SYNC_EXTRUDER_MOTION EXTRUDER=my_extra_stepper MOTION_QUEUE=
G1 X40 Y40 E9.0

# Enable extruder stepper motor
SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER=extruder
SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=extruder
G1 X45 Y45 E9.5

# Switch to just my_extra_stepper stepper motor
SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER=
SYNC_STEPPER_TO_EXTRUDER STEPPER=my_extra_stepper EXTRUDER=extruder
SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=
SYNC_EXTRUDER_MOTION EXTRUDER=my_extra_stepper MOTION_QUEUE=extruder
G1 X50 Y50 E10.0

# Test pressure advance move
Expand Down