From f2c74ec0239ca9fe4b6c84d05337e86fa093b492 Mon Sep 17 00:00:00 2001 From: Tircown <74233386+Tircown@users.noreply.github.com> Date: Mon, 3 May 2021 20:31:23 +0200 Subject: [PATCH] kinematics: Add hybrid-corexy and hybrid-corexz (#4229) Signed-off-by: Fabrice GALLET --- config/example-hybrid-corexy.cfg | 79 +++++++++++++++++++++++ config/example-hybrid-corexz.cfg | 79 +++++++++++++++++++++++ docs/Config_Reference.md | 71 +++++++++++++++++++- klippy/kinematics/hybrid_corexy.py | 100 +++++++++++++++++++++++++++++ klippy/kinematics/hybrid_corexz.py | 100 +++++++++++++++++++++++++++++ test/klippy/printers.test | 2 + 6 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 config/example-hybrid-corexy.cfg create mode 100644 config/example-hybrid-corexz.cfg create mode 100644 klippy/kinematics/hybrid_corexy.py create mode 100644 klippy/kinematics/hybrid_corexz.py diff --git a/config/example-hybrid-corexy.cfg b/config/example-hybrid-corexy.cfg new file mode 100644 index 00000000..41a90eaa --- /dev/null +++ b/config/example-hybrid-corexy.cfg @@ -0,0 +1,79 @@ +# This file is an example config file for hybrid corexy style printers also +# known as Markforged kinematic. One may copy and edit this file to configure +# a new hybrid corexy printer. + +# DO NOT COPY THIS FILE WITHOUT CAREFULLY READING AND UPDATING IT +# FIRST. Incorrectly configured parameters may cause damage. + +# See docs/Config_Reference.md for a description of parameters. + +[stepper_x] +step_pin: PF0 +dir_pin: PF1 +enable_pin: !PD7 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PE5 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_y] +step_pin: PF6 +dir_pin: PF7 +enable_pin: !PF2 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PJ1 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_z] +step_pin: PL3 +dir_pin: PL1 +enable_pin: !PK0 +microsteps: 16 +rotation_distance: 8 +endstop_pin: ^PD3 +position_endstop: 0.5 +position_max: 200 + +[extruder] +step_pin: PA4 +dir_pin: PA6 +enable_pin: !PA2 +microsteps: 16 +rotation_distance: 33.500 +nozzle_diameter: 0.400 +filament_diameter: 1.750 +heater_pin: PB4 +sensor_type: ATC Semitec 104GT-2 +sensor_pin: PK5 +control: pid +pid_Kp: 22.2 +pid_Ki: 1.08 +pid_Kd: 114 +min_temp: 0 +max_temp: 250 + +[heater_bed] +heater_pin: PH5 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK6 +control: watermark +min_temp: 0 +max_temp: 130 + +[fan] +pin: PH6 + +[mcu] +serial: /dev/ttyACM0 + +[printer] +kinematics: hybrid_corexy +max_velocity: 300 +max_accel: 3000 +max_z_velocity: 25 +max_z_accel: 30 diff --git a/config/example-hybrid-corexz.cfg b/config/example-hybrid-corexz.cfg new file mode 100644 index 00000000..d2cf907c --- /dev/null +++ b/config/example-hybrid-corexz.cfg @@ -0,0 +1,79 @@ +# This file is an example config file for hybrid corexz style printers also +# known as Markforged kinematic. One may copy and edit this file to configure +# a new hybrid corexy printer. + +# DO NOT COPY THIS FILE WITHOUT CAREFULLY READING AND UPDATING IT +# FIRST. Incorrectly configured parameters may cause damage. + +# See docs/Config_Reference.md for a description of parameters. + +[stepper_x] +step_pin: PF0 +dir_pin: PF1 +enable_pin: !PD7 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PE5 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_y] +step_pin: PF6 +dir_pin: PF7 +enable_pin: !PF2 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PJ1 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_z] +step_pin: PL3 +dir_pin: PL1 +enable_pin: !PK0 +microsteps: 16 +rotation_distance: 8 +endstop_pin: ^PD3 +position_endstop: 0.5 +position_max: 200 + +[extruder] +step_pin: PA4 +dir_pin: PA6 +enable_pin: !PA2 +microsteps: 16 +rotation_distance: 33.500 +nozzle_diameter: 0.400 +filament_diameter: 1.750 +heater_pin: PB4 +sensor_type: ATC Semitec 104GT-2 +sensor_pin: PK5 +control: pid +pid_Kp: 22.2 +pid_Ki: 1.08 +pid_Kd: 114 +min_temp: 0 +max_temp: 250 + +[heater_bed] +heater_pin: PH5 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK6 +control: watermark +min_temp: 0 +max_temp: 130 + +[fan] +pin: PH6 + +[mcu] +serial: /dev/ttyACM0 + +[printer] +kinematics: hybrid_corexz +max_velocity: 300 +max_accel: 3000 +max_z_velocity: 25 +max_z_accel: 30 diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index a4ad4c0a..c089b420 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -82,7 +82,8 @@ The printer section controls high level printer settings. [printer] kinematics: # The type of printer in use. This option may be one of: cartesian, -# corexy, corexz, delta, rotary_delta, polar, winch, or none. This +# corexy, corexz, hybrid-codexy, hybrid-corexz, rotary_delta, delta, +# polar, winch, or none. This # parameter must be specified. max_velocity: # Maximum velocity (in mm/s) of the toolhead (relative to the @@ -365,6 +366,74 @@ max_z_accel: [stepper_z] ``` +## Hybrid-CoreXY Kinematics + +See [example-hybrid-corexy.cfg](../config/example-hybrid-corexy.cfg) +for an example hybrid corexy kinematics config file. + +This kinematic is also known as Markforged kinematic. + +Only parameters specific to hybrid corexy printers are described here +see [common kinematic settings](#common-kinematic-settings) for available +parameters. + +``` +[printer] +kinematics: hybrid_corexy +max_z_velocity: +# This sets the maximum velocity (in mm/s) of movement along the z +# axis. The default is to use max_velocity for max_z_velocity. +max_z_accel: +# This sets the maximum acceleration (in mm/s^2) of movement along +# the z axis. The default is to use max_accel for max_z_accel. + +# The stepper_x section is used to describe the X axis as well as the +# stepper controlling the X-Y movement. +[stepper_x] + +# The stepper_y section is used to describe the stepper controlling +# the Y axis. +[stepper_y] + +# The stepper_z section is used to describe the stepper controlling +# the Z axis. +[stepper_z] +``` + +## Hybrid-CoreXZ Kinematics + +See [example-hybrid-corexz.cfg](../config/example-hybrid-corexz.cfg) +for an example hybrid corexz kinematics config file. + +This kinematic is also known as Markforged kinematic. + +Only parameters specific to hybrid corexy printers are described here +see [common kinematic settings](#common-kinematic-settings) for available +parameters. + +``` +[printer] +kinematics: hybrid_corexz +max_z_velocity: +# This sets the maximum velocity (in mm/s) of movement along the z +# axis. The default is to use max_velocity for max_z_velocity. +max_z_accel: +# This sets the maximum acceleration (in mm/s^2) of movement along +# the z axis. The default is to use max_accel for max_z_accel. + +# The stepper_x section is used to describe the X axis as well as the +# stepper controlling the X-Z movement. +[stepper_x] + +# The stepper_y section is used to describe the stepper controlling +# the Y axis. +[stepper_y] + +# The stepper_z section is used to describe the stepper controlling +# the Z axis. +[stepper_z] +``` + ## Polar Kinematics See [example-polar.cfg](../config/example-polar.cfg) for an example diff --git a/klippy/kinematics/hybrid_corexy.py b/klippy/kinematics/hybrid_corexy.py new file mode 100644 index 00000000..74657e25 --- /dev/null +++ b/klippy/kinematics/hybrid_corexy.py @@ -0,0 +1,100 @@ +# Code for handling the kinematics of hybrid-corexy robots +# +# Copyright (C) 2021 Fabrice Gallet +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import logging +import stepper + +# The hybrid-corexy kinematic is also known as Markforged kinematics +class HybridCoreXYKinematics: + def __init__(self, toolhead, config): + self.printer = config.get_printer() + printer_config = config.getsection('printer') + # itersolve parameters + self.rails = [ stepper.PrinterRail(config.getsection('stepper_x')), + stepper.LookupMultiRail(config.getsection('stepper_y')), + stepper.LookupMultiRail(config.getsection('stepper_z'))] + self.rails[2].get_endstops()[0][0].add_stepper( + self.rails[0].get_steppers()[0]) + self.rails[0].setup_itersolve('corexy_stepper_alloc', '-') + self.rails[1].setup_itersolve('cartesian_stepper_alloc', 'y') + self.rails[2].setup_itersolve('cartesian_stepper_alloc', 'z') + ranges = [r.get_range() for r in self.rails] + self.axes_min = toolhead.Coord(*[r[0] for r in ranges], e=0.) + self.axes_max = toolhead.Coord(*[r[1] for r in ranges], e=0.) + for s in self.get_steppers(): + s.set_trapq(toolhead.get_trapq()) + toolhead.register_step_generator(s.generate_steps) + self.printer.register_event_handler("stepper_enable:motor_off", + self._motor_off) + # Setup boundary checks + max_velocity, max_accel = toolhead.get_max_velocity() + self.max_z_velocity = config.getfloat( + 'max_z_velocity', max_velocity, above=0., maxval=max_velocity) + self.max_z_accel = config.getfloat( + 'max_z_accel', max_accel, above=0., maxval=max_accel) + self.limits = [(1.0, -1.0)] * 3 + def get_steppers(self): + return [s for rail in self.rails for s in rail.get_steppers()] + def calc_tag_position(self): + pos = [rail.get_tag_position() for rail in self.rails] + return [pos[0] + pos[1], pos[1], pos[2]] + def set_position(self, newpos, homing_axes): + for i, rail in enumerate(self.rails): + rail.set_position(newpos) + if i in homing_axes: + self.limits[i] = rail.get_range() + def note_z_not_homed(self): + # Helper for Safe Z Home + self.limits[2] = (1.0, -1.0) + def _home_axis(self, homing_state, axis, rail): + position_min, position_max = rail.get_range() + hi = rail.get_homing_info() + homepos = [None, None, None, None] + homepos[axis] = hi.position_endstop + forcepos = list(homepos) + if hi.positive_dir: + forcepos[axis] -= 1.5 * (hi.position_endstop - position_min) + else: + forcepos[axis] += 1.5 * (position_max - hi.position_endstop) + # Perform homing + homing_state.home_rails([rail], forcepos, homepos) + def home(self, homing_state): + for axis in homing_state.get_axes(): + self._home_axis(homing_state, axis, self.rails[axis]) + def _motor_off(self, print_time): + self.limits = [(1.0, -1.0)] * 3 + def _check_endstops(self, move): + end_pos = move.end_pos + for i in (0, 1, 2): + if (move.axes_d[i] + and (end_pos[i] < self.limits[i][0] + or end_pos[i] > self.limits[i][1])): + if self.limits[i][0] > self.limits[i][1]: + raise move.move_error("Must home axis first") + raise move.move_error() + def check_move(self, move): + limits = self.limits + xpos, ypos = move.end_pos[:2] + if (xpos < limits[0][0] or xpos > limits[0][1] + or ypos < limits[1][0] or ypos > limits[1][1]): + self._check_endstops(move) + if not move.axes_d[2]: + # Normal XY move - use defaults + return + # Move with Z - update velocity and accel for slower Z axis + self._check_endstops(move) + z_ratio = move.move_d / abs(move.axes_d[2]) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + def get_status(self, eventtime): + axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h] + return { + 'homed_axes': "".join(axes), + 'axis_minimum': self.axes_min, + 'axis_maximum': self.axes_max, + } + +def load_kinematics(toolhead, config): + return HybridCoreXYKinematics(toolhead, config) diff --git a/klippy/kinematics/hybrid_corexz.py b/klippy/kinematics/hybrid_corexz.py new file mode 100644 index 00000000..85f81ce9 --- /dev/null +++ b/klippy/kinematics/hybrid_corexz.py @@ -0,0 +1,100 @@ +# Code for handling the kinematics of hybrid-corexz robots +# +# Copyright (C) 2021 Fabrice Gallet +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import logging +import stepper + +# The hybrid-corexz kinematic is also known as Markforged kinematics +class HybridCoreXZKinematics: + def __init__(self, toolhead, config): + self.printer = config.get_printer() + printer_config = config.getsection('printer') + # itersolve parameters + self.rails = [ stepper.PrinterRail(config.getsection('stepper_x')), + stepper.LookupMultiRail(config.getsection('stepper_y')), + stepper.LookupMultiRail(config.getsection('stepper_z'))] + self.rails[2].get_endstops()[0][0].add_stepper( + self.rails[0].get_steppers()[0]) + self.rails[0].setup_itersolve('corexz_stepper_alloc', '-') + self.rails[1].setup_itersolve('cartesian_stepper_alloc', 'y') + self.rails[2].setup_itersolve('cartesian_stepper_alloc', 'z') + ranges = [r.get_range() for r in self.rails] + self.axes_min = toolhead.Coord(*[r[0] for r in ranges], e=0.) + self.axes_max = toolhead.Coord(*[r[1] for r in ranges], e=0.) + for s in self.get_steppers(): + s.set_trapq(toolhead.get_trapq()) + toolhead.register_step_generator(s.generate_steps) + self.printer.register_event_handler("stepper_enable:motor_off", + self._motor_off) + # Setup boundary checks + max_velocity, max_accel = toolhead.get_max_velocity() + self.max_z_velocity = config.getfloat( + 'max_z_velocity', max_velocity, above=0., maxval=max_velocity) + self.max_z_accel = config.getfloat( + 'max_z_accel', max_accel, above=0., maxval=max_accel) + self.limits = [(1.0, -1.0)] * 3 + def get_steppers(self): + return [s for rail in self.rails for s in rail.get_steppers()] + def calc_tag_position(self): + pos = [rail.get_tag_position() for rail in self.rails] + return [pos[0] + pos[2], pos[1], pos[2]] + def set_position(self, newpos, homing_axes): + for i, rail in enumerate(self.rails): + rail.set_position(newpos) + if i in homing_axes: + self.limits[i] = rail.get_range() + def note_z_not_homed(self): + # Helper for Safe Z Home + self.limits[2] = (1.0, -1.0) + def _home_axis(self, homing_state, axis, rail): + position_min, position_max = rail.get_range() + hi = rail.get_homing_info() + homepos = [None, None, None, None] + homepos[axis] = hi.position_endstop + forcepos = list(homepos) + if hi.positive_dir: + forcepos[axis] -= 1.5 * (hi.position_endstop - position_min) + else: + forcepos[axis] += 1.5 * (position_max - hi.position_endstop) + # Perform homing + homing_state.home_rails([rail], forcepos, homepos) + def home(self, homing_state): + for axis in homing_state.get_axes(): + self._home_axis(homing_state, axis, self.rails[axis]) + def _motor_off(self, print_time): + self.limits = [(1.0, -1.0)] * 3 + def _check_endstops(self, move): + end_pos = move.end_pos + for i in (0, 1, 2): + if (move.axes_d[i] + and (end_pos[i] < self.limits[i][0] + or end_pos[i] > self.limits[i][1])): + if self.limits[i][0] > self.limits[i][1]: + raise move.move_error("Must home axis first") + raise move.move_error() + def check_move(self, move): + limits = self.limits + xpos, ypos = move.end_pos[:2] + if (xpos < limits[0][0] or xpos > limits[0][1] + or ypos < limits[1][0] or ypos > limits[1][1]): + self._check_endstops(move) + if not move.axes_d[2]: + # Normal XY move - use defaults + return + # Move with Z - update velocity and accel for slower Z axis + self._check_endstops(move) + z_ratio = move.move_d / abs(move.axes_d[2]) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + def get_status(self, eventtime): + axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h] + return { + 'homed_axes': "".join(axes), + 'axis_minimum': self.axes_min, + 'axis_maximum': self.axes_max, + } + +def load_kinematics(toolhead, config): + return HybridCoreXZKinematics(toolhead, config) diff --git a/test/klippy/printers.test b/test/klippy/printers.test index 460e6281..74a5973f 100644 --- a/test/klippy/printers.test +++ b/test/klippy/printers.test @@ -6,6 +6,8 @@ DICTIONARY atmega2560.dict CONFIG ../../config/example-cartesian.cfg CONFIG ../../config/example-corexy.cfg CONFIG ../../config/example-corexz.cfg +CONFIG ../../config/example-hybrid-corexy.cfg +CONFIG ../../config/example-hybrid-corexz.cfg CONFIG ../../config/example-delta.cfg CONFIG ../../config/example-rotary-delta.cfg CONFIG ../../config/example-winch.cfg