Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial limited-corexz #1

Open
wants to merge 1 commit into
base: work-peraxis
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)