Skip to content

Instantly share code, notes, and snippets.

@ChipCE
Last active Jun 25, 2022
Embed
What would you like to do?
Klipper bed mesh on print area only macro install guide

Klipper mesh on print area only install guide

What this macro do

  • This macro will dymanic change the bed_mesh area based on the size of the printed part. The fw will only probe on the area that the part will be printed (plus mesh_area_offset value)

Setup guide

  • (1) Add the following macrro to your printer config, this will replace the default BED_MESH_CALIBRATE command.
[gcode_macro BED_MESH_CALIBRATE]
rename_existing: BED_MESH_CALIBRATE_BASE
; gcode parameters
variable_parameter_AREA_START : 0,0
variable_parameter_AREA_END : 0,0
; the clearance between print area and probe area 
variable_mesh_area_offset : 5.0
; number of sample per probe point
variable_probe_samples : 2
; minimum probe count
variable_min_probe_count : 3
; scale up the probe count, should be 1.0 ~ < variable_max_probe_count/variable_min_probe_count
variable_probe_count_scale_factor : 1.0
gcode:
    {% if params.AREA_START and params.AREA_END %}
        {% set bedMeshConfig = printer["configfile"].config["bed_mesh"] %}
        {% set safe_min_x = bedMeshConfig.mesh_min.split(",")[0]|float %}
        {% set safe_min_y = bedMeshConfig.mesh_min.split(",")[1]|float %}
        {% set safe_max_x = bedMeshConfig.mesh_max.split(",")[0]|float %}
        {% set safe_max_y = bedMeshConfig.mesh_max.split(",")[1]|float %}

        {% set area_min_x = params.AREA_START.split(",")[0]|float %}
	{% set area_min_y = params.AREA_START.split(",")[1]|float %}
	{% set area_max_x = params.AREA_END.split(",")[0]|float %}
	{% set area_max_y = params.AREA_END.split(",")[1]|float %}

	{% if bedMeshConfig.probe_count.split(",")|length == 2 %}
            {% set meshPointX = bedMeshConfig.probe_count.split(",")[0]|int %}
            {% set meshPointY = bedMeshConfig.probe_count.split(",")[1]|int %}
        {% else %}
            {% set meshPointX = bedMeshConfig.probe_count.split(",")[0]|int %}
            {% set meshPointY = bedMeshConfig.probe_count.split(",")[0]|int %}
        {% endif %}

	{% set meshMaxPointX = meshPointX %}
	{% set meshMaxPointY = meshPointY %}


        {% if (area_min_x < area_max_x) and (area_min_y < area_max_y) %}
            {% if area_min_x - mesh_area_offset >=  safe_min_x %}
                {% set area_min_x = area_min_x - mesh_area_offset %}
            {% else %}
                {% set area_min_x = safe_min_x %}
            {% endif %}

            {% if area_min_y - mesh_area_offset >=  safe_min_y %}
                {% set area_min_y = area_min_y - mesh_area_offset %}
            {% else %}
                {% set area_min_y = safe_min_y %}
            {% endif %}

            {% if area_max_x + mesh_area_offset <=  safe_max_x %}
                {% set area_max_x = area_max_x + mesh_area_offset %}
            {% else %}
                {% set area_max_x = safe_max_x %}
            {% endif %}

            {% if area_max_y + mesh_area_offset <=  safe_max_y %}
                {% set area_max_y = area_max_y + mesh_area_offset %}
            {% else %}
                {% set area_max_y = safe_max_y %}
            {% endif %}

            {% set meshPointX = (meshPointX * (area_max_x - area_min_x) / (safe_max_x - safe_min_x) * probe_count_scale_factor)|round(0)|int %}
            {% if meshPointX < min_probe_count %}
                {% set meshPointX = min_probe_count %}
            {% endif %}
	    {% if meshPointX > meshMaxPointX %}
                {% set meshPointX = meshMaxPointX %}
            {% endif %}

            {% set meshPointY = (meshPointY * (area_max_y -area_min_y ) / (safe_max_y - safe_min_y) * probe_count_scale_factor )|round(0)|int %}
            {% if meshPointY < min_probe_count %}
                {% set meshPointY = min_probe_count %}
            {% endif %}
	    {% if meshPointY > meshMaxPointY %}
                {% set meshPointY = meshMaxPointY %}
            {% endif %}

            BED_MESH_CALIBRATE_BASE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} samples={probe_samples|int}
        {% else %}
            BED_MESH_CALIBRATE_BASE
        {% endif %}
    {% else %}
        BED_MESH_CALIBRATE_BASE
    {% endif %}
  • (2) Go to slicer setting and replace the old bed mesh gcode the following command.

Prusa Slicer
BED_MESH_CALIBRATE AREA_START={first_layer_print_min[0]},{first_layer_print_min[1]} AREA_END={first_layer_print_max[0]},{first_layer_print_max[1]}

Ideal maker
BED_MESH_CALIBRATE AREA_START={print_pos_min_x},{print_pos_min_y} AREA_END={print_pos_max_x},{print_pos_max_y}

Cura slicer
BED_MESH_CALIBRATE AREA_START=%MINX%,%MINY% AREA_END=%MAXX%,%MAXY%

*(Cura slicer plugin) To make the macro to work in Cura slicer, you need to install the post process plugin by frankbags - In cura menu Help -> Show configuration folder. - Copy the python script from the above link in to scripts folder. - Restart Cura - In cura menu Extensions -> Post processing -> Modify G-Code and select Mesh Print Size

For user using single command START_PRINT

  • (*) If you use single command start gcode like START_PRINT BED_TEMP={material_bed_temperature_layer_0} EXTRUDER_TEMP={material_print_temperature_layer_0} .You might need to add parameter parsing to BED_MESH_CALIBRATE inside START_PRINT. This is an example, also check my macro sample
[gcode_macro START_PRINT]
variable_parameter_EXTRUDER_TEMP: 190
variable_parameter_BED_TEMP: 60
; gcode parameters for area bed mesh
variable_parameter_AREA_START : 0,0
variable_parameter_AREA_END : 0,0
gcode:
    # preheat, homing, etc
    BED_MESH_CALIBRATE AREA_START={params.AREA_START|default("0,0")} AREA_END={params.AREA_END|default("0,0")}
    # the rest of your start macro here

And you will need to change Slicer start gcode to this

  • Cura: START_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0} AREA_START=%MINX%,%MINY% AREA_END=%MAXX%,%MAXY%
  • Prusa slicer: START_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature] AREA_START={first_layer_print_min[0]},{first_layer_print_min[1]} AREA_END={first_layer_print_max[0]},{first_layer_print_max[1]}
@Dlugin2
Copy link

Dlugin2 commented Feb 25, 2022

Guys! I'm using klicky and macros from here https://github.com/jlas1/Klicky-Probe/tree/main/Klipper_macros. Where should I paste Bed Mesh Calibrate macro? Do I need make some changes?

@moedope
Copy link

moedope commented Mar 2, 2022

Guys! I'm using klicky and macros from here https://github.com/jlas1/Klicky-Probe/tree/main/Klipper_macros. Where should I paste Bed Mesh Calibrate macro? Do I need make some changes?

im also using klicky, have you got this to work?

@lithiumconrad
Copy link

