screws_tilt_adjust: Add DIRECTION parameter to SCREWS_TILT_CALCULATE (#4357)

Signed-off-by: Matthew Lloyd <github@matthewlloyd.net>
This commit is contained in:
Matthew Lloyd 2021-06-22 15:18:05 -04:00 committed by GitHub
parent f1091a484b
commit c2907c998c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 27 deletions

View File

@ -456,12 +456,13 @@ The following commands are available when the
[screws_tilt_adjust config section](Config_Reference.md#screws_tilt_adjust)
is enabled (also see the
[manual level guide](Manual_Level.md#adjusting-bed-leveling-screws-using-the-bed-probe)):
- `SCREWS_TILT_CALCULATE [<probe_parameter>=<value>]`: This command
will invoke the bed screws adjustment tool. It will command the
- `SCREWS_TILT_CALCULATE [DIRECTION=CW|CCW] [<probe_parameter>=<value>]`:
This command will invoke the bed screws adjustment tool. It will command the
nozzle to different locations (as defined in the config file)
probing the z height and calculate the number of knob turns to
adjust the bed level. See the PROBE command for details on the
optional probe parameters.
adjust the bed level. If DIRECTION is specified, the knob turns will all
be in the same direction, clockwise (CW) or counterclockwise (CCW).
See the PROBE command for details on the optional probe parameters.
IMPORTANT: You MUST always do a G28 before using this command.
## Z Tilt

View File

@ -163,17 +163,18 @@ screw_thread: CW-M3
```
The screw1 is always the reference point for the others, so the system
assumes that screw1 is in the correct height. Always run `G28` first
assumes that screw1 is at the correct height. Always run `G28` first
and then run `SCREWS_TILT_CALCULATE` - it should produce output
similar to:
```
Send: G28
Recv: ok
Send: SCREWS_TILT_CALCULATE
Recv: // front left screw (Base): X -5.0, Y 30.0, Z 2.48750
Recv: // front right screw : X 155.0, Y 30.0, Z 2.36000 : Adjust -> CW 01:15
Recv: // rear right screw : X 155.0, Y 190.0, Z 2.71500 : Adjust -> CCW 00:50
Recv: // read left screw : X -5.0, Y 190.0, Z 2.47250 : Adjust -> CW 00:02
Recv: // 01:20 means 1 full turn and 20 minutes, CW=clockwise, CCW=counter-clockwise
Recv: // front left screw (base) : x=-5.0, y=30.0, z=2.48750
Recv: // front right screw : x=155.0, y=30.0, z=2.36000 : adjust CW 01:15
Recv: // rear right screw : y=155.0, y=190.0, z=2.71500 : adjust CCW 00:50
Recv: // read left screw : x=-5.0, y=190.0, z=2.47250 : adjust CW 00:02
Recv: ok
```
This means that:
@ -198,3 +199,12 @@ the mesh was created. For example, `SCREWS_TILT_CALCULATE MAX_DEVIATION=0.01`
can be added to the custom start gcode of the slicer before the mesh is loaded.
It will abort the print if the configured limit is exceeded (0.01mm in this
example), giving the user a chance to adjust the screws and restart the print.
The `DIRECTION` parameter is useful if you can turn your bed adjustment
screws in one direction only. For example, you might have screws that start
tightened in their lowest (or highest) possible position, which can only be
turned in a single direction, to raise (or lower) the bed. If you can only
turn the screws clockwise, run `SCREWS_TILT_CALCULATE DIRECTION=CW`. If you can
only turn them counter-clockwise, run `SCREWS_TILT_CALCULATE DIRECTION=CCW`.
A suitable reference point will be chosen such that the bed can be leveled
by turning all the screws in the given direction.

View File

@ -1,6 +1,7 @@
# Helper script to adjust bed screws tilt using Z probe
#
# Copyright (C) 2019 Rui Caridade <rui.mcbc@gmail.com>
# Copyright (C) 2021 Matthew Lloyd <github@matthewlloyd.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import math
@ -53,44 +54,64 @@ class ScrewsTiltAdjust:
def cmd_SCREWS_TILT_CALCULATE(self, gcmd):
self.max_diff = gcmd.get_float("MAX_DEVIATION", None)
# Option to force all turns to be in the given direction (CW or CCW)
direction = gcmd.get("DIRECTION", default=None)
if direction is not None:
direction = direction.upper()
if direction not in ('CW', 'CCW'):
raise gcmd.error(
"Error on '%s': DIRECTION must be either CW or CCW" % (
gcmd.get_commandline(),))
self.direction = direction
self.probe_helper.start_probe(gcmd)
def probe_finalize(self, offsets, positions):
# Factors used for CW-M3, CCW-M3, CW-M4, CCW-M4, CW-M5 and CCW-M5
threads_factor = {0: 0.5, 1: 0.5, 2: 0.7, 3: 0.7, 4: 0.8, 5: 0.8}
is_clockwise_thread = (self.thread & 1) == 0
screw_diff = []
# Process the read Z values and
for i, screw in enumerate(self.screws):
if i == 0:
# First screw is the base position used for comparison
z_base = positions[i][2]
coord_base, name_base = screw
# Show the results
self.gcode.respond_info("%s (Base): X %.1f, Y %.1f, Z %.5f" %
(name_base, coord_base[0],
coord_base[1], z_base))
# Process the read Z values
if self.direction is not None:
# Lowest or highest screw is the base position used for comparison
use_max = ((is_clockwise_thread and self.direction == 'CW')
or (not is_clockwise_thread and self.direction == 'CCW'))
min_or_max = max if use_max else min
i_base, z_base = min_or_max(
enumerate([pos[2] for pos in positions]), key=lambda (i, z): z)
else:
# Calculate how knob must me adjusted for other positions
# First screw is the base position used for comparison
i_base, z_base = 0, positions[0][2]
# Provide the user some information on how to read the results
self.gcode.respond_info("01:20 means 1 full turn and 20 minutes, "
"CW=clockwise, CCW=counter-clockwise")
for i, screw in enumerate(self.screws):
z = positions[i][2]
coord, name = screw
if i == i_base:
# Show the results
self.gcode.respond_info(
"%s : x=%.1f, y=%.1f, z=%.5f" %
(name + ' (base)', coord[0], coord[1], z))
else:
# Calculate how knob must be adjusted for other positions
diff = z_base - z
screw_diff.append(abs(diff))
if abs(diff) < 0.001:
adjust = 0
else:
adjust = diff / threads_factor.get(self.thread, 0.5)
if (self.thread & 1) == 1:
sign = "CW" if adjust < 0 else "CCW"
if is_clockwise_thread:
sign = "CW" if adjust >= 0 else "CCW"
else:
sign = "CCW" if adjust < 0 else "CW"
sign = "CCW" if adjust >= 0 else "CW"
adjust = abs(adjust)
full_turns = math.trunc(adjust)
decimal_part = adjust - full_turns
minutes = round(decimal_part * 60, 0)
# Show the results
self.gcode.respond_info("%s : X %.1f, Y %.1f, Z %.5f : "
"Adjust -> %s %02d:%02d" %
(name, coord[0], coord[1], z, sign,
abs(full_turns), abs(minutes)))
self.gcode.respond_info(
"%s : x=%.1f, y=%.1f, z=%.5f : adjust %s %02d:%02d" %
(name, coord[0], coord[1], z, sign, full_turns, minutes))
if self.max_diff and any((d > self.max_diff) for d in screw_diff):
raise self.gcode.error(
"bed level exceeds configured limits ({}mm)! " \