добавлена щетка, смещение тача, переписан авд, праймлайн на тпу

This commit is contained in:
2025-04-01 02:11:44 +03:00
parent 228d45b7bf
commit 25091da86b
9 changed files with 1212 additions and 2 deletions

View File

@@ -0,0 +1,242 @@
#########################################
########## ADAPTIVE BED MESH ############
#########################################
# Written by Frix_x#0161 #
# @version: 4.0
# CHANGELOG:
# v4.0: - patched and re-simplified the macro to work with latest Klipper changes: zero_reference_position is much more constrained and all the fancy stuff
# that was used in the past for homing over the RRI with virtual probe or Z calibration plugin is not possible anymore. Now homing must be done at
# fixed zero_reference_poisition and can't be dynamic anymore (but it's also simpler)
# - this change also allow the mesh to have even probe point now for more flexibility
# v3.0: - added the use of [exclude_object] tags to extract the first layer bounding box (many thanks to Kyleisah for the excellent idea and inspiration)
# the macro is still fully compatible with the old way using the SIZE parameter: it will use it if specified, or else
# fallback to the [exclude_object] method and if both are not available, it will do a full and normal bed mesh as usual.
# - also added a FORCE_MESH parameter to mesh even for very small parts
# - removed the RRI that was always added put in the BED_MESH_CALIBRATE call. Now it's added only when there is one defined in the [bed_mesh] section
# v2.3: moved the install notes into a proper markdown file in: docs > features > adaptive_bed_mesh.md
# v2.2: removed the requirement to set mesh_pps in the [bed_mesh] section. It's now again optional as it should be
# v2.1: fix for the nominal mesh (when no SIZE parameter is used or SIZE=0_0_0_0)
# v2.0: split in multple macros to be able to use the center point in the z calibration bed probing position before doing the mesh
# v1.1: fix for a bug when parsing string when using uppercase letters in the [bed_mesh] section
# v1.0: first adaptive bed mesh macro
# -------------------------------------------------------------------------------------------------------------------------
# If you want to use it into your own config, please install it as a standalone macro as described in the
# installation section of this file: docs > features > adaptive_bed_mesh.md
# -------------------------------------------------------------------------------------------------------------------------
### What is it ? ###
# The adaptive bed mesh is simple: it's a normal bed mesh, but only "where" and "when" it's necessary.
# Sometime I print small parts, sometime I print full plates and I like to get a precise bed_mesh (like 9x9 or more). However, it take a
# lot of time and it's useless to probe all the plate for only a 5cm² part. So this is where the adaptive bed mesh is helping:
# 1. It get the corners coordinates of the fisrt layer surface either from the slicer or the [exclude_object] tags
# 2. It compute a new set of points to probe on this new zone to get at least the same precision as your standard bed mesh. For example, if
# a normal bed mesh is set to 9x9 for 300mm², it will then compute 3x3 for a 100mm² surface. Also if for whatever reason your parts are in
# the corner of the build plate (like for a damaged PEI in the center), it will follow them to probe this exact area.
# 3. To go further, it will not do any bed_mesh if there is less than 3x3 points to probe (very small part alone) and choose/change the
# algorithm (bicubic/lagrange) depending of the size and shape of the mesh computed (like 3x3 vs 3x9)
# Feel free to ping me on Discord (Frix_x#0161) if you need help or have any comments to improve it :)
# ===========================================================================================================
# DO NOT MODIFY THOSE VARIABLES (they are used internaly by the adaptive bed mesh macro)
[gcode_macro _ADAPTIVE_MESH_VARIABLES]
variable_ready: False
variable_do_mesh: False
variable_do_nominal: False
variable_mesh_min: 0,0
variable_mesh_max: 0,0
variable_probe_count: 0,0
variable_algo: "bicubic"
gcode:
[gcode_macro COMPUTE_MESH_PARAMETERS]
description: Compute the mesh parameters and store them for later use
gcode:
# 1 ----- GET ORIGINAL BEDMESH PARAMS FROM CONFIG ----------------------
{% set xMinConf, yMinConf = printer["configfile"].config["bed_mesh"]["mesh_min"].split(',')|map('trim')|map('int') %}
{% set xMaxConf, yMaxConf = printer["configfile"].config["bed_mesh"]["mesh_max"].split(',')|map('trim')|map('int') %}
{% set xProbeCntConf, yProbeCntConf = printer["configfile"].config["bed_mesh"]["probe_count"].split(',')|map('trim')|map('int') %}
{% set algo = printer["configfile"].config["bed_mesh"]["algorithm"]|lower %}
{% set xMeshPPS, yMeshPPS = (printer["configfile"].config["bed_mesh"]["mesh_pps"]|default('2,2')).split(',')|map('trim')|map('int') %}
{% set margin = params.MARGIN|default(5)|int %} # additional margin to mesh around the first layer
{% set force_mesh = params.FORCE_MESH|default(False) %} # force the mesh even if it's a small part (ie. computed less than 3x3)
# 2 ----- GET FIRST LAYER COORDINATES and SIZE -------------------------------------
# If the SIZE parameter is defined and not a dummy placeholder, we use it to do the adaptive bed mesh logic
{% set coordinatesFound = false %}
{% if params.SIZE is defined and params.SIZE != "0_0_0_0" %}
RESPOND MSG="Got a SIZE parameter for the adaptive bed mesh"
{% set xMinSpec, yMinSpec, xMaxSpec, yMaxSpec = params.SIZE.split('_')|map('trim')|map('int') %}
{% set coordinatesFound = true %}
{% elif printer.exclude_object is defined %}
{% if printer.exclude_object.objects %}
# Else if SIZE is not defined, we fallback to use the [exclude_object] tags
# This method is derived from Kyleisah KAMP repository: https://github.com/kyleisah/Klipper-Adaptive-Meshing-Purging)
RESPOND MSG="No SIZE parameter, using the [exclude_object] tags for the adaptive bed mesh"
{% set eo_points = printer.exclude_object.objects|map(attribute='polygon')|sum(start=[]) %}
{% set xMinSpec = eo_points|map(attribute=0)|min %}
{% set yMinSpec = eo_points|map(attribute=1)|min %}
{% set xMaxSpec = eo_points|map(attribute=0)|max %}
{% set yMaxSpec = eo_points|map(attribute=1)|max %}
{% set coordinatesFound = true %}
{% endif %}
{% endif %}
{% if not coordinatesFound %}
# If no SIZE parameter and no [exclude_object] tags, then we want to do a nominal bed mesh
# so nothing to do here...
RESPOND MSG="No info about the first layer coordinates, doing a nominal bed mesh instead of adaptive"
{% endif %}
# If the first layer size was correctly retrieved, we can do the adaptive bed mesh logic, else we
# fallback to the original and nominal BED_MESH_CALIBRATE function (full bed probing)
{% if xMinSpec and yMinSpec and xMaxSpec and yMaxSpec %}
# 3 ----- APPLY MARGINS ----------------------------------------------
# We use min/max function as we want it to be constrained by the original
# bedmesh size. This will avoid going outside the machine limits
{% set xMin = [xMinConf, (xMinSpec - margin)]|max %}
{% set xMax = [xMaxConf, (xMaxSpec + margin)]|min %}
{% set yMin = [yMinConf, (yMinSpec - margin)]|max %}
{% set yMax = [yMaxConf, (yMaxSpec + margin)]|min %}
# 4 ----- COMPUTE A NEW PROBE COUNT ----------------------------------
# The goal is to have at least the same precision as from the config. So we compute an equivalent number
# of probe points on each X/Y dimensions (distance between two points should be the same as in the config)
{% set xProbeCnt = ((xMax - xMin) * xProbeCntConf / (xMaxConf - xMinConf))|round(0, 'ceil')|int %}
{% set yProbeCnt = ((yMax - yMin) * yProbeCntConf / (yMaxConf - yMinConf))|round(0, 'ceil')|int %}
# Then, three possibilities :
# a) Both dimensions have less than 3 probe points : the bed_mesh is not needed as it's a small print (if not forced).
# b) If one of the dimension is less than 3 and the other is greater. The print looks to be elongated and
# need the adaptive bed_mesh : we add probing points to the small direction to reach 3 and be able to do it.
# c) If both direction are greater than 3, we need the adaptive bed_mesh and it's ok.
# At the end we control (according to Klipper bed_mesh method: "_verify_algorithm") that the computed probe_count is
# valid according to the choosen algorithm or change it if needed.
{% if xProbeCnt < 3 and yProbeCnt < 3 %}
{% if force_mesh %}
RESPOND MSG="Bed mesh forced (small part detected): meshing 3x3..."
{% set xProbeCnt = 3 %}
{% set yProbeCnt = 3 %}
{% set algo = "lagrange" %}
{% set mesh_min = "%d,%d"|format(xMin, yMin) %}
{% set mesh_max = "%d,%d"|format(xMax, yMax) %}
{% set probe_count = "%d,%d"|format(xProbeCnt, yProbeCnt) %}
RESPOND MSG="Computed mesh parameters: MESH_MIN={mesh_min} MESH_MAX={mesh_max} PROBE_COUNT={probe_count} ALGORITHM={algo}"
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=do_mesh VALUE={True}
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=do_nominal VALUE={False}
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=mesh_min VALUE='"{mesh_min}"'
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=mesh_max VALUE='"{mesh_max}"'
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=probe_count VALUE='"{probe_count}"'
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=algo VALUE='"{algo}"'
{% else %}
RESPOND MSG="Computed mesh parameters: none, bed mesh not needed for very small parts"
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=do_mesh VALUE={False}
{% endif %}
{% else %}
{% set xProbeCnt = [3, xProbeCnt]|max %}
{% set yProbeCnt = [3, yProbeCnt]|max %}
# Check of the probe points and interpolation algorithms according to Klipper code
{% if xMeshPPS != 0 or yMeshPPS != 0 %}
{% set probeCntMin = [xProbeCnt, yProbeCnt]|min %}
{% set probeCntMax = [xProbeCnt, yProbeCnt]|max %}
{% if algo == "lagrange" and probeCntMax > 6 %}
# Lagrange interpolation tends to oscillate when using more than 6 samples: swith to bicubic
{% set algo = "bicubic" %}
{% endif %}
{% if algo == "bicubic" and probeCntMin < 4 %}
{% if probeCntMax > 6 %}
# Impossible case: need to add probe point on the small axis to be >= 4 (we want 5 to keep it odd)
{% if xProbeCnt > yProbeCnt %}
{% set yProbeCnt = 5 %}
{% else %}
{% set xProbeCnt = 5 %}
{% endif %}
{% else %}
# In this case bicubic is not adapted (less than 4 points): switch to lagrange
{% set algo = "lagrange" %}
{% endif %}
{% endif %}
{% endif %}
# 5 ----- FORMAT THE PARAMETERS AND SAVE THEM ---------------------------
{% set mesh_min = "%d,%d"|format(xMin, yMin) %}
{% set mesh_max = "%d,%d"|format(xMax, yMax) %}
{% set probe_count = "%d,%d"|format(xProbeCnt, yProbeCnt) %}
RESPOND MSG="Computed mesh parameters: MESH_MIN={mesh_min} MESH_MAX={mesh_max} PROBE_COUNT={probe_count} ALGORITHM={algo}"
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=do_mesh VALUE={True}
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=do_nominal VALUE={False}
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=mesh_min VALUE='"{mesh_min}"'
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=mesh_max VALUE='"{mesh_max}"'
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=probe_count VALUE='"{probe_count}"'
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=algo VALUE='"{algo}"'
{% endif %}
{% else %}
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=do_mesh VALUE={True}
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=do_nominal VALUE={True}
{% endif %}
# Finaly save in the variables that we already computed the values
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=ready VALUE={True}
[gcode_macro ADAPTIVE_BED_MESH]
description: Perform a bed mesh, but only where and when it's needed
gcode:
{% set ready = printer["gcode_macro _ADAPTIVE_MESH_VARIABLES"].ready %}
{% if not 'xyz' in printer.toolhead.homed_axes %}
{ action_raise_error("Must Home printer first!") }
{% endif %}
# If the parameters where computed, we can do the mesh by calling the _DO_ADAPTIVE_MESH
{% if ready %}
_DO_ADAPTIVE_MESH
# If the parameters where not computed prior to the ADAPTIVE_BED_MESH call, we call the COMPUTE_MESH_PARAMETERS
# macro first and then call the _DO_ADAPTIVE_MESH macro after it
{% else %}
RESPOND MSG="Adaptive bed mesh: parameters not already computed, automatically calling the COMPUTE_MESH_PARAMETERS macro prior to the mesh"
COMPUTE_MESH_PARAMETERS {rawparams}
M400 # mandatory to flush the gcode buffer and be sure to use the last computed parameters
_DO_ADAPTIVE_MESH
{% endif %}
[gcode_macro _DO_ADAPTIVE_MESH]
gcode:
# 1 ----- POPULATE BEDMESH PARAMS FROM SAVED VARIABLES ----------------------
{% set do_mesh = printer["gcode_macro _ADAPTIVE_MESH_VARIABLES"].do_mesh %}
{% set do_nominal = printer["gcode_macro _ADAPTIVE_MESH_VARIABLES"].do_nominal %}
{% set mesh_min = printer["gcode_macro _ADAPTIVE_MESH_VARIABLES"].mesh_min %}
{% set mesh_max = printer["gcode_macro _ADAPTIVE_MESH_VARIABLES"].mesh_max %}
{% set probe_count = printer["gcode_macro _ADAPTIVE_MESH_VARIABLES"].probe_count %}
{% set algo = printer["gcode_macro _ADAPTIVE_MESH_VARIABLES"].algo %}
# 2 --------- ADAPTIVE_BED_MESH LOGIC --------------------------------------
# If it's necessary to do a mesh
{% if do_mesh %}
# If it's a standard bed_mesh to be done
{% if do_nominal %}
RESPOND MSG="Adaptive bed mesh: nominal bed mesh"
BED_MESH_CALIBRATE
{% else %}
RESPOND MSG="Adaptive bed mesh: MESH_MIN={mesh_min} MESH_MAX={mesh_max} PROBE_COUNT={probe_count} ALGORITHM={algo}"
BED_MESH_CALIBRATE MESH_MIN={mesh_min} MESH_MAX={mesh_max} PROBE_COUNT={probe_count} ALGORITHM={algo}
{% endif %}
{% else %}
RESPOND MSG="Adaptive bed mesh: no mesh to be done"
{% endif %}
# Set back the 'ready' parameter to false
SET_GCODE_VARIABLE MACRO=_ADAPTIVE_MESH_VARIABLES VARIABLE=ready VALUE={False}