aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/kinematics/idex_modes.py
diff options
context:
space:
mode:
Diffstat (limited to 'klippy/kinematics/idex_modes.py')
-rw-r--r--klippy/kinematics/idex_modes.py105
1 files changed, 105 insertions, 0 deletions
diff --git a/klippy/kinematics/idex_modes.py b/klippy/kinematics/idex_modes.py
new file mode 100644
index 00000000..92cb39a3
--- /dev/null
+++ b/klippy/kinematics/idex_modes.py
@@ -0,0 +1,105 @@
+# Support for duplication and mirroring modes for IDEX printers
+#
+# Copyright (C) 2021 Fabrice Gallet <tircown@gmail.com>
+#
+# This file may be distributed under the terms of the GNU GPLv3 license.
+import math
+
+class DualCarriages:
+ def __init__(self, printer, rail_0, rail_1, axis):
+ self.printer = printer
+ self.axis = axis
+ self.dc = (rail_0, rail_1)
+ self.saved_state = None
+ self.printer.add_object('dual_carriage', self)
+ gcode = self.printer.lookup_object('gcode')
+ gcode.register_command(
+ 'SET_DUAL_CARRIAGE', self.cmd_SET_DUAL_CARRIAGE,
+ desc=self.cmd_SET_DUAL_CARRIAGE_help)
+ def toggle_active_dc_rail(self, index):
+ toolhead = self.printer.lookup_object('toolhead')
+ toolhead.flush_step_generation()
+ pos = toolhead.get_position()
+ kin = toolhead.get_kinematics()
+ for i, dc in enumerate(self.dc):
+ dc_rail = dc.get_rail()
+ if i != index:
+ dc.inactivate(pos)
+ kin.override_rail(3, dc_rail)
+ elif dc.is_active() is False:
+ newpos = pos[:self.axis] + [dc.axis_position] \
+ + pos[self.axis+1:]
+ dc.activate(newpos)
+ kin.override_rail(self.axis, dc_rail)
+ toolhead.set_position(newpos)
+ kin.update_limits(self.axis, dc_rail.get_range())
+ def get_status(self, eventtime):
+ dc0, dc1 = self.dc
+ if (dc0.is_active() is True):
+ return { 'mode': 'FULL_CONTROL', 'active_carriage': 'CARRIAGE_0' }
+ else:
+ return { 'mode': 'FULL_CONTROL', 'active_carriage': 'CARRIAGE_1' }
+ def save_idex_state(self):
+ dc0, dc1 = self.dc
+ if (dc0.is_active() is True):
+ mode, active_carriage = ('FULL_CONTROL', 'CARRIAGE_0')
+ else:
+ mode, active_carriage = ('FULL_CONTROL', 'CARRIAGE_1')
+ self.saved_state = {
+ 'mode': mode,
+ 'active_carriage': active_carriage,
+ 'axis_positions': (dc0.axis_position, dc1.axis_position)
+ }
+ def restore_idex_state(self):
+ if self.saved_state is not None:
+ # set carriage 0 active
+ if (self.saved_state['active_carriage'] == 'CARRIAGE_0'
+ and self.dc[0].is_active() is False):
+ self.toggle_active_dc_rail(0)
+ # set carriage 1 active
+ elif (self.saved_state['active_carriage'] == 'CARRIAGE_1'
+ and self.dc[1].is_active() is False):
+ self.toggle_active_dc_rail(1)
+ cmd_SET_DUAL_CARRIAGE_help = "Set which carriage is active"
+ def cmd_SET_DUAL_CARRIAGE(self, gcmd):
+ index = gcmd.get_int('CARRIAGE', minval=0, maxval=1)
+ if (not(self.dc[0].is_active() == self.dc[1].is_active() == True)
+ and self.dc[index].is_active() is False):
+ self.toggle_active_dc_rail(index)
+
+class DualCarriagesRail:
+ ACTIVE=1
+ INACTIVE=2
+ def __init__(self, printer, rail, axis, active, stepper_alloc_active,
+ stepper_alloc_inactive=None):
+ self.printer = printer
+ self.rail = rail
+ self.axis = axis
+ self.status = (self.INACTIVE, self.ACTIVE)[active]
+ self.stepper_alloc_active = stepper_alloc_active
+ self.stepper_alloc_inactive = stepper_alloc_inactive
+ self.axis_position = -1
+ def _stepper_alloc(self, position, active=True):
+ toolhead = self.printer.lookup_object('toolhead')
+ self.axis_position = position[self.axis]
+ self.rail.set_trapq(None)
+ if active is True:
+ self.status = self.ACTIVE
+ if self.stepper_alloc_active is not None:
+ self.rail.setup_itersolve(*self.stepper_alloc_active)
+ self.rail.set_position(position)
+ self.rail.set_trapq(toolhead.get_trapq())
+ else:
+ self.status = self.INACTIVE
+ if self.stepper_alloc_inactive is not None:
+ self.rail.setup_itersolve(*self.stepper_alloc_inactive)
+ self.rail.set_position(position)
+ self.rail.set_trapq(toolhead.get_trapq())
+ def get_rail(self):
+ return self.rail
+ def is_active(self):
+ return self.status == self.ACTIVE
+ def activate(self, position):
+ self._stepper_alloc(position, active=True)
+ def inactivate(self, position):
+ self._stepper_alloc(position, active=False)