lithiumconrad commented Mar 3, 2022

Guys! I'm using klicky and macros from here https://github.com/jlas1/Klicky-Probe/tree/main/Klipper_macros. Where should I paste Bed Mesh Calibrate macro? Do I need make some changes?

Same here

@thbl
Copy link

thbl commented Mar 14, 2022

im gettings this error https://pastebin.com/BbLThQZ4
any suggestions @ChipCE @ChipCE

@ge123
Copy link

ge123 commented Mar 18, 2022

I'm having the same problem. Something changed and now it doesn't work. There was a recent Klipper update. I wonder if it broke it.

@ChipCE
Copy link
Author

ChipCE commented Mar 18, 2022

@thbl @ge123 Change variable_min_probe_count : 3 to 4

@ge123
Copy link

ge123 commented Mar 23, 2022

@ChipCE Thank you for helping me with this problem. I changed variable_min_probe_count to 4. The next file I printed worked well, but after that, I started getting the error again. Do you have any other suggestions?

Thanks!

@ge123
Copy link

ge123 commented Mar 24, 2022

I've been doing more tests, and it seems that the macro works for some files and not for others. I'm adding part of klippy.log below. Should I keep increasing variable_min_probe_count? What does variable_probe_count_scale_factor do?

Generating new points...
bed_mesh: generated points
Index | Tool Adjusted | Probe
0 | (121.3, 100.7) | (121.3, 120.5)
1 | (140.4, 100.7) | (140.4, 120.5)
2 | (159.5, 100.7) | (159.5, 120.5)
3 | (178.6, 100.7) | (178.6, 120.5)
4 | (178.6, 120.4) | (178.6, 140.2)
5 | (159.5, 120.4) | (159.5, 140.2)
6 | (140.4, 120.4) | (140.4, 140.2)
7 | (121.3, 120.4) | (121.3, 140.2)
8 | (121.3, 140.1) | (121.3, 159.8)
9 | (140.4, 140.1) | (140.4, 159.8)
10 | (159.5, 140.1) | (159.5, 159.8)
11 | (178.6, 140.1) | (178.6, 159.8)
12 | (178.6, 159.8) | (178.6, 179.5)
13 | (159.5, 159.8) | (159.5, 179.5)
14 | (140.4, 159.8) | (140.4, 179.5)
15 | (121.3, 159.8) | (121.3, 179.5)
Internal error on command:"BED_MESH_CALIBRATE_BASE"
Traceback (most recent call last):
File "/home/pi/klipper/klippy/gcode.py", line 198, in _process_commands
handler(gcmd)
File "/home/pi/klipper/klippy/gcode.py", line 135, in
func = lambda params: origfunc(self._get_extended_params(params))
File "/home/pi/klipper/klippy/gcode.py", line 135, in
func = lambda params: origfunc(self._get_extended_params(params))
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 601, in cmd_BED_MESH_CALIBRATE
self.update_config(gcmd)
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 572, in update_config
self.print_generated_points(gcmd.respond_info)
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 402, in print_generated_points
% (rri, self.points[rri][0], self.points[rri][1]))

@noahliketheark
Copy link

noahliketheark commented Apr 2, 2022

Any idea how I can pass "median" as a variable to keep with the theme? This has relative index auto calculated and redundant probing.

#####################################################################################
############################### Probe Print Area ###############################
#####################################################################################

[gcode_macro BED_MESH_CALIBRATE]
rename_existing: BED_MESH_CALIBRATE_BASE
; gcode parameters
variable_parameter_AREA_START : 51,38
variable_parameter_AREA_END : 0,0
; the clearance between print area and probe area
variable_mesh_area_offset : 1.0
; minimum probe count
variable_min_probe_count : 4
; scale up the probe count, should be 1.0 ~ < variable_max_probe_count/variable_min_probe_count
variable_probe_count_scale_factor : 1.0
; number of sample per probe point
variable_probe_samples=3
; distance to lift the toolhead between each sample
variable_probe_sample_retract_dist=5.0
; calculation method when sampling more than once
variable_probe_samples_result=median
; maximum Z distance that a sample may differ from other, default is 0.100 mm
variable_probe_samples_tolerance=0.015
; number of times to retry if a sample is found that exceeds samples_tolerance
variable_probe_samples_tolerance_retries=3
gcode:
...
{% set referenceIndex = (meshPointX * meshPointY / 2 - 1 )|round(0)|int %}
BED_MESH_CALIBRATE_BASE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} relative_reference_index={referenceIndex} samples={probe_samples|int} sample_retract_dist={probe_sample_retract_dist|int} samples_result={probe_samples_result|'XYZ' %} samples_tolerance={probe_samples_tolerance|float %} samples_tolerance_retries={probe_samples_tolerance_retries|int}
...

@ChipCE
Copy link
Author

ChipCE commented Apr 3, 2022

@noahliketheark This macro will not change the sample method of your probe. If your setting is median, it will keep that untouch.

in your probe/bltouch/or other probe setting, set samples_result: median

@ChipCE
Copy link
Author

ChipCE commented Apr 3, 2022

@ge123

variable_probe_count_scale_factor

it use to scale up the probe count (if you want more probe points even if the print area is small). For example with normal area scale down it will do 3x3 mesh, but with variable_probe_count_scale_factor=2 it will do (3 x variable_probe_count_scale_factor)x(3 x variable_probe_count_scale_factor) -> 6x6 mesh.

@diegomarino
Copy link

diegomarino commented Apr 3, 2022

Guys! I'm using klicky and macros from here https://github.com/jlas1/Klicky-Probe/tree/main/Klipper_macros. Where should I paste Bed Mesh Calibrate macro? Do I need make some changes?

I made it work. On this new macro you need 2 modifications:

  • This 3 lines at the beginning of the gcode section
gcode:
    _CheckProbe action=query
    G90
    Attach_Probe
 .............
  • A Dock_Probe before end the end of the file.

You can see in this screenshot the mesh generated for a benchy placed at the center of my 340x340 bed:
Screenshot 2022-04-03 172731

If you use the plugin to automatically calibrate the z-offset, you should update it to the latest version. There's a PR from a few weeks ago that gets the RRI from the latest mesh.

The only issue I see with using this macro is related to a famous plugin to automatically calibrate the z-offset. To generate a mesh, my config is:

[bed_mesh]
probe_count: 3,3
mesh_pps: 3,3
relative_reference_index: 4

This macro is using the center of it's mesh as the RRI (in this screenshot x=153.61 y=149.99, while the CALIBRATE_Z command of the plugin sets the RRI at the center of the default mesh (x=170 y=152 in my case)). It doesn't makes much of a difference when placing the model at the center of the bed and it is mostly flat (and probably it will be easy to fiddle with the start gcode to send the RRI coordinates as a parameter for the CALIBRATE_Z macro of the plugin), but JFYI.

@Taracair
Copy link

Taracair commented Apr 9, 2022

@ChipCE

Is there a way to increase the amount of probing points to, let's say 36 points (6x6) on area around 5x5cm? My bed is so warped I'd need even more detailed mesh.

Edit
Sorry, just found the answer few posts above to tune "variable_probe_count_scale_factor".

@noahliketheark
Copy link

noahliketheark commented Apr 11, 2022

