Automatic control of Rectangular HEATBED sections based on PRINT AREA

Our Voron 2.4 printer has 8 (each ~100x100mm) shaped heatbed sections; Arranged in a 4x2 grid, they are controlled by a 8 channel SSR. Each one is 100W AC Silicone pad heater, totaling 800W.
There are two SKR 1.3 Boards for the printer. SKR 1.3 supports these pins for thermistor analog inputs - 0.23, 0.24, 0.25, 1.30, 1.31.
The first 4 heatbeds are connected to the first SKR board (MCU Z), the next 4 heatbeds are connected to the other board (MCU XYE). Every heatbed and its thermistor is connected to the same MCU respectively.
SKR 1.3 pinout

However only after building the printer did we find out that multiple heatbeds are not yet fully supported by Slicers or Klipper. For a while we have been manually enabling the heatbeds. But this was not ideal. Thanks to the flexibility of Klipper macros, it is possible to enable the required heatbeds automatically.

In the configuration, the first heatbed is defined as the default heater_bed. The rest are defined as heater_generic ( heater_bed2, heater_bed3, heater_bed4,…)

The implementation of this method is simple and straightforward. The Print Area is compared with a Heatbed Area- If the two rectangles overlap, then the corresponding heatbed section is enabled

1 Like

Current limitations:

  • The print area reported by the slicer is a rectangle, For some shapes this can cause a heater bed to be enabled even when there is no actual print on it. Here’s an example: In this case the heatbed 4 will be enabled since the assumed print area overlaps it.

  • Temperature wait commands are not yet implemented since the heatbeds reach their temperature very quickly. This can be an issue for some printers if heatbeds are slow.

1 Like

Example Setup:

Auto Heatbed macro:

[gcode_macro HEATBED_AUTO]
variable_parameter_AREA_START : 0,0
variable_parameter_AREA_END : 0,0
gcode:

#Set the coordinates of the heatbed sections
    {% set x0 = 0 %}
    {% set x1 = 100 %}
    {% set x2 = 200 %}
    {% set x3 = 300 %}
    {% set x4 = 400 %}

    {% set y0 = 0 %}
    {% set y1 = 105 %}
    {% set y2 = 210 %}
#Get parameters from Slicer
    {% set BED_TEMP = params.BED_TEMP|default(50)|float %}
    {% if params.AREA_START and params.AREA_END %}
        {% set A = params.AREA_START.split(",")[0]|float %}
    	{% set B = params.AREA_START.split(",")[1]|float %}
    	{% set C = params.AREA_END.split(",")[0]|float %}
    	{% set D = params.AREA_END.split(",")[1]|float %}

#Check and enable the required heatbeds
    #Heatbed 1  x1,y0  x2,y1
        {% if ((C > x1) and (D > y0) and (A < x2) and (B < y1)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={BED_TEMP}        
        {% endif %}
    #Heatbed 2  x0,y0  x1,y1
        {% if ((C > x0) and (D > y0) and (A < x1) and (B < y1)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed2 TARGET={BED_TEMP}         
        {% endif %}
    #Heatbed 3  x0,y1  x1,y2
        {% if ((C > x0) and (D > y1) and (A < x1) and (B < y2)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed3 TARGET={BED_TEMP}         
        {% endif %}
    #Heatbed 4  x1,y1  x2,y2
        {% if ((C > x1) and (D > y1) and (A < x2) and (B < y2)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed4 TARGET={BED_TEMP}        
        {% endif %}
    #Heatbed 5  x2,y1  x3,y2
        {% if ((C > x2) and (D > y1) and (A < x3) and (B < y2)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed5 TARGET={BED_TEMP}         
        {% endif %}
    #Heatbed 6  x3,y1  x4,y2
        {% if ((C > x3) and (D > y1) and (A < x4) and (B < y2)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed6 TARGET={BED_TEMP}         
        {% endif %}
    #Heatbed 7  x3,y0  x4,y1
        {% if ((C > x3) and (D > y0) and (A < x4) and (B < y1)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed7 TARGET={BED_TEMP}        
        {% endif %}
    #Heatbed 8  x2,y0  x3,y1
        {% if ((C > x2) and (D > y0) and (A < x3) and (B < y1)) %}
            SET_HEATER_TEMPERATURE HEATER=heater_bed8 TARGET={BED_TEMP}         
        {% endif %}
    {% endif %}

Slicer Setup:
Cura: requires MeshPrintSize.py post processing script by frankbags
START_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0} AREA_START=%MINX%,%MINY% AREA_END=%MAXX%,%MAXY%

SuperSlicer / PrusaSlicer:
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]}

PRINT_START macro:
The Heater bed command in the PRINT_START macro must be modified:
HEATBED_AUTO BED_TEMP={params.BED|default(50)|float} AREA_START={params.AREA_START|default("0,0")} AREA_END={params.AREA_END|default("0,0")}

2 Likes