Skip to content

Commit

Permalink
initial limited-corexz
Browse files Browse the repository at this point in the history
  • Loading branch information
kdb424 committed Feb 12, 2023
1 parent ae295ba commit 3376973
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 0 deletions.
78 changes: 78 additions & 0 deletions config/example-limited-corexz.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# This file is an example config file for corexz style printers. One
# may copy and edit this file to configure a new corexz 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: limited_corexz
max_velocity: 300
max_accel: 3000
max_z_velocity: 50
max_z_accel: 30
59 changes: 59 additions & 0 deletions docs/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,65 @@ max_z_accel:
[stepper_z]
```

### CoreXZ Kinematics with limits for X and Y axes

Behaves exactly the as corexz kinematics, but allows to set a velocity and
acceleration limit for X and Y axis.

If you set accelerations per feature type in the slicer, and have tuned your
acceleration to get similar resonance amplitudes and level of smoothing on X and
Y, you may want to enable `scale_xy_accel: true`. This will scale the X and Y
accelerations by the ratio `M204 acceleration / config.max_accel`. For example,
if you have `max_accel: 10000` in your config and set in the slicer an
acceleration of 5000 mm/s² (`M204 S5000`), effective `max_x_accel` and
`max_y_accel` values will be halved compared to their original values set in the
`[printer]` config. Otherwise, with `scale_xy_accel: false` (the default) they
behave as machine limits, like `max_z_accel` and `max_z_velocity` always do.
Gcode velocities under the limits are never scaled per axis and stay isotropic.

```
[printer]
kinematics: limited_corexz
max_x_velocity:
# This sets the maximum velocity (in mm/s) of movement along the x
# axis. This setting can be used to restrict the maximum speed of
# the x stepper motor. The default is to use max_velocity for
# max_x_velocity.
max_y_velocity:
# This sets the maximum velocity (in mm/s) of movement along the y
# axis. This setting can be used to restrict the maximum speed of
# the y stepper motor. The default is to use max_velocity for
# max_x_velocity.
max_z_velocity:
# See cartesian above.
max_velocity:
# In order to get maximum velocity gains on diagonals, this should be equal or
# greater than the hypotenuse (sqrt(x*x + y*y)) of max_x_velocity and
# max_y_velocity.
max_x_accel:
# This sets the maximum acceleration (in mm/s^2) of movement along
# the x axis. It limits the acceleration of the x stepper motor. The
# default is to use max_accel for max_x_accel.
max_y_accel:
# This sets the maximum acceleration (in mm/s^2) of movement along
# the y axis. It limits the acceleration of the y stepper motor. The
# default is to use max_accel for max_y_accel.
max_z_accel:
# See cartesian above.
max_accel:
# In order to get maximum acceleration gains on diagonals, this should be
# equal or greater than the hypotenuse (sqrt(x*x + y*y)) of max_x_accel and
# max_y_accel.
scale_xy_accel:
# If scale_xy_accel is False, `max_accel`, set by M204 or SET_VELOCITY_LIMIT,
# acts as a third limit. This means that moves with an acceleration lower
# than max_x_accel and max_y_accel, have no per-axis limits applied. When set
# to True, max_x_accel and max_y_accel are scaled by the ratio of the
# acceleration set at runtime and the max_accel value from the config. Then
# the actual acceleration will always depend on the orientation.
```


### Hybrid-CoreXY Kinematics

See [example-hybrid-corexy.cfg](../config/example-hybrid-corexy.cfg)
Expand Down
130 changes: 130 additions & 0 deletions klippy/kinematics/limited_corexz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Code for handling the kinematics of corexz robots
# with per-axis limits for velocity and acceleration
#
# Copyright (C) 2020-2021 Mael Kerbiriou <[email protected]>
# Copyright (C) 2023 Kyle Brown <[email protected]>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
#
# Usage:
# Copying this file under `klipper/klippy/kinematics/` should be enough (click
# the `raw` button on github, then save as)
# Then your config's [printer] should look like:
# [printer]
# kinematics: limited_corexz
# max_velocity: 500 # Hypotenuse of the two values bellow
# max_x_velocity: 400
# max_y_velocity: 300
# max_z_velocity: 5
# max_accel: 1500 # Default acceleration of your choice
# max_x_accel: 12000
# max_y_accel: 9000
# max_z_accel: 100
# scale_xy_accel: [True/False, default False]
#
# max_velocity is usually the hypotenuses of X and Y velocity, For example:
# with max_x_velocity = 300 and max_y_velocity = 400, the recommended value
# is max_velocity = 500.
#
# If scale_xy_accel is False, `max_accel`, set by M204 or
# SET_VELOCITY_LIMIT, acts as a third limit. In that case, this module
# doesn't apply limitations to moves with an acceleration lower than
# max_x_accel and max_y_accel.
# When scale_xy_accel is True, max_x_accel and max_y_accel are scaled by
# the ratio of the dynamically set acceleration and the hypotenuse of
# max_x_accel and max_y_accel, as reported from `SET_KINEMATICS_LIMIT`.
# This means that the actual acceleration will always depend on the
# direction.
# For example with these settings:
# [printer]
# max_x_accel: 12000
# max_y_accel: 9000
# scale_xy_accel: true
# SET_KINEMATICS_LIMIT will report a maximum acceleration of 15000 mm/s^2
# on 37 degrees diagonals. Thus, setting an acceleration of 3000 mm/s^2 in
# the slicer will make the toolhead accelerate at 3000 mm/s^2 on these 37
# and 143 degrees diagonals, but only 12000 * 3000 / 15000 = 2400 mm/s^2
# for moves aligned with the X axis and 18000 mm/s^2 for pure Y moves.


from sys import float_info
from math import hypot, atan2, pi

from . import corexz

EPSILON = float_info.epsilon


class LimitedCoreXZKinematics(corexz.CoreXZKinematics):
def __init__(self, toolhead, config):
corexz.CoreXZKinematics.__init__(self, toolhead, config)
# Setup y axis limits
max_velocity, max_accel = toolhead.get_max_velocity()
self.max_velocities = [
config.getfloat("max_%s_velocity" % ax, max_velocity, above=0.0)
for ax in "xyz"
]
self.max_accels = [
config.getfloat("max_%s_accel" % ax, max_accel, above=0.0) for ax in "xyz"
]
self.xy_hypot_accel = hypot(*self.max_accels[:2])
self.scale_per_axis = config.getboolean("scale_xy_accel", False)
config.get_printer().lookup_object("gcode").register_command(
"SET_KINEMATICS_LIMIT", self.cmd_SET_KINEMATICS_LIMIT
)

def cmd_SET_KINEMATICS_LIMIT(self, gcmd):
self.max_velocities = [
gcmd.get_float("%s_VELOCITY" % ax, max_v, above=0.0)
for max_v, ax in zip(self.max_velocities, "XYZ")
]
self.max_accels = [
gcmd.get_float("%s_ACCEL" % ax, max_a, above=0.0)
for max_a, ax in zip(self.max_accels, "XYZ")
]
self.xy_hypot_accel = hypot(*self.max_accels[:2])
self.scale_per_axis = bool(
gcmd.get_int("SCALE", self.scale_per_axis, minval=0, maxval=1)
)
msg = ("x,y,z max_velocities: %r\n" "x,y,z max_accels: %r\n") % (
self.max_velocities,
self.max_accels,
)
if self.scale_per_axis:
msg += "Per axis accelerations limits scale with current acceleration.\n"
else:
msg += "Per axis accelerations limits are independent of current acceleration.\n"
msg += (
"Maximum XY velocity of %.1f mm/s reached on %.0f degrees diagonals.\n"
"Maximum XY acceleration of %.0f mm/s^2 reached on %.0f degrees diagonals."
) % (
hypot(*self.max_velocities[:2]),
180 * atan2(self.max_velocities[1], self.max_velocities[0]) / pi,
self.xy_hypot_accel,
180 * atan2(self.max_accels[1], self.max_accels[0]) / pi,
)
gcmd.respond_info(msg)

def check_move(self, move):
if not move.is_kinematic_move:
return
self._check_endstops(move)
x_r, y_r, z_r = move.axes_r[:3]
x_max_v, y_max_v, z_max_v = self.max_velocities
x_max_a, y_max_a, z_max_a = self.max_accels
x_r = max(abs(x_r), EPSILON)
y_r = max(abs(y_r), EPSILON)
max_v = min(x_max_v / x_r, y_max_v / y_r)
max_a = min(x_max_a / x_r, y_max_a / y_r)
if self.scale_per_axis:
_, toolhead_max_a = move.toolhead.get_max_velocity()
max_a *= toolhead_max_a / self.xy_hypot_accel
if z_r:
z_r = abs(z_r)
max_v = min(max_v, z_max_v / z_r)
max_a = min(max_a, z_max_a / z_r)
move.limit_speed(max_v, max_a)


def load_kinematics(toolhead, config):
return LimitedCoreXZKinematics(toolhead, config)

0 comments on commit 3376973

Please sign in to comment.