@Taracair @ChipCE
What do you think of this? It forces odd mesh spacing to ensure a refence point in the exact center of the probed area. It defines the mesh based on a maximum distance between probe points up to a defined maximum, or 11 points (I wasn't sure how to code a loop).

[gcode_macro BED_MESH_CALIBRATE]
rename_existing: BED_MESH_CALIBRATE_BASE
variable_mesh_delta : 25 ;; distance between points
variable_x_mesh_max : 7 ;; max points on x-axis
variable_y_mesh_max : 7 ;; max points on y-axis
variable_mesh_area_offset : 0 ;; the clearance between print area and probe area
variable_parameter_AREA_START : 0,0 ;; gcode parameter to be defined by slicer
variable_parameter_AREA_END : 0,0 ;; gcode parameter to be defined by slicer
gcode=
{% if params.AREA_START and params.AREA_END %}

;; get [bltouch] config parameters
{% set BLTouchConfig = printer["configfile"].config["bltouch"] %}
{% set probe_samples = BLTouchConfig.samples|int %}
{% set probe_samples_tolerance_retries = BLTouchConfig.samples_tolerance_retries|int %}
{% set probe_samples_tolerance = BLTouchConfig.samples_tolerance|float %}
{% set probe_sample_retract_dist = BLTouchConfig.sample_retract_dist|float %}
{% set probe_samples_result = samples_result %}

;; get [bed_mesh] config parameters
{% set bedMeshConfig = printer["configfile"].config["bed_mesh"] %}
{% set mesh_algorithm = bedMeshConfig.algorithm %}
{% set mesh_bicubic_tension = bedMeshConfig.bicubic_tension|float %}
{% set safe_min_x = bedMeshConfig.mesh_min.split(",")[0]|float %}
{% set safe_min_y = bedMeshConfig.mesh_min.split(",")[1]|float %}
{% set safe_max_x = bedMeshConfig.mesh_max.split(",")[0]|float %}
{% set safe_max_y = bedMeshConfig.mesh_max.split(",")[1]|float %}
{% set meshPointX = bedMeshConfig.probe_count.split(",")[0]|int %}
{% set meshPointY = bedMeshConfig.probe_count.split(",")[1]|int %}
{% set meshMaxPointX = meshPointX %}
{% set meshMaxPointY = meshPointY %}

;; get print area min/max from slicer gcode
{% set area_min_x = params.AREA_START.split(",")[0]|float %}
{% set area_min_y = params.AREA_START.split(",")[1]|float %}
{% set area_max_x = params.AREA_END.split(",")[0]|float %}
{% set area_max_y = params.AREA_END.split(",")[1]|float %}

;; check if print area min/max from slicer gcode is compatable with [bed_mesh] min/max
{% if (area_min_x < area_max_x) and (area_min_y < area_max_y) %}
;; set probing area
{% if area_min_x - mesh_area_offset >= safe_min_x %}
{% set area_min_x = area_min_x - mesh_area_offset %}
{% else %}
{% set area_min_x = safe_min_x %}
{% endif %}
{% if area_min_y - mesh_area_offset >= safe_min_y %}
{% set area_min_y = area_min_y - mesh_area_offset %}
{% else %}
{% set area_min_y = safe_min_y %}
{% endif %}
{% if area_max_x + mesh_area_offset <= safe_max_x %}
{% set area_max_x = area_max_x + mesh_area_offset %}
{% else %}
{% set area_max_x = safe_max_x %}
{% endif %}
{% if area_max_y + mesh_area_offset <= safe_max_y %}
{% set area_max_y = area_max_y + mesh_area_offset %}
{% else %}
{% set area_max_y = safe_max_y %}
{% endif %}

;; set probe counts
{% if (area_max_x - area_min_x) / 3 < mesh_delta %}
{% set meshPointX = 3 %}
{% elif (area_max_x - area_min_x) / 5 < mesh_delta %}
{% set meshPointX = 5 %}
{% elif (area_max_x - area_min_x) / 7 < mesh_delta %}
{% set meshPointX = 7 %}
{% elif (area_max_x - area_min_x) / 9 < mesh_delta %}
{% set meshPointX = 9 %}
{% elif (area_max_x - area_min_x) / 11 < mesh_delta %}
{% set meshPointX = 11 %}
{% endif %}
{% if (area_max_y - area_min_y) / 3 < mesh_delta %}
{% set meshPointY = 3 %}
{% elif (area_max_y - area_min_y) / 5 < mesh_delta %}
{% set meshPointY = 5 %}
{% elif (area_max_y - area_min_y) / 7 < mesh_delta %}
{% set meshPointY = 7 %}
{% elif (area_max_y - area_min_y) / 9 < mesh_delta %}
{% set meshPointY = 9 %}
{% elif (area_max_y - area_min_y) / 11 < mesh_delta %}
{% set meshPointY = 11 %}
{% endif %}

;; check probe count vs max
{% if meshPointX > x_mesh_max %}
{% set meshPointX = x_mesh_max %}
{% endif %}
{% if meshPointY > y_mesh_max %}
{% set meshPointY = y_mesh_max %}
{% endif %}

;; check for 7x3 or 3x7 mesh
{% if meshPointX > 5 %}
{% if meshPointY == 3 %} # 7x3 mesh invlaid for bicubic
{% set meshPointY = 5 %} # set 7x5 mesh
{% endif %}
{% endif %}
{% if meshPointY > 5 %}
{% if meshPointX == 3 %} # 3x7 mesh invlaid for bicubic
{% set meshPointX = 5 %} # set 5x7 mesh
{% endif %}
{% endif %}

;; set new reference index point
{% set referenceIndex = (meshPointX * meshPointY / 2 - 1 )|round(0)|int %}

;; send bed mesh parameters
M117 Mesh {meshPointX}x{meshPointY}
BED_MESH_CALIBRATE_BASE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} relative_reference_index={referenceIndex} samples={probe_samples} sample_retract_dist={probe_sample_retract_dist} samples_tolerance={probe_samples_tolerance} samples_tolerance_retries={probe_samples_tolerance_retries} samples_result={probe_samples_result} samples_result={probe_samples_result} algorithm={mesh_algorithm}
{% else %}
BED_MESH_CALIBRATE_BASE
{% endif %}
{% else %}
BED_MESH_CALIBRATE_BASE
{% endif %}

@krpepe
Copy link

krpepe commented Apr 21, 2022

Internal error on command:"BED_MESH_CALIBRATE_BASE"
Once the underlying issue is corrected, use the
"FIRMWARE_RESTART" command to reset the firmware, reload the
config, and restart the host software.
Printer is shutdown

any idea what I might be doing wrong

@selrahc13
Copy link

selrahc13 commented May 9, 2022

