Skip to content

Instantly share code, notes, and snippets.

@ChipCE
Last active April 16, 2024 23:07
Show Gist options
  • Save ChipCE/95fdbd3c2f3a064397f9610f915f7d02 to your computer and use it in GitHub Desktop.
Save ChipCE/95fdbd3c2f3a064397f9610f915f7d02 to your computer and use it in GitHub Desktop.
Klipper bed mesh on print area only macro install guide

READ THIS FIRST

Adaptive bed mesh is merged into klipper master branch. You can use this feature without this custom macro. Official klipper adaptive bed mesh

Klipper mesh on print area only install guide

What this macro do

  • This macro will dynamically changing the bed mesh area based on the size of the parts will be printed. 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 macro 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 : 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
; enable preference index
variable_enable_reference_index : False
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 %}

            {% set algorithm = "bicubic" %}
	    {% if "algorithm" in bedMeshConfig %}
	        {% set algorithm = bedMeshConfig.algorithm %}
            {% endif %}
            {% if meshPointX >=7 or meshPointY >=7 %}
                {% set algorithm = "bicubic" %}
            {% endif %}

            {% if enable_reference_index %}
                {% 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} samples={probe_samples|int} algorithm={algorithm} relative_reference_index={referenceIndex}
            {% else %}
                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} algorithm={algorithm}
            {% endif %}
        {% 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 click here to download (based on frankbags's script)
- 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 Klipper print area mesh

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]}

change logs

  • 2022/07/21
    • Added force lagrange algorithm for mesh with lower than 3 points
    • Added enable_reference_index config flag

The code does not work?

  • I will try to help if possible, you will have to post ALL of your configs, your slicer start gcode and your sliced gcode.
  • If I'm cannot or too slow to respose, our discord members might help you. Check our discord here
@mohalsa
Copy link

mohalsa commented Jan 25, 2024

I am using a single line Gcode in Orca slicer and a macro in my klipper, I can't seem to get it to work with ORCA Slicer, What would be the start and end Gcode in Orca slicer in order to make it parse the correct data and act upon it.

This is my current Machine Code in Orca slicer:

START_PRINT EXTRUDER_TEMP=[nozzle_temperature_initial_layer] BED_TEMP=[bed_temperature_initial_layer]

This is my klipper START_PRINT macro:

[gcode_macro START_PRINT]
variable_parameter_EXTRUDER_TEMP: 220
variable_parameter_BED_TEMP: 65
variable_parameter_AREA_START : 0,0
variable_parameter_AREA_END : 0,0
gcode:
  {% set BED_TEMP = params.BED_TEMP|default(60)|float %}
  {% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(200)|float %}
  M190 S{BED_TEMP}
  ;Set and wait for nozzle to reach temperature
  M109 S{EXTRUDER_TEMP}
  G28
  ;Enable the below line to allow auto bed mesh generation for the object being printed.
  BED_MESH_CALIBRATE AREA_START={params.AREA_START|default("0,0")} AREA_END={params.AREA_END|default("0,0")}
  G92 E0 #Reset Extruder
  G1 Z2.0 F300 #Move Z Axis up
  G1 X10.1 Y20 Z0.28 F5000.0 #Move to start position
  G1 X10.1 Y200.0 Z0.28 F1500.0 E15 #Draw the first line
  G1 X10.4 Y200.0 Z0.28 F5000.0 #Move to side a little
  G1 X10.4 Y20 Z0.28 F1500.0 E30 #Draw the second line
  G92 E0 #Reset Extruder
  G1 Z2.0 F3000 #Move Z Axis up

@DDen87
Copy link

DDen87 commented Jan 27, 2024

@ChipCE do you have some advice on getting this working with the Orca Slicer? I believe it has something to do with the START G-code. This is how mine look like:
START_PRINT EXTRUDER_TEMP=[nozzle_temperature_initial_layer]
BED_TEMP=[bed_temperature_initial_layer_single] MATERIAL=[filament_type]
AREA_START=%MINX%,%MINY% AREA_END=%MAXX%,%MAXY%

@frankbags
Copy link

@ChipCE do you have some advice on getting this working with the Orca Slicer? I believe it has something to do with the START G-code. This is how mine look like: START_PRINT EXTRUDER_TEMP=[nozzle_temperature_initial_layer] BED_TEMP=[bed_temperature_initial_layer_single] MATERIAL=[filament_type] AREA_START=%MINX%,%MINY% AREA_END=%MAXX%,%MAXY%

This is the wrong start g-code for PrusaSlicer flavors. You are using the Cura one.

@DDen87
Copy link

DDen87 commented Jan 28, 2024

@frankbags thanks for the help! It worked!

@wwian
Copy link

wwian commented Feb 27, 2024

Hello @ChipCE!

I saw on the KLIPPER Configuration Changes (20230619) that RELATIVE_REFERENCE_INDEX is no longer available as a parameter for the BED_MESH_CALIBRATE gcode command.

Would you please update the Klipper bed mesh on print area only macro readme.md sample code to reflect this deprecation?

@andchisar
Copy link

For Cura users version 5.7 on Windows, To make the slicer work with the plugin I made it work by putting the file in:
C:\Program Files\UltiMaker Cura 5.7.0\share\cura\plugins\PostProcessingPlugin\scripts.

To put it there you need to be the admin of your PC.
The file must have the same name as the class. (KlipperPrintArea.py)

Finally, select the plugin from Extension->Post Processing->Modify G-Code.

The file I'm referring to is the one reported at the point:
#(Cura slicer plugin) To make the macro to work in Cura slicer, you need to install the post process plugin click here to download (based on frankbags's script)

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