-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbed_mesh.cfg
134 lines (118 loc) · 9.31 KB
/
bed_mesh.cfg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#########################################
########## ADAPTIVE BED MESH ############
#########################################
# Written by Frix_x#0161 #
### 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 in the center. So this is where the adaptive bed mesh is helping:
# 1. It get the corners coordinates of the fisrt layer surface from the slicer
# 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. As the probed point computed are odd, it will also compute the new relative reference index point in the center of the zone
# 4. To go further, the macro 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)
### Installation ###
# 1. You need to change some custom settings in your slicer:
# a. SuperSlicer is easy: add in your custom g_code PRINT_START macro the SIZE argument like this:
# PRINT_START [all your shit..] SIZE={first_layer_print_min[0]}_{first_layer_print_min[1]}_{first_layer_print_max[0]}_{first_layer_print_max[1]}
# b. Cura is a bit more tricky as you need to install the post process plugin by frankbags called MeshPrintSize.py.
# In Cura menu, click Help > Show configuration folder. Copy the python script from the following link into the plugins folder: https://gist.github.com/frankbags/c85d37d9faff7bce67b6d18ec4e716ff#file-meshprintsize-py
# Then restart Cura and select in the menu: Extensions > Post processing > select Mesh Print Size
# At the end, change your custom g_code PRINT_START macro the SIZE argument like this:
# PRINT_START [all your shit..] SIZE=%MINX%_%MINY%_%MAXX%_%MAXY%
# 2. In klipper, configure a normal [bed_mesh] section in your config as you want for your machine (it will be the base to compute the new adaptive bed mesh). Keep
# in mind that you can push the precision a little bit with a mesh of 9x9 for example as not all the points will be probed.
# 3. VERY IMPORTANT CHECKS:
# a. Be sure to put the "mesh_pps" entry in the [bed_mesh] section. You can choose what you want or let it to default, but even if it's optional for Klipper, it's mandatory
# to really specify it in your config for my macro to work correctly.
# b. Also check that the mesh_min, mesh_max, probe_count and mesh_pps configs entry in your [bed_mesh] section are specified using double numbers like "probe_count: 9,9"
# as my macro is waiting for TWO numbers and will fail if there is only one specified at thoose positions.
# 4. In your PRINT_START macro definition, get the SIZE argument and pass it to the ADAPTIVE_BED_MESH to start the probing sequence like so:
# {% set FL_SIZE = params.SIZE|default("0_0_0_0")|string %}
# ADAPTIVE_BED_MESH SIZE={FL_SIZE}
# 5. Optional: my macro is using the RESPOND command for debugging purposes: add the [respond] section to your config or delete all the RESPOND lines in my macro
# Feel free to ping me on Discord (Frix_x#0161) if you need help or have any comments to improve it :)
[gcode_macro ADAPTIVE_BED_MESH]
description: Perform a bed mesh, but only where and when it's needed
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"] %}
{% set xMeshPPS, yMeshPPS = printer["configfile"].config["bed_mesh"]["mesh_pps"].split(',')|map('trim')|map('int') %}
# If the SIZE parameter is defined and set not a dummy placeholder, we do the adaptive
# bed mesh logic. If it's ommited, we still do the original BED_MESH_CALIBRATE function
{% if params.SIZE is defined and params.SIZE != "0_0_0_0" %}
# 2 ----- GET MESH SIZE AND MARGIN FROM MACRO CALL --------------------
{% set xMinSpec, yMinSpec, xMaxSpec, yMaxSpec = params.SIZE.split('_')|map('trim')|map('int') %}
{% set margin = params.MARGIN|default(5)|int %}
# 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.
# 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 probe 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 %}
RESPOND MSG="Adaptive bed mesh: mesh not needed"
{% else %}
{% set xProbeCnt = [3, xProbeCnt]|max %}
{% set yProbeCnt = [3, yProbeCnt]|max %}
# We verify that the number of probe points on each axis is odd or add
# one to it. This is to have a relative_reference_index point at the center of the mesh
{% if xProbeCnt % 2 == 0 %}
{% set xProbeCnt = xProbeCnt + 1 %}
{% endif %}
{% if yProbeCnt % 2 == 0 %}
{% set yProbeCnt = yProbeCnt + 1 %}
{% endif %}
# 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 ----- COMPUTE THE RELATIVE_REFERENCE_INDEX POINT --------------------
{% set rRefIndex = (((xProbeCnt * yProbeCnt) - 1) / 2)|int %}
# 6 ----- FORMAT THE PARAMETERS TO CALL BED_MESH_CALIBRATE --------------
{% 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="Adaptive bed mesh: MESH_MIN={mesh_min} MESH_MAX={mesh_max} PROBE_COUNT={probe_count} RELATIVE_REFERENCE_INDEX={rRefIndex} ALGORITHM={algo}"
BED_MESH_CALIBRATE MESH_MIN={mesh_min} MESH_MAX={mesh_max} PROBE_COUNT={probe_count} RELATIVE_REFERENCE_INDEX={rRefIndex} ALGORITHM={algo}
{% endif %}
{% else %}
RESPOND MSG="Adaptive bed mesh: nominal bed mesh"
BED_MESH_CALIBRATE
{% endif %}