@Taracair @ChipCE What do you think of this? It forces odd mesh spacing to ensure a refence point in the exact center of the probed area. It defines the mesh based on a maximum distance between probe points up to a defined maximum, or 11 points (I wasn't sure how to code a loop).

[gcode_macro BED_MESH_CALIBRATE]
rename_existing: BED_MESH_CALIBRATE_BASE
variable_mesh_delta : 25 ;; distance between points
variable_x_mesh_max : 7 ;; max points on x-axis
variable_y_mesh_max : 7 ;; max points on y-axis
variable_mesh_area_offset : 0 ;; the clearance between print area and probe area
variable_parameter_AREA_START : 0,0 ;; gcode parameter to be defined by slicer
variable_parameter_AREA_END : 0,0 ;; gcode parameter to be defined by slicer
gcode=
{% if params.AREA_START and params.AREA_END %}

;; get [bltouch] config parameters
{% set BLTouchConfig = printer["configfile"].config["bltouch"] %}
{% set probe_samples = BLTouchConfig.samples|int %}
{% set probe_samples_tolerance_retries = BLTouchConfig.samples_tolerance_retries|int %}
{% set probe_samples_tolerance = BLTouchConfig.samples_tolerance|float %}
{% set probe_sample_retract_dist = BLTouchConfig.sample_retract_dist|float %}
{% set probe_samples_result = samples_result %}

;; get [bed_mesh] config parameters
{% set bedMeshConfig = printer["configfile"].config["bed_mesh"] %}
{% set mesh_algorithm = bedMeshConfig.algorithm %}
{% set mesh_bicubic_tension = bedMeshConfig.bicubic_tension|float %}
{% set safe_min_x = bedMeshConfig.mesh_min.split(",")[0]|float %}
{% set safe_min_y = bedMeshConfig.mesh_min.split(",")[1]|float %}
{% set safe_max_x = bedMeshConfig.mesh_max.split(",")[0]|float %}
{% set safe_max_y = bedMeshConfig.mesh_max.split(",")[1]|float %}
{% set meshPointX = bedMeshConfig.probe_count.split(",")[0]|int %}
{% set meshPointY = bedMeshConfig.probe_count.split(",")[1]|int %}
{% set meshMaxPointX = meshPointX %}
{% set meshMaxPointY = meshPointY %}

;; get print area min/max from slicer gcode
{% set area_min_x = params.AREA_START.split(",")[0]|float %}
{% set area_min_y = params.AREA_START.split(",")[1]|float %}
{% set area_max_x = params.AREA_END.split(",")[0]|float %}
{% set area_max_y = params.AREA_END.split(",")[1]|float %}

;; check if print area min/max from slicer gcode is compatable with [bed_mesh] min/max
{% if (area_min_x < area_max_x) and (area_min_y < area_max_y) %}
;; set probing area
{% if area_min_x - mesh_area_offset >= safe_min_x %}
{% set area_min_x = area_min_x - mesh_area_offset %}
{% else %}
{% set area_min_x = safe_min_x %}
{% endif %}
{% if area_min_y - mesh_area_offset >= safe_min_y %}
{% set area_min_y = area_min_y - mesh_area_offset %}
{% else %}
{% set area_min_y = safe_min_y %}
{% endif %}
{% if area_max_x + mesh_area_offset <= safe_max_x %}
{% set area_max_x = area_max_x + mesh_area_offset %}
{% else %}
{% set area_max_x = safe_max_x %}
{% endif %}
{% if area_max_y + mesh_area_offset <= safe_max_y %}
{% set area_max_y = area_max_y + mesh_area_offset %}
{% else %}
{% set area_max_y = safe_max_y %}
{% endif %}

;; set probe counts
{% if (area_max_x - area_min_x) / 3 < mesh_delta %}
{% set meshPointX = 3 %}
{% elif (area_max_x - area_min_x) / 5 < mesh_delta %}
{% set meshPointX = 5 %}
{% elif (area_max_x - area_min_x) / 7 < mesh_delta %}
{% set meshPointX = 7 %}
{% elif (area_max_x - area_min_x) / 9 < mesh_delta %}
{% set meshPointX = 9 %}
{% elif (area_max_x - area_min_x) / 11 < mesh_delta %}
{% set meshPointX = 11 %}
{% endif %}
{% if (area_max_y - area_min_y) / 3 < mesh_delta %}
{% set meshPointY = 3 %}
{% elif (area_max_y - area_min_y) / 5 < mesh_delta %}
{% set meshPointY = 5 %}
{% elif (area_max_y - area_min_y) / 7 < mesh_delta %}
{% set meshPointY = 7 %}
{% elif (area_max_y - area_min_y) / 9 < mesh_delta %}
{% set meshPointY = 9 %}
{% elif (area_max_y - area_min_y) / 11 < mesh_delta %}
{% set meshPointY = 11 %}
{% endif %}

;; check probe count vs max
{% if meshPointX > x_mesh_max %}
{% set meshPointX = x_mesh_max %}
{% endif %}
{% if meshPointY > y_mesh_max %}
{% set meshPointY = y_mesh_max %}
{% endif %}

;; check for 7x3 or 3x7 mesh
{% if meshPointX > 5 %}
{% if meshPointY == 3 %} # 7x3 mesh invlaid for bicubic
{% set meshPointY = 5 %} # set 7x5 mesh
{% endif %}
{% endif %}
{% if meshPointY > 5 %}
{% if meshPointX == 3 %} # 3x7 mesh invlaid for bicubic
{% set meshPointX = 5 %} # set 5x7 mesh
{% endif %}
{% endif %}

;; set new reference index point
{% set referenceIndex = (meshPointX * meshPointY / 2 - 1 )|round(0)|int %}

;; send bed mesh parameters
M117 Mesh {meshPointX}x{meshPointY}
BED_MESH_CALIBRATE_BASE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} relative_reference_index={referenceIndex} samples={probe_samples} sample_retract_dist={probe_sample_retract_dist} samples_tolerance={probe_samples_tolerance} samples_tolerance_retries={probe_samples_tolerance_retries} samples_result={probe_samples_result} samples_result={probe_samples_result} algorithm={mesh_algorithm}
{% else %}
BED_MESH_CALIBRATE_BASE
{% endif %}
{% else %}
BED_MESH_CALIBRATE_BASE
{% endif %}

I had to explicitly define some bed_mesh and bltouch probe parameters and separate BED_MESH_CALIBRATE_BASE with a separate PROBE gcode line as well, but this actually worked for me in the end

@DerBierBaron
Copy link

DerBierBaron commented May 18, 2022

Internal error on command:"BED_MESH_CALIBRATE_BASE" Once the underlying issue is corrected, use the "FIRMWARE_RESTART" command to reset the firmware, reload the config, and restart the host software. Printer is shutdown

any idea what I might be doing wrong

Same thing happens to me. I followed the instructions in the readme file and when running the BED_MESH_CALIBRATE command klipper goes into shutdown on internal error inside BED_MESH_CALIBRATE_BASE.

Here's the klippy log from right after one of these events:

