mirror of
https://github.com/Klipper3d/klipper.git
synced 2026-02-07 08:41:02 -07:00
generic_cartesian: Full IQEX printers support (#7165)
Signed-off-by: Dmitry Butyugin <dmbutyugin@google.com>
This commit is contained in:
parent
ca7d90084c
commit
4c89f7f826
12 changed files with 1099 additions and 164 deletions
|
|
@ -743,7 +743,7 @@ max_accel:
|
|||
|
||||
```
|
||||
|
||||
Then a user must define three carriages for X, Y, and Z axes, e.g.:
|
||||
Then a user must define three primary carriages for X, Y, and Z axes, e.g.:
|
||||
```
|
||||
[carriage carriage_x]
|
||||
axis:
|
||||
|
|
@ -2455,10 +2455,16 @@ Please note that in this case the `[dual_carriage]` configuration deviates
|
|||
from the configuration described above:
|
||||
```
|
||||
[dual_carriage my_dc_carriage]
|
||||
primary_carriage:
|
||||
# Defines the matching primary carriage of this dual carriage and
|
||||
# the corresponding IDEX axis. Must match a name of a defined `[carriage]`.
|
||||
# This parameter must be provided.
|
||||
#primary_carriage:
|
||||
# Defines the matching carriage on the same gantry as this dual carriage and
|
||||
# the corresponding dual axis. Must match a name of a defined `[carriage]` or
|
||||
# another independent `[dual_carriage]`. If not set, which is a default,
|
||||
# defines a dual carriage independent of a `[carriage]` with the same axis
|
||||
# as this one (e.g. on a different gantry).
|
||||
#axis:
|
||||
# Axis of a carriage, either x or y. If 'primary_carriage' is defined, then
|
||||
# this parameter defaults to the 'axis' parameter of that primary carriage,
|
||||
# otherwise this parameter must be defined.
|
||||
#safe_distance:
|
||||
# The minimum distance (in mm) to enforce between the dual and the primary
|
||||
# carriages. If a G-Code command is executed that will bring the carriages
|
||||
|
|
@ -2467,7 +2473,8 @@ primary_carriage:
|
|||
# position_min and position_max for the dual and primary carriages. If set
|
||||
# to 0 (or safe_distance is unset and position_min and position_max are
|
||||
# identical for the primary and dual carriages), the carriages proximity
|
||||
# checks will be disabled.
|
||||
# checks will be disabled. Only valid for a dual_carriage with a defined
|
||||
# 'primary_carriage'.
|
||||
endstop_pin:
|
||||
#position_min:
|
||||
position_endstop:
|
||||
|
|
|
|||
|
|
@ -350,8 +350,9 @@ reference a defined primary or dual carriage for `generic_cartesian`
|
|||
kinematics or be 0 (for primary carriage) or 1 (for dual carriage)
|
||||
for all other kinematics supporting IDEX. Setting the mode to `PRIMARY`
|
||||
deactivates the other carriage and makes the specified carriage execute
|
||||
subsequent G-Code commands as-is. `COPY` and `MIRROR` modes are supported
|
||||
only for dual carriages. When set to either of these modes, dual carriage
|
||||
subsequent G-Code commands as-is. Before activating `COPY` or `MIRROR`
|
||||
mode for a carriage, a different one must be activated as `PRIMARY` on
|
||||
the same axis. When set to either of these two modes, the carriage
|
||||
will then track the subsequent moves of its primary carriage and either
|
||||
copy relative movements of it (in `COPY` mode) or execute them in the
|
||||
opposite (mirror) direction (in `MIRROR` mode).
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ class CartKinematics:
|
|||
self.dc_module = idex_modes.DualCarriages(
|
||||
self.printer, [self.rails[self.dual_carriage_axis]],
|
||||
[self.rails[3]], axes=[self.dual_carriage_axis],
|
||||
safe_dist=dc_config.getfloat(
|
||||
'safe_distance', None, minval=0.))
|
||||
safe_dist=[dc_config.getfloat(
|
||||
'safe_distance', None, minval=0.)])
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
# Setup boundary checks
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@
|
|||
#
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
import copy, itertools, logging, math
|
||||
import collections, copy, itertools, logging, math
|
||||
import gcode, mathutil, stepper
|
||||
from . import idex_modes
|
||||
from . import kinematic_stepper as ks
|
||||
|
||||
VALID_AXES = ['x', 'y', 'z']
|
||||
|
||||
def mat_mul(a, b):
|
||||
if len(a[0]) != len(b):
|
||||
return None
|
||||
|
|
@ -35,13 +37,11 @@ class MainCarriage:
|
|||
def __init__(self, config):
|
||||
self.rail = stepper.GenericPrinterRail(config)
|
||||
carriage_name = self.rail.get_name(short=True)
|
||||
valid_axes = ['x', 'y', 'z']
|
||||
if carriage_name in valid_axes:
|
||||
axis_name = config.getchoice('axis', valid_axes, carriage_name)
|
||||
if carriage_name in VALID_AXES:
|
||||
self.axis_name = config.getchoice('axis', VALID_AXES, carriage_name)
|
||||
else:
|
||||
axis_name = config.getchoice('axis', valid_axes)
|
||||
self.axis = ord(axis_name) - ord('x')
|
||||
self.axis_name = axis_name
|
||||
self.axis_name = config.getchoice('axis', VALID_AXES)
|
||||
self.axis = ord(self.axis_name) - ord('x')
|
||||
self.dual_carriage = None
|
||||
def get_name(self):
|
||||
return self.rail.get_name(short=True)
|
||||
|
|
@ -56,9 +56,7 @@ class MainCarriage:
|
|||
return True
|
||||
return self.dual_carriage.get_dc_module().is_active(self.rail)
|
||||
def set_dual_carriage(self, carriage):
|
||||
old_dc = self.dual_carriage
|
||||
self.dual_carriage = carriage
|
||||
return old_dc
|
||||
def get_dual_carriage(self):
|
||||
return self.dual_carriage
|
||||
|
||||
|
|
@ -78,23 +76,49 @@ class ExtraCarriage:
|
|||
self.endstop_pin, self.name)
|
||||
|
||||
class DualCarriage:
|
||||
def __init__(self, config, carriages):
|
||||
def __init__(self, config):
|
||||
self.printer = config.get_printer()
|
||||
self.rail = stepper.GenericPrinterRail(config)
|
||||
self.primary_carriage = config.getchoice('primary_carriage', carriages)
|
||||
if self.primary_carriage.set_dual_carriage(self) is not None:
|
||||
raise config.error(
|
||||
"Redefinition of dual_carriage for carriage '%s'" %
|
||||
self.primary_carriage.get_name())
|
||||
self.primary_carriage_name = config.get('primary_carriage', None)
|
||||
if self.primary_carriage_name is None:
|
||||
self.axis_name = config.getchoice('axis', VALID_AXES)
|
||||
self.axis = ord(self.axis_name) - ord('x')
|
||||
self.safe_dist = None
|
||||
else:
|
||||
self.axis_name = config.getchoice('axis', VALID_AXES + [None], None)
|
||||
self.safe_dist = config.getfloat('safe_distance', None, minval=0.)
|
||||
self.primary_carriage = self.dual_carriage = None
|
||||
self.config_error = config.error
|
||||
def resolve_primary_carriage(self, carriages):
|
||||
if self.primary_carriage_name is None:
|
||||
return
|
||||
if self.primary_carriage_name not in carriages:
|
||||
raise self.config_error(
|
||||
"primary_carriage = '%s' for '%s' is not a valid choice"
|
||||
% (self.primary_carriage_name, self.get_name()))
|
||||
self.primary_carriage = carriages[self.primary_carriage_name]
|
||||
axis_name = self.axis_name or self.primary_carriage.axis_name
|
||||
if axis_name != self.primary_carriage.axis_name:
|
||||
raise self.config_error("Mismatching axes between carriage '%s' "
|
||||
"(axis=%s) and dual_carriage '%s' (axis=%s)"
|
||||
% (self.primary_carriage.get_name(),
|
||||
self.primary_carriage.axis_name,
|
||||
self.get_name(), axis_name))
|
||||
self.axis = ord(axis_name) - ord('x')
|
||||
if self.primary_carriage.get_dual_carriage():
|
||||
raise self.config_error(
|
||||
"Multiple dual carriages ('%s', '%s') for carriage '%s'" %
|
||||
(self.primary_carriage.get_dual_carriage().get_name(),
|
||||
self.get_name(), self.primary_carriage.get_name()))
|
||||
self.primary_carriage.set_dual_carriage(self)
|
||||
self.axis = self.primary_carriage.get_axis()
|
||||
if self.axis > 1:
|
||||
raise config.error("Invalid axis '%s' for dual_carriage" %
|
||||
"xyz"[self.axis])
|
||||
self.safe_dist = config.getfloat('safe_distance', None, minval=0.)
|
||||
raise self.config_error("Invalid axis '%s' for dual_carriage '%s'" %
|
||||
("xyz"[self.axis], self.get_name()))
|
||||
def get_name(self):
|
||||
return self.rail.get_name(short=True)
|
||||
def get_axis(self):
|
||||
return self.primary_carriage.get_axis()
|
||||
return self.axis
|
||||
def get_rail(self):
|
||||
return self.rail
|
||||
def get_safe_dist(self):
|
||||
|
|
@ -103,7 +127,13 @@ class DualCarriage:
|
|||
return self.printer.lookup_object('dual_carriage')
|
||||
def is_active(self):
|
||||
return self.get_dc_module().is_active(self.rail)
|
||||
def set_dual_carriage(self, carriage):
|
||||
self.dual_carriage = carriage
|
||||
def get_dual_carriage(self):
|
||||
if self.dual_carriage is not None:
|
||||
return self.dual_carriage
|
||||
return self.primary_carriage
|
||||
def get_primary_carriage(self):
|
||||
return self.primary_carriage
|
||||
def add_stepper(self, kin_stepper):
|
||||
self.rail.add_stepper(kin_stepper.get_stepper())
|
||||
|
|
@ -116,27 +146,38 @@ class GenericCartesianKinematics:
|
|||
s.set_trapq(toolhead.get_trapq())
|
||||
self.dc_module = None
|
||||
if self.dc_carriages:
|
||||
pcs = [dc.get_dual_carriage() for dc in self.dc_carriages]
|
||||
dc_axes = set(dc.get_axis() for dc in self.dc_carriages)
|
||||
pcs = ([pc for pc in self.primary_carriages
|
||||
if pc.get_axis() in dc_axes] +
|
||||
[dc for dc in self.dc_carriages
|
||||
if dc.get_primary_carriage() is None])
|
||||
dcs = [pc.get_dual_carriage() for pc in pcs]
|
||||
primary_rails = [pc.get_rail() for pc in pcs]
|
||||
dual_rails = [dc.get_rail() for dc in self.dc_carriages]
|
||||
axes = [dc.get_axis() for dc in self.dc_carriages]
|
||||
safe_dist = {dc.get_axis() : dc.get_safe_dist()
|
||||
for dc in self.dc_carriages}
|
||||
dual_rails = [dc.get_rail() if dc else None for dc in dcs]
|
||||
axes = [pc.get_axis() for pc in pcs]
|
||||
safe_dist = [dc.get_safe_dist() if dc else None for dc in dcs]
|
||||
self.dc_module = dc_module = idex_modes.DualCarriages(
|
||||
self.printer, primary_rails, dual_rails, axes, safe_dist)
|
||||
zero_pos = (0., 0.)
|
||||
for acs in itertools.product(*zip(pcs, self.dc_carriages)):
|
||||
for acs in itertools.product(*zip(pcs, dcs)):
|
||||
for c in acs:
|
||||
if c is None:
|
||||
continue
|
||||
dc_module.get_dc_rail_wrapper(c.get_rail()).activate(
|
||||
idex_modes.PRIMARY, zero_pos)
|
||||
dc_rail = c.get_dual_carriage().get_rail()
|
||||
dc_module.get_dc_rail_wrapper(dc_rail).inactivate(zero_pos)
|
||||
dc = c.get_dual_carriage()
|
||||
if dc is not None:
|
||||
dc_module.get_dc_rail_wrapper(dc.get_rail()).inactivate(
|
||||
zero_pos)
|
||||
self._check_kinematics(config.error)
|
||||
for c in pcs:
|
||||
dc_module.get_dc_rail_wrapper(c.get_rail()).activate(
|
||||
for dc in self.dc_carriages:
|
||||
dc_module.get_dc_rail_wrapper(dc.get_rail()).inactivate(
|
||||
zero_pos)
|
||||
for pc in self.primary_carriages:
|
||||
if pc.get_axis() not in dc_axes:
|
||||
continue
|
||||
dc_module.get_dc_rail_wrapper(pc.get_rail()).activate(
|
||||
idex_modes.PRIMARY, zero_pos)
|
||||
dc_rail = c.get_dual_carriage().get_rail()
|
||||
dc_module.get_dc_rail_wrapper(dc_rail).inactivate(zero_pos)
|
||||
else:
|
||||
self._check_kinematics(config.error)
|
||||
# Setup boundary checks
|
||||
|
|
@ -152,25 +193,32 @@ class GenericCartesianKinematics:
|
|||
self.cmd_SET_STEPPER_CARRIAGES,
|
||||
desc=self.cmd_SET_STEPPER_CARRIAGES_help)
|
||||
def _load_kinematics(self, config):
|
||||
carriages = {}
|
||||
primary_carriages = []
|
||||
for mcconfig in config.get_prefix_sections('carriage '):
|
||||
c = MainCarriage(mcconfig)
|
||||
axis = c.get_axis()
|
||||
dups = [mc for mc in carriages.values() if mc.get_axis() == axis]
|
||||
if dups:
|
||||
primary_carriages.append(MainCarriage(mcconfig))
|
||||
for axis, axis_name in enumerate(VALID_AXES):
|
||||
dups = [pc.get_name() for pc in primary_carriages
|
||||
if pc.get_axis() == axis]
|
||||
if len(dups) > 1:
|
||||
raise config.error(
|
||||
"Axis '%s' referenced by multiple carriages (%s, %s)"
|
||||
% ("xyz"[axis], c.get_name(), dups[0].get_name()))
|
||||
carriages[c.get_name()] = c
|
||||
"Axis '%s' is set for multiple primary carriages (%s)"
|
||||
% (axis_name, ', '.join(dups)))
|
||||
elif not dups:
|
||||
raise config.error(
|
||||
"No carriage defined for axis '%s'" % axis_name)
|
||||
dc_carriages = []
|
||||
for dcconfig in config.get_prefix_sections('dual_carriage '):
|
||||
dc_carriages.append(DualCarriage(dcconfig, carriages))
|
||||
for dc in dc_carriages:
|
||||
name = dc.get_name()
|
||||
dc_carriages.append(DualCarriage(dcconfig))
|
||||
carriages = {}
|
||||
for carriage in primary_carriages + dc_carriages:
|
||||
name = carriage.get_name()
|
||||
if name in carriages:
|
||||
raise config.error("Redefinition of carriage %s" % name)
|
||||
carriages[name] = dc
|
||||
carriages[name] = carriage
|
||||
for dc in dc_carriages:
|
||||
dc.resolve_primary_carriage(carriages)
|
||||
self.carriages = dict(carriages)
|
||||
self.primary_carriages = primary_carriages
|
||||
self.dc_carriages = dc_carriages
|
||||
ec_carriages = []
|
||||
for ecconfig in config.get_prefix_sections('extra_carriage '):
|
||||
|
|
@ -207,16 +255,19 @@ class GenericCartesianKinematics:
|
|||
def get_steppers(self):
|
||||
return [s.get_stepper() for s in self.kin_steppers]
|
||||
def get_primary_carriages(self):
|
||||
carriages = [None] * 3
|
||||
for carriage in self.carriages.values():
|
||||
a = carriage.get_axis()
|
||||
if carriage.get_dual_carriage() is not None:
|
||||
carriages = []
|
||||
for a in range(3):
|
||||
c = None
|
||||
if self.dc_module is not None and a in self.dc_module.get_axes():
|
||||
primary_rail = self.dc_module.get_primary_rail(a)
|
||||
for c in self.carriages.values():
|
||||
if c.get_rail() == primary_rail:
|
||||
carriages[a] = c
|
||||
break
|
||||
else:
|
||||
carriages[a] = carriage
|
||||
for c in self.primary_carriages:
|
||||
if c.get_axis() == a:
|
||||
break
|
||||
carriages.append(c)
|
||||
return carriages
|
||||
def _get_kinematics_coeffs(self):
|
||||
matr = {s.get_name() : list(s.get_kin_coeffs())
|
||||
|
|
@ -227,9 +278,9 @@ class GenericCartesianKinematics:
|
|||
[0. for s in self.kin_steppers])
|
||||
axes = [dc.get_axis() for dc in self.dc_carriages]
|
||||
orig_matr = copy.deepcopy(matr)
|
||||
for dc in self.dc_carriages:
|
||||
axis = dc.get_axis()
|
||||
for c in [dc.get_dual_carriage(), dc]:
|
||||
for c in self.carriages.values():
|
||||
axis = c.get_axis()
|
||||
if axis in self.dc_module.get_axes():
|
||||
m, o = self.dc_module.get_transform(c.get_rail())
|
||||
for s in c.get_rail().get_steppers():
|
||||
matr[s.get_name()][axis] *= m
|
||||
|
|
@ -289,16 +340,14 @@ class GenericCartesianKinematics:
|
|||
homing_state.home_rails([rail], forcepos, homepos)
|
||||
def home(self, homing_state):
|
||||
self._check_kinematics(self.printer.command_error)
|
||||
primary_carriages = self.get_primary_carriages()
|
||||
# Each axis is homed independently and in order
|
||||
for axis in homing_state.get_axes():
|
||||
for carriage in self.carriages.values():
|
||||
if carriage.get_axis() != axis:
|
||||
continue
|
||||
if carriage.get_dual_carriage() != None:
|
||||
self.dc_module.home(homing_state, axis)
|
||||
else:
|
||||
self.home_axis(homing_state, axis, carriage.get_rail())
|
||||
break
|
||||
if self.dc_module is not None and axis in self.dc_module.get_axes():
|
||||
self.dc_module.home(homing_state, axis)
|
||||
else:
|
||||
carriage = primary_carriages[axis]
|
||||
self.home_axis(homing_state, axis, carriage.get_rail())
|
||||
def _check_endstops(self, move):
|
||||
end_pos = move.end_pos
|
||||
for i in (0, 1, 2):
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class HybridCoreXYKinematics:
|
|||
self.rails[3].setup_itersolve('corexy_stepper_alloc', b'+')
|
||||
self.dc_module = idex_modes.DualCarriages(
|
||||
self.printer, [self.rails[0]], [self.rails[3]], axes=[0],
|
||||
safe_dist=dc_config.getfloat(
|
||||
'safe_distance', None, minval=0.))
|
||||
safe_dist=[dc_config.getfloat(
|
||||
'safe_distance', None, minval=0.)])
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
# Setup boundary checks
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class HybridCoreXZKinematics:
|
|||
self.rails[3].setup_itersolve('corexz_stepper_alloc', b'+')
|
||||
self.dc_module = idex_modes.DualCarriages(
|
||||
self.printer, [self.rails[0]], [self.rails[3]], axes=[0],
|
||||
safe_dist=dc_config.getfloat(
|
||||
'safe_distance', None, minval=0.))
|
||||
safe_dist=[dc_config.getfloat(
|
||||
'safe_distance', None, minval=0.)])
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
# Setup boundary checks
|
||||
|
|
|
|||
|
|
@ -14,36 +14,37 @@ MIRROR = 'MIRROR'
|
|||
|
||||
class DualCarriages:
|
||||
VALID_MODES = [PRIMARY, COPY, MIRROR]
|
||||
def __init__(self, printer, primary_rails, dual_rails, axes,
|
||||
safe_dist={}):
|
||||
def __init__(self, printer, primary_rails, dual_rails, axes, safe_dist):
|
||||
self.printer = printer
|
||||
self.axes = axes
|
||||
self._init_steppers(primary_rails + dual_rails)
|
||||
self.primary_rails = [
|
||||
DualCarriagesRail(printer, c, dual_rails[i],
|
||||
axes[i], active=True)
|
||||
for i, c in enumerate(primary_rails)]
|
||||
safe_dist = list(safe_dist)
|
||||
for i, dc in enumerate(dual_rails):
|
||||
if dc is None or safe_dist[i] is not None:
|
||||
continue
|
||||
pc = primary_rails[i]
|
||||
safe_dist[i] = min(abs(pc.position_min - dc.position_min),
|
||||
abs(pc.position_max - dc.position_max))
|
||||
self.primary_mode_dcs = [None] * 3
|
||||
self.primary_rails = []
|
||||
for i, c in enumerate(primary_rails):
|
||||
activate = self.primary_mode_dcs[axes[i]] is None
|
||||
dc_rail = DualCarriagesRail(
|
||||
printer, c, dual_rails[i], axes[i], safe_dist[i],
|
||||
active=activate)
|
||||
if activate:
|
||||
self.primary_mode_dcs[axes[i]] = dc_rail
|
||||
self.primary_rails.append(dc_rail)
|
||||
self.dual_rails = [
|
||||
DualCarriagesRail(printer, c, primary_rails[i],
|
||||
axes[i], active=False)
|
||||
axes[i], safe_dist[i], active=False)
|
||||
if c is not None else None
|
||||
for i, c in enumerate(dual_rails)]
|
||||
self.dc_rails = collections.OrderedDict(
|
||||
[(c.rail.get_name(short=True), c)
|
||||
for c in self.primary_rails + self.dual_rails])
|
||||
for c in self.primary_rails + self.dual_rails
|
||||
if c is not None])
|
||||
self.saved_states = {}
|
||||
self.safe_dist = {}
|
||||
for i, dc in enumerate(dual_rails):
|
||||
axis = axes[i]
|
||||
if isinstance(safe_dist, dict):
|
||||
if axis in safe_dist:
|
||||
self.safe_dist[axis] = safe_dist[axis]
|
||||
continue
|
||||
elif safe_dist is not None:
|
||||
self.safe_dist[axis] = safe_dist
|
||||
continue
|
||||
pc = primary_rails[i]
|
||||
self.safe_dist[axis] = min(abs(pc.position_min - dc.position_min),
|
||||
abs(pc.position_max - dc.position_max))
|
||||
self.axes = sorted(set(axes))
|
||||
self.printer.add_object('dual_carriage', self)
|
||||
self.printer.register_event_handler("klippy:ready", self._handle_ready)
|
||||
gcode = self.printer.lookup_object('gcode')
|
||||
|
|
@ -64,6 +65,8 @@ class DualCarriages:
|
|||
self.orig_stepper_kinematics = []
|
||||
steppers = set()
|
||||
for rail in rails:
|
||||
if rail is None:
|
||||
continue
|
||||
c_steppers = rail.get_steppers()
|
||||
if not c_steppers:
|
||||
raise self.printer.config_error(
|
||||
|
|
@ -80,10 +83,9 @@ class DualCarriages:
|
|||
def get_axes(self):
|
||||
return self.axes
|
||||
def get_primary_rail(self, axis):
|
||||
for dc_rail in self.dc_rails.values():
|
||||
if dc_rail.mode == PRIMARY and dc_rail.axis == axis:
|
||||
return dc_rail.rail
|
||||
return None
|
||||
if self.primary_mode_dcs[axis] is None:
|
||||
return None
|
||||
return self.primary_mode_dcs[axis].rail
|
||||
def get_dc_rail_wrapper(self, rail):
|
||||
for dc_rail in self.dc_rails.values():
|
||||
if dc_rail.rail == rail:
|
||||
|
|
@ -109,22 +111,27 @@ class DualCarriages:
|
|||
if target_dc.mode != PRIMARY:
|
||||
newpos = pos[:axis] + [target_dc.get_axis_position(pos)] \
|
||||
+ pos[axis+1:]
|
||||
self.primary_mode_dcs[axis] = target_dc
|
||||
target_dc.activate(PRIMARY, newpos, old_position=pos)
|
||||
toolhead.set_position(newpos)
|
||||
kin.update_limits(axis, target_dc.rail.get_range())
|
||||
def home(self, homing_state, axis):
|
||||
kin = self.printer.lookup_object('toolhead').get_kinematics()
|
||||
dcs = [dc for dc in self.dc_rails.values() if dc.axis == axis]
|
||||
if (self.get_dc_order(dcs[0], dcs[1]) > 0) != \
|
||||
dcs[0].rail.get_homing_info().positive_dir:
|
||||
# The second carriage must home first, because the carriages home in
|
||||
# the same direction and the first carriage homes on the second one
|
||||
dcs.reverse()
|
||||
for dc in dcs:
|
||||
self.toggle_active_dc_rail(dc)
|
||||
kin.home_axis(homing_state, axis, dc.rail)
|
||||
# Restore the original rails ordering
|
||||
self.activate_dc_mode(dcs[0], PRIMARY)
|
||||
homing_rails = [r for r in self.primary_rails if r.axis == axis]
|
||||
for dc_rail in homing_rails:
|
||||
dcs = [dc for dc in self.dc_rails.values()
|
||||
if dc_rail.rail in [dc.rail, dc.dual_rail]]
|
||||
if len(dcs) > 1 and (self.get_dc_order(dcs[0], dcs[1]) > 0) != \
|
||||
dcs[0].rail.get_homing_info().positive_dir:
|
||||
# The second carriage must home first, because the carriages
|
||||
# home in the same direction and the first carriage homes on
|
||||
# the second one, so reversing the oder
|
||||
dcs.reverse()
|
||||
for dc in dcs:
|
||||
self.toggle_active_dc_rail(dc)
|
||||
kin.home_axis(homing_state, dc.axis, dc.rail)
|
||||
# Restore the first rail as primary after all homed
|
||||
self.activate_dc_mode(homing_rails[0], PRIMARY)
|
||||
def get_status(self, eventtime=None):
|
||||
status = {'carriages' : {dc.get_name() : dc.mode
|
||||
for dc in self.dc_rails.values()}}
|
||||
|
|
@ -132,46 +139,62 @@ class DualCarriages:
|
|||
status.update({('carriage_%d' % (i,)) : dc.mode
|
||||
for i, dc in enumerate(self.dc_rails.values())})
|
||||
return status
|
||||
def get_kin_range(self, toolhead, mode, axis):
|
||||
def get_kin_range(self, toolhead, axis):
|
||||
pos = toolhead.get_position()
|
||||
dcs = [dc for dc in self.dc_rails.values() if dc.axis == axis]
|
||||
axes_pos = [dc.get_axis_position(pos) for dc in dcs]
|
||||
dc0_rail = dcs[0].rail
|
||||
dc1_rail = dcs[1].rail
|
||||
if mode != PRIMARY or dcs[0].is_active():
|
||||
range_min = dc0_rail.position_min
|
||||
range_max = dc0_rail.position_max
|
||||
else:
|
||||
range_min = dc1_rail.position_min
|
||||
range_max = dc1_rail.position_max
|
||||
safe_dist = self.safe_dist[axis]
|
||||
if not safe_dist:
|
||||
return (range_min, range_max)
|
||||
primary_carriage = self.primary_mode_dcs[axis]
|
||||
if primary_carriage is None:
|
||||
return (1.0, -1.0)
|
||||
primary_pos = primary_carriage.get_axis_position(pos)
|
||||
range_min = primary_carriage.rail.position_min
|
||||
range_max = primary_carriage.rail.position_max
|
||||
for carriage in self.dc_rails.values():
|
||||
if carriage.axis != axis:
|
||||
continue
|
||||
dcs = [carriage] + [dc for dc in self.dc_rails.values()
|
||||
if carriage.rail is dc.dual_rail]
|
||||
axes_pos = [dc.get_axis_position(pos) for dc in dcs]
|
||||
# Check how dcs[0] affects the motion range of primary_carriage
|
||||
if not dcs[0].is_active():
|
||||
continue
|
||||
elif dcs[0].mode == COPY:
|
||||
range_min = max(range_min, primary_pos
|
||||
+ dcs[0].rail.position_min - axes_pos[0])
|
||||
range_max = min(range_max, primary_pos
|
||||
+ dcs[0].rail.position_max - axes_pos[0])
|
||||
elif dcs[0].mode == MIRROR:
|
||||
range_min = max(range_min, primary_pos
|
||||
+ axes_pos[0] - dcs[0].rail.position_max)
|
||||
range_max = min(range_max, primary_pos
|
||||
+ axes_pos[0] - dcs[0].rail.position_min)
|
||||
safe_dist = dcs[0].safe_dist
|
||||
if not safe_dist or len(dcs) == 1:
|
||||
continue
|
||||
if dcs[0].mode == dcs[1].mode or \
|
||||
set((dcs[0].mode, dcs[1].mode)) == set((PRIMARY, COPY)):
|
||||
# dcs[0] and dcs[1] carriages move in the same direction and
|
||||
# cannot collide with each other
|
||||
continue
|
||||
|
||||
if mode == COPY:
|
||||
range_min = max(range_min,
|
||||
axes_pos[0] - axes_pos[1] + dc1_rail.position_min)
|
||||
range_max = min(range_max,
|
||||
axes_pos[0] - axes_pos[1] + dc1_rail.position_max)
|
||||
elif mode == MIRROR:
|
||||
# Compute how much dcs[0] can move towards dcs[1]
|
||||
dcs_dist = axes_pos[1] - axes_pos[0]
|
||||
if self.get_dc_order(dcs[0], dcs[1]) > 0:
|
||||
range_min = max(range_min,
|
||||
0.5 * (sum(axes_pos) + safe_dist))
|
||||
range_max = min(range_max,
|
||||
sum(axes_pos) - dc1_rail.position_min)
|
||||
safe_move_dist = dcs_dist + safe_dist
|
||||
else:
|
||||
range_max = min(range_max,
|
||||
0.5 * (sum(axes_pos) - safe_dist))
|
||||
range_min = max(range_min,
|
||||
sum(axes_pos) - dc1_rail.position_max)
|
||||
else:
|
||||
# mode == PRIMARY
|
||||
active_idx = 1 if dcs[1].is_active() else 0
|
||||
inactive_idx = 1 - active_idx
|
||||
if self.get_dc_order(dcs[active_idx], dcs[inactive_idx]) > 0:
|
||||
range_min = max(range_min, axes_pos[inactive_idx] + safe_dist)
|
||||
else:
|
||||
range_max = min(range_max, axes_pos[inactive_idx] - safe_dist)
|
||||
safe_move_dist = dcs_dist - safe_dist
|
||||
if dcs[1].is_active():
|
||||
safe_move_dist *= 0.5
|
||||
|
||||
if dcs[0].mode in (PRIMARY, COPY):
|
||||
if self.get_dc_order(dcs[0], dcs[1]) > 0:
|
||||
range_min = max(range_min, primary_pos + safe_move_dist)
|
||||
else:
|
||||
range_max = min(range_max, primary_pos + safe_move_dist)
|
||||
else: # dcs[0].mode == MIRROR
|
||||
if self.get_dc_order(dcs[0], dcs[1]) > 0:
|
||||
range_max = min(range_max, primary_pos - safe_move_dist)
|
||||
else:
|
||||
range_min = max(range_min, primary_pos - safe_move_dist)
|
||||
|
||||
if range_min > range_max:
|
||||
# During multi-MCU homing it is possible that the carriage
|
||||
# position will end up below position_min or above position_max
|
||||
|
|
@ -208,12 +231,13 @@ class DualCarriages:
|
|||
axis = dc.axis
|
||||
if mode == INACTIVE:
|
||||
dc.inactivate(toolhead.get_position())
|
||||
if self.primary_mode_dcs[axis] is dc:
|
||||
self.primary_mode_dcs[axis] = None
|
||||
elif mode == PRIMARY:
|
||||
self.toggle_active_dc_rail(dc)
|
||||
else:
|
||||
self.toggle_active_dc_rail(self.get_dc_rail_wrapper(dc.dual_rail))
|
||||
dc.activate(mode, toolhead.get_position())
|
||||
kin.update_limits(axis, self.get_kin_range(toolhead, mode, axis))
|
||||
kin.update_limits(axis, self.get_kin_range(toolhead, axis))
|
||||
def _handle_ready(self):
|
||||
for dc_rail in self.dc_rails.values():
|
||||
dc_rail.apply_transform()
|
||||
|
|
@ -241,10 +265,9 @@ class DualCarriages:
|
|||
if mode not in self.VALID_MODES:
|
||||
raise gcmd.error("Invalid mode=%s specified" % (mode,))
|
||||
if mode in [COPY, MIRROR]:
|
||||
if dc_rail in self.primary_rails:
|
||||
if self.primary_mode_dcs[dc_rail.axis] in [None, dc_rail]:
|
||||
raise gcmd.error(
|
||||
"Mode=%s is not supported for carriage=%s" % (
|
||||
mode, dc_rail.get_name()))
|
||||
"Must activate another carriage as PRIMARY first")
|
||||
curtime = self.printer.get_reactor().monotonic()
|
||||
kin = self.printer.lookup_object('toolhead').get_kinematics()
|
||||
axis = 'xyz'[dc_rail.axis]
|
||||
|
|
@ -291,18 +314,21 @@ class DualCarriages:
|
|||
for i, dc in enumerate(dcs)]
|
||||
for axis in self.axes:
|
||||
dc_ind = [i for i, dc in enumerate(dcs) if dc.axis == axis]
|
||||
if abs(dl[dc_ind[0]]) >= abs(dl[dc_ind[1]]):
|
||||
primary_ind, secondary_ind = dc_ind[0], dc_ind[1]
|
||||
else:
|
||||
primary_ind, secondary_ind = dc_ind[1], dc_ind[0]
|
||||
abs_dl = [abs(dl[i]) for i in dc_ind]
|
||||
primary_ind = dc_ind[abs_dl.index(max(abs_dl))]
|
||||
primary_dc = dcs[primary_ind]
|
||||
self.toggle_active_dc_rail(primary_dc)
|
||||
move_pos[axis] = carriage_positions[primary_dc.get_name()]
|
||||
dc_mode = INACTIVE if min(abs(dl[primary_ind]),
|
||||
abs(dl[secondary_ind])) < .000000001 \
|
||||
else COPY if dl[primary_ind] * dl[secondary_ind] > 0 \
|
||||
else MIRROR
|
||||
if dc_mode != INACTIVE:
|
||||
for secondary_ind in dc_ind:
|
||||
if secondary_ind == primary_ind:
|
||||
continue
|
||||
if min(abs(dl[primary_ind]),
|
||||
abs(dl[secondary_ind])) < .000000001:
|
||||
continue
|
||||
if dl[primary_ind] * dl[secondary_ind] > 0:
|
||||
dc_mode = COPY
|
||||
else:
|
||||
dc_mode = MIRROR
|
||||
dcs[secondary_ind].activate(dc_mode, cur_pos[primary_ind])
|
||||
dcs[secondary_ind].override_axis_scaling(
|
||||
abs(dl[secondary_ind] / dl[primary_ind]),
|
||||
|
|
@ -312,18 +338,26 @@ class DualCarriages:
|
|||
# Make sure the scaling coefficients are restored with the mode
|
||||
for dc in dcs:
|
||||
dc.inactivate(move_pos)
|
||||
saved_modes = saved_state['carriage_modes']
|
||||
saved_primary_dcs = [dc for dc in self.dc_rails.values()
|
||||
if saved_modes[dc.get_name()] == PRIMARY]
|
||||
# First activate all primary carriages
|
||||
for dc in saved_primary_dcs:
|
||||
self.activate_dc_mode(dc, PRIMARY)
|
||||
# Then set the modes the remaining carriages
|
||||
for dc in self.dc_rails.values():
|
||||
saved_mode = saved_state['carriage_modes'][dc.get_name()]
|
||||
self.activate_dc_mode(dc, saved_mode)
|
||||
if dc not in saved_primary_dcs:
|
||||
self.activate_dc_mode(dc, saved_modes[dc.get_name()])
|
||||
|
||||
class DualCarriagesRail:
|
||||
ENC_AXES = [b'x', b'y']
|
||||
def __init__(self, printer, rail, dual_rail, axis, active):
|
||||
def __init__(self, printer, rail, dual_rail, axis, safe_dist, active):
|
||||
self.printer = printer
|
||||
self.rail = rail
|
||||
self.dual_rail = dual_rail
|
||||
self.sks = [s.get_stepper_kinematics() for s in rail.get_steppers()]
|
||||
self.axis = axis
|
||||
self.safe_dist = safe_dist
|
||||
self.mode = (INACTIVE, PRIMARY)[active]
|
||||
self.offset = 0.
|
||||
self.scale = 1. if active else 0.
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ primary_carriage: carriage_z
|
|||
endstop_pin: ^PD2
|
||||
|
||||
[dual_carriage carriage_u]
|
||||
axis: x
|
||||
primary_carriage: carriage_x
|
||||
safe_distance: 70
|
||||
position_endstop: 300
|
||||
|
|
@ -32,6 +33,7 @@ homing_speed: 50
|
|||
endstop_pin: ^PE4
|
||||
|
||||
[dual_carriage carriage_v]
|
||||
axis: y
|
||||
primary_carriage: carriage_y
|
||||
safe_distance: 50
|
||||
position_endstop: 200
|
||||
|
|
|
|||
386
test/klippy/generic_cartesian_iqex.cfg
Normal file
386
test/klippy/generic_cartesian_iqex.cfg
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
# Test config for generic cartesian kinematics with quad independent extruders
|
||||
[mcu]
|
||||
serial: /dev/ttyACM0
|
||||
|
||||
[mcu extboard]
|
||||
serial: /dev/ttyACM1
|
||||
|
||||
[carriage carriage_t0]
|
||||
axis: x
|
||||
position_endstop: 0
|
||||
position_max: 300
|
||||
homing_speed: 50
|
||||
endstop_pin: extboard:PG6
|
||||
|
||||
[dual_carriage carriage_t1]
|
||||
primary_carriage: carriage_t0
|
||||
safe_distance: 70
|
||||
position_endstop: 300
|
||||
position_max: 300
|
||||
homing_speed: 50
|
||||
endstop_pin: extboard:PG9
|
||||
|
||||
[dual_carriage carriage_t2]
|
||||
axis: x
|
||||
position_endstop: 0
|
||||
position_max: 300
|
||||
homing_speed: 50
|
||||
endstop_pin: extboard:PG10
|
||||
|
||||
[dual_carriage carriage_t3]
|
||||
primary_carriage: carriage_t2
|
||||
safe_distance: 70
|
||||
position_endstop: 300
|
||||
position_max: 300
|
||||
homing_speed: 50
|
||||
endstop_pin: extboard:PG11
|
||||
|
||||
[carriage carriage_gantry0_left]
|
||||
axis: y
|
||||
position_endstop: 0
|
||||
position_max: 200
|
||||
homing_speed: 50
|
||||
endstop_pin: PG6
|
||||
|
||||
[extra_carriage carriage_gantry0_right]
|
||||
primary_carriage: carriage_gantry0_left
|
||||
endstop_pin: PG9
|
||||
|
||||
[dual_carriage carriage_gantry1_left]
|
||||
primary_carriage: carriage_gantry0_left
|
||||
safe_distance: 50
|
||||
position_endstop: 200
|
||||
position_max: 200
|
||||
homing_speed: 50
|
||||
endstop_pin: PG10
|
||||
|
||||
[extra_carriage carriage_gantry1_right]
|
||||
primary_carriage: carriage_gantry1_left
|
||||
endstop_pin: PG11
|
||||
|
||||
[carriage carriage_z0]
|
||||
axis: z
|
||||
position_endstop: 0.5
|
||||
position_max: 100
|
||||
endstop_pin: PG12
|
||||
|
||||
[extra_carriage carriage_z1]
|
||||
primary_carriage: carriage_z0
|
||||
endstop_pin: PG13
|
||||
|
||||
[extra_carriage carriage_z2]
|
||||
primary_carriage: carriage_z0
|
||||
endstop_pin: PG14
|
||||
|
||||
[stepper stepper_t0_x]
|
||||
carriages: carriage_t0
|
||||
step_pin: extboard:PF13
|
||||
dir_pin: extboard:PF12
|
||||
enable_pin: !extboard:PF14
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper stepper_t1_x]
|
||||
carriages: carriage_t1
|
||||
step_pin: extboard:PG0
|
||||
dir_pin: extboard:PG1
|
||||
enable_pin: !extboard:PF15
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper stepper_t2_x]
|
||||
carriages: carriage_t2
|
||||
step_pin: extboard:PF11
|
||||
dir_pin: extboard:PG3
|
||||
enable_pin: !extboard:PG5
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper stepper_t3_x]
|
||||
carriages: carriage_t3
|
||||
step_pin: extboard:PG4
|
||||
dir_pin: extboard:PC1
|
||||
enable_pin: !extboard:PA2
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry0_left]
|
||||
carriages: carriage_gantry0_left
|
||||
step_pin: PF13
|
||||
dir_pin: PF12
|
||||
enable_pin: !PF14
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry0_right]
|
||||
carriages: carriage_gantry0_right
|
||||
step_pin: PG0
|
||||
dir_pin: PG1
|
||||
enable_pin: !PF15
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry1_left]
|
||||
carriages: carriage_gantry1_left
|
||||
step_pin: PF11
|
||||
dir_pin: PG3
|
||||
enable_pin: !PG5
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry1_right]
|
||||
carriages: carriage_gantry1_right
|
||||
step_pin: PG4
|
||||
dir_pin: PC1
|
||||
enable_pin: !PA2
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper z0]
|
||||
carriages: carriage_z0
|
||||
step_pin: PF9
|
||||
dir_pin: PF10
|
||||
enable_pin: !PG2
|
||||
microsteps: 16
|
||||
rotation_distance: 8
|
||||
|
||||
[stepper z1]
|
||||
carriages: carriage_z1
|
||||
step_pin: PC13
|
||||
dir_pin: PF0
|
||||
enable_pin: !PF1
|
||||
microsteps: 16
|
||||
rotation_distance: 8
|
||||
|
||||
[stepper z2]
|
||||
carriages: carriage_z2
|
||||
step_pin: PE2
|
||||
dir_pin: PE3
|
||||
enable_pin: !PD4
|
||||
microsteps: 16
|
||||
rotation_distance: 8
|
||||
|
||||
[extruder]
|
||||
step_pin: extboard:PF9
|
||||
dir_pin: extboard:PF10
|
||||
enable_pin: !extboard:PG2
|
||||
heater_pin: extboard:PA0 # HE0
|
||||
sensor_pin: extboard:PF4 # T0
|
||||
microsteps: 16
|
||||
rotation_distance: 33.500
|
||||
nozzle_diameter: 0.400
|
||||
filament_diameter: 1.750
|
||||
sensor_type: EPCOS 100K B57560G104F
|
||||
control: pid
|
||||
pid_Kp: 22.2
|
||||
pid_Ki: 1.08
|
||||
pid_Kd: 114
|
||||
min_temp: 0
|
||||
max_temp: 250
|
||||
|
||||
[extruder1]
|
||||
step_pin: extboard:PC13
|
||||
dir_pin: extboard:PF0
|
||||
enable_pin: !extboard:PF1
|
||||
heater_pin: extboard:PA3 # HE1
|
||||
sensor_pin: extboard:PF5 # T1
|
||||
microsteps: 16
|
||||
rotation_distance: 33.5
|
||||
nozzle_diameter: 0.400
|
||||
filament_diameter: 1.750
|
||||
sensor_type: EPCOS 100K B57560G104F
|
||||
control: pid
|
||||
pid_Kp: 22.2
|
||||
pid_Ki: 1.08
|
||||
pid_Kd: 114
|
||||
min_temp: 0
|
||||
max_temp: 250
|
||||
|
||||
[extruder2]
|
||||
step_pin: extboard:PE2
|
||||
dir_pin: extboard:PE3
|
||||
enable_pin: !extboard:PD4
|
||||
heater_pin: extboard:PB0 # HE2
|
||||
sensor_pin: extboard:PF6 # T2
|
||||
microsteps: 16
|
||||
rotation_distance: 33.5
|
||||
nozzle_diameter: 0.400
|
||||
filament_diameter: 1.750
|
||||
sensor_type: EPCOS 100K B57560G104F
|
||||
control: pid
|
||||
pid_Kp: 22.2
|
||||
pid_Ki: 1.08
|
||||
pid_Kd: 114
|
||||
min_temp: 0
|
||||
max_temp: 250
|
||||
|
||||
[extruder3]
|
||||
step_pin: extboard:PE6
|
||||
dir_pin: extboard:PA14
|
||||
enable_pin: !extboard:PE0
|
||||
heater_pin: extboard:PB11 # HE3
|
||||
sensor_pin: extboard:PF7 # T3
|
||||
microsteps: 16
|
||||
rotation_distance: 33.5
|
||||
nozzle_diameter: 0.400
|
||||
filament_diameter: 1.750
|
||||
sensor_type: EPCOS 100K B57560G104F
|
||||
control: pid
|
||||
pid_Kp: 22.2
|
||||
pid_Ki: 1.08
|
||||
pid_Kd: 114
|
||||
min_temp: 0
|
||||
max_temp: 250
|
||||
|
||||
[gcode_macro PARK_EXTRUDERS]
|
||||
gcode:
|
||||
G90
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
G1 Y{printer.configfile.settings["dual_carriage carriage_gantry1_left"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t3"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t1"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
|
||||
[gcode_macro T0]
|
||||
gcode:
|
||||
PARK_EXTRUDERS
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
|
||||
[gcode_macro T1]
|
||||
gcode:
|
||||
PARK_EXTRUDERS
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder1
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder1
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
|
||||
[gcode_macro T2]
|
||||
gcode:
|
||||
PARK_EXTRUDERS
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder2
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder2
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
|
||||
[gcode_macro T3]
|
||||
gcode:
|
||||
PARK_EXTRUDERS
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder3 MOTION_QUEUE=extruder3
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder3
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
|
||||
[gcode_macro SET_COPY_MODE]
|
||||
gcode:
|
||||
G90
|
||||
{% set y_center = 0.5 * (printer.configfile.settings["dual_carriage carriage_gantry1_left"].position_max + printer.configfile.settings["carriage carriage_gantry0_left"].position_min) %}
|
||||
{% set x_max = [printer.configfile.settings["dual_carriage carriage_t3"].position_max, printer.configfile.settings["dual_carriage carriage_t1"].position_max]|min %}
|
||||
{% set x_min = [printer.configfile.settings["dual_carriage carriage_t2"].position_min, printer.configfile.settings["carriage carriage_t0"].position_min]|max %}
|
||||
{% set x_center = 0.5 * (x_max + x_min) %}
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
G1 Y{y_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3
|
||||
G1 X{x_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{x_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0 MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left MODE=COPY
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder3 MOTION_QUEUE=extruder
|
||||
|
||||
[gcode_macro SET_MIRROR_MODE1]
|
||||
gcode:
|
||||
G90
|
||||
{% set y_center = 0.5 * (printer.configfile.settings["dual_carriage carriage_gantry1_left"].position_max + printer.configfile.settings["carriage carriage_gantry0_left"].position_min) %}
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
G1 Y{y_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t3"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t1"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0 MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1 MODE=MIRROR
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3 MODE=MIRROR
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left MODE=COPY
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder3 MOTION_QUEUE=extruder
|
||||
|
||||
[gcode_macro SET_MIRROR_MODE2]
|
||||
gcode:
|
||||
G90
|
||||
{% set x_max = [printer.configfile.settings["dual_carriage carriage_t3"].position_max, printer.configfile.settings["dual_carriage carriage_t1"].position_max]|min %}
|
||||
{% set x_min = [printer.configfile.settings["dual_carriage carriage_t2"].position_min, printer.configfile.settings["carriage carriage_t0"].position_min]|max %}
|
||||
{% set x_center = 0.5 * (x_max + x_min) %}
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
G1 Y{printer.configfile.settings["dual_carriage carriage_gantry1_left"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3
|
||||
G1 X{x_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{x_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0 MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left MODE=MIRROR
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder3 MOTION_QUEUE=extruder
|
||||
|
||||
[heater_bed]
|
||||
heater_pin: PA1
|
||||
sensor_pin: PF3 # TB
|
||||
sensor_type: ATC Semitec 104GT-2
|
||||
control: watermark
|
||||
min_temp: 0
|
||||
max_temp: 130
|
||||
|
||||
[fan]
|
||||
pin: PA8
|
||||
|
||||
[printer]
|
||||
kinematics: generic_cartesian
|
||||
max_velocity: 300
|
||||
max_accel: 3000
|
||||
max_z_velocity: 5
|
||||
max_z_accel: 100
|
||||
|
||||
[input_shaper]
|
||||
71
test/klippy/generic_cartesian_iqex.test
Normal file
71
test/klippy/generic_cartesian_iqex.test
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# Test cases on printers with quad independent extruders
|
||||
DICTIONARY stm32h723.dict extboard=stm32h723.dict
|
||||
CONFIG generic_cartesian_iqex.cfg
|
||||
|
||||
# First home the printer
|
||||
G90
|
||||
M83
|
||||
G28
|
||||
|
||||
# Perform a dummy move
|
||||
G1 X10 Y20 Z10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
|
||||
# Test other tools
|
||||
T1
|
||||
G1 X120 Y50 F6000
|
||||
G1 X119 E0.1 F3000
|
||||
|
||||
T2
|
||||
G1 X200 Y70 F6000
|
||||
G1 X199 E0.1 F3000
|
||||
|
||||
T3
|
||||
G1 X70 Y50 F6000
|
||||
G1 X71 E0.1 F3000
|
||||
|
||||
# Go back to main tool
|
||||
T0
|
||||
G1 X20 Y100 F6000
|
||||
|
||||
# Save dual carriage state
|
||||
SAVE_DUAL_CARRIAGE_STATE
|
||||
|
||||
G1 Y100 F6000
|
||||
|
||||
T2
|
||||
# Activate the dual carriage on Y axis
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
G1 X10 Y150 F6000
|
||||
|
||||
# Restore dual carriage state
|
||||
RESTORE_DUAL_CARRIAGE_STATE
|
||||
|
||||
QUERY_ENDSTOPS
|
||||
|
||||
# Configure input shaper
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t3
|
||||
SET_INPUT_SHAPER SHAPER_TYPE_X=ei SHAPER_FREQ_X=50 SHAPER_TYPE_Y=2hump_ei SHAPER_FREQ_Y=80
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
SET_INPUT_SHAPER SHAPER_TYPE_X=ei SHAPER_FREQ_X=45 SHAPER_TYPE_Y=2hump_ei SHAPER_FREQ_Y=80
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
SET_INPUT_SHAPER SHAPER_TYPE_X=mzv SHAPER_FREQ_X=50 SHAPER_TYPE_Y=2hump_ei SHAPER_FREQ_Y=70
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
SET_INPUT_SHAPER SHAPER_TYPE_X=zvd SHAPER_FREQ_X=55 SHAPER_TYPE_Y=2hump_ei SHAPER_FREQ_Y=70
|
||||
|
||||
T0
|
||||
G1 X100 Y150 F6000
|
||||
|
||||
SET_COPY_MODE
|
||||
G1 X10 Y10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
|
||||
SET_MIRROR_MODE1
|
||||
G1 X10 Y10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
|
||||
SET_MIRROR_MODE2
|
||||
G1 X10 Y10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
320
test/klippy/generic_cartesian_itex.cfg
Normal file
320
test/klippy/generic_cartesian_itex.cfg
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
# Test config for generic cartesian kinematics with triple independent extruders
|
||||
[mcu]
|
||||
serial: /dev/ttyACM0
|
||||
|
||||
[mcu extboard]
|
||||
serial: /dev/ttyACM1
|
||||
|
||||
[carriage carriage_t0]
|
||||
axis: x
|
||||
position_endstop: 0
|
||||
position_max: 300
|
||||
homing_speed: 50
|
||||
endstop_pin: extboard:PG6
|
||||
|
||||
[dual_carriage carriage_t1]
|
||||
primary_carriage: carriage_t0
|
||||
safe_distance: 70
|
||||
position_endstop: 300
|
||||
position_max: 300
|
||||
homing_speed: 50
|
||||
endstop_pin: extboard:PG9
|
||||
|
||||
[dual_carriage carriage_t2]
|
||||
axis: x
|
||||
position_endstop: 0
|
||||
position_max: 300
|
||||
homing_speed: 50
|
||||
endstop_pin: extboard:PG10
|
||||
|
||||
[carriage carriage_gantry0_left]
|
||||
axis: y
|
||||
position_endstop: 0
|
||||
position_max: 200
|
||||
homing_speed: 50
|
||||
endstop_pin: PG6
|
||||
|
||||
[extra_carriage carriage_gantry0_right]
|
||||
primary_carriage: carriage_gantry0_left
|
||||
endstop_pin: PG9
|
||||
|
||||
[dual_carriage carriage_gantry1]
|
||||
primary_carriage: carriage_gantry0_left
|
||||
safe_distance: 50
|
||||
position_endstop: 200
|
||||
position_max: 200
|
||||
homing_speed: 50
|
||||
endstop_pin: PG10
|
||||
|
||||
[carriage carriage_z0]
|
||||
axis: z
|
||||
position_endstop: 0.5
|
||||
position_max: 100
|
||||
endstop_pin: PG12
|
||||
|
||||
[extra_carriage carriage_z1]
|
||||
primary_carriage: carriage_z0
|
||||
endstop_pin: PG13
|
||||
|
||||
[extra_carriage carriage_z2]
|
||||
primary_carriage: carriage_z0
|
||||
endstop_pin: PG14
|
||||
|
||||
[stepper stepper_t0_x]
|
||||
carriages: carriage_t0
|
||||
step_pin: extboard:PF13
|
||||
dir_pin: extboard:PF12
|
||||
enable_pin: !extboard:PF14
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper stepper_t1_x]
|
||||
carriages: carriage_t1
|
||||
step_pin: extboard:PG0
|
||||
dir_pin: extboard:PG1
|
||||
enable_pin: !extboard:PF15
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry0_left]
|
||||
carriages: carriage_gantry0_left
|
||||
step_pin: PF13
|
||||
dir_pin: PF12
|
||||
enable_pin: !PF14
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry0_right]
|
||||
carriages: carriage_gantry0_right
|
||||
step_pin: PG0
|
||||
dir_pin: PG1
|
||||
enable_pin: !PF15
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry1_a]
|
||||
carriages: carriage_t2-carriage_gantry1
|
||||
step_pin: PF11
|
||||
dir_pin: PG3
|
||||
enable_pin: !PG5
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper gantry1_b]
|
||||
carriages: carriage_t2+carriage_gantry1
|
||||
step_pin: PG4
|
||||
dir_pin: PC1
|
||||
enable_pin: !PA2
|
||||
microsteps: 16
|
||||
rotation_distance: 40
|
||||
|
||||
[stepper z0]
|
||||
carriages: carriage_z0
|
||||
step_pin: PF9
|
||||
dir_pin: PF10
|
||||
enable_pin: !PG2
|
||||
microsteps: 16
|
||||
rotation_distance: 8
|
||||
|
||||
[stepper z1]
|
||||
carriages: carriage_z1
|
||||
step_pin: PC13
|
||||
dir_pin: PF0
|
||||
enable_pin: !PF1
|
||||
microsteps: 16
|
||||
rotation_distance: 8
|
||||
|
||||
[stepper z2]
|
||||
carriages: carriage_z2
|
||||
step_pin: PE2
|
||||
dir_pin: PE3
|
||||
enable_pin: !PD4
|
||||
microsteps: 16
|
||||
rotation_distance: 8
|
||||
|
||||
[extruder]
|
||||
step_pin: extboard:PF9
|
||||
dir_pin: extboard:PF10
|
||||
enable_pin: !extboard:PG2
|
||||
heater_pin: extboard:PA0 # HE0
|
||||
sensor_pin: extboard:PF4 # T0
|
||||
microsteps: 16
|
||||
rotation_distance: 33.500
|
||||
nozzle_diameter: 0.400
|
||||
filament_diameter: 1.750
|
||||
sensor_type: EPCOS 100K B57560G104F
|
||||
control: pid
|
||||
pid_Kp: 22.2
|
||||
pid_Ki: 1.08
|
||||
pid_Kd: 114
|
||||
min_temp: 0
|
||||
max_temp: 250
|
||||
|
||||
[extruder1]
|
||||
step_pin: extboard:PC13
|
||||
dir_pin: extboard:PF0
|
||||
enable_pin: !extboard:PF1
|
||||
heater_pin: extboard:PA3 # HE1
|
||||
sensor_pin: extboard:PF5 # T1
|
||||
microsteps: 16
|
||||
rotation_distance: 33.5
|
||||
nozzle_diameter: 0.400
|
||||
filament_diameter: 1.750
|
||||
sensor_type: EPCOS 100K B57560G104F
|
||||
control: pid
|
||||
pid_Kp: 22.2
|
||||
pid_Ki: 1.08
|
||||
pid_Kd: 114
|
||||
min_temp: 0
|
||||
max_temp: 250
|
||||
|
||||
[extruder2]
|
||||
step_pin: extboard:PE2
|
||||
dir_pin: extboard:PE3
|
||||
enable_pin: !extboard:PD4
|
||||
heater_pin: extboard:PB0 # HE2
|
||||
sensor_pin: extboard:PF6 # T2
|
||||
microsteps: 16
|
||||
rotation_distance: 33.5
|
||||
nozzle_diameter: 0.400
|
||||
filament_diameter: 1.750
|
||||
sensor_type: EPCOS 100K B57560G104F
|
||||
control: pid
|
||||
pid_Kp: 22.2
|
||||
pid_Ki: 1.08
|
||||
pid_Kd: 114
|
||||
min_temp: 0
|
||||
max_temp: 250
|
||||
|
||||
[gcode_macro PARK_EXTRUDERS]
|
||||
gcode:
|
||||
G90
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1
|
||||
G1 Y{printer.configfile.settings["dual_carriage carriage_gantry1"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t1"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
|
||||
[gcode_macro T0]
|
||||
gcode:
|
||||
PARK_EXTRUDERS
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
|
||||
[gcode_macro T1]
|
||||
gcode:
|
||||
PARK_EXTRUDERS
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder1
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder1
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
|
||||
[gcode_macro T2]
|
||||
gcode:
|
||||
PARK_EXTRUDERS
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder2
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder2
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
|
||||
[gcode_macro SET_COPY_MODE]
|
||||
gcode:
|
||||
G90
|
||||
{% set y_center = 0.5 * (printer.configfile.settings["dual_carriage carriage_gantry1"].position_max + printer.configfile.settings["carriage carriage_gantry0_left"].position_min) %}
|
||||
{% set x_max = printer.configfile.settings["dual_carriage carriage_t1"].position_max %}
|
||||
{% set x_min = [printer.configfile.settings["dual_carriage carriage_t2"].position_min, printer.configfile.settings["carriage carriage_t0"].position_min]|max %}
|
||||
{% set x_center = 0.5 * (x_max + x_min) %}
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1
|
||||
G1 Y{y_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{x_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0 MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1 MODE=COPY
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder
|
||||
|
||||
[gcode_macro SET_MIRROR_MODE1]
|
||||
gcode:
|
||||
G90
|
||||
{% set y_center = 0.5 * (printer.configfile.settings["dual_carriage carriage_gantry1"].position_max + printer.configfile.settings["carriage carriage_gantry0_left"].position_min) %}
|
||||
{% set x_max = printer.configfile.settings["dual_carriage carriage_t1"].position_max %}
|
||||
{% set x_min = [printer.configfile.settings["dual_carriage carriage_t2"].position_min, printer.configfile.settings["carriage carriage_t0"].position_min]|max %}
|
||||
{% set x_center = 0.5 * (x_max + x_min) %}
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1
|
||||
G1 Y{y_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{x_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0 MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1 MODE=COPY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2 MODE=MIRROR
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1 MODE=COPY
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder
|
||||
|
||||
[gcode_macro SET_MIRROR_MODE2]
|
||||
gcode:
|
||||
{% set y_center = 0.5 * (printer.configfile.settings["dual_carriage carriage_gantry1"].position_max + printer.configfile.settings["carriage carriage_gantry0_left"].position_min) %}
|
||||
G90
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
G1 Y{printer.configfile.settings["carriage carriage_gantry0_left"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1
|
||||
G1 Y{y_center} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t2"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
G1 X{printer.configfile.settings["carriage carriage_t0"].position_min} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
G1 X{printer.configfile.settings["dual_carriage carriage_t1"].position_max} F12000
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0 MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1 MODE=MIRROR
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2 MODE=MIRROR
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left MODE=PRIMARY
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1 MODE=COPY
|
||||
ACTIVATE_EXTRUDER EXTRUDER=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder1 MOTION_QUEUE=extruder
|
||||
SYNC_EXTRUDER_MOTION EXTRUDER=extruder2 MOTION_QUEUE=extruder
|
||||
|
||||
[heater_bed]
|
||||
heater_pin: PA1
|
||||
sensor_pin: PF3 # TB
|
||||
sensor_type: ATC Semitec 104GT-2
|
||||
control: watermark
|
||||
min_temp: 0
|
||||
max_temp: 130
|
||||
|
||||
[fan]
|
||||
pin: PA8
|
||||
|
||||
[printer]
|
||||
kinematics: generic_cartesian
|
||||
max_velocity: 300
|
||||
max_accel: 3000
|
||||
max_z_velocity: 5
|
||||
max_z_accel: 100
|
||||
|
||||
[input_shaper]
|
||||
65
test/klippy/generic_cartesian_itex.test
Normal file
65
test/klippy/generic_cartesian_itex.test
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Test cases on printers with triple independent extruders
|
||||
DICTIONARY stm32h723.dict extboard=stm32h723.dict
|
||||
CONFIG generic_cartesian_itex.cfg
|
||||
|
||||
# First home the printer
|
||||
G90
|
||||
M83
|
||||
G28
|
||||
|
||||
# Perform a dummy move
|
||||
G1 X10 Y20 Z10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
|
||||
# Test other tools
|
||||
T1
|
||||
G1 X120 Y50 F6000
|
||||
G1 X119 E0.1 F3000
|
||||
|
||||
T2
|
||||
G1 X200 Y70 F6000
|
||||
G1 X199 E0.1 F3000
|
||||
|
||||
# Go back to main tool
|
||||
T0
|
||||
G1 X20 Y100 F6000
|
||||
|
||||
# Save dual carriage state
|
||||
SAVE_DUAL_CARRIAGE_STATE
|
||||
|
||||
G1 Y100 F6000
|
||||
|
||||
T2
|
||||
# Activate the dual carriage on Y axis
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1
|
||||
G1 X10 Y150 F6000
|
||||
|
||||
# Restore dual carriage state
|
||||
RESTORE_DUAL_CARRIAGE_STATE
|
||||
|
||||
QUERY_ENDSTOPS
|
||||
|
||||
# Configure input shaper
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry1
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t2
|
||||
SET_INPUT_SHAPER SHAPER_TYPE_X=ei SHAPER_FREQ_X=45 SHAPER_TYPE_Y=2hump_ei SHAPER_FREQ_Y=80
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_gantry0_left
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t1
|
||||
SET_INPUT_SHAPER SHAPER_TYPE_X=mzv SHAPER_FREQ_X=50 SHAPER_TYPE_Y=2hump_ei SHAPER_FREQ_Y=70
|
||||
SET_DUAL_CARRIAGE CARRIAGE=carriage_t0
|
||||
SET_INPUT_SHAPER SHAPER_TYPE_X=zvd SHAPER_FREQ_X=55 SHAPER_TYPE_Y=2hump_ei SHAPER_FREQ_Y=70
|
||||
|
||||
T0
|
||||
G1 X100 Y150 F6000
|
||||
|
||||
SET_COPY_MODE
|
||||
G1 X10 Y10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
|
||||
SET_MIRROR_MODE1
|
||||
G1 X10 Y10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
|
||||
SET_MIRROR_MODE2
|
||||
G1 X10 Y10 F6000
|
||||
G1 X11 E0.1 F3000
|
||||
Loading…
Add table
Add a link
Reference in a new issue