Klipper поддерживает большинство, но не все стандартные команды G-code, к которым мы привыкли во время пользования Marlin. В то время, как команды Marlin записываются букво-численным кодом, например, M118
или M104 S240
, сам Klipper использует человекочитаемый формат команд, например, та же команда M104 S240
будет иметь вид SET_HEATER_TEMPERATURE HEATER=extruder TARGET=240
. Klipper примет оба варианта. Документация по командам
Киллер-фича Klipper - это макросы - последовательности команд G-code, которые можно запускать одной командой. Например, все команды, которые вы прописали в стартовый G-code слайсера, можно прописать в макрос и запускать одной командой START_PRINT
. В интернете существует огромное количество вариантов макросов для Klipper. Обязательно тщательно изучите последовательность команд в добавляемом макросе, чтобы избежать возможных проблем, связанных с несовместимостью параметров нашего принтера и принтера составителя макроса. Документация по макросам
Ниже представлены мои макросы, составленные по принципу «Я художник, я так вижу».
Соответственно, название макроса пишется в квадратных скобках в формате [gcode_macro НАЗВАНИЕ_МАКРОСА]
, затем указываются переменные, если нужно, а сами команды идут после gcode:
с обязательным отступом. Макросы чувствительны к форматированию, будьте внимательны.
В Fluidd можно выборочно добавить кнопки запуска макросов на специальную панель.
[gcode_macro START_PRINT]
variable_retract: 5
gcode:
{% set extruder_temp = params.EXTRUDER_TEMP|default(240)|float %}
{% set bed_temp = params.BED_TEMP|default(70)|float %}
{% set E = printer["gcode_macro START_PRINT"].retract|float %}
CLEAR_PAUSE
M220 S100 # reset feedrate
M221 S100 # reset flowrate
SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={bed_temp} # set bed t℃
TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={bed_temp * 0.75} # wait until bed is partially heated
SET_HEATER_TEMPERATURE HEATER=extruder TARGET={extruder_temp} # set nozzle t℃
G90 # absolute positioning
M82 # absolute extrusion mode
TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={bed_temp} # wait until
TEMPERATURE_WAIT SENSOR=extruder MINIMUM={extruder_temp} # wait until
G28 # home
G0 Z10 F1500 # raise Z
G92 E0 # reset extruder
G1 E{E} F1500 # prime
G92 E0 # reset extruder
Макрос начала печати. Стартовый код для Super/PrusaSlicer’а:
START_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]
для Cura:
START_PRINT EXTRUDER_TEMP={material_print_temperature_layer_0} BED_TEMP={material_bed_temperature_layer_0}
Макрос задаёт целевую температуру прогрева стола, а по достижении неполного нагрева (75%) подключает нагрев сопла. Выставьте коэффициент таким, чтобы стол и сопло у вас достигали целевого нагрева примерно одновременно. Если у вас блок питания работает на пределе, то стоит убрать одновременный нагрев стола и сопла. Тогда замените bed_temp * 0.75
на bed_temp
или удалите эту строчку. Вместо команд Klipper можно использовать и M109/M104/M190/M140, но, по моим наблюдениям, команда M190
ждёт стабилизацию температуры на указанном уровне, что увеличивает время выполнения этого макроса.
Команда set
в теле макроса используется для инициализации переменной и присвоения значения params
которое было передано с командой на выполнение макроса. Здесь передаётся температура нагрева. Если передать только команду START_PRINT
без параметров, то будут использованы указанные в макросе значения по умолчанию. Здесь - 240 ℃ для экструдера и 70 ℃ для стола.
variable_retract
здесь используется в качестве глобальной переменной, которая используется сразу во всех макросах, связанных с печатью для того, чтобы значение ретракта при окончании, отмене или паузе печати совпадало с подачей при начале или возобновлении печати. Значение выставьте удобное для вас. Вызов переменной происходит командой {% set E = printer["gcode_macro START_PRINT"].retract|float %}
Для нормализации подачи пластика в начале печати можно использовать юбку в слайсере. Или добавить в стартовый код слайсера после START_PRINT
макрос PRIME_LINE
, который будет описан позже.
[gcode_macro END_PRINT]
gcode:
{% set E = printer["gcode_macro START_PRINT"].retract|float %}
TURN_OFF_HEATERS
M107 # turn off fan
G91 # relative positioning
G1 E-{E} F1500 # retract
G0 X5 Y5 Z0.2 F5000 # wipe
G0 Z2 F1500 # raise Z
G90 # absolute positioning
PARK
M84 # turn off all motors
BEEP P=200 S=250
Из макросов можно запускать другие макросы! Здесь запускается макрос PARK
, он описан ниже.
[gcode_macro PARK]
gcode:
{% set x_park = params.X|default(0)|float %}
{% set y_park = params.Y|default(-4)|float %}
{% set z_park = params.Z|default(10)|float + printer.toolhead.position.z|float %}
{% set x_max = printer.toolhead.axis_maximum.x|float %}
{% set y_max = printer.toolhead.axis_maximum.y|float %}
{% set z_max = printer.toolhead.axis_maximum.z|float %}
{% if x_park > x_max %}
{% set x_park = x_max %}
{% endif %}
{% if y_park > y_max %}
{% set y_park = y_max %}
{% endif %}
{% if z_park > z_max %}
{% set z_park = z_max %}
{% endif %}
SAVE_GCODE_STATE NAME=PARK_STATE
G90 # absolute positioning
G1 Z{z_park} F1500
G1 X{x_park} Y{y_park} F5000
RESTORE_GCODE_STATE name=PARK_STATE
В макросах можно использовать шаблонизатор Jinja. Полезно для вычислений и условных конструкций «если - то». Здесь в параметрах координаты парковки по X и Y указываются абсолютно, а координата по Z - отностительно. Эти параметры можно передавать при вызове макроса. Например, у меня в макросе END_PRINT
парковка происходит у задней стенки с опусканием стола: PARK X=127 Y=200 Z=50
. При этом по трём осям происходит проверка и корректировка координат, чтобы они находились в пределах лимитов, Z-координата становится абсолютной.
[gcode_macro PAUSE]
rename_existing: BASE_PAUSE
gcode:
{% set E = printer["gcode_macro START_PRINT"].retract|float %}
SAVE_GCODE_STATE NAME=PAUSE_STATE
BASE_PAUSE
G91
G1 E-{E} F1500 # retract
G90
PARK
А ещё есть встроенные макросы, такие как PAUSE
. А если такой макрос вас чем-то не устраивает, его можно изменить или дополнить. Здесь сначала переименовывается встроенный макрос командой rename_existing
, а затем используется в коде под новым именем BASE_PAUSE
.
Ещё здесь используется команда на запоминание режима позиционирования принтера SAVE_GCODE_STATE
. Внутри действия этой команды, такие команды как M82
, M83
, G90
, G91
, G92
могут применяться как вам угодно, т.к. режим позиционирования вернётся к сохранённому после команды RESTORE_GCODE_STATE
. Ссылка
Обязательный для Fluidd макрос. Кнопка вызова добавляется в блок информации о текущей печати.
[gcode_macro RESUME]
rename_existing: BASE_RESUME
gcode:
{% set E = printer["gcode_macro START_PRINT"].retract|float %}
G91
G1 E{E} F1500 # unretract
G90
RESTORE_GCODE_STATE NAME=PAUSE_STATE MOVE=1
BASE_RESUME
Антагонист макроса PAUSE
. Тоже обязательный для Fluidd.
[gcode_macro CANCEL_PRINT]
rename_existing: BASE_CANCEL_PRINT
gcode:
{% set E = printer["gcode_macro START_PRINT"].retract|float %}
TURN_OFF_HEATERS
M107 # turn off fan
G91
G1 E-{E} F1500 # retract
G90
CLEAR_PAUSE
SDCARD_RESET_FILE
BASE_CANCEL_PRINT
PARK
Последний обязательный для Fluidd макрос.
[gcode_macro BEEP]
gcode:
{% set frequency = params.S|default(1000)|float %}
{% set duration = params.P|default(100)|float %}
SET_PIN PIN=BEEPER_pin VALUE={frequency}
G4 P{duration}
SET_PIN PIN=BEEPER_pin VALUE=0
Принтер пищит по команде BEEP
, то же самое, что M300
. За частоту отвечает параметр S
, по умолчанию 1kHz. За длительность - P
, по умолчанию 10ms.
Обратите внимание, что пин пищалки находится на штатном экране принтеров FBG4S и FBG5. Если вы меняли экран, то пин пищалки у вас может быть другим или вообще отсутствовать (например в экране MKS TFT35). Лучше заранее проверьте в консоли команду BEEP
и, в случае ошибки, удалите её из всех макросов.
[gcode_macro FILAMENT_CHANGE]
gcode:
SAVE_GCODE_STATE NAME=FILAMENT_CHANGE_STATE
{% set timer = params.T|default(300)|float %}
{% set unload = params.U|default(100)|float %}
{% set load = params.L|default(100)|float %}
{% if printer.pause_resume.is_paused %}
M118 Already paused
{% else %}
{% if printer.toolhead.homed_axes != "xyz" %}
M118 Homing
G28 # home if not homed
{% else %}
M118 Pausing print
PAUSE
{% endif %}
{% endif %}
M118 Changing filament
SET_IDLE_TIMEOUT TIMEOUT=7200
FILAMENT_UNLOAD U={unload}
COUNTDOWN TIME={timer} MSG="Change filament! Time left: "
FILAMENT_LOAD L={load}
RESTORE_GCODE_STATE NAME=FILAMENT_CHANGE_STATE
{% if printer.pause_resume.is_paused %}
M118 Resuming print
RESUME
{% endif %}
Составной макрос смены филамента. Ставит на паузу PAUSE
, вызывает макрос FILAMENT_UNLOAD
для выгрузки филамента, подаёт звуковой сигнал BEEP
, COUNTDOWN
ждёт 5 минут, пока вы заправите новый филамент в фидер, снова подаёт звуковой сигнал и FILAMENT_LOAD
загружает филамент, RESUME
запустит печать дальше, если макрос был вызван в процессе печати, например из G-code.
[gcode_macro FILAMENT_LOAD]
gcode:
{% set load = params.L|default(100)|float * 0.5 %}
{% set extruder_temp = params.T|default(240)|float %}
SAVE_GCODE_STATE NAME=FILAMENT_LOAD_STATE
LOW_TEMP_CHECK T={extruder_temp}
M118 Loading filament
M83 # relative extrusion
G1 E{load} F1500 # extrude fast
G4 P1000 # wait 1 second
G1 E{load} F200 # extrude slow
BEEP
RESTORE_GCODE_STATE NAME=FILAMENT_LOAD_STATE
[gcode_macro FILAMENT_UNLOAD]
gcode:
{% set unload = params.U|default(100)|float %}
{% set extruder_temp = params.T|default(180)|float %}
SAVE_GCODE_STATE NAME=FILAMENT_UNLOAD_STATE
LOW_TEMP_CHECK T={extruder_temp}
M118 Unloading filament
M83 # relative extrusion
G1 E2 F200 # extrude a little
G1 E-10 F200 # retract a little
G1 E-{unload} F1500 # retract a lot
BEEP
RESTORE_GCODE_STATE NAME=FILAMENT_UNLOAD_STATE
Оба вызывают LOW_TEMP_CHECK
для проверки температуры сопла.
[gcode_macro LOW_TEMP_CHECK]
gcode:
{% set extruder_temp = params.T|default(240)|float %}
{% if printer.extruder.target > extruder_temp %} # if there is a setpoint for extruder
{% set extruder_temp = printer.extruder.target %}
{% endif %}
{% if printer.extruder.temperature < extruder_temp %} # heat to the target
M118 Heating to {extruder_temp}
SET_HEATER_TEMPERATURE HEATER=extruder TARGET={extruder_temp}
TEMPERATURE_WAIT SENSOR=extruder MINIMUM={extruder_temp}
{% endif %}
Если сопло холодное и нагрев не включен, то он запустится с указанным параметром по умолчанию: 180℃ для выгрузки и 240℃ для загрузки.
[gcode_macro COUNTDOWN]
gcode:
{% set timer = params.TIME|default(10)|int %}
{% set message = params.MSG|default("Time: ") %}
# countdown
{% if timer > 60 %}
{% for s in range(timer, 60, -10) %}
M118 {message} {s}s
G4 P10000 # dwell 10 seconds
{% endfor %}
{% set timer = 60 %}
{% endif %}
{% if timer > 10 %}
{% for s in range(timer, 10, -5) %}
M118 {message} {s}s
G4 P5000 # dwell 5 seconds
{% endfor %}
{% set timer = 10 %}
{% endif %}
{% if timer > 0 %}
{% for s in range(timer, 0, -1) %}
M118 {message} {s}s
G4 P1000 # dwell 1 second
{% endfor %}
{% endif %}
BEEP
Совместимость с командами Marlin G-code. Преобразования команд, таких как M204, M900, M600 и так далее, у которых нет реализации в Klipper, либо реализованы в его человекочитаемом формате. Часть из них важна для лёгкой передачи настроек из слайстеров, как M204. Часть не важна и показаны скорее для полноты картины.
[gcode_macro M76] # Marlin Compatibility
gcode:
PAUSE
[gcode_macro M601] # Prusa Compatibility
gcode:
PAUSE
[gcode_macro G27] # Marlin Compatibility
gcode:
PARK
[gcode_macro M125] # Marlin Compatibility
gcode:
PARK
[gcode_macro M300] # Marlin Compatibility
gcode:
BEEP
[gcode_macro M600] # Marlin Compatibility
gcode:
FILAMENT_CHANGE
[gcode_macro M701] # Marlin Compatibility
gcode:
FILAMENT_LOAD
[gcode_macro M702] # Marlin Compatibility
gcode:
FILAMENT_UNLOAD
[gcode_macro M92]
gcode:
{% set extruder_steps = params.E|default(0.0025)|float %}
SET_EXTRUDER_STEP_DISTANCE DISTANCE={extruder_steps}
[gcode_macro M500]
gcode:
SAVE_CONFIG
Марлин принимает команду M204
, но либо в виде M204 S<value>
, либо M204 P<value> T<value>
, где указаны оба параметра. Cura прописывает ускорение в G-code в виде M204 S<value>
, так что с ней проблем нет, а вот Prusa(Super)Slicer - в виде M204 P<value>
, без T<value>
, что вызывает ошибку. Исправляем, теперь Klipper принимает любые комбинации этих параметров:
[gcode_macro M204]
rename_existing: M204.1
gcode:
{% set factor = params.F|default(0.5)|float %}
{% if 'S' in params %}
SET_VELOCITY_LIMIT ACCEL={S} ACCEL_TO_DECEL={ S|float * factor }
{% else %}
{% if 'P' in params %}
{% if 'T' in params %}
{% if P|int < T|int %}
SET_VELOCITY_LIMIT ACCEL={P} ACCEL_TO_DECEL={ P|float * factor }
{% else %}
SET_VELOCITY_LIMIT ACCEL={T} ACCEL_TO_DECEL={ T|float * factor }
{% endif %}
{% else %}
SET_VELOCITY_LIMIT ACCEL={P} ACCEL_TO_DECEL={ P|float * factor }
{% endif %}
{% elif 'T' in params %}
SET_VELOCITY_LIMIT ACCEL={T} ACCEL_TO_DECEL={ T|float * factor }
{% endif %}
{% endif %}
Использование этого макроса не совсем корректно, так как SQUARE_CORNER_VELOCITY
в Klipper не является прямым аналогом ни JD, ни Jerk, и значения будут совсем другими. Но для передачи настроек из слайсера в Klipper сойдёт, если вы выставите корректные значения в слайсере. Хотя, по большому счёту их вполне можно один раз откалибровать, больше не трогать и запретить слайсеру менять значения.
[gcode_macro M205]
gcode:
{% if 'J' in params %}
SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY={J}
{% elif 'X' in params %}
SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY={X}
{% elif 'Y' in params %}
SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY={Y}
{% endif %}
Управление прошивочным откатом.
[gcode_macro M207]
gcode:
{% set length = params.S|default(0.5)|float %}
{% set speed = params.F|default(25)|float %}
SET_RETRACTION RETRACT_LENGTH={length} RETRACT_SPEED={speed}
Ещё один костыль для такого слайсера, как Cura. В случае Prusa(Super)Slicer можно прописать SET_PRESSURE_ADVANCE ADVANCE=<value>
в стартовом G-code филамента, что очень удобно.
[gcode_macro M900]
gcode:
{% if 'K' in params %}
SET_PRESSURE_ADVANCE ADVANCE={ params.K|float }
{% endif %}
Макрос ну для совсем специфической совместимости, например с отдельными G-code файлами с набором команд для настройки PID. Лучше делать это руками, командой PID_CALIBRATE
[gcode_macro M303]
gcode:
{% if 'E' in params %}
{% set heater = params.E|default(0)|int %}
{% set temp = params.T|default(0)|float %}
{% if heater == 0 %} # extruder
{% if temp >= printer.configfile.settings.extruder.min_extrude_temp|float %}
{% if temp <= printer.configfile.settings.extruder.max_temp|float %}
PID_CALIBRATE HEATER=extruder TARGET={T}
{% endif %}
{% endif %}
{% elif heater == -1 %} # bed
{% if temp <= printer.configfile.settings.heater_bed.max_temp|float %}
PID_CALIBRATE HEATER=heater_bed TARGET={T}
{% endif %}
{% endif %}
{% endif %}
Команда M486
в слайсере присваивает ярлыки моделям для того, чтоб плагинам Октопринт было легче отменить печать отдельных моделей, не прерывая печать остальных. В Klipper такой функциональности нет и команда M486
постоянно показывает ошибку в терминале. Для удаления этой ошибки можно использовать «пустой» макрос:
[gcode_macro M486]
gcode:
# Do nothing
В качестве бонуса моя версия макроса для нормализации потока и убирания вытекшего в простое пластика. В сети полно примеров попроще, но этот макрос является универсальным, так как учитывает диаметр сопла и скорость печати первого слоя в слайсере, что критично для флексов. Для этого производит упрощённый подсчёт объёма выдавленного пластика V = lwh, где l - длина линии, w - ширина (равна диаметру сопла), h - высота (равна примерно 3/4 ширины сопла, кратна 0.04). Рисует линию вдоль края стола по оси X по умолчанию, или, если указать параметр Y
, то вдоль оси Y соответственно. Для вызова добавляем в стартовый код принтера в слайсере
PRIME_LINE F={first_layer_speed}
PRIME_LINE F={speed_print_layer_0}
Является заменой юбки. Основное преимущество - легче удалять.
[gcode_macro PRIME_LINE]
gcode:
{% set feedrate = params.F|default(10)|float * 60 %}
{% set length = 100.0 %}
{% set width = printer.configfile.settings.extruder.nozzle_diameter|float %}
{% set height = ( (width / 0.04)|int - (width / 0.04 / 4)|int )|float * 0.04 %}
{% set extrude = length * width * height / 1.6 %}
SAVE_GCODE_STATE NAME=PRIME_LINE_STATE
SET_IDLE_TIMEOUT TIMEOUT=7200
{% if 'Y' in params %}
{% set x_start = 1.0 %}
{% set y_start = (printer.toolhead.axis_maximum.y|float - 100) / 2 %}
G0 X{x_start} Y{y_start} F5000 # move to start position
G0 Z{height} F1500
G91 # relative positioning
G1 Y100 E{extrude} F{feedrate} # draw the 1st line
G0 X{width} F5000 # move to the next line
G1 Y-100 E{extrude} F{feedrate} # draw the 2nd line
{% else %}
{% set x_start = (printer.toolhead.axis_maximum.x|float - 100) / 2 %}
{% set y_start = 1.0 %}
G0 X{x_start} Y{y_start} F5000 # move to start position
G0 Z{height} F1500
G91 # relative positioning
G1 E4 F{feedrate} # prime
G1 X100 E{extrude} F{feedrate} # draw the 1st line
G0 Y{width} F5000 # move to the next line
G1 X-100 E{extrude} F{feedrate} # draw the 2nd line
{% endif %}
RESTORE_GCODE_STATE NAME=PRIME_LINE_STATE