Generating new points...
bed_mesh: generated points
Index | Tool Adjusted | Probe
0 | (73.7, 51.8) | (54.5, 75.8)
1 | (98.4, 51.8) | (79.3, 75.8)
2 | (123.2, 51.8) | (104.0, 75.8)
3 | (147.9, 51.8) | (128.8, 75.8)
4 | (147.9, 73.8) | (128.8, 97.7)
5 | (123.2, 73.8) | (104.0, 97.7)
6 | (98.4, 73.8) | (79.3, 97.7)
7 | (73.7, 73.8) | (54.5, 97.7)
8 | (73.7, 95.8) | (54.5, 119.7)
9 | (98.4, 95.8) | (79.3, 119.7)
10 | (123.2, 95.8) | (104.0, 119.7)
11 | (147.9, 95.8) | (128.8, 119.7)
12 | (147.9, 117.7) | (128.8, 141.7)
13 | (123.2, 117.7) | (104.0, 141.7)
14 | (98.4, 117.7) | (79.3, 141.7)
15 | (73.7, 117.7) | (54.5, 141.7)
Internal error on command:"BED_MESH_CALIBRATE_BASE"
Traceback (most recent call last):
File "/home/pi/klipper/klippy/gcode.py", line 199, in _process_commands
handler(gcmd)
File "/home/pi/klipper/klippy/gcode.py", line 136, in
func = lambda params: origfunc(self._get_extended_params(params))
File "/home/pi/klipper/klippy/gcode.py", line 136, in
func = lambda params: origfunc(self._get_extended_params(params))
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 600, in cmd_BED_MESH_CALIBRATE
self.update_config(gcmd)
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 571, in update_config
self.print_generated_points(gcmd.respond_info)
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 401, in print_generated_points
% (rri, self.points[rri][0], self.points[rri][1]))
IndexError: list index out of range
Transition to shutdown state: Internal error on command:"BED_MESH_CALIBRATE_BASE"

Then some dump lines and afterwards this:

Read 6295.795388: 'BED_MESH_CALIBRATE AREA_START=59.4947,80.7517 AREA_END=123.799,136.674\n'
gcode state: absolute_coord=True absolute_extrude=False base_position=[0.0, 0.0, 0.0, 0.0] last_position=[273.0000097657055, 127.70260742187827, 4.977523195091998, 0.0] homing_position=[0.0, 0.0, 0.0, 0.0] speed_factor=0.0166666666667 extrude_factor=1.0 speed=20.0
Reactor garbage collection: (6288.271120751, 0.0, 0.0)
Internal error on command:"BED_MESH_CALIBRATE_BASE"
Internal error on command:"BED_MESH_CALIBRATE"
Traceback (most recent call last):
File "/home/pi/klipper/klippy/gcode.py", line 199, in _process_commands
handler(gcmd)
File "/home/pi/klipper/klippy/gcode.py", line 136, in
func = lambda params: origfunc(self._get_extended_params(params))
File "/home/pi/klipper/klippy/extras/gcode_macro.py", line 186, in cmd
self.template.run_gcode_from_command(kwparams)
File "/home/pi/klipper/klippy/extras/gcode_macro.py", line 68, in run_gcode_from_command
self.gcode.run_script_from_command(self.render(context))
File "/home/pi/klipper/klippy/gcode.py", line 214, in run_script_from_command
self._process_commands(script.split('\n'), need_ack=False)
File "/home/pi/klipper/klippy/gcode.py", line 199, in _process_commands
handler(gcmd)
File "/home/pi/klipper/klippy/gcode.py", line 136, in
func = lambda params: origfunc(self._get_extended_params(params))
File "/home/pi/klipper/klippy/gcode.py", line 136, in
func = lambda params: origfunc(self._get_extended_params(params))
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 600, in cmd_BED_MESH_CALIBRATE
self.update_config(gcmd)
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 571, in update_config
self.print_generated_points(gcmd.respond_info)
File "/home/pi/klipper/klippy/extras/bed_mesh.py", line 401, in print_generated_points
% (rri, self.points[rri][0], self.points[rri][1]))
IndexError: list index out of range
Internal error on command:"BED_MESH_CALIBRATE"
MCU 'rpi' shutdown: Command request
clocksync state: mcu_freq=50000000 last_clock=25568762177 clock_est=(6266.926 24141143000 49998000.724) min_half_rtt=0.000049 min_rtt_time=5786.204 time_avg=6266.926(843.403) clock_avg=24141143000.805(42168466407.952) pred_variance=17265271.615 clock_adj=(0.446 50000401.761)
Dumping serial stats: bytes_write=3895 bytes_read=13731 bytes_retransmit=0 bytes_invalid=0 send_seq=625 receive_seq=625 retransmit_seq=0 srtt=0.000 rttvar=0.000 rto=0.025 ready_bytes=0 stalled_bytes=0

What I find interesting is that before this there was a regular mesh calculation;

bed_mesh: generated points
Index | Tool Adjusted | Probe
0 | (20.2, 0.0) | (1.0, 23.9)
1 | (62.2, 0.0) | (43.1, 23.9)
2 | (104.3, 0.0) | (85.2, 23.9)
3 | (146.4, 0.0) | (127.2, 23.9)
4 | (188.5, 0.0) | (169.3, 23.9)
5 | (230.6, 0.0) | (211.4, 23.9)
6 | (272.6, 0.0) | (253.5, 23.9)
7 | (272.6, 43.5) | (253.5, 67.4)
8 | (230.6, 43.5) | (211.4, 67.4)
9 | (188.5, 43.5) | (169.3, 67.4)
10 | (146.4, 43.5) | (127.2, 67.4)
11 | (104.3, 43.5) | (85.2, 67.4)
12 | (62.3, 43.5) | (43.1, 67.4)
13 | (20.2, 43.5) | (1.0, 67.4)
14 | (20.2, 87.0) | (1.0, 110.9)
15 | (62.2, 87.0) | (43.1, 110.9)
16 | (104.3, 87.0) | (85.2, 110.9)
17 | (146.4, 87.0) | (127.2, 110.9)
18 | (188.5, 87.0) | (169.3, 110.9)
19 | (230.6, 87.0) | (211.4, 110.9)
20 | (272.6, 87.0) | (253.5, 110.9)
21 | (272.6, 130.5) | (253.5, 154.4)
22 | (230.6, 130.5) | (211.4, 154.4)
23 | (188.5, 130.5) | (169.3, 154.4)
24 | (146.4, 130.5) | (127.2, 154.4)
25 | (104.3, 130.5) | (85.2, 154.4)
26 | (62.3, 130.5) | (43.1, 154.4)
27 | (20.2, 130.5) | (1.0, 154.4)
28 | (20.2, 174.0) | (1.0, 198.0)
29 | (62.2, 174.0) | (43.1, 198.0)
30 | (104.3, 174.0) | (85.2, 198.0)
31 | (146.4, 174.0) | (127.2, 198.0)
32 | (188.5, 174.0) | (169.3, 198.0)
33 | (230.6, 174.0) | (211.4, 198.0)
34 | (272.6, 174.0) | (253.5, 198.0)
35 | (272.6, 217.5) | (253.5, 241.5)
36 | (230.6, 217.5) | (211.4, 241.5)
37 | (188.5, 217.5) | (169.3, 241.5)
38 | (146.4, 217.5) | (127.2, 241.5)
39 | (104.3, 217.5) | (85.2, 241.5)
40 | (62.3, 217.5) | (43.1, 241.5)
41 | (20.2, 217.5) | (1.0, 241.5)
42 | (20.2, 261.1) | (1.0, 285.0)
43 | (62.2, 261.1) | (43.1, 285.0)
44 | (104.3, 261.1) | (85.2, 285.0)
45 | (146.4, 261.1) | (127.2, 285.0)
46 | (188.5, 261.1) | (169.3, 285.0)
47 | (230.6, 261.1) | (211.4, 285.0)
48 | (272.6, 261.1) | (253.5, 285.0)
bed_mesh: relative_reference_index 24 is (127.24, 154.45)
BLTouch set output mode: 5V
Starting heater checks for heater_bed
Starting heater checks for extruder

