aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/kinematics/idex_modes.py
diff options
context:
space:
mode:
authorDmitry Butyugin <dmbutyugin@google.com>2023-09-30 02:46:42 +0900
committerGitHub <noreply@github.com>2023-09-29 13:46:42 -0400
commita4cd0336bdd9df78c1b2a1296a481e84efc2b821 (patch)
treecc2b4a3a02eca0ff19ae2e2973e7976d663b8abe /klippy/kinematics/idex_modes.py
parent21b784297916ac31b0e83161976effea048b53cb (diff)
downloadkutter-a4cd0336bdd9df78c1b2a1296a481e84efc2b821.tar.gz
kutter-a4cd0336bdd9df78c1b2a1296a481e84efc2b821.tar.xz
kutter-a4cd0336bdd9df78c1b2a1296a481e84efc2b821.zip
idex_modes: Fixed the case when carriages home in the same direction (#6310)
Previous version of the code assumed that dual carriages home away from each other, which is not true on some machines, which have the second dual carriage homing on the first carriage. The new code correctly identifies the relative order of the carriages now. This fixes discrepancies between the documentation and the actual implementation of the carriages kinematic ranges calculation. Notes about dual_carriage homing and proximity checks changes Fixed clearing of homing state after homing in certain modes In case of multi-MCU homing it is possible that the carriage position will end up outside of the allowed motion range due to latencies in data transmission between MCUs. Selecting certain modes after homing could result in home state clearing instead of blocking the motion of the active carriage. This commit fixes this undesired behavior. Signed-off-by: Dmitry Butyugin <dmbutyugin@google.com>
Diffstat (limited to 'klippy/kinematics/idex_modes.py')
-rw-r--r--klippy/kinematics/idex_modes.py53
1 files changed, 45 insertions, 8 deletions
diff --git a/klippy/kinematics/idex_modes.py b/klippy/kinematics/idex_modes.py
index b54f9657..2ce91afe 100644
--- a/klippy/kinematics/idex_modes.py
+++ b/klippy/kinematics/idex_modes.py
@@ -65,7 +65,13 @@ class DualCarriages:
kin.update_limits(self.axis, target_dc.get_rail().get_range())
def home(self, homing_state):
kin = self.printer.lookup_object('toolhead').get_kinematics()
- for i, dc_rail in enumerate(self.dc):
+ enumerated_dcs = list(enumerate(self.dc))
+ if (self.get_dc_order(0, 1) > 0) != \
+ self.dc[0].get_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
+ enumerated_dcs.reverse()
+ for i, dc_rail in enumerated_dcs:
self.toggle_active_dc_rail(i, override_rail=True)
kin.home_axis(homing_state, self.axis, dc_rail.get_rail())
# Restore the original rails ordering
@@ -78,9 +84,15 @@ class DualCarriages:
axes_pos = [dc.get_axis_position(pos) for dc in self.dc]
dc0_rail = self.dc[0].get_rail()
dc1_rail = self.dc[1].get_rail()
- range_min = dc0_rail.position_min
- range_max = dc0_rail.position_max
+ if mode != PRIMARY or self.dc[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
+ if not safe_dist:
+ return (range_min, range_max)
if mode == COPY:
range_min = max(range_min,
@@ -88,7 +100,7 @@ class DualCarriages:
range_max = min(range_max,
axes_pos[0] - axes_pos[1] + dc1_rail.position_max)
elif mode == MIRROR:
- if dc0_rail.get_homing_info().positive_dir:
+ if self.get_dc_order(0, 1) > 0:
range_min = max(range_min,
0.5 * (sum(axes_pos) + safe_dist))
range_max = min(range_max,
@@ -102,14 +114,39 @@ class DualCarriages:
# mode == PRIMARY
active_idx = 1 if self.dc[1].is_active() else 0
inactive_idx = 1 - active_idx
- if active_idx:
- range_min = dc1_rail.position_min
- range_max = dc1_rail.position_max
- if self.dc[active_idx].get_rail().get_homing_info().positive_dir:
+ if self.get_dc_order(active_idx, 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)
+ 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
+ # if position_endstop is too close to the rail motion ends due
+ # to inherent latencies of the data transmission between MCUs.
+ # This can result in an invalid range_min > range_max range
+ # in certain modes, which may confuse the kinematics code.
+ # So, return an empty range instead, which will correctly
+ # block the carriage motion until a different mode is selected
+ # which actually permits carriage motion.
+ return (range_min, range_min)
return (range_min, range_max)
+ def get_dc_order(self, first, second):
+ if first == second:
+ return 0
+ # Check the relative order of the first and second carriages and
+ # return -1 if the first carriage position is always smaller
+ # than the second one and 1 otherwise
+ first_rail = self.dc[first].get_rail()
+ second_rail = self.dc[second].get_rail()
+ first_homing_info = first_rail.get_homing_info()
+ second_homing_info = second_rail.get_homing_info()
+ if first_homing_info.positive_dir != second_homing_info.positive_dir:
+ # Carriages home away from each other
+ return 1 if first_homing_info.positive_dir else -1
+ # Carriages home in the same direction
+ if first_rail.position_endstop > second_rail.position_endstop:
+ return 1
+ return -1
def activate_dc_mode(self, index, mode):
toolhead = self.printer.lookup_object('toolhead')
toolhead.flush_step_generation()