From 0105aa330f2a4865b01cbbc548cba1322be5371e Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sun, 3 Dec 2023 18:50:44 -0500 Subject: [PATCH] toolhead: Replace max_accel_to_decel with minimum_cruise_ratio The user facing max_accel_to_decel setting is complicated and confusing. Replace it with a new minimum_cruise_ratio parameter. Internally this user-facing parameter will calculate the existing low-level "accel_to_decel" mechanism. Signed-off-by: Kevin O'Connor --- config/printer-anycubic-4maxpro-2.0-2021.cfg | 1 - config/printer-sovol-sv05-2022.cfg | 2 +- docs/Config_Changes.md | 8 ++++ docs/Config_Reference.md | 25 ++++++++--- docs/G-Codes.md | 2 +- docs/Kinematics.md | 28 +++++++----- docs/Resonance_Compensation.md | 10 ++--- docs/Status_Reference.md | 2 +- klippy/extras/resonance_tester.py | 10 ++--- klippy/toolhead.py | 47 ++++++++++++-------- 10 files changed, 85 insertions(+), 50 deletions(-) diff --git a/config/printer-anycubic-4maxpro-2.0-2021.cfg b/config/printer-anycubic-4maxpro-2.0-2021.cfg index e0c83b6ae..203e3c8f2 100644 --- a/config/printer-anycubic-4maxpro-2.0-2021.cfg +++ b/config/printer-anycubic-4maxpro-2.0-2021.cfg @@ -126,7 +126,6 @@ restart_method: arduino kinematics: cartesian max_velocity: 150 max_accel: 3000 -max_accel_to_decel: 1500 max_z_velocity: 7 max_z_accel: 50 square_corner_velocity: 5 diff --git a/config/printer-sovol-sv05-2022.cfg b/config/printer-sovol-sv05-2022.cfg index dafc6f3cf..0ec03f84a 100644 --- a/config/printer-sovol-sv05-2022.cfg +++ b/config/printer-sovol-sv05-2022.cfg @@ -19,7 +19,7 @@ restart_method: command kinematics: cartesian max_velocity: 300 max_accel: 1000 -max_accel_to_decel: 1000 +minimum_cruise_ratio: 0.0 max_z_velocity: 5 max_z_accel: 100 diff --git a/docs/Config_Changes.md b/docs/Config_Changes.md index 980c4f33a..668732f99 100644 --- a/docs/Config_Changes.md +++ b/docs/Config_Changes.md @@ -8,6 +8,14 @@ All dates in this document are approximate. ## Changes +20240313: The `max_accel_to_decel` parameter in the `[printer]` config +section has been deprecated. The `ACCEL_TO_DECEL` parameter of the +`SET_VELOCITY_LIMIT` command has been deprecated. The +`printer.toolhead.max_accel_to_decel` status has been removed. Use the +[minimum_cruise_ratio parameter](./Config_Reference.md#printer) +instead. The deprecated features will be removed in the near future, +and using them in the interim may result in subtly different behavior. + 20240215: Several deprecated features have been removed. Using "NTC 100K beta 3950" as a thermistor name has been removed (deprecated on 20211110). The `SYNC_STEPPER_TO_EXTRUDER` and diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index 14b89200f..1b833eaf1 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -97,13 +97,22 @@ max_accel: # will do so at the rate specified here. The value specified here # may be changed at runtime using the SET_VELOCITY_LIMIT command. # This parameter must be specified. -#max_accel_to_decel: -# A pseudo acceleration (in mm/s^2) controlling how fast the -# toolhead may go from acceleration to deceleration. It is used to -# reduce the top speed of short zig-zag moves (and thus reduce -# printer vibration from these moves). The value specified here may -# be changed at runtime using the SET_VELOCITY_LIMIT command. The -# default is half of max_accel. +#minimum_cruise_ratio: 0.5 +# Most moves will accelerate to a cruising speed, travel at that +# cruising speed, and then decelerate. However, some moves that +# travel a short distance could nominally accelerate and then +# immediately decelerate. This option reduces the top speed of these +# moves to ensure there is always a minimum distance traveled at a +# cruising speed. That is, it enforces a minimum distance traveled +# at cruising speed relative to the total distance traveled. It is +# intended to reduce the top speed of short zigzag moves (and thus +# reduce printer vibration from these moves). For example, a +# minimum_cruise_ratio of 0.5 would ensure that a standalone 1.5mm +# move would have a minimum cruising distance of 0.75mm. Specify a +# ratio of 0.0 to disable this feature (there would be no minimum +# cruising distance enforced between acceleration and deceleration). +# The value specified here may be changed at runtime using the +# SET_VELOCITY_LIMIT command. The default is 0.5. #square_corner_velocity: 5.0 # The maximum velocity (in mm/s) that the toolhead may travel a 90 # degree corner at. A non-zero value can reduce changes in extruder @@ -116,6 +125,8 @@ max_accel: # decelerate to zero at each corner. The value specified here may be # changed at runtime using the SET_VELOCITY_LIMIT command. The # default is 5mm/s. +#max_accel_to_decel: +# This parameter is deprecated and should no longer be used. ``` ### [stepper] diff --git a/docs/G-Codes.md b/docs/G-Codes.md index 199dc283b..1f88937aa 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -1291,7 +1291,7 @@ The toolhead module is automatically loaded. #### SET_VELOCITY_LIMIT `SET_VELOCITY_LIMIT [VELOCITY=] [ACCEL=] -[ACCEL_TO_DECEL=] [SQUARE_CORNER_VELOCITY=]`: This +[MINIMUM_CRUISE_RATIO=] [SQUARE_CORNER_VELOCITY=]`: This command can alter the velocity limits that were specified in the printer config file. See the [printer config section](Config_Reference.md#printer) for a diff --git a/docs/Kinematics.md b/docs/Kinematics.md index 313d5dce0..1996579d2 100644 --- a/docs/Kinematics.md +++ b/docs/Kinematics.md @@ -96,7 +96,7 @@ Key formula for look-ahead: end_velocity^2 = start_velocity^2 + 2*accel*move_distance ``` -### Smoothed look-ahead +### Minimum cruise ratio Klipper also implements a mechanism for smoothing out the motions of short "zigzag" moves. Consider the following moves: @@ -105,21 +105,27 @@ short "zigzag" moves. Consider the following moves: In the above, the frequent changes from acceleration to deceleration can cause the machine to vibrate which causes stress on the machine -and increases the noise. To reduce this, Klipper tracks both regular -move acceleration as well as a virtual "acceleration to deceleration" -rate. Using this system, the top speed of these short "zigzag" moves -are limited to smooth out the printer motion: +and increases the noise. Klipper implements a mechanism to ensure +there is always some movement at a cruising speed between acceleration +and deceleration. This is done by reducing the top speed of some moves +(or sequence of moves) to ensure there is a minimum distance traveled +at cruising speed relative to the distance traveled during +acceleration and deceleration. + +Klipper implements this feature by tracking both a regular move +acceleration as well as a virtual "acceleration to deceleration" rate: ![smoothed](img/smoothed.svg.png) Specifically, the code calculates what the velocity of each move would be if it were limited to this virtual "acceleration to deceleration" -rate (half the normal acceleration rate by default). In the above -picture the dashed gray lines represent this virtual acceleration rate -for the first move. If a move can not reach its full cruising speed -using this virtual acceleration rate then its top speed is reduced to -the maximum speed it could obtain at this virtual acceleration -rate. For most moves the limit will be at or above the move's existing +rate. In the above picture the dashed gray lines represent this +virtual acceleration rate for the first move. If a move can not reach +its full cruising speed using this virtual acceleration rate then its +top speed is reduced to the maximum speed it could obtain at this +virtual acceleration rate. + +For most moves the limit will be at or above the move's existing limits and no change in behavior is induced. For short zigzag moves, however, this limit reduces the top speed. Note that it does not change the actual acceleration within the move - the move continues to diff --git a/docs/Resonance_Compensation.md b/docs/Resonance_Compensation.md index aaeaf7abf..31f1b35e3 100644 --- a/docs/Resonance_Compensation.md +++ b/docs/Resonance_Compensation.md @@ -48,8 +48,8 @@ First, measure the **ringing frequency**. to 5.0. It is not advised to increase it when using input shaper because it can cause more smoothing in parts - it is better to use higher acceleration value instead. -2. Increase `max_accel_to_decel` by issuing the following command: - `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000` +2. Disable the `miminum_cruise_ratio` feature by issuing the following + command: `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0` 3. Disable Pressure Advance: `SET_PRESSURE_ADVANCE ADVANCE=0` 4. If you have already added `[input_shaper]` section to the printer.cfg, execute `SET_INPUT_SHAPER SHAPER_FREQ_X=0 SHAPER_FREQ_Y=0` command. If you @@ -149,7 +149,7 @@ a few other related parameters. Print the ringing test model as follows: 1. Restart the firmware: `RESTART` -2. Prepare for test: `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000` +2. Prepare for test: `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0` 3. Disable Pressure Advance: `SET_PRESSURE_ADVANCE ADVANCE=0` 4. Execute: `SET_INPUT_SHAPER SHAPER_TYPE=MZV` 5. Execute the command: @@ -270,7 +270,7 @@ frequencies after enabling [input_shaper], this section will not help with that. Assuming that you have sliced the ringing model with suggested parameters, complete the following steps for each of the axes X and Y: -1. Prepare for test: `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000` +1. Prepare for test: `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0` 2. Make sure Pressure Advance is disabled: `SET_PRESSURE_ADVANCE ADVANCE=0` 3. Execute: `SET_INPUT_SHAPER SHAPER_TYPE=ZV` 4. From the existing ringing test model with your chosen input shaper select @@ -331,7 +331,7 @@ with suggested parameters, print the test model 3 times as follows. First time, prior to printing, run 1. `RESTART` -2. `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000` +2. `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0` 3. `SET_PRESSURE_ADVANCE ADVANCE=0` 4. `SET_INPUT_SHAPER SHAPER_TYPE=2HUMP_EI SHAPER_FREQ_X=60 SHAPER_FREQ_Y=60` 5. `TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5` diff --git a/docs/Status_Reference.md b/docs/Status_Reference.md index 055d1dc0e..0e72a12b1 100644 --- a/docs/Status_Reference.md +++ b/docs/Status_Reference.md @@ -511,7 +511,7 @@ The following information is available in the `toolhead` object limit value (eg, `axis_minimum.x`, `axis_maximum.z`). - For Delta printers the `cone_start_z` is the max z height at maximum radius (`printer.toolhead.cone_start_z`). -- `max_velocity`, `max_accel`, `max_accel_to_decel`, +- `max_velocity`, `max_accel`, `minimum_cruise_ratio`, `square_corner_velocity`: The current printing limits that are in effect. This may differ from the config file settings if a `SET_VELOCITY_LIMIT` (or `M204`) command alters them at run-time. diff --git a/klippy/extras/resonance_tester.py b/klippy/extras/resonance_tester.py index d249412ca..fe8717d58 100644 --- a/klippy/extras/resonance_tester.py +++ b/klippy/extras/resonance_tester.py @@ -77,11 +77,11 @@ def run_test(self, axis, gcmd): systime = self.printer.get_reactor().monotonic() toolhead_info = toolhead.get_status(systime) old_max_accel = toolhead_info['max_accel'] - old_max_accel_to_decel = toolhead_info['max_accel_to_decel'] + old_minimum_cruise_ratio = toolhead_info['minimum_cruise_ratio'] max_accel = self.freq_end * self.accel_per_hz self.gcode.run_script_from_command( - "SET_VELOCITY_LIMIT ACCEL=%.3f ACCEL_TO_DECEL=%.3f" % ( - max_accel, max_accel)) + "SET_VELOCITY_LIMIT ACCEL=%.3f MINIMUM_CRUISE_RATIO=0" + % (max_accel,)) input_shaper = self.printer.lookup_object('input_shaper', None) if input_shaper is not None and not gcmd.get_int('INPUT_SHAPING', 0): input_shaper.disable_shaping() @@ -108,8 +108,8 @@ def run_test(self, axis, gcmd): gcmd.respond_info("Testing frequency %.0f Hz" % (freq,)) # Restore the original acceleration values self.gcode.run_script_from_command( - "SET_VELOCITY_LIMIT ACCEL=%.3f ACCEL_TO_DECEL=%.3f" % ( - old_max_accel, old_max_accel_to_decel)) + "SET_VELOCITY_LIMIT ACCEL=%.3f MINIMUM_CRUISE_RATIO=%.3f" + % (old_max_accel, old_minimum_cruise_ratio)) # Restore input shaper if it was disabled for resonance testing if input_shaper is not None: input_shaper.enable_shaping() diff --git a/klippy/toolhead.py b/klippy/toolhead.py index ce014365c..d386ec8e9 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -217,12 +217,19 @@ def __init__(self, config): # Velocity and acceleration control self.max_velocity = config.getfloat('max_velocity', above=0.) self.max_accel = config.getfloat('max_accel', above=0.) - self.requested_accel_to_decel = config.getfloat( - 'max_accel_to_decel', self.max_accel * 0.5, above=0.) - self.max_accel_to_decel = self.requested_accel_to_decel + self.min_cruise_ratio = config.getfloat('minimum_cruise_ratio', None, + below=1., minval=0.) + if self.min_cruise_ratio is None: + self.min_cruise_ratio = 0.5 + req_accel_to_decel = config.getfloat('max_accel_to_decel', None, + above=0.) + if req_accel_to_decel is not None: + config.deprecate('max_accel_to_decel') + self.min_cruise_ratio = 1. - min(1., (req_accel_to_decel + / self.max_accel)) self.square_corner_velocity = config.getfloat( 'square_corner_velocity', 5., minval=0.) - self.junction_deviation = 0. + self.junction_deviation = self.max_accel_to_decel = 0. self._calc_junction_deviation() # Input stall detection self.check_stall_time = 0. @@ -561,7 +568,7 @@ def get_status(self, eventtime): 'position': self.Coord(*self.commanded_pos), 'max_velocity': self.max_velocity, 'max_accel': self.max_accel, - 'max_accel_to_decel': self.requested_accel_to_decel, + 'minimum_cruise_ratio': self.min_cruise_ratio, 'square_corner_velocity': self.square_corner_velocity}) return res def _handle_shutdown(self): @@ -600,8 +607,7 @@ def get_max_velocity(self): def _calc_junction_deviation(self): scv2 = self.square_corner_velocity**2 self.junction_deviation = scv2 * (math.sqrt(2.) - 1.) / self.max_accel - self.max_accel_to_decel = min(self.requested_accel_to_decel, - self.max_accel) + self.max_accel_to_decel = self.max_accel * (1. - self.min_cruise_ratio) def cmd_G4(self, gcmd): # Dwell delay = gcmd.get_float('P', 0., minval=0.) / 1000. @@ -615,29 +621,34 @@ def cmd_SET_VELOCITY_LIMIT(self, gcmd): max_accel = gcmd.get_float('ACCEL', None, above=0.) square_corner_velocity = gcmd.get_float( 'SQUARE_CORNER_VELOCITY', None, minval=0.) - requested_accel_to_decel = gcmd.get_float( - 'ACCEL_TO_DECEL', None, above=0.) + min_cruise_ratio = gcmd.get_float( + 'MINIMUM_CRUISE_RATIO', None, minval=0., below=1.) + if min_cruise_ratio is None: + req_accel_to_decel = gcmd.get_float('ACCEL_TO_DECEL', + None, above=0.) + if req_accel_to_decel is not None and max_accel is not None: + min_cruise_ratio = 1. - min(1., req_accel_to_decel / max_accel) + elif req_accel_to_decel is not None and max_accel is None: + min_cruise_ratio = 1. - min(1., (req_accel_to_decel + / self.max_accel)) if max_velocity is not None: self.max_velocity = max_velocity if max_accel is not None: self.max_accel = max_accel if square_corner_velocity is not None: self.square_corner_velocity = square_corner_velocity - if requested_accel_to_decel is not None: - self.requested_accel_to_decel = requested_accel_to_decel + if min_cruise_ratio is not None: + self.min_cruise_ratio = min_cruise_ratio self._calc_junction_deviation() msg = ("max_velocity: %.6f\n" "max_accel: %.6f\n" - "max_accel_to_decel: %.6f\n" + "minimum_cruise_ratio: %.6f\n" "square_corner_velocity: %.6f" % ( self.max_velocity, self.max_accel, - self.requested_accel_to_decel, - self.square_corner_velocity)) + self.min_cruise_ratio, self.square_corner_velocity)) self.printer.set_rollover_info("toolhead", "toolhead: %s" % (msg,)) - if (max_velocity is None and - max_accel is None and - square_corner_velocity is None and - requested_accel_to_decel is None): + if (max_velocity is None and max_accel is None + and square_corner_velocity is None and min_cruise_ratio is None): gcmd.respond_info(msg, log=False) def cmd_M204(self, gcmd): # Use S for accel