Any ideas where the issue is coming from?

@noahliketheark
Copy link

noahliketheark commented May 19, 2022

This is simplified and should be less buggy. The errors are because I had more defined in my BLTouch and Bed_Mesh configurations that you were missing.

[gcode_macro BED_MESH_CALIBRATE]
rename_existing: BED_MESH_CALIBRATE_BASE
variable_mesh_delta : 25 ## distance between points
variable_x_mesh_max : 7 ## max points on x-axis
variable_y_mesh_max : 7 ## max points on y-axis
variable_mesh_area_offset : 5 ## the clearance between print area and probe area
gcode=
{% if params.AREA_START and params.AREA_END %}
## get [bed_mesh] config parameters
{% set bedMeshConfig = printer["configfile"].config["bed_mesh"] %}
{% set safe_min_x = bedMeshConfig.mesh_min.split(",")[0]|float %}
{% set safe_min_y = bedMeshConfig.mesh_min.split(",")[1]|float %}
{% set safe_max_x = bedMeshConfig.mesh_max.split(",")[0]|float %}
{% set safe_max_y = bedMeshConfig.mesh_max.split(",")[1]|float %}
## get print area min/max from slicer gcode
{% set area_min_x = params.AREA_START.split(",")[0]|float %}
{% set area_min_y = params.AREA_START.split(",")[1]|float %}
{% set area_max_x = params.AREA_END.split(",")[0]|float %}
{% set area_max_y = params.AREA_END.split(",")[1]|float %}
## set probing area
{% if area_min_x - mesh_area_offset >= safe_min_x %}
{% set area_min_x = area_min_x - mesh_area_offset %}
{% else %}
{% set area_min_x = safe_min_x %}
{% endif %}
{% if area_min_y - mesh_area_offset >= safe_min_y %}
{% set area_min_y = area_min_y - mesh_area_offset %}
{% else %}
{% set area_min_y = safe_min_y %}
{% endif %}
{% if area_max_x + mesh_area_offset <= safe_max_x %}
{% set area_max_x = area_max_x + mesh_area_offset %}
{% else %}
{% set area_max_x = safe_max_x %}
{% endif %}
{% if area_max_y + mesh_area_offset <= safe_max_y %}
{% set area_max_y = area_max_y + mesh_area_offset %}
{% else %}
{% set area_max_y = safe_max_y %}
{% endif %}
## set probe counts
{% set meshPointX = ((area_max_x - area_min_x) / mesh_delta + 1)|round(0)|int %}
{% if meshPointX < 3 %}
{% set meshPointX = 3 %}
{% elif meshPointX x_mesh_max %}
{% set meshPointX = x_mesh_max %}
{% endif %}
{% set meshPointY = ((area_max_y - area_min_y) / mesh_delta + 1)|round(0)|int %}
{% if meshPointY < 3 %}
{% set meshPointY = 3 %}
{% elif meshPointY y_mesh_max %}
{% set meshPointY = y_mesh_max %}
{% endif %}
## check for invalid mesh
{% if meshPointX 5 %}
{% if meshPointY == 3 %} # 7x3 mesh invlaid for bicubic
{% set meshPointY = 5 %} # set 7x5 mesh
{% endif %}
{% endif %}
{% if meshPointY 5 %}
{% if meshPointX == 3 %} # 3x7 mesh invlaid for bicubic
{% set meshPointX = 5 %} # set 5x7 mesh
{% endif %}
{% endif %}
## set new reference index point
{% set referenceIndex = (meshPointX * meshPointY / 2 - 1 )|round(0)|int %}
## send bed mesh parameters
M117 probe_count={meshPointX},{meshPointY}
BED_MESH_CALIBRATE_BASE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} relative_reference_index={referenceIndex}
{% else %}
BED_MESH_CALIBRATE_BASE
{% endif %}

@DerBierBaron
Copy link

DerBierBaron commented May 19, 2022

@noahliketheark
Thanks for the code, unfortunately I'm not yet familiar with python syntax and I get syntax errors telling me it expects "end of statement blocks" and if I add "==" between the elif and the condition for x_mesh_max it tells me the issue now is with y_mesh_max, if I add the "==" in that elif it still tels me y_mesh_max is the issue. Could you repost the code in a "paste-ready" format, because I appear to not be able to figure it out myself?

@noahliketheark
Copy link

noahliketheark commented May 20, 2022

@DerBierBaron @krpepe @selrahc13
Sorry, I haven't been able to figure out how to post the code correctly on Github. Here it is on pastebin
https://pastebin.com/Y1EGXu8M

@DerBierBaron
Copy link

DerBierBaron commented May 20, 2022

@noahliketheark
Thanks again! Works like a charm, no compile errors and no internal errors. Also factors in the bicubic algorith that works miles better on my heated bed. Would a min count of 4 not also be sufficient for bicubic? Anyways, cool stuff!

@mohalsa
Copy link

mohalsa commented May 21, 2022

Will give it a try today! Amazing Idea

@teeedubb
Copy link

teeedubb commented May 23, 2022

Thanks for sharing this macro - it's awesome, works really well!

@selrahc13
Copy link

selrahc13 commented May 23, 2022

Here's an edited version that works well for me, and has not yet had a failure:

[gcode_macro BED_MESH_CALIBRATE]
rename_existing: BED_MESH_CALIBRATE_BASE
gcode:
    {% set mesh_delta = 25 %} ;; distance between points
    {% set x_mesh_max = 7 %} ;; max points on x-axis
    {% set y_mesh_max = 7 %} ;; max points on y-axis
    {% set mesh_area_offset = 0 %};; the clearance between print area and probe area
    {% set parameter_AREA_START = "0,0" %} ;; gcode parameter to be defined by slicer
    {% set parameter_AREA_END = "0,0" %} ;; gcode parameter to be defined by slicer
    {% if params.AREA_START and params.AREA_END %}
        ;; get [bltouch] config parameters
        {% set BLTouchConfig = printer["configfile"].config["bltouch"] %}
        {% set probe_samples = BLTouchConfig.samples|int %}
        {% set probe_samples_tolerance_retries = BLTouchConfig.samples_tolerance_retries|int %}
        {% set probe_samples_tolerance = BLTouchConfig.samples_tolerance|float %}
        {% set probe_sample_retract_dist = BLTouchConfig.sample_retract_dist|float %}
        {% set probe_samples_result = samples_result %}

        ;; get [bed_mesh] config parameters
        {% set bedMeshConfig = printer["configfile"].config["bed_mesh"] %}
        {% set mesh_algorithm = bedMeshConfig.algorithm %}
        {% set mesh_bicubic_tension = bedMeshConfig.bicubic_tension|float %}
        {% set safe_min_x = bedMeshConfig.mesh_min.split(",")[0]|float %}
        {% set safe_min_y = bedMeshConfig.mesh_min.split(",")[1]|float %}
        {% set safe_max_x = bedMeshConfig.mesh_max.split(",")[0]|float %}
        {% set safe_max_y = bedMeshConfig.mesh_max.split(",")[1]|float %}
        {% set meshPointX = bedMeshConfig.probe_count.split(",")[0]|int %}
        {% set meshPointY = bedMeshConfig.probe_count.split(",")[1]|int %}
        {% set meshMaxPointX = meshPointX %}
        {% set meshMaxPointY = meshPointY %}

        ;; get print area min/max from slicer gcode
        {% set area_min_x = params.AREA_START.split(",")[0]|float %}
        {% set area_min_y = params.AREA_START.split(",")[1]|float %}
        {% set area_max_x = params.AREA_END.split(",")[0]|float %}
        {% set area_max_y = params.AREA_END.split(",")[1]|float %}

        ;; check if print area min/max from slicer gcode is compatable with [bed_mesh] min/max
        {% if (area_min_x < area_max_x) and (area_min_y < area_max_y) %}
        ;; set probing area
            {% if area_min_x - mesh_area_offset >= safe_min_x %}
                {% set area_min_x = area_min_x - mesh_area_offset %}
            {% else %}
                {% set area_min_x = safe_min_x %}
            {% endif %}
            {% if area_min_y - mesh_area_offset >= safe_min_y %}
                {% set area_min_y = area_min_y - mesh_area_offset %}
            {% else %}
                {% set area_min_y = safe_min_y %}
            {% endif %}
            {% if area_max_x + mesh_area_offset <= safe_max_x %}
                {% set area_max_x = area_max_x + mesh_area_offset %}
            {% else %}
                {% set area_max_x = safe_max_x %}
            {% endif %}
            {% if area_max_y + mesh_area_offset <= safe_max_y %}
                {% set area_max_y = area_max_y + mesh_area_offset %}
            {% else %}
                {% set area_max_y = safe_max_y %}
            {% endif %}

                ;; set probe counts
            {% if (area_max_x - area_min_x) / 3 < mesh_delta %}
                {% set meshPointX = 3 %}
            {% elif (area_max_x - area_min_x) / 5 < mesh_delta %}
                {% set meshPointX = 5 %}
            {% elif (area_max_x - area_min_x) / 7 < mesh_delta %}
                {% set meshPointX = 7 %}
            {% elif (area_max_x - area_min_x) / 9 < mesh_delta %}
                {% set meshPointX = 9 %}
            {% elif (area_max_x - area_min_x) / 11 < mesh_delta %}
                {% set meshPointX = 11 %}
            {% endif %}
            {% if (area_max_y - area_min_y) / 3 < mesh_delta %}
                {% set meshPointY = 3 %}
            {% elif (area_max_y - area_min_y) / 5 < mesh_delta %}
                {% set meshPointY = 5 %}
            {% elif (area_max_y - area_min_y) / 7 < mesh_delta %}
                {% set meshPointY = 7 %}
            {% elif (area_max_y - area_min_y) / 9 < mesh_delta %}
                {% set meshPointY = 9 %}
            {% elif (area_max_y - area_min_y) / 11 < mesh_delta %}
                {% set meshPointY = 11 %}
            {% endif %}

                ;; check probe count vs max
            {% if meshPointX > x_mesh_max %}
                {% set meshPointX = x_mesh_max %}
            {% endif %}
            {% if meshPointY > y_mesh_max %}
                {% set meshPointY = y_mesh_max %}
            {% endif %}

                ;; check for 7x3 or 3x7 mesh
            {% if meshPointX > 5 %}
                {% if meshPointY == 3 %} # 7x3 mesh invlaid for bicubic
                    {% set meshPointY = 5 %} # set 7x5 mesh
                {% endif %}
            {% endif %}
            {% if meshPointY > 5 %}
                {% if meshPointX == 3 %} # 3x7 mesh invlaid for bicubic
                    {% set meshPointX = 5 %} # set 5x7 mesh
                {% endif %}
            {% endif %}

            ;; set new reference index point
            {% set referenceIndex = (meshPointX * meshPointY / 2 - 1 )|round(0)|int %}

            ;; send bed mesh parameters
            M117 Mesh {meshPointX}x{meshPointY}
            M118 Mesh {meshPointX}x{meshPointY}
            M118 PROBE samples={probe_samples} sample_retract_dist={probe_sample_retract_dist} samples_tolerance={probe_samples_tolerance} samples_tolerance_retries={probe_samples_tolerance_retries} samples_result={probe_samples_result}
            M118 BED_MESH_CALIBRATE_BASE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} relative_reference_index={referenceIndex} algorithm={mesh_algorithm}
            PROBE samples={probe_samples} sample_retract_dist={probe_sample_retract_dist} samples_tolerance={probe_samples_tolerance} samples_tolerance_retries={probe_samples_tolerance_retries} samples_result={probe_samples_result}
            BED_MESH_CALIBRATE_BASE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} relative_reference_index={referenceIndex} algorithm={mesh_algorithm}
        {% else %}
            BED_MESH_CALIBRATE_BASE
        {% endif %}
    {% else %}
        BED_MESH_CALIBRATE_BASE
    {% endif %}

@Lecso11
Copy link

Lecso11 commented May 31, 2022

Guys! I'm using klicky and macros from here https://github.com/jlas1/Klicky-Probe/tree/main/Klipper_macros. Where should I paste Bed Mesh Calibrate macro? Do I need make some changes?

I made it work. On this new macro you need 2 modifications:

* This 3 lines at the beginning of the gcode section
gcode:
    _CheckProbe action=query
    G90
    Attach_Probe
 .............
* A `Dock_Probe` before end the end of the file.

You can see in this screenshot the mesh generated for a benchy placed at the center of my 340x340 bed: Screenshot 2022-04-03 172731

If you use the plugin to automatically calibrate the z-offset, you should update it to the latest version. There's a PR from a few weeks ago that gets the RRI from the latest mesh.

The only issue I see with using this macro is related to a famous plugin to automatically calibrate the z-offset. To generate a mesh, my config is:

[bed_mesh]
probe_count: 3,3
mesh_pps: 3,3
relative_reference_index: 4

This macro is using the center of it's mesh as the RRI (in this screenshot x=153.61 y=149.99, while the CALIBRATE_Z command of the plugin sets the RRI at the center of the default mesh (x=170 y=152 in my case)). It doesn't makes much of a difference when placing the model at the center of the bed and it is mostly flat (and probably it will be easy to fiddle with the start gcode to send the RRI coordinates as a parameter for the CALIBRATE_Z macro of the plugin), but JFYI.

Hi. I'm also using klicky and auto Z calibration, and I can't get it to work. Where do I need that 3 line exactly? Would you mind sharing your config files?

@panik988
Copy link

panik988 commented Jun 6, 2022

@diegomarino can you share your macro?
I tryed with this but it doesn't work :-(

[gcode_macro BED_MESH_CALIBRATE]
rename_existing: _BED_MESH_CALIBRATE
; gcode parameters
variable_parameter_AREA_START : 0,0
variable_parameter_AREA_END : 0,0
; the clearance between print area and probe area
variable_mesh_area_offset : 5.0
; number of sample per probe point
variable_probe_samples : 2
; minimum probe count
variable_min_probe_count : 3
; scale up the probe count, should be 1.0 ~ < variable_max_probe_count/variable_min_probe_count
variable_probe_count_scale_factor : 1.0
gcode:

{% set V = printer["gcode_macro _User_Variables"].verbose %}
{% if V %}
    { action_respond_info("Bed Mesh Calibrate") }
{% endif %}

_CheckProbe action=query
G90
Attach_Probe

{% if params.AREA_START and params.AREA_END %}
    {% set bedMeshConfig = printer["configfile"].config["bed_mesh"] %}
    {% set safe_min_x = bedMeshConfig.mesh_min.split(",")[0]|float %}
    {% set safe_min_y = bedMeshConfig.mesh_min.split(",")[1]|float %}
    {% set safe_max_x = bedMeshConfig.mesh_max.split(",")[0]|float %}
    {% set safe_max_y = bedMeshConfig.mesh_max.split(",")[1]|float %}

    {% set area_min_x = params.AREA_START.split(",")[0]|float %}
{% set area_min_y = params.AREA_START.split(",")[1]|float %}
{% set area_max_x = params.AREA_END.split(",")[0]|float %}
{% set area_max_y = params.AREA_END.split(",")[1]|float %}

{% if bedMeshConfig.probe_count.split(",")|length == 2 %}
        {% set meshPointX = bedMeshConfig.probe_count.split(",")[0]|int %}
        {% set meshPointY = bedMeshConfig.probe_count.split(",")[1]|int %}
    {% else %}
        {% set meshPointX = bedMeshConfig.probe_count.split(",")[0]|int %}
        {% set meshPointY = bedMeshConfig.probe_count.split(",")[0]|int %}
    {% endif %}

{% set meshMaxPointX = meshPointX %}
{% set meshMaxPointY = meshPointY %}


    {% if (area_min_x < area_max_x) and (area_min_y < area_max_y) %}
        {% if area_min_x - mesh_area_offset >=  safe_min_x %}
            {% set area_min_x = area_min_x - mesh_area_offset %}
        {% else %}
            {% set area_min_x = safe_min_x %}
        {% endif %}

        {% if area_min_y - mesh_area_offset >=  safe_min_y %}
            {% set area_min_y = area_min_y - mesh_area_offset %}
        {% else %}
            {% set area_min_y = safe_min_y %}
        {% endif %}

        {% if area_max_x + mesh_area_offset <=  safe_max_x %}
            {% set area_max_x = area_max_x + mesh_area_offset %}
        {% else %}
            {% set area_max_x = safe_max_x %}
        {% endif %}

        {% if area_max_y + mesh_area_offset <=  safe_max_y %}
            {% set area_max_y = area_max_y + mesh_area_offset %}
        {% else %}
            {% set area_max_y = safe_max_y %}
        {% endif %}

        {% set meshPointX = (meshPointX * (area_max_x - area_min_x) / (safe_max_x - safe_min_x) * probe_count_scale_factor)|round(0)|int %}
        {% if meshPointX < min_probe_count %}
            {% set meshPointX = min_probe_count %}
        {% endif %}
    {% if meshPointX > meshMaxPointX %}
            {% set meshPointX = meshMaxPointX %}
        {% endif %}

        {% set meshPointY = (meshPointY * (area_max_y -area_min_y ) / (safe_max_y - safe_min_y) * probe_count_scale_factor )|round(0)|int %}
        {% if meshPointY < min_probe_count %}
            {% set meshPointY = min_probe_count %}
        {% endif %}
    {% if meshPointY > meshMaxPointY %}
            {% set meshPointY = meshMaxPointY %}
        {% endif %}

        _BED_MESH_CALIBRATE mesh_min={area_min_x},{area_min_y} mesh_max={area_max_x},{area_max_y} probe_count={meshPointX},{meshPointY} samples={probe_samples|int}
    {% else %}
        _BED_MESH_CALIBRATE
    {% endif %}
{% else %}
    _BED_MESH_CALIBRATE
{% endif %}

Dock_Probe

@panik988
Copy link

panik988 commented Jun 7, 2022

@diegomarino unfortunately it doesn't work for me. Thanks for your help

@brotherdust
Copy link

brotherdust commented Jun 20, 2022

@ChipCE I believe the error that some of the users are experiencing, specifically IndexError: list index out of range is related to a [bed_mesh] config that has faulty regions. After commenting the faulty regions out of my config, this macro worked fine.

[bed_mesh]
speed: 500
mesh_min: 35,7
mesh_max: 240,198
probe_count: 7,7
mesh_pps: 2,2
#algorithm: lagrange
algorithm: bicubic
bicubic_tension: 0.2
horizontal_move_z: 5
#relative_reference_index: 13
relative_reference_index: 25
#faulty_region_1_min: 130.0, 0.0
#faulty_region_1_max: 145.0, 40.0
#faulty_region_2_min: 225.0, 0.0
#faulty_region_2_max: 250.0, 25.0
#faulty_region_3_min: 165.0, 95.0
#faulty_region_3_max: 205.0, 110.0
#faulty_region_4_min: 30.0, 170.0
#faulty_region_4_max: 45.0, 210.0

I'm not sure how to fix it, but I thought you might want the info. Thanks!

@VozzickaR
Copy link

VozzickaR commented Jun 20, 2022

Hi,
I have a problem with Heating Bed/Extruder after implementing this Macro. Can you help me with that?
After start print klipper say

 17:40:32
Error on 'M140 S': unable to parse

On slicer Cura i use Start G  code:
START_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0} AREA_START=%MINX%,%MINY% AREA_END=%MAXX%,%MAXY%






# [gcode_macro START_PRINT]


variable_parameter_EXTRUDER_TEMP: 190
 variable_parameter_BED_TEMP: 60
 gcode parameters for area bed mesh
variable_parameter_AREA_START : 0,0
variable_parameter_AREA_END : 0,0
gcode:

 Start bed/EXTRUDER heating
 M140 S{BED_TEMP}
    M104 S{EXTRUDER_TEMP}
     # Use absolute coordinates
     G90
     # Reset the G-Code Z offset (adjust Z offset if needed)
     SET_GCODE_OFFSET Z=0.0
     ## Home the printer
     G28
      BED_MESH_CALIBRATE AREA_START={params.AREA_START|default("0,0")} AREA_END={params.AREA_END|default("0,0")}
    M140 S{BED_TEMP} ; set bed temp in background, do not wait
    ; report temperature
    M104 S{EXTRUDER_TEMP} ; set extruder temp
    G1 Z25 X8 F1500
    # Wait for bed to reach temperature
    M190 S{bed_temp}
    # Set and wait for nozzle to reach temperature
    M109 S{extruder_temp}
    # Reset Extruder
    G92 E0
    # Move Z Axis up
    G1 Z2.0 F3000
    # Move to start position
    G1 X8 Y20 Z0.28 F5000.0
    # Draw the first line
    G1 X8 Y200.0 Z0.28 F1500.0 E15
    # Move to side a little
    G1 X8.3 Y200.0 Z0.28 F5000.0
    # Draw the second line
    G1 X8.3 Y20 Z0.28 F1500.0 E30
    # Reset Extruder
    G92 E0
    # Move Z Axis up
    G1 Z2.0 F3000
    # Print message on LCD
`
`[Full Config](https://pastebin.com/apU3WAZK) 

Problem solved
Now i repeate adding your macro in Cfg, and its work, idk where, or what mistake i do...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment