LeoVoron2.4 config (history squashed 2026-10-11)
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
#########################################
|
||||
###### FLOW MULTIPLIER CALIBRATION ######
|
||||
#########################################
|
||||
# Written by Frix_x#0161 #
|
||||
# @version: 1.5
|
||||
|
||||
# CHANGELOG:
|
||||
# v1.5: moved the install notes into a proper markdown file in: doc > features > flow_calibration.md
|
||||
# v1.4: fix issue when extrude_factor is != 1
|
||||
# v1.3: fix the logging
|
||||
# v1.2: fix for those using absolute extrusion that leads to an error
|
||||
# v1.1: added part cooling fan control and some speed optimizations
|
||||
# v1.0: first flow calibration macro
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------------
|
||||
# If you want to use it into your own config, please install it as a standalone macro as described in the
|
||||
# installation section of this file: doc > features > flow_calibration.md
|
||||
# -------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
### What is it ? ###
|
||||
# The main reason for this set of macros is to get a filament and slicer agnostic way to calibrate the flow extrusion multiplier.
|
||||
# The goal is to make it easy to set, share and use it.
|
||||
|
||||
# This macro is parametric and most of the values can be adjusted with their respective input parameters.
|
||||
# It can be called without any parameters - in which case the default values would be used - or with any combination of parameters as desired.
|
||||
|
||||
# Feel free to ping me on Discord (Frix_x#0161) if you need help or have any comments to improve it :)
|
||||
|
||||
# https://github.com/yomgui1/klipper-voron-config/blob/main/doc/features/flow_calibration.md?ysclid=lzuo22xrfl138875688
|
||||
|
||||
# ===========================================================================================================
|
||||
# DO NOT MODIFY THOSE VARIABLES (they are used internaly by the flow calibration macro)
|
||||
[gcode_macro _FLOW_CALIB_VARIABLES]
|
||||
variable_last_shell_thickness: 0.0
|
||||
variable_last_evalue: 0.0
|
||||
gcode:
|
||||
|
||||
[gcode_macro FLOW_MULTIPLIER_CALIBRATION]
|
||||
description: Print a small tower to calibrate the extrusion flow multiplier by measuring the shell
|
||||
gcode:
|
||||
#
|
||||
# PARAMETERS
|
||||
#
|
||||
{% set do_raft = params.DO_RAFT|default(1)|int %} # whether to print a raft or not
|
||||
{% set do_retract = params.DO_RECTRACT|default(0)|int %} # whether to enable retract/unrectract on travel moves
|
||||
{% set print_size = params.PRINT_SIZE|default(40)|int %} # size of the printed object on the build plate
|
||||
{% set print_height = params.HEIGHT|default(15)|int %} # height of the printed object
|
||||
{% set corner_radius = params.CORNER_RADIUS|default(8)|int %} # radius of the corners to smooth the shell and toolpath
|
||||
{% set number_of_perimeters = params.PERIMETERS|default(2)|int %} # number of perimeters to print the shell
|
||||
{% set fan_speed = params.FAN_SPEED|default(20)|int %} # part cooling fan speed in percent (0-100)
|
||||
|
||||
{% set e_multiplier = params.EXTRUSION_MULTIPLIER|default(1.00)|float %} # extrusion multiplier for the shell
|
||||
{% set filament_diameter = params.FILAMENT_DIAMETER|default(1.75)|float %} # filament diameter
|
||||
{% set extrusion_width = params.EXTRUSION_WIDTH|default(0.4)|float %} # extrusion width goal for one line
|
||||
{% set layer_height = params.LAYER_HEIGHT|default(0.2)|float %} # layer height for the print
|
||||
|
||||
{% set retract_length = params.RETRACT_LENGTH|default(0.5)|float %} # how much to retract when traveling between print moves
|
||||
{% set initial_purge = params.PURGE_MM|default(1)|int %} # mm of filament to purge before printing. set to 0 to disable
|
||||
{% set z_hop_height = 2 * layer_height %}
|
||||
|
||||
{% set feedrate_print = params.CONTROL_SPEED|default(100)|int * 60 %} # print feedrate
|
||||
{% set feedrate_travel = params.TRAVEL_SPEED|default(200)|int * 60 %} # travel feedrate between print moves
|
||||
{% set feedrate_raft = params.RAFT_SPEED|default(60)|int * 60 %} # print feedrate for printing raft
|
||||
{% set feedrate_z = params.Z_LIFT_SPEED|default(20)|int * 60 %} # z axis travel feedrate
|
||||
{% set feedrate_retract = params.RETRACT_SPEED|default(50)|int * 60 %} # retract and deretract feedrate
|
||||
|
||||
#
|
||||
# COMPUTED VALUES
|
||||
#
|
||||
{% set e_per_mm = ((extrusion_width - layer_height) * layer_height + 3.14159 * (layer_height / 2)**2) / (3.14159 * (filament_diameter / 2)**2) %} # computed E factor (similar to Slic3r/PrusaSlicer/SuperSlicer)
|
||||
{% set spacing = extrusion_width - layer_height * (1 - 3.14159 / 4) %} # line spacing during the print
|
||||
{% set shell_thickness = extrusion_width + (number_of_perimeters|float - 1) * spacing %} # theoric shell thickness
|
||||
|
||||
{% set max_x = printer.toolhead.axis_maximum.x|float %}
|
||||
{% set max_y = printer.toolhead.axis_maximum.y|float %}
|
||||
{% set x_start = max_x / 2 - print_size / 2 %}
|
||||
{% set y_start = max_y / 2 - print_size / 2 %}
|
||||
{% set x_end = x_start + print_size %}
|
||||
{% set y_end = y_start + print_size %}
|
||||
|
||||
{% set num_raft_lines = ([print_size, max_x]|min / spacing)|round(0, 'floor')|int %}
|
||||
{% set raft_size = num_raft_lines * spacing %}
|
||||
|
||||
#
|
||||
# STARTING...
|
||||
#
|
||||
{action_respond_info("")}
|
||||
{action_respond_info("Starting extrusion flow calibration print")}
|
||||
{action_respond_info("This operation can not be interrupted by normal means. Hit the \"emergency stop\" button to stop it if needed")}
|
||||
{action_respond_info("")}
|
||||
{action_respond_info("Exrusion multiplier used: %.4f" % e_multiplier)}
|
||||
{action_respond_info("Number of perimeters to print: %d" % number_of_perimeters)}
|
||||
{action_respond_info("THEORIC SHELL THICKNESS: %.4f" % shell_thickness)}
|
||||
{action_respond_info("")}
|
||||
{action_respond_info("Measure the shell thickness using a caliper or micrometer. Then call the computation macro with the measured value:")}
|
||||
{action_respond_info("COMPUTE_FLOW_MULTIPLIER MEASURED_THICKNESS=xxx.xxx")}
|
||||
{action_respond_info("")}
|
||||
|
||||
SAVE_GCODE_STATE NAME=STATE_FLOW_MULTIPLIER_CALIBRATION
|
||||
|
||||
#
|
||||
# set variables for later computation
|
||||
#
|
||||
SET_GCODE_VARIABLE MACRO=_FLOW_CALIB_VARIABLES VARIABLE=last_shell_thickness VALUE={shell_thickness}
|
||||
SET_GCODE_VARIABLE MACRO=_FLOW_CALIB_VARIABLES VARIABLE=last_evalue VALUE={e_multiplier}
|
||||
|
||||
#
|
||||
# purging before raft
|
||||
#
|
||||
G90
|
||||
M83
|
||||
G92 E0.0
|
||||
G0 X{x_start} Y{y_start - 5} Z{layer_height} F{feedrate_travel} # move at the start position to do a purge line
|
||||
|
||||
G91 # use relative coordinates for the prime line
|
||||
G1 E{initial_purge} F{5 * 60}
|
||||
G1 X{raft_size} E{raft_size * e_per_mm * 1.5} F{feedrate_raft / 2} # print prime line
|
||||
G1 Y-{extrusion_width} E{extrusion_width * e_per_mm} F{feedrate_raft / 2} # move to next line
|
||||
G1 X-{raft_size} E{raft_size * e_per_mm} F{feedrate_raft / 2} # print second prime line
|
||||
|
||||
G1 E-{retract_length} F{feedrate_retract} # retract
|
||||
G0 Z{z_hop_height} F{feedrate_z} # z-hop
|
||||
|
||||
G90 # back to absolute coordinates
|
||||
G0 X{x_start} Y{y_start} F{feedrate_travel} # move to start position
|
||||
G1 Z{layer_height} F{feedrate_z} # move to print height
|
||||
G1 E{retract_length} F{feedrate_retract} # unretract
|
||||
|
||||
# set extrude_factor
|
||||
M221 S{e_multiplier * 100}
|
||||
|
||||
#
|
||||
# print the raft
|
||||
#
|
||||
{% if do_raft == 1 %}
|
||||
G91 # use relative coordinates for the raft
|
||||
{% for curr_raft_line in range(1, num_raft_lines + 2) %}
|
||||
# print a raft line with alternating direction
|
||||
G1 Y{loop.cycle(1.0, -1.0) * raft_size} E{raft_size * e_per_mm} F{feedrate_raft}
|
||||
|
||||
# spacing move
|
||||
{% if not loop.last %}
|
||||
G1 X{spacing} E{spacing * e_per_mm} F{feedrate_raft}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
G1 E-{retract_length} F{feedrate_retract} # retract
|
||||
G0 Z{z_hop_height} F{feedrate_z} # z-hop
|
||||
G90 # back to absolute coordinates
|
||||
{% endif %}
|
||||
|
||||
#
|
||||
# print the shell
|
||||
#
|
||||
G90
|
||||
M106 S{fan_speed * 255 / 100}
|
||||
|
||||
# for each layer
|
||||
{% for curr_layer in range(1, (print_height / layer_height)|round|int) %}
|
||||
G0 X{x_start + corner_radius} Y{y_start} F{feedrate_travel} # move to XY start position
|
||||
G1 Z{(curr_layer * layer_height) + (layer_height if do_raft == 1 else 0)} F{feedrate_z} # move to Z start position
|
||||
|
||||
# print one layer of the shell (in a for loop to do all the perimeters of one layer)
|
||||
{% for perim_num in range(number_of_perimeters) %}
|
||||
# compute values for the current perimeter (offset and radius)
|
||||
{% set perim_offset = perim_num * spacing %}
|
||||
{% set perim_radius = corner_radius - (perim_num * spacing) %}
|
||||
|
||||
# start position of the current perimeter
|
||||
G1 X{x_start + corner_radius} Y{y_start + perim_offset} F{feedrate_travel}
|
||||
{% if do_retract == 1 %}
|
||||
G1 E{retract_length} F{feedrate_retract} # unretract
|
||||
{% endif %}
|
||||
|
||||
# print the perimeter using the offset and radius computed
|
||||
G1 X{x_end - corner_radius} Y{y_start + perim_offset} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print}
|
||||
G3 X{x_end - perim_offset} Y{y_start + corner_radius} J{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print}
|
||||
G1 X{x_end - perim_offset} Y{y_end - corner_radius} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print}
|
||||
G3 X{x_end - corner_radius} Y{y_end - perim_offset} I-{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print}
|
||||
G1 X{x_start + corner_radius} Y{y_end - perim_offset} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print}
|
||||
G3 X{x_start + perim_offset} Y{y_end - corner_radius} J-{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print}
|
||||
G1 X{x_start + perim_offset} Y{y_start + corner_radius} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print}
|
||||
G3 X{x_start + corner_radius} Y{y_start + perim_offset} I{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print}
|
||||
|
||||
{% if do_retract == 1 %}
|
||||
G1 E-{retract_length} F{feedrate_retract} # retract
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if do_retract == 1 %}
|
||||
G91
|
||||
G0 Z{z_hop_height} F{feedrate_z}
|
||||
G90
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
#
|
||||
# retract and move away
|
||||
#
|
||||
G1 E-{retract_length} F{feedrate_retract}
|
||||
G91
|
||||
G0 Z20 F{feedrate_travel}
|
||||
|
||||
RESTORE_GCODE_STATE NAME=STATE_FLOW_MULTIPLIER_CALIBRATION
|
||||
|
||||
|
||||
[gcode_macro COMPUTE_FLOW_MULTIPLIER]
|
||||
description: Compute a new flow multiplier by using the measured shell thickness on the calibration print
|
||||
gcode:
|
||||
{% set evalue = params.OLD_EXTRUSION_MULTIPLIER|default(0.0)|float %} # extrusion multiplier used for the calibration print
|
||||
{% set theorical_thickness = params.THEORICAL_THICKNESS|default(0.0)|float %} # theorical shell thickness
|
||||
{% set measured_thickness = params.MEASURED_THICKNESS|default(0.0)|float %} # measured shell thickness on the calibration print
|
||||
|
||||
# if there is no OLD_EXTRUSION_MULTIPLIER passed as param, get the one from the last print calib run
|
||||
{% if evalue == 0.0 %}
|
||||
{% set last_evalue = printer["gcode_macro _FLOW_CALIB_VARIABLES"].last_evalue %}
|
||||
|
||||
# then, if there is also no evalue saved from the last run, alert user
|
||||
{% if last_evalue == 0.0 %}
|
||||
{action_respond_info("It seems that no calibration print was run prior to this (or a restart of Klipper occured).")}
|
||||
{action_respond_info("You can still manually use it by calling again this macro like that:")}
|
||||
{action_respond_info("COMPUTE_FLOW_MULTIPLIER OLD_EXTRUSION_MULTIPLIER=xxx.xxx THEORICAL_THICKNESS=xxx.xxx MEASURED_THICKNESS=xxx.xxx")}
|
||||
{action_raise_error("not enough data to perform the computation of the new flow !")}
|
||||
{% else %}
|
||||
{% set final_evalue = last_evalue %}
|
||||
{action_respond_info("Using OLD_EXTRUSION_MULTIPLIER: %.3f" % final_evalue)}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set final_evalue = evalue %}
|
||||
{action_respond_info("Using OLD_EXTRUSION_MULTIPLIER: %.3f" % final_evalue)}
|
||||
{% endif %}
|
||||
|
||||
# similarly, if there is no THEORICAL_THICKNESS passed as param, get the one from the last print calib run
|
||||
{% if theorical_thickness == 0.0 %}
|
||||
{% set last_shell_thickness = printer["gcode_macro _FLOW_CALIB_VARIABLES"].last_shell_thickness %}
|
||||
|
||||
# then, if there is also no evalue saved from the last run, alert user
|
||||
{% if last_shell_thickness == 0.0 %}
|
||||
{action_respond_info("It seems that no calibration print was run prior to this (or a restart of Klipper occured).")}
|
||||
{action_respond_info("You can still manually use it by calling again this macro like that:")}
|
||||
{action_respond_info("COMPUTE_FLOW_MULTIPLIER OLD_EXTRUSION_MULTIPLIER=xxx.xxx THEORICAL_THICKNESS=xxx.xxx MEASURED_THICKNESS=xxx.xxx")}
|
||||
{action_raise_error("not enough data to perform the computation of the new flow !")}
|
||||
{% else %}
|
||||
{% set final_theorical_thickness = last_shell_thickness %}
|
||||
{action_respond_info("Using THEORICAL_THICKNESS: %.3f" % final_theorical_thickness)}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set final_theorical_thickness = theorical_thickness %}
|
||||
{action_respond_info("Using THEORICAL_THICKNESS: %.3f" % final_theorical_thickness)}
|
||||
{% endif %}
|
||||
|
||||
# use the measured thickness from the user to compute a new flow value
|
||||
{% if measured_thickness == 0.0 %}
|
||||
{action_respond_info("You must use a caliper or micrometer to measure the calibration print shell thickness and call this macro with the measured value !!!")}
|
||||
{action_respond_info("COMPUTE_FLOW_MULTIPLIER MEASURED_THICKNESS=xxx.xxx")}
|
||||
{action_raise_error("not enough data to perform the computation of the new flow !")}
|
||||
{% else %}
|
||||
{% set new_evalue = final_theorical_thickness * final_evalue / measured_thickness %}
|
||||
{action_respond_info("NEW COMPUTED FLOW VALUE: %.3f" % new_evalue)}
|
||||
{action_respond_info("Use this new value as extrusion multiplier in your slicer of choice")}
|
||||
{action_respond_info("")}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
[gcode_shell_command backup_cfg]
|
||||
command: sh /home/biqu/printer_data/config/.autocommit.sh
|
||||
timeout: 30
|
||||
verbose: True
|
||||
|
||||
[gcode_macro BACKUP_CFG]
|
||||
description: Backs up config directory GitHub
|
||||
gcode:
|
||||
RUN_SHELL_COMMAND CMD=backup_cfg
|
||||
@@ -0,0 +1,174 @@
|
||||
[gcode_macro MOVE_UP]
|
||||
variable_set_kinematic_z: 20
|
||||
variable_up_z: 10
|
||||
gcode:
|
||||
SAVE_GCODE_STATE NAME=my_move_up_state
|
||||
{% if not 'z' in printer.toolhead.homed_axes %}
|
||||
SET_KINEMATIC_POSITION Z={set_kinematic_z}
|
||||
{% endif %}
|
||||
G91
|
||||
G0 Z{up_z} F1200
|
||||
RESTORE_GCODE_STATE NAME=my_move_up_state
|
||||
|
||||
[gcode_macro _HOME_X]
|
||||
variable_homing_current: 0.49
|
||||
variable_start_retract: 15
|
||||
gcode:
|
||||
# Always use consistent run_current on A/B steppers during sensorless homing
|
||||
{% set RUN_CURRENT_X = printer.configfile.settings['tmc5160 stepper_x'].run_current|float %}
|
||||
{% set RUN_CURRENT_Y = printer.configfile.settings['tmc5160 stepper_y'].run_current|float %}
|
||||
SET_TMC_CURRENT STEPPER=stepper_x CURRENT={homing_current}
|
||||
SET_TMC_CURRENT STEPPER=stepper_y CURRENT={homing_current}
|
||||
|
||||
M117 Homing X...
|
||||
|
||||
SET_KINEMATIC_POSITION X={start_retract}
|
||||
G91
|
||||
G1 X-{start_retract} F1200
|
||||
|
||||
M400
|
||||
G28 X
|
||||
|
||||
G91
|
||||
G1 X-40 F1200
|
||||
#G4 P500
|
||||
|
||||
M117
|
||||
|
||||
SET_TMC_CURRENT STEPPER=stepper_x CURRENT={RUN_CURRENT_X}
|
||||
SET_TMC_CURRENT STEPPER=stepper_y CURRENT={RUN_CURRENT_Y}
|
||||
|
||||
|
||||
[gcode_macro _HOME_Y]
|
||||
variable_homing_current: 0.49
|
||||
variable_start_retract: 15
|
||||
gcode:
|
||||
# Set current for sensorless homing
|
||||
{% set RUN_CURRENT_X = printer.configfile.settings['tmc5160 stepper_x'].run_current|float %}
|
||||
{% set RUN_CURRENT_Y = printer.configfile.settings['tmc5160 stepper_y'].run_current|float %}
|
||||
SET_TMC_CURRENT STEPPER=stepper_x CURRENT={homing_current}
|
||||
SET_TMC_CURRENT STEPPER=stepper_y CURRENT={homing_current}
|
||||
#SET_TMC_FIELD FIELD=SGT STEPPER=stepper_x VALUE=1
|
||||
#G4 P1000
|
||||
|
||||
M117 Homing Y...
|
||||
|
||||
SET_KINEMATIC_POSITION Y={start_retract}
|
||||
G91
|
||||
G1 Y-{start_retract} F1200
|
||||
|
||||
M400
|
||||
G28 Y
|
||||
|
||||
G91
|
||||
G1 Y-10 F1200
|
||||
#G4 P500
|
||||
|
||||
M117
|
||||
# Set current during print
|
||||
SET_TMC_CURRENT STEPPER=stepper_x CURRENT={RUN_CURRENT_X}
|
||||
SET_TMC_CURRENT STEPPER=stepper_y CURRENT={RUN_CURRENT_Y}
|
||||
|
||||
|
||||
[homing_override]
|
||||
axes: xyz
|
||||
gcode:
|
||||
{% set home_all = 'X' not in params and 'Y' not in params and 'Z' not in params %}
|
||||
{% set move_x = params.X|default(printer.toolhead.axis_maximum.y/2)|int %}
|
||||
{% set move_y = params.Y|default(printer.toolhead.axis_maximum.y/2)|int %}
|
||||
{% if params.Z == '' %}
|
||||
{% set move_z = 10 %}
|
||||
{% else %}
|
||||
{% set move_z = params.Z|default(10)|int %}
|
||||
{% endif %}
|
||||
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=homing VALUE=True
|
||||
STATUS_HOMING
|
||||
|
||||
{% if home_all or 'X' or 'Y' in params %}
|
||||
INIT_TMC STEPPER=stepper_y
|
||||
INIT_TMC STEPPER=stepper_x
|
||||
{% endif %}
|
||||
|
||||
{% if home_all or 'Z' in params %}
|
||||
BED_MESH_CLEAR
|
||||
MOVE_UP
|
||||
{% endif %}
|
||||
|
||||
{% if home_all or 'X' in params %}
|
||||
_HOME_X
|
||||
{% endif %}
|
||||
|
||||
{% if home_all or 'Y' in params %}
|
||||
_HOME_Y
|
||||
{% endif %}
|
||||
|
||||
|
||||
G90
|
||||
|
||||
{% if home_all or 'Z' in params %}
|
||||
G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y/2} F12000 #probe point
|
||||
G28 Z
|
||||
G1 Z{move_z} F1200
|
||||
{% endif %}
|
||||
|
||||
#{ action_respond_info("Move X,Y => {},{}".format(params.X,params.Y)) }
|
||||
|
||||
{% if params.X %}
|
||||
|
||||
G1 X{move_x} F12000
|
||||
{% endif %}
|
||||
|
||||
{% if params.Y %}
|
||||
G1 Y{move_y} F12000
|
||||
{% endif %}
|
||||
|
||||
STATUS_OFF
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=homing VALUE=False
|
||||
|
||||
[gcode_macro CG28]
|
||||
gcode:
|
||||
{% if "xyz" not in printer.toolhead.homed_axes %}
|
||||
G28
|
||||
{% endif %}
|
||||
|
||||
[gcode_macro PARKFRONT]
|
||||
gcode:
|
||||
CG28 ; home if not already homed
|
||||
SAVE_GCODE_STATE NAME=PARKFRONT
|
||||
G90 ; absolute positioning
|
||||
G0 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_minimum.y+5} Z{printer.toolhead.axis_maximum.z/2} F6000
|
||||
RESTORE_GCODE_STATE NAME=PARKFRONT
|
||||
|
||||
[gcode_macro PARKFRONTLOW]
|
||||
gcode:
|
||||
CG28 ; home if not already homed
|
||||
SAVE_GCODE_STATE NAME=PARKFRONT
|
||||
G90 ; absolute positioning
|
||||
G0 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_minimum.y+5} Z20 F6000
|
||||
RESTORE_GCODE_STATE NAME=PARKFRONT
|
||||
|
||||
[gcode_macro PARKREAR]
|
||||
gcode:
|
||||
CG28 ; home if not already homed
|
||||
SAVE_GCODE_STATE NAME=PARKREAR
|
||||
G90 ; absolute positioning
|
||||
G0 X{printer.toolhead.axis_minimum.x+10} Y{printer.toolhead.axis_maximum.y-10} Z{printer.toolhead.axis_maximum.z-50} F6000
|
||||
RESTORE_GCODE_STATE NAME=PARKREAR
|
||||
|
||||
[gcode_macro PARKCENTER]
|
||||
gcode:
|
||||
CG28 ; home if not already homed
|
||||
SAVE_GCODE_STATE NAME=PARKCENTER
|
||||
G90 ; absolute positioning
|
||||
G0 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y/2} Z{printer.toolhead.axis_maximum.z/2} F6000
|
||||
RESTORE_GCODE_STATE NAME=PARKCENTER
|
||||
|
||||
[gcode_macro PARKBED]
|
||||
gcode:
|
||||
CG28 ; home if not already homed
|
||||
SAVE_GCODE_STATE NAME=PARKBED
|
||||
G90 ; absolute positioning
|
||||
G0 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y/2} Z15 F6000
|
||||
RESTORE_GCODE_STATE NAME=PARKBED
|
||||
|
||||
+746
@@ -0,0 +1,746 @@
|
||||
[include stealthburner_leds.cfg]
|
||||
[include config_backup.cfg]
|
||||
|
||||
[gcode_macro _KNOMI_STATUS]
|
||||
variable_homing: False
|
||||
variable_probing: False
|
||||
variable_qgling: False
|
||||
variable_heating_nozzle: False
|
||||
variable_heating_bed: False
|
||||
gcode:
|
||||
|
||||
|
||||
[include homing.cfg]
|
||||
#[include private.cfg]
|
||||
#[include nozzle_scrub.cfg]
|
||||
[include ../KAMP_Settings.cfg]
|
||||
#[include ../KAMP/KAMP_Settings.cfg]
|
||||
[include tools.cfg]
|
||||
[include nevermore.cfg]
|
||||
|
||||
|
||||
|
||||
|
||||
[delayed_gcode init_printer]
|
||||
initial_duration: 1
|
||||
gcode:
|
||||
STATUS_READY
|
||||
_Set_SoC_FAN_Speed Mode=Idle
|
||||
#SET_FAN_SPEED FAN=SoC SPEED=0.3
|
||||
|
||||
[delayed_gcode _INIT_TIMELAPSE_CHECK_TIME]
|
||||
initial_duration: 1
|
||||
gcode: SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=check_time VALUE=0.5
|
||||
|
||||
[gcode_button ps_lose]
|
||||
pin: PC2
|
||||
press_gcode:
|
||||
{ action_respond_info("Power lose!") }
|
||||
SHUTDOWN
|
||||
|
||||
[gcode_macro SHUTDOWN]
|
||||
gcode:
|
||||
SET_PIN PIN=ps_on VALUE=0
|
||||
{action_respond_info('action:poweroff')}
|
||||
{action_call_remote_method("shutdown_machine")}
|
||||
|
||||
[gcode_macro _SET_IDLE_MODE]
|
||||
gcode:
|
||||
_CHAMBER_LED_OFF
|
||||
_Set_SoC_FAN_Speed Mode=Idle
|
||||
M84
|
||||
|
||||
|
||||
[gcode_macro _CHAMBER_LED_OFF]
|
||||
gcode:
|
||||
SET_LED LED="chamber_leds" RED=0 GREEN=0 BLUE=0 SYNC=0 TRANSMIT=1
|
||||
|
||||
[gcode_macro _CHAMBER_LED_ON]
|
||||
gcode:
|
||||
SET_LED LED="chamber_leds" RED=1 GREEN=1 BLUE=1 SYNC=0 TRANSMIT=1
|
||||
|
||||
[gcode_macro _Set_SoC_FAN_Speed]
|
||||
description: Установка режима работы вентиляторов обдува блока электроники
|
||||
variable_fan_mode_speeds: { 'Idle': [0,0], 'Printing': [0.3,0.6] }
|
||||
variable_exist_fans: [ 'SoC_Left', 'SoC_Right']
|
||||
gcode:
|
||||
{% set mode = params.MODE|default("Idle") %}
|
||||
{% set fan_speeds = fan_mode_speeds[mode] %}
|
||||
{ action_respond_info("set soc fans %s" % (fan_speeds)) }
|
||||
{% for fan in exist_fans %}
|
||||
SET_FAN_SPEED FAN={fan} SPEED={fan_speeds[loop.index0]}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
[gcode_macro _LED_SWITCH]
|
||||
gcode:
|
||||
{% set color_data = printer["neopixel chamber_leds"].color_data %}
|
||||
{% if color_data[0][0] or color_data[0][1] or color_data[0][2] %}
|
||||
SET_LED LED="chamber_leds" RED=0 GREEN=0 BLUE=0 SYNC=0 TRANSMIT=1
|
||||
{% else %}
|
||||
SET_LED LED="chamber_leds" RED=1 GREEN=1 BLUE=1 SYNC=0 TRANSMIT=1
|
||||
{% endif %}
|
||||
|
||||
|
||||
[gcode_button ps_double_click]
|
||||
pin: !PG13
|
||||
press_gcode:
|
||||
{ action_respond_info("Double click!") }
|
||||
_LED_SWITCH
|
||||
|
||||
[gcode_button ps_triple_click]
|
||||
pin: !PG12
|
||||
press_gcode:
|
||||
{ action_respond_info("Triple click!") }
|
||||
{ action_emergency_stop() }
|
||||
|
||||
|
||||
[gcode_macro START_BED_MESH_CALIBRATE]
|
||||
#rename_existing: _BED_MESH_CALIBRATE
|
||||
gcode:
|
||||
STATUS_MESHING
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=probing VALUE=True
|
||||
BED_MESH_CALIBRATE ADAPTIVE=1
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=probing VALUE=False
|
||||
STATUS_READY
|
||||
|
||||
|
||||
[gcode_macro QUAD_GANTRY_LEVEL]
|
||||
rename_existing: QUAD_GANTRY_LEVEL_BASE
|
||||
gcode:
|
||||
_Set_SoC_FAN_Speed Mode=Printing
|
||||
_CHAMBER_LED_ON
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=qgling VALUE=True
|
||||
STATUS_LEVELING
|
||||
QUAD_GANTRY_LEVEL_BASE
|
||||
STATUS_READY
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=qgling VALUE=False
|
||||
|
||||
[gcode_macro G32]
|
||||
gcode:
|
||||
M117 Homing
|
||||
BED_MESH_CLEAR
|
||||
G28
|
||||
QUAD_GANTRY_LEVEL
|
||||
STATUS_CALIBRATING_Z
|
||||
#G0 X350 Y350 Z30 F3600
|
||||
G28 Z
|
||||
G0 Z10 F3600
|
||||
STATUS_READY
|
||||
M117
|
||||
|
||||
[gcode_macro PRINT_START]
|
||||
gcode:
|
||||
#PRINT_MIN={first_layer_print_min[0]},{first_layer_print_min[1]} PRINT_MAX={first_layer_print_max[0]},{first_layer_print_max[1]}
|
||||
{% set BED_TEMP = params.BED|default(60)|float %}
|
||||
{% set EXTRUDER_TEMP = params.EXTRUDER|default(210)|float %}
|
||||
{% set CHAMBER = params.CHAMBER|default(35)|float %}
|
||||
{% set use_purge = params.PURGE|default(0)|int %}
|
||||
{% if params.BED_TYPE %}
|
||||
INIT_BED_TYPE BED_TYPE="{params.BED_TYPE}"
|
||||
{% endif %}
|
||||
SAVE_GCODE_STATE NAME=start
|
||||
M117 Starting...
|
||||
M140 S{BED_TEMP}
|
||||
M141 S{CHAMBER}
|
||||
M109 S150
|
||||
M190 S{BED_TEMP}
|
||||
BED_MESH_CLEAR
|
||||
G90 # Use absolute coordinates
|
||||
#SET_GCODE_OFFSET Z=0.0
|
||||
G32
|
||||
#{% if not 'xyz' in printer.toolhead.homed_axes %}
|
||||
#G32 ; home all axes
|
||||
#{% elif not printer.quad_gantry_level.applied %}
|
||||
#QUAD_GANTRY_LEVEL
|
||||
#{% else %}
|
||||
#G28 Z10
|
||||
#{% endif %}
|
||||
START_BED_MESH_CALIBRATE #PRINT_MIN={params.PRINT_MIN} PRINT_MAX={params.PRINT_MAX} FORCE_NEW_MESH=True
|
||||
#M191 S{CHAMBER}
|
||||
Smart_Park
|
||||
M117 Heating...
|
||||
#M190 S{BED_TEMP}
|
||||
M109 S{EXTRUDER_TEMP} ; M109 heat and wait for it to reach temp
|
||||
{% if BED_TEMP > 90 %}
|
||||
_NEVERMORE_ON
|
||||
{% endif %}
|
||||
M117
|
||||
STATUS_CLEANING
|
||||
{% if use_purge %}
|
||||
VORON_PURGE
|
||||
{% endif %}
|
||||
STATUS_PRINTING
|
||||
RESTORE_GCODE_STATE NAME=start
|
||||
SKEW_PROFILE LOAD=default
|
||||
#SET_SKEW XY=140.56,141.21,99.82
|
||||
|
||||
|
||||
|
||||
[gcode_macro PRINT_END]
|
||||
gcode:
|
||||
{% set use_park = params.PARK|default(1)|int %}
|
||||
{% if use_park %}
|
||||
PRINT_END_PARK
|
||||
{% endif %}
|
||||
TURN_OFF_HEATERS
|
||||
M107 ; turn off fan
|
||||
_NEVERMORE_OFF
|
||||
SET_STEPPER_ENABLE STEPPER=extruder ENABLE=0 #disable stepper
|
||||
STATUS_OFF
|
||||
INIT_BED_TYPE BED_TYPE="None"
|
||||
M400
|
||||
TIMELAPSE_TAKE_FRAME
|
||||
|
||||
[gcode_macro PRINT_END_PARK]
|
||||
variable_retract_amount: 18 #
|
||||
variable_park_speed: 6000 #3600
|
||||
variable_park_xy: [350,350]
|
||||
variable_up_z: 4 #12
|
||||
gcode:
|
||||
{% set max_velocity = printer.configfile.settings['extruder'].max_extrude_only_velocity * 60 %}
|
||||
STATUS_BUSY
|
||||
SET_SKEW CLEAR=1
|
||||
M400 ; wait for buffer to clear
|
||||
G92 E0 ; zero the extruder
|
||||
G1 E-{retract_amount} F{max_velocity} ;3600 ; retract filament {max_velocity}
|
||||
G91 ; relative positioning
|
||||
G0 Z1.00 X20.0 Y20.0 F20000 ; move nozzle to remove stringing
|
||||
G1 Z{up_z} F3000 ; move nozzle up 2mm
|
||||
G90 ; absolute positioning
|
||||
G0 X{park_xy[0]} Y{park_xy[1]} F{park_speed} ; park nozzle at rear
|
||||
SET_VELOCITY_DEFAULT
|
||||
|
||||
|
||||
|
||||
[gcode_macro SET_VELOCITY_DEFAULT]
|
||||
gcode:
|
||||
SET_VELOCITY_LIMIT ACCEL={printer.configfile.settings.printer.max_accel}
|
||||
SET_VELOCITY_LIMIT ACCEL_TO_DECEL={printer.configfile.settings.printer.max_accel / 2}
|
||||
SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY={printer.configfile.settings.printer.square_corner_velocity}
|
||||
|
||||
|
||||
[gcode_macro M141]
|
||||
gcode:
|
||||
{% set s = params.S|default(0)|float %}
|
||||
#SET_TEMPERATURE_FAN_TARGET temperature_fan=chamber target={s}
|
||||
|
||||
[gcode_macro M191]
|
||||
gcode:
|
||||
{% set s = params.S|default(0)|float %}
|
||||
M141 S{s}
|
||||
#TEMPERATURE_WAIT SENSOR="temperature_fan chamber" MINIMUM={s}
|
||||
|
||||
|
||||
|
||||
[gcode_macro M600]
|
||||
gcode:
|
||||
#LCDRGB R=0 G=1 B=0 ; Turn LCD green
|
||||
PAUSE ; Pause
|
||||
|
||||
#[gcode_macro M106]
|
||||
#rename_existing: M99106
|
||||
#variable_fan_aliases: { 'exhaust_fan': ['fan3'] }
|
||||
#gcode:
|
||||
#{% set fan = 'fan' + (params.P|int if params.P is defined else 0)|string %}
|
||||
#{% set speed = (params.S|float / 255 if params.S is defined else 1.0) %}
|
||||
#{ action_respond_info("M106 P{} S{}".format(params.P, params.S)) }
|
||||
#{% if params.P is defined %}
|
||||
#{% for key in fan_aliases %}
|
||||
#{% if fan in fan_aliases[key] %}
|
||||
#SET_FAN_SPEED FAN={key} SPEED={speed}
|
||||
#{% endif %}
|
||||
#{% endfor %}
|
||||
#{% else %}
|
||||
#M99106 S{speed}
|
||||
#{% endif %}
|
||||
|
||||
|
||||
[gcode_macro PAUSE]
|
||||
rename_existing: BASE_PAUSE
|
||||
gcode:
|
||||
# Parameters
|
||||
{% set z = params.Z|default(10)|int %} ; z hop amount
|
||||
|
||||
{% if printer['pause_resume'].is_paused|int == 0 %}
|
||||
SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE={z} ; set z hop variable for reference in resume macro
|
||||
SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target} ; set hotend temp variable for reference in resume macro
|
||||
SAVE_GCODE_STATE NAME=PAUSE ; save current print position for resume
|
||||
BASE_PAUSE ; pause print
|
||||
{% if (printer.gcode_move.position.z + z) < printer.toolhead.axis_maximum.z %} ; check that zhop doesn't exceed z max
|
||||
G91 ; relative positioning
|
||||
G1 Z{z} F900 ; raise Z up by z hop amount
|
||||
{% else %}
|
||||
{ action_respond_info("Pause zhop exceeds maximum Z height.") } ; if z max is exceeded, show message and set zhop value for resume to 0
|
||||
SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE=0
|
||||
{% endif %}
|
||||
G90 ; absolute positioning
|
||||
G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_minimum.y+5} F6000 ; park toolhead at front center
|
||||
SAVE_GCODE_STATE NAME=PAUSEPARK ; save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)
|
||||
M104 S0 ; turn off hotend
|
||||
SET_IDLE_TIMEOUT TIMEOUT=43200 ; set timeout to 12 hours
|
||||
{% endif %}
|
||||
|
||||
[gcode_macro RESUME]
|
||||
rename_existing: BASE_RESUME
|
||||
variable_zhop: 0
|
||||
variable_etemp: 0
|
||||
gcode:
|
||||
# Parameters
|
||||
{% set e = params.E|default(2.5)|int %}
|
||||
|
||||
{% if printer['pause_resume'].is_paused|int == 1 %}
|
||||
#RESETRGB ; reset LCD color
|
||||
SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout} ; set timeout back to configured value
|
||||
{% if etemp > 0 %}
|
||||
M109 S{etemp|int} ; wait for hotend to heat back up
|
||||
{% endif %}
|
||||
RESTORE_GCODE_STATE NAME=PAUSEPARK MOVE=1 MOVE_SPEED=100 ; go back to parked position in case toolhead was moved during pause (otherwise the return zhop can error)
|
||||
G91 ; relative positioning
|
||||
M83 ; relative extruder positioning
|
||||
{% if printer[printer.toolhead.extruder].temperature >= printer.configfile.settings.extruder.min_extrude_temp %}
|
||||
G1 Z{zhop * -1} E{e} F900 ; prime nozzle by E, lower Z back down
|
||||
{% else %}
|
||||
G1 Z{zhop * -1} F900 ; lower Z back down without priming (just in case we are testing the macro with cold hotend)
|
||||
{% endif %}
|
||||
RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=60 ; restore position
|
||||
BASE_RESUME ; resume print
|
||||
{% endif %}
|
||||
|
||||
[gcode_macro CANCEL_PRINT]
|
||||
description: Cancel the actual running print
|
||||
rename_existing: CANCEL_PRINT_BASE
|
||||
gcode:
|
||||
SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout} ;
|
||||
CLEAR_PAUSE
|
||||
SDCARD_RESET_FILE
|
||||
PRINT_END
|
||||
CANCEL_PRINT_BASE
|
||||
|
||||
|
||||
|
||||
[gcode_macro DUMP_PARAMETERS]
|
||||
gcode:
|
||||
{% for name1 in printer %}
|
||||
{% for name2 in printer[name1] %}
|
||||
{ action_respond_info("printer['%s'].%s = %s" % (name1, name2, printer[name1][name2])) }
|
||||
{% else %}
|
||||
{ action_respond_info("printer['%s'] = %s" % (name1, printer[name1])) }
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
[gcode_macro M109]
|
||||
rename_existing: M99109
|
||||
gcode:
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=heating_nozzle VALUE=True
|
||||
STATUS_HEATING
|
||||
{% set s = params.S|float %}
|
||||
|
||||
{% if s != 0 %}
|
||||
M104 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %} ; Set hotend temp
|
||||
TEMPERATURE_WAIT SENSOR=extruder MINIMUM={s} MAXIMUM={s+1} ; Wait for hotend temp (within 1 degree)
|
||||
{% endif %}
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=heating_nozzle VALUE=False
|
||||
STATUS_OFF
|
||||
|
||||
[gcode_macro M190]
|
||||
rename_existing: M99190
|
||||
gcode:
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=heating_bed VALUE=True
|
||||
STATUS_HEATING
|
||||
{% set s = params.S|float %}
|
||||
|
||||
{% if s != 0 %}
|
||||
M140 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %} ; Set bed temp
|
||||
TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={s} MAXIMUM={s+1} ; Wait for bed temp (within 1 degree)
|
||||
{% endif %}
|
||||
SET_GCODE_VARIABLE MACRO=_KNOMI_STATUS VARIABLE=heating_bed VALUE=False
|
||||
STATUS_OFF
|
||||
|
||||
[gcode_macro DISABLE_XY]
|
||||
gcode:
|
||||
SET_STEPPER_ENABLE STEPPER=stepper_x ENABLE=0
|
||||
SET_STEPPER_ENABLE STEPPER=stepper_y ENABLE=0
|
||||
|
||||
[gcode_macro INIT_BED_TYPE]
|
||||
variable_bed_z_offset: 0
|
||||
variable_bed_types: { 'Textured PEI Plate': -0.03, 'None': 0 }
|
||||
gcode:
|
||||
{% set bed_type = params.BED_TYPE|default("None") %}
|
||||
{% set new_bed_z_offset = bed_types[bed_type] %}
|
||||
{% if bed_z_offset != 0 %}
|
||||
SET_GCODE_OFFSET Z_ADJUST={0-bed_z_offset|float}
|
||||
SET_GCODE_VARIABLE MACRO=INIT_BED_TYPE VARIABLE=bed_z_offset VALUE=0
|
||||
{% endif %}
|
||||
{ action_respond_info("Selected bed type: {}".format(bed_type)) }
|
||||
{ action_respond_info("Used bed z offset: {}".format(bed_z_offset)) }
|
||||
{% if new_bed_z_offset %}
|
||||
{ action_respond_info("Use bed type {} with z offset {}".format(bed_type, new_bed_z_offset)) }
|
||||
SET_GCODE_VARIABLE MACRO=INIT_BED_TYPE VARIABLE=bed_z_offset VALUE={new_bed_z_offset}
|
||||
SET_GCODE_OFFSET Z_ADJUST={new_bed_z_offset}
|
||||
{% endif %}
|
||||
|
||||
|
||||
[gcode_macro LOAD_FILAMENT]
|
||||
variable_load_distance: 72
|
||||
variable_purge_distance: 0
|
||||
gcode:
|
||||
{% set speed = params.SPEED|default(300) %}
|
||||
{% set max_velocity = printer.configfile.settings['extruder'].max_extrude_only_velocity * 60 %}
|
||||
SAVE_GCODE_STATE NAME=load_state
|
||||
G91
|
||||
G92 E0
|
||||
G1 E{16} F300 # fast-load
|
||||
G1 E{load_distance} F{max_velocity} # fast-load
|
||||
G1 E{purge_distance} F{speed} # purge
|
||||
RESTORE_GCODE_STATE NAME=load_state
|
||||
|
||||
[gcode_macro UNLOAD_FILAMENT]
|
||||
variable_unload_distance: 76
|
||||
variable_purge_distance: 0
|
||||
gcode:
|
||||
{% set speed = params.SPEED|default(300) %}
|
||||
{% set max_velocity = printer.configfile.settings['extruder'].max_extrude_only_velocity * 60 %}
|
||||
SAVE_GCODE_STATE NAME=unload_state
|
||||
G91
|
||||
G92 E0
|
||||
G1 E{purge_distance} F{speed} # purge
|
||||
G1 E-{unload_distance} F{max_velocity} # fast-unload
|
||||
RESTORE_GCODE_STATE NAME=unload_state
|
||||
|
||||
[gcode_macro PURGE_AFTER_FILAMENT_CHANGE]
|
||||
description: Безопасная очистка сопла после замены филамента с опциональным автоматическим хомингом
|
||||
gcode:
|
||||
# === ПРОВЕРКА СОСТОЯНИЯ ПРИНТЕРА ===
|
||||
{% if printer.idle_timeout.state == "Printing" %}
|
||||
{action_respond_info("⚠️ ПРИНТЕР ЗАНЯТ ПЕЧАТЬЮ!")}
|
||||
{action_respond_info("🛑 Очистка невозможна во время печати!")}
|
||||
{action_raise_error("ОШИБКА: Принтер занят печатью!")}
|
||||
{% elif printer['toolhead'].is_printing == true %}
|
||||
{action_respond_info("⚠️ ДЕТЕКТИРОВАНА АКТИВНАЯ ПЕЧАТЬ!")}
|
||||
{action_raise_error("ОШИБКА: Активная печать обнаружена!")}
|
||||
{% endif %}
|
||||
|
||||
# === ПРОВЕРКА НЕОБХОДИМОСТИ ХОМИНГА ===
|
||||
{% set homed_axes = printer.toolhead.homed_axes %}
|
||||
{% set need_homing = false %}
|
||||
|
||||
{% if 'x' not in homed_axes or 'y' not in homed_axes or 'z' not in homed_axes %}
|
||||
{% set need_homing = true %}
|
||||
{action_respond_info("🔍 Обнаружены непрохоменные оси: %s" % (['x','y','z']|reject('in', homed_axes)|join(', ')))}
|
||||
|
||||
# Проверяем параметр AUTO_HOME
|
||||
{% if params.AUTO_HOME|default(1)|int == 1 %}
|
||||
{action_respond_info("✅ АВТОМАТИЧЕСКИЙ ХОМИНГ ВКЛЮЧЕН (AUTO_HOME=1)")}
|
||||
{action_respond_info("🔄 Выполняем G28 для всех осей...")}
|
||||
G28
|
||||
{% set need_homing = false %} # После хоминга оси прохомены
|
||||
{% else %}
|
||||
{action_respond_info("❓ Для автоматического хоминга используйте: PURGE_AFTER_FILAMENT_CHANGE AUTO_HOME=1")}
|
||||
{action_respond_info("🛑 ИЛИ выполните хоминг вручную (кнопка 'Home All' в интерфейсе)")}
|
||||
{action_raise_error("ТРЕБУЕТСЯ ХОМИНГ ОСЕЙ ПЕРЕД ОЧИСТКОЙ")}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
# === НАСТРОЙКА ПОД МАТЕРИАЛ ===
|
||||
{% set material = params.MATERIAL|default('PLA')|lower %}
|
||||
|
||||
{% if material == 'pla' %}
|
||||
{% set default_temp = 210 %}
|
||||
{% set fan_speed_final = 255 %}
|
||||
{% elif material == 'petg' %}
|
||||
{% set default_temp = 230 %}
|
||||
{% set fan_speed_final = 180 %}
|
||||
{% elif material == 'abs' %}
|
||||
{% set default_temp = 240 %}
|
||||
{% set fan_speed_final = 0 %}
|
||||
{% elif material == 'tpu' %}
|
||||
{% set default_temp = 220 %}
|
||||
{% set fan_speed_final = 100 %}
|
||||
{% else %}
|
||||
{% set default_temp = 220 %}
|
||||
{% set fan_speed_final = 255 %}
|
||||
{% endif %}
|
||||
|
||||
{% set target_temp = params.TEMP|default(default_temp)|int %}
|
||||
|
||||
# === СТАНДАРТНЫЕ ПАРАМЕТРЫ ===
|
||||
{% set retract_length = 18 %}
|
||||
{% set retract_speed = 60 %}
|
||||
{% set min_extrude = 50 %}
|
||||
{% set max_extrude = 150 %}
|
||||
|
||||
# === РАСЧЕТ ДЛИНЫ ВЫДАВЛИВАНИЯ ===
|
||||
{% set nozzle_diameter = params.NOZZLE|default(0.4)|float %}
|
||||
{% set filament_diameter = params.FILAMENT_DIAM|default(1.75)|float %}
|
||||
|
||||
{% set base_length = 80 %}
|
||||
{% set diameter_factor = nozzle_diameter / 0.4 %}
|
||||
{% set calculated_length = base_length * diameter_factor %}
|
||||
|
||||
{% set total_length = params.LENGTH|default(calculated_length|round(0))|float %}
|
||||
|
||||
{% if total_length < min_extrude %}
|
||||
{action_respond_info("⚠️ Установлена минимальная длина очистки: %dмм" % min_extrude)}
|
||||
{% set total_length = min_extrude %}
|
||||
{% elif total_length > max_extrude %}
|
||||
{action_respond_info("⚠️ ПРЕДУПРЕЖДЕНИЕ: Запрашиваемая длина %.1fмм превышает безопасный лимит %dмм" % (total_length, max_extrude))}
|
||||
{% set total_length = max_extrude %}
|
||||
{% endif %}
|
||||
|
||||
{% set extrude_speed = params.SPEED|default(20)|int %}
|
||||
|
||||
# === БЕЗОПАСНОЕ ПЕРЕМЕЩЕНИЕ В БЕЗОПАСНУЮ ПОЗИЦИЮ ===
|
||||
M118 СТАРТ: Перемещение в безопасную позицию
|
||||
|
||||
# Проверяем текущие позиции и границы
|
||||
{% set x_max = printer.configfile.settings['stepper_x']['position_max']|float %}
|
||||
{% set y_max = printer.configfile.settings['stepper_y']['position_max']|float %}
|
||||
|
||||
# Вычисляем безопасные координаты (90% от максимума)
|
||||
{% set safe_x = x_max * 0.9 %}
|
||||
{% set safe_y = y_max * 0.9 %}
|
||||
|
||||
# Проверяем текущую Z позицию
|
||||
{% set current_z = printer.toolhead.position.z %}
|
||||
{% set safe_z = 50 if current_z < 50 else current_z %}
|
||||
|
||||
# Проверяем, что координаты в допустимых пределах
|
||||
{% if safe_x > x_max %}
|
||||
{% set safe_x = x_max * 0.8 %}
|
||||
{% endif %}
|
||||
|
||||
{% if safe_y > y_max %}
|
||||
{% set safe_y = y_max * 0.8 %}
|
||||
{% endif %}
|
||||
|
||||
# Относительное перемещение по Z сначала (если нужно поднять)
|
||||
{% if current_z < 50 %}
|
||||
M118 ПОЗИЦИЯ: Подъем по оси Z до 50мм
|
||||
G91
|
||||
G1 Z{50 - current_z} F300
|
||||
G90
|
||||
{% endif %}
|
||||
|
||||
# Перемещение в XY безопасную позицию
|
||||
M118 ПОЗИЦИЯ: Перемещение в XY позицию (%.1f, %.1f) % (safe_x, safe_y)
|
||||
G1 X{safe_x} Y{safe_y} F6000
|
||||
|
||||
# НАГРЕВ СОПЛА
|
||||
M118 ПРОГРЕСС: Нагрев сопла до {target_temp|int}C для {material|upper}
|
||||
M104 S{target_temp}
|
||||
M109 S{target_temp}
|
||||
|
||||
# ЦИКЛЫ ОЧИСТКИ
|
||||
M118 ПРОГРЕСС: Предварительная очистка (3 цикла)
|
||||
|
||||
{% for i in range(3) %}
|
||||
G92 E0
|
||||
G1 E10 F{extrude_speed|float*60}
|
||||
G1 E-5 F{retract_speed|float*60}
|
||||
G4 P300
|
||||
M118 ПРОГРЕСС: Цикл {i+1}/3 завершен
|
||||
{% endfor %}
|
||||
|
||||
# ОСНОВНОЕ ВЫДАВЛИВАНИЕ
|
||||
G92 E0
|
||||
|
||||
{% set first_part = total_length * 0.8 %}
|
||||
M118 ПРОГРЕСС: Основное выдавливание: {first_part|round(1)}мм
|
||||
G1 E{first_part} F{extrude_speed|float*60}
|
||||
|
||||
{% set second_part = total_length * 0.2 %}
|
||||
M118 ПРОГРЕСС: Финальное выдавливание: {second_part|round(1)}мм
|
||||
M106 S{fan_speed_final}
|
||||
G1 E{total_length} F{extrude_speed|float*60}
|
||||
|
||||
G4 P1000
|
||||
|
||||
# РЕТРАКТ
|
||||
M118 ПРОГРЕСС: Ретракт на {retract_length}мм
|
||||
G91
|
||||
G1 E-{retract_length} F{retract_speed|float*60}
|
||||
G90
|
||||
|
||||
# ЗАДЕРЖКА И ОХЛАЖДЕНИЕ
|
||||
M118 ПРОГРЕСС: Задержка 2с для охлаждения
|
||||
G4 P2000
|
||||
|
||||
M118 ПРОГРЕСС: Отключение обдува
|
||||
M107
|
||||
|
||||
M118 ПРОГРЕСС: Охлаждение сопла
|
||||
M104 S150
|
||||
G4 P3000
|
||||
M104 S0
|
||||
|
||||
# ФИНАЛЬНАЯ СТАТИСТИКА
|
||||
{% set total_extruded = total_length - retract_length %}
|
||||
{% set filament_area = 3.14159 * (filament_diameter/2)**2 %}
|
||||
{% set volume_flow = filament_area * extrude_speed %}
|
||||
{% set total_time = (total_length / extrude_speed) + 10 %}
|
||||
|
||||
M118 СТАТИСТИКА: Материал: {material|upper}
|
||||
M118 СТАТИСТИКА: Сопло: {nozzle_diameter|round(1)}мм
|
||||
M118 СТАТИСТИКА: Выдавлено: {total_length|round(1)}мм (всего)
|
||||
M118 СТАТИСТИКА: Чистый материал: {total_extruded|round(1)}мм
|
||||
M118 СТАТИСТИКА: Объемный расход: {volume_flow|round(1)}мм3/сек
|
||||
M118 ГОТОВО: Очистка завершена! ✅
|
||||
|
||||
[gcode_macro test_speed_fast]
|
||||
gcode:
|
||||
G28 X0 Y0
|
||||
GET_POSITION
|
||||
G1 X0 Y0 F27000
|
||||
G1 X350 Y350 F27000
|
||||
G1 X0 Y0 F27000
|
||||
G1 X350 Y350 F27000
|
||||
|
||||
G1 X0 Y350 F36000
|
||||
|
||||
G1 X350 Y0 F27000
|
||||
G1 X0 Y350 F27000
|
||||
G1 X350 Y0 F27000
|
||||
G1 X0 Y350 F27000
|
||||
|
||||
G1 X0 Y0 F36000
|
||||
G1 X350 Y0 F36000
|
||||
G1 X350 Y350 F36000
|
||||
G1 X0 Y350 F36000
|
||||
G1 X0 Y0 F36000
|
||||
#DISABLE_XY
|
||||
G28 X0 Y0
|
||||
GET_POSITION
|
||||
|
||||
[gcode_macro TEST_SPEED]
|
||||
# Home, get position, throw around toolhead, home again.
|
||||
# If MCU stepper positions (first line in GET_POSITION) are greater than a full step different (your number of microsteps), then skipping occured.
|
||||
# We only measure to a full step to accomodate for endstop variance.
|
||||
# Example: TEST_SPEED SPEED=300 ACCEL=5000 ITERATIONS=10
|
||||
# https://github.com/AndrewEllis93/Print-Tuning-Guide/blob/main/articles/determining_max_speeds_accels.md
|
||||
|
||||
description: Test for max speed and acceleration parameters for the printer. Procedure: Home -> ReadPositionFromMCU -> MovesToolhead@Vel&Accel -> Home -> ReadPositionfromMCU
|
||||
|
||||
gcode:
|
||||
# Speed
|
||||
{% set speed = params.SPEED|default(printer.configfile.settings.printer.max_velocity)|int %}
|
||||
# Iterations
|
||||
{% set iterations = params.ITERATIONS|default(5)|int %}
|
||||
# Acceleration
|
||||
{% set accel = params.ACCEL|default(printer.configfile.settings.printer.max_accel)|int %}
|
||||
# Minimum Cruise Ratio
|
||||
{% set min_cruise_ratio = params.MIN_CRUISE_RATIO|default(0.5)|float %}
|
||||
# Bounding inset for large pattern (helps prevent slamming the toolhead into the sides after small skips, and helps to account for machines with imperfectly set dimensions)
|
||||
{% set bound = params.BOUND|default(20)|int %}
|
||||
# Size for small pattern box
|
||||
{% set smallpatternsize = SMALLPATTERNSIZE|default(20)|int %}
|
||||
|
||||
# Large pattern
|
||||
# Max positions, inset by BOUND
|
||||
{% set x_min = printer.toolhead.axis_minimum.x + bound %}
|
||||
{% set x_max = printer.toolhead.axis_maximum.x - bound %}
|
||||
{% set y_min = printer.toolhead.axis_minimum.y + bound %}
|
||||
{% set y_max = printer.toolhead.axis_maximum.y - bound %}
|
||||
|
||||
# Small pattern at center
|
||||
# Find X/Y center point
|
||||
{% set x_center = (printer.toolhead.axis_minimum.x|float + printer.toolhead.axis_maximum.x|float ) / 2 %}
|
||||
{% set y_center = (printer.toolhead.axis_minimum.y|float + printer.toolhead.axis_maximum.y|float ) / 2 %}
|
||||
|
||||
# Set small pattern box around center point
|
||||
{% set x_center_min = x_center - (smallpatternsize/2) %}
|
||||
{% set x_center_max = x_center + (smallpatternsize/2) %}
|
||||
{% set y_center_min = y_center - (smallpatternsize/2) %}
|
||||
{% set y_center_max = y_center + (smallpatternsize/2) %}
|
||||
|
||||
# Save current gcode state (absolute/relative, etc)
|
||||
SAVE_GCODE_STATE NAME=TEST_SPEED
|
||||
|
||||
# Output parameters to g-code terminal
|
||||
{ action_respond_info("TEST_SPEED: starting %d iterations at speed %d, accel %d" % (iterations, speed, accel)) }
|
||||
|
||||
# Home and get position for comparison later:
|
||||
M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
|
||||
G28
|
||||
# QGL if not already QGLd (only if QGL section exists in config)
|
||||
{% if printer.configfile.settings.quad_gantry_level %}
|
||||
{% if printer.quad_gantry_level.applied == False %}
|
||||
QUAD_GANTRY_LEVEL
|
||||
G28 Z
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
# Move 50mm away from max position and home again (to help with hall effect endstop accuracy - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/24)
|
||||
G90
|
||||
G1 X{printer.toolhead.axis_maximum.x-50} Y{printer.toolhead.axis_maximum.y-50} F{30*60}
|
||||
M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
|
||||
G28 X Y
|
||||
G0 X{printer.toolhead.axis_maximum.x-1} Y{printer.toolhead.axis_maximum.y-1} F{30*60}
|
||||
G4 P1000
|
||||
GET_POSITION
|
||||
|
||||
# Go to starting position
|
||||
G0 X{x_min} Y{y_min} Z{bound + 10} F{speed*60}
|
||||
|
||||
# Set new limits
|
||||
{% if printer.configfile.settings.printer.minimum_cruise_ratio is defined %}
|
||||
SET_VELOCITY_LIMIT VELOCITY={speed} ACCEL={accel} MINIMUM_CRUISE_RATIO={min_cruise_ratio}
|
||||
{% else %}
|
||||
SET_VELOCITY_LIMIT VELOCITY={speed} ACCEL={accel} ACCEL_TO_DECEL={accel / 2}
|
||||
{% endif %}
|
||||
|
||||
{% for i in range(iterations) %}
|
||||
# Large pattern diagonals
|
||||
G0 X{x_min} Y{y_min} F{speed*60}
|
||||
G0 X{x_max} Y{y_max} F{speed*60}
|
||||
G0 X{x_min} Y{y_min} F{speed*60}
|
||||
G0 X{x_max} Y{y_min} F{speed*60}
|
||||
G0 X{x_min} Y{y_max} F{speed*60}
|
||||
G0 X{x_max} Y{y_min} F{speed*60}
|
||||
|
||||
# Large pattern box
|
||||
G0 X{x_min} Y{y_min} F{speed*60}
|
||||
G0 X{x_min} Y{y_max} F{speed*60}
|
||||
G0 X{x_max} Y{y_max} F{speed*60}
|
||||
G0 X{x_max} Y{y_min} F{speed*60}
|
||||
|
||||
# Small pattern diagonals
|
||||
G0 X{x_center_min} Y{y_center_min} F{speed*60}
|
||||
G0 X{x_center_max} Y{y_center_max} F{speed*60}
|
||||
G0 X{x_center_min} Y{y_center_min} F{speed*60}
|
||||
G0 X{x_center_max} Y{y_center_min} F{speed*60}
|
||||
G0 X{x_center_min} Y{y_center_max} F{speed*60}
|
||||
G0 X{x_center_max} Y{y_center_min} F{speed*60}
|
||||
|
||||
# Small pattern box
|
||||
G0 X{x_center_min} Y{y_center_min} F{speed*60}
|
||||
G0 X{x_center_min} Y{y_center_max} F{speed*60}
|
||||
G0 X{x_center_max} Y{y_center_max} F{speed*60}
|
||||
G0 X{x_center_max} Y{y_center_min} F{speed*60}
|
||||
{% endfor %}
|
||||
|
||||
# Restore max speed/accel/accel_to_decel to their configured values
|
||||
{% if printer.configfile.settings.printer.minimum_cruise_ratio is defined %}
|
||||
SET_VELOCITY_LIMIT VELOCITY={printer.configfile.settings.printer.max_velocity} ACCEL={printer.configfile.settings.printer.max_accel} MINIMUM_CRUISE_RATIO={printer.configfile.settings.printer.minimum_cruise_ratio}
|
||||
{% else %}
|
||||
SET_VELOCITY_LIMIT VELOCITY={printer.configfile.settings.printer.max_velocity} ACCEL={printer.configfile.settings.printer.max_accel} ACCEL_TO_DECEL={printer.configfile.settings.printer.max_accel_to_decel}
|
||||
{% endif %}
|
||||
|
||||
# Re-home and get position again for comparison:
|
||||
M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
|
||||
G28 # This is a full G28 to fix an issue with CoreXZ - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/12
|
||||
# Go to XY home positions (in case your homing override leaves it elsewhere)
|
||||
G90
|
||||
G0 X{printer.toolhead.axis_maximum.x-1} Y{printer.toolhead.axis_maximum.y-1} F{30*60}
|
||||
G4 P1000
|
||||
GET_POSITION
|
||||
|
||||
# Restore previous gcode state (absolute/relative, etc)
|
||||
RESTORE_GCODE_STATE NAME=TEST_SPEED
|
||||
|
||||
|
||||
[gcode_macro _bot_data]
|
||||
variable_lapse_video_size: 0
|
||||
variable_lapse_filename: 'None'
|
||||
variable_lapse_path: 'None'
|
||||
gcode:
|
||||
M118 Setting bot lapse variables
|
||||
@@ -0,0 +1,30 @@
|
||||
## This is a simple include for the Nevermore. To use it with your printer, edit
|
||||
## the pin definition in line 16 so it matches your printer.
|
||||
## What you get:
|
||||
## - a generic fan "Nevermore" which is adjustable in GCODE and in Mainsail/Fluidd
|
||||
## - Commands in your 12864-controller to turn the fan on/off or adjust in 10%-steps
|
||||
## - a Macro to turn the fan off some time after the print.
|
||||
##
|
||||
## Slicer integration: Add "SET_FAN_SPEED FAN=Nevermore SPEED=1" in your start-macro
|
||||
## (or less fan depending on your needs, like SPEED=0.8)
|
||||
## in your end print code, add "UPDATE_DELAYED_GCODE ID=filter_off DURATION=180"
|
||||
## this keeps your Nevermore running for 180s after the print finishes to clean the chamber a bit more.
|
||||
[delayed_gcode filter_off]
|
||||
gcode:
|
||||
SET_FAN_SPEED FAN=Nevermore SPEED=0
|
||||
|
||||
[gcode_macro TOGGLE_NEVERMORE]
|
||||
gcode:
|
||||
{% if printer['fan_generic Nevermore'].speed > 0 %}
|
||||
SET_FAN_SPEED FAN=Nevermore SPEED=0
|
||||
{% else %}
|
||||
SET_FAN_SPEED FAN=Nevermore SPEED=1
|
||||
{% endif %}
|
||||
|
||||
[gcode_macro _NEVERMORE_ON]
|
||||
gcode:
|
||||
SET_FAN_SPEED FAN=Nevermore SPEED=1
|
||||
|
||||
[gcode_macro _NEVERMORE_OFF]
|
||||
gcode:
|
||||
SET_FAN_SPEED FAN=Nevermore SPEED=0
|
||||
@@ -0,0 +1,158 @@
|
||||
[gcode_macro clean_nozzle]
|
||||
variable_location_bucket_rear: True
|
||||
variable_enable_purge: True
|
||||
|
||||
# These parameters define your filament purging. The retract variable is used to retract right after purging to prevent unnecessary
|
||||
# oozing. Some filament are particularly oozy and may continue to ooze out of the nozzle for a second or two after retracting. The
|
||||
# ooze dwell variable makes allowance for this. Update as necessary. If you decided to not enable purge, you can ignore this section.
|
||||
variable_purge_len: 20 ; Amount of filament, in mm, to purge.
|
||||
variable_purge_spd: 150 ; Speed, in mm/min, of the purge.
|
||||
variable_purge_temp_min: 200 ; Minimum nozzle temperature to permit a purge. Otherwise, purge will not occur.
|
||||
variable_purge_ret: 2 ; Retract length, in mm, after purging to prevent slight oozing. Adjust as necessary.
|
||||
variable_ooze_dwell: 4 ; Dwell/wait time, in seconds, after purging and retracting.
|
||||
|
||||
# Adjust this so that your nozzle scrubs within the brush. Currently defaulted to be a lot higher for safety. Be careful not to go too low!
|
||||
variable_brush_top: 0
|
||||
|
||||
# These parameters define your scrubbing, travel speeds, safe z clearance and how many times you want to wipe. Update as necessary. Wipe
|
||||
# direction is randomized based off whether the left or right bucket is randomly selected in the purge & scrubbing routine.
|
||||
variable_clearance_z: 5 ; When traveling, but not cleaning, the clearance along the z-axis between nozzle and brush.
|
||||
variable_wipe_qty: 3 ; Number of complete (A complete wipe: left, right, left OR right, left, right) wipes.
|
||||
variable_prep_spd_xy: 3000 ; Travel (not cleaning) speed along x and y-axis in mm/min.
|
||||
variable_prep_spd_z: 1500 ; Travel (not cleaning) speed along z axis in mm/min.
|
||||
variable_wipe_spd_xy: 5000 ; Nozzle wipe speed in mm/min.
|
||||
|
||||
|
||||
# These parameters define the size of the brush. Update as necessary. A visual reference is provided below. Note that orientation of
|
||||
# parameters remain the same whether bucket is at rear or front.
|
||||
#
|
||||
# ← brush_width →
|
||||
# _________________ ↑
|
||||
# | | ↑ If you chose location_bucket_rear = True, Y position is acquired
|
||||
# brush_start (x) | | brush_depth from your stepper_y position_max. Adjust your brush physically in
|
||||
# |_________________| ↓ Y so that the nozzle scrubs within the brush.
|
||||
# (y) ↓
|
||||
# brush_front
|
||||
# __________________________________________________________
|
||||
# PRINTER FRONT
|
||||
#
|
||||
#
|
||||
variable_brush_start: 75
|
||||
# This value is defaulted from brush location in CAD (rear left). Change if your brush width is different.
|
||||
variable_brush_width: 52
|
||||
|
||||
## These are only used if location_bucket_rear is False. You specify a custom location in y axis for your brush - see diagram above. ##
|
||||
variable_brush_front: 0
|
||||
variable_brush_depth: 2
|
||||
|
||||
|
||||
# These parameters define the size of your purge bucket. Update as necessary. If you decided to not enable purge, you can ignore
|
||||
# this section. A visual reference is provided below. Note that orientation of parameters remain the same whether bucket is at rear
|
||||
# or front.
|
||||
#
|
||||
# bucket_gap
|
||||
# ← ---- →
|
||||
# __________________________________________
|
||||
# | | | |
|
||||
# | | | |
|
||||
# bucket_start (x) | |______| |
|
||||
# | | | |
|
||||
# | | | |
|
||||
# |_________________|. . . |_________________|
|
||||
# ← ------------- → ← ------------- →
|
||||
# bucket_left_width bucket_right_width
|
||||
# _______________________________________________________________________________________
|
||||
# PRINTER FRONT
|
||||
#
|
||||
## For V2.4 350mm build, uncomment below
|
||||
variable_bucket_left_width: 92
|
||||
|
||||
# These values are defaulted from bucket geometry in CAD (rear left location). Change only if you're using a custom bucket.
|
||||
variable_bucket_right_width: 40
|
||||
variable_bucket_gap: 22
|
||||
|
||||
# For V1.8, you may need to measure where your bucket start is and input into bucket_start. Otherwise, a value of 0 is for a default
|
||||
# installation of purge bucket at rear left.
|
||||
variable_bucket_start: 0
|
||||
variable_bucket_pos: 1
|
||||
gcode:
|
||||
STATUS_CLEANING
|
||||
# First, check if the axes are homed.
|
||||
{% if "xyz" in printer.toolhead.homed_axes %}
|
||||
|
||||
## Save the gcode state in this macro instance.
|
||||
SAVE_GCODE_STATE NAME=clean_nozzle
|
||||
|
||||
## Set to absolute positioning.
|
||||
G90
|
||||
|
||||
## Grab max position of Y-axis from config to use in setting a fixed y position for location_bucket_rear = True.
|
||||
{% set Ry = printer.configfile.config["stepper_y"]["position_max"]|float %}
|
||||
|
||||
## Check if user enabled purge option or not.
|
||||
{% if enable_purge %}
|
||||
|
||||
### Randomly select left or right bin for purge. 0 = left, 1 = right
|
||||
SET_GCODE_VARIABLE MACRO=clean_nozzle VARIABLE=bucket_pos VALUE={(range(2) | random)}
|
||||
|
||||
### Raise Z for travel.
|
||||
G1 Z{brush_top + clearance_z} F{prep_spd_z}
|
||||
|
||||
### Check if user chose to use rear location.
|
||||
{% if location_bucket_rear %}
|
||||
G1 Y{Ry} F{prep_spd_xy}
|
||||
{% else %}
|
||||
G1 Y{brush_front + (brush_depth / 2)} F{prep_spd_xy}
|
||||
{% endif %}
|
||||
|
||||
### Position for purge. Randomly selects middle of left or right bucket. It references from the middle of the left bucket.
|
||||
G1 X{bucket_start + (bucket_left_width / (2 - bucket_pos)) + (bucket_pos * bucket_gap) + (bucket_pos * (bucket_right_width / 2))}
|
||||
|
||||
### Perform purge if the temp is up to min temp. If not, it will skip and continue executing rest of macro. Small retract after
|
||||
### purging to minimize any persistent oozing at 5x purge_spd. G4 dwell is in milliseconds, hence * 1000 in formula.
|
||||
{% if printer.extruder.temperature >= purge_temp_min %}
|
||||
M83 ; relative mode
|
||||
G1 E{purge_len} F{purge_spd}
|
||||
G1 E-{purge_ret} F{purge_spd * 5}
|
||||
G4 P{ooze_dwell * 1000}
|
||||
G92 E0 ; reset extruder
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
## Position for wipe. Either left or right of brush based off bucket_pos to avoid unnecessary travel.
|
||||
G1 Z{brush_top + clearance_z} F{prep_spd_z}
|
||||
G1 X{brush_start + (brush_width * bucket_pos)} F{prep_spd_xy}
|
||||
|
||||
## Check if user chose to use rear location.
|
||||
{% if location_bucket_rear %}
|
||||
G1 Y{Ry}
|
||||
{% else %}
|
||||
G1 Y{brush_front + (brush_depth / 2)}
|
||||
{% endif %}
|
||||
|
||||
## Move nozzle down into brush.
|
||||
G1 Z{brush_top} F{prep_spd_z}
|
||||
|
||||
## Perform wipe. Wipe direction based off bucket_pos for cool random scrubby routine.
|
||||
{% for wipes in range(1, (wipe_qty + 1)) %}
|
||||
G1 X{brush_start + (brush_width * (1 - bucket_pos))} F{wipe_spd_xy}
|
||||
G1 X{brush_start + (brush_width * bucket_pos)} F{wipe_spd_xy}
|
||||
{% endfor %}
|
||||
|
||||
## Clear from area.
|
||||
M117 Cleaned!
|
||||
G1 Z{brush_top + clearance_z} F{prep_spd_z}
|
||||
G1 X{bucket_start + (bucket_left_width / 4)} F{prep_spd_xy} #bugfix for right side mounted buckets
|
||||
|
||||
## Restore the gcode state to how it was before the macro.
|
||||
RESTORE_GCODE_STATE NAME=clean_nozzle
|
||||
|
||||
{% else %}
|
||||
|
||||
## raise error will stop any macros that clean_nozzle is referenced in from proceeding for safety.
|
||||
{ action_raise_error("Please home your axes!") }
|
||||
M117 Please home first!
|
||||
|
||||
{% endif %}
|
||||
STATUS_READY
|
||||
@@ -0,0 +1,254 @@
|
||||
# Macros for setting the status leds on the Voron StealthBurner toolhead (or for any neopixel-type leds).
|
||||
#
|
||||
# You will need to configure a neopixel (or other addressable led, such as dotstar). See
|
||||
# https://www.klipper3d.org/Config_Reference.html#neopixel for configuration details.
|
||||
|
||||
|
||||
#####################################
|
||||
# INSTRUCTIONS #
|
||||
#####################################
|
||||
# How to use all this stuff:
|
||||
#
|
||||
# 1. Copy this .cfg file into your Klipper config directory and then add [include stealthburner_leds.cfg]
|
||||
# to the top of your printer.cfg in order to register the LEDs and macros with Klipper.
|
||||
# 2. Define your LEDs by editing [neopixel sb_leds] below and entering the data pin from your control board
|
||||
# as well as the color order.
|
||||
#
|
||||
# Note: RGB and RGBW are different and must be defined explicitly. RGB and RGBW are also not able to
|
||||
# be mix-and-matched in the same chain. A separate data line would be needed for proper functioning.
|
||||
#
|
||||
# RGBW LEDs will have a visible yellow-ish phosphor section to the chip. If your LEDs do not have
|
||||
# this yellow portion, you have RGB LEDs.
|
||||
#
|
||||
# 3. Save your config and restart Klipper.
|
||||
#
|
||||
# Note: We set RED and BLUE to 1.0 to make it easier for users and supporters to detect
|
||||
# misconfigurations or miswiring. The default color format is for Neopixels with a dedicated
|
||||
# white LED. On startup, all three SB LEDs should light up.
|
||||
#
|
||||
# If you get random colors across your LEDs, change the color_order to GRB and restart. Then
|
||||
# omit the W for each suggested color_order in the next paragraph.
|
||||
#
|
||||
# If you get MAGENTA, your color order is correct. If you get CYAN, you need to use RGBW. If
|
||||
# you get YELLOW, you need to use BRGW (note that BRG is only supported in the latest Klipper
|
||||
# version).
|
||||
#
|
||||
# 4. Once you have confirmed that the LEDs are set up correctly, you must now decide where you want
|
||||
# these macros called up...which means adding them to your existing gcode macros. NOTHING will happen
|
||||
# unless you add the STATUS_????? macros to your existing gcode macros.
|
||||
#
|
||||
# Example: add STATUS_LEVELING to the beginning of your QGL gcode macro, and then add STATUS_READY
|
||||
# to the end of it to set the logo LED and nozzle LEDs back to the `ready` state.
|
||||
#
|
||||
# Example: add STATUS_CLEANING to the beginning of your nozzle-cleaning macro, and then STATUS_READY
|
||||
# to the end of it to return the LEDs back to `ready` state.
|
||||
#
|
||||
# 5. Feel free to change colors of each macro, create new ones if you have a need to. The macros provided below
|
||||
# are just an example of what is possible. If you want to try some more complex animations, you will most
|
||||
# likely have to use WLED with Moonraker and a small micro-controller
|
||||
#
|
||||
#####################################
|
||||
# END INSTRUCTRUCTIONS #
|
||||
#####################################
|
||||
|
||||
[neopixel sb_leds]
|
||||
#pin: EBBCan:gpio16 #sht:RGBLED
|
||||
#pin: EXP1_6
|
||||
# The pin connected to the neopixel. This parameter must be provided.
|
||||
chain_count: 3
|
||||
# The number of Neopixel chips that are "daisy chained" to the
|
||||
# provided pin. The default is 1 (which indicates only a single
|
||||
# Neopixel is connected to the pin).
|
||||
color_order: GRBW
|
||||
# Set the pixel order required by the LED hardware. Options are GRB,
|
||||
# RGB, GRBW, or RGBW. The default is GRB.
|
||||
initial_RED: 1.0
|
||||
initial_GREEN: 0.0
|
||||
initial_BLUE: 1.0
|
||||
initial_WHITE: 0.0
|
||||
# Sets the initial LED color of the Neopixel. Each value should be
|
||||
# between 0.0 and 1.0. The WHITE option is only available on RGBW
|
||||
# LEDs. The default for each color is 0.#
|
||||
|
||||
# Most configuration for the macros can be done by modifying the variables in the _sb_vars macro
|
||||
# at the start of this file.
|
||||
|
||||
##########
|
||||
# MACROS #
|
||||
##########
|
||||
|
||||
# The following status macros are available (these go inside of your macros):
|
||||
#
|
||||
# STATUS_READY
|
||||
# STATUS_OFF
|
||||
# STATUS_BUSY
|
||||
# STATUS_HEATING
|
||||
# STATUS_LEVELING
|
||||
# STATUS_HOMING
|
||||
# STATUS_CLEANING
|
||||
# STATUS_MESHING
|
||||
# STATUS_CALIBRATING_Z
|
||||
#
|
||||
# With additional macros for basic control:
|
||||
#
|
||||
# SET_NOZZLE_LEDS_ON
|
||||
# SET_LOGO_LEDS_OFF
|
||||
# SET_NOZZLE_LEDS_OFF
|
||||
#
|
||||
# Contributed by Voron discord users wile.e, Tetsunosuke, and etherwalker
|
||||
|
||||
|
||||
[gcode_macro _sb_vars]
|
||||
# User settings for the StealthBurner status leds. You can change the status colors and led
|
||||
# configurations for the logo and nozzle here.
|
||||
variable_colors: {
|
||||
'logo': { # Colors for logo states
|
||||
'busy': {'r': 0.4, 'g': 0.0, 'b': 0.0, 'w': 0.0},
|
||||
'cleaning': {'r': 0.0, 'g': 0.02, 'b': 0.5, 'w': 0.0},
|
||||
'calibrating_z': {'r': 0.8, 'g': 0., 'b': 0.35, 'w': 0.0},
|
||||
'heating': {'r': 0.3, 'g': 0.18, 'b': 0.0, 'w': 0.0},
|
||||
'homing': {'r': 0.0, 'g': 0.6, 'b': 0.2, 'w': 0.0},
|
||||
'leveling': {'r': 0.5, 'g': 0.1, 'b': 0.4, 'w': 0.0},
|
||||
'meshing': {'r': 0.2, 'g': 1.0, 'b': 0.0, 'w': 0.0},
|
||||
'off': {'r': 0.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
|
||||
'printing': {'r': 1.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
|
||||
'standby': {'r': 0.01, 'g': 0.01, 'b': 0.01, 'w': 0.1},
|
||||
},
|
||||
'nozzle': { # Colors for nozzle states
|
||||
'heating': {'r': 0.8, 'g': 0.35, 'b': 0.0, 'w':0.0},
|
||||
'off': {'r': 0.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
|
||||
'on': {'r': 0.8, 'g': 0.8, 'b': 0.8, 'w':1.0},
|
||||
'standby': {'r': 0.6, 'g': 0.0, 'b': 0.0, 'w':0.0},
|
||||
},
|
||||
'thermal': {
|
||||
'hot': {'r': 1.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
|
||||
'cold': {'r': 0.3, 'g': 0.0, 'b': 0.3, 'w': 0.0}
|
||||
}
|
||||
}
|
||||
variable_logo_led_name: "sb_leds"
|
||||
# The name of the addressable LED chain that contains the logo LED(s)
|
||||
variable_logo_idx: "1"
|
||||
# A comma-separated list of indexes LEDs in the logo
|
||||
variable_nozzle_led_name: "sb_leds"
|
||||
# The name of the addressable LED chain that contains the nozzle LED(s). This will
|
||||
# typically be the same LED chain as the logo.
|
||||
variable_nozzle_idx: "2,3"
|
||||
# A comma-separated list of indexes of LEDs in the nozzle
|
||||
gcode:
|
||||
# This section is required. Do Not Delete.
|
||||
|
||||
|
||||
[gcode_macro _set_sb_leds]
|
||||
gcode:
|
||||
{% set red = params.RED|default(0)|float %}
|
||||
{% set green = params.GREEN|default(0)|float %}
|
||||
{% set blue = params.BLUE|default(0)|float %}
|
||||
{% set white = params.WHITE|default(0)|float %}
|
||||
{% set led = params.LED|string %}
|
||||
{% set idx = (params.IDX|string).split(',') %}
|
||||
{% set transmit_last = params.TRANSMIT|default(1) %}
|
||||
|
||||
{% for led_index in idx %}
|
||||
{% set transmit=transmit_last if loop.last else 0 %}
|
||||
set_led led={led} red={red} green={green} blue={blue} white={white} index={led_index} transmit={transmit}
|
||||
{% endfor %}
|
||||
|
||||
[gcode_macro _set_sb_leds_by_name]
|
||||
gcode:
|
||||
{% set leds_name = params.LEDS %}
|
||||
{% set color_name = params.COLOR %}
|
||||
{% set color = printer["gcode_macro _sb_vars"].colors[leds_name][color_name] %}
|
||||
{% set led = printer["gcode_macro _sb_vars"][leds_name + "_led_name"] %}
|
||||
{% set idx = printer["gcode_macro _sb_vars"][leds_name + "_idx"] %}
|
||||
{% set transmit = params.TRANSMIT|default(1) %}
|
||||
|
||||
_set_sb_leds led={led} red={color.r} green={color.g} blue={color.b} white={color.w} idx="{idx}" transmit={transmit}
|
||||
|
||||
[gcode_macro _set_logo_leds]
|
||||
gcode:
|
||||
{% set red = params.RED|default(0)|float %}
|
||||
{% set green = params.GREEN|default(0)|float %}
|
||||
{% set blue = params.BLUE|default(0)|float %}
|
||||
{% set white = params.WHITE|default(0)|float %}
|
||||
{% set led = printer["gcode_macro _sb_vars"].logo_led_name %}
|
||||
{% set idx = printer["gcode_macro _sb_vars"].logo_idx %}
|
||||
{% set transmit=params.TRANSMIT|default(1) %}
|
||||
|
||||
_set_sb_leds led={led} red={red} green={green} blue={blue} white={white} idx="{idx}" transmit={transmit}
|
||||
|
||||
[gcode_macro _set_nozzle_leds]
|
||||
gcode:
|
||||
{% set red = params.RED|default(0)|float %}
|
||||
{% set green = params.GREEN|default(0)|float %}
|
||||
{% set blue = params.BLUE|default(0)|float %}
|
||||
{% set white = params.WHITE|default(0)|float %}
|
||||
{% set led = printer["gcode_macro _sb_vars"].nozzle_led_name %}
|
||||
{% set idx = printer["gcode_macro _sb_vars"].nozzle_idx %}
|
||||
{% set transmit=params.TRANSMIT|default(1) %}
|
||||
|
||||
_set_sb_leds led={led} red={red} green={green} blue={blue} white={white} idx="{idx}" transmit={transmit}
|
||||
|
||||
[gcode_macro set_logo_leds_off]
|
||||
gcode:
|
||||
{% set transmit=params.TRANSMIT|default(1) %}
|
||||
_set_logo_leds red=0 blue=0 green=0 white=0 transmit={transmit}
|
||||
|
||||
[gcode_macro set_nozzle_leds_on]
|
||||
gcode:
|
||||
{% set transmit=params.TRANSMIT|default(1) %}
|
||||
_set_sb_leds_by_name leds="nozzle" color="on" transmit={transmit}
|
||||
|
||||
[gcode_macro set_nozzle_leds_off]
|
||||
gcode:
|
||||
{% set transmit=params.TRANSMIT|default(1) %}
|
||||
_set_sb_leds_by_name leds="nozzle" color="off" transmit={transmit}
|
||||
|
||||
[gcode_macro status_off]
|
||||
gcode:
|
||||
set_logo_leds_off transmit=0
|
||||
set_nozzle_leds_off
|
||||
|
||||
[gcode_macro status_ready]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="standby" transmit=0
|
||||
_set_sb_leds_by_name leds="nozzle" color="standby" transmit=1
|
||||
|
||||
[gcode_macro status_busy]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="busy" transmit=0
|
||||
set_nozzle_leds_on
|
||||
|
||||
[gcode_macro status_heating]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="heating" transmit=0
|
||||
_set_sb_leds_by_name leds="nozzle" color="heating" transmit=1
|
||||
|
||||
[gcode_macro status_leveling]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="leveling" transmit=0
|
||||
set_nozzle_leds_on
|
||||
|
||||
[gcode_macro status_homing]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="homing" transmit=0
|
||||
set_nozzle_leds_on
|
||||
|
||||
[gcode_macro status_cleaning]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="cleaning" transmit=0
|
||||
set_nozzle_leds_on
|
||||
|
||||
[gcode_macro status_meshing]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="meshing" transmit=0
|
||||
set_nozzle_leds_on
|
||||
|
||||
[gcode_macro status_calibrating_z]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="calibrating_z" transmit=0
|
||||
set_nozzle_leds_on
|
||||
|
||||
[gcode_macro status_printing]
|
||||
gcode:
|
||||
_set_sb_leds_by_name leds="logo" color="printing" transmit=0
|
||||
set_nozzle_leds_on
|
||||
@@ -0,0 +1,91 @@
|
||||
#Аргументы
|
||||
#NAME (строка) — отфильтруйте результаты по названию (отображайте только переменные с названиями, содержащими эту строку)
|
||||
#VALUE (строка) — отфильтруйте результаты по значению (отображайте только значения, содержащие это значение)
|
||||
#SHOW_CFG (целое число, 0-1) — установите значение 1, чтобы включить в вывод всю конфигурацию. По умолчанию 0 (конфигурация отфильтровывается)
|
||||
#Примеры
|
||||
#DUMP_VARIABLES: Возвращает все переменные (за исключением printer['configfile'].config и printer['configfile'].settings, так как они содержат всю конфигурацию).
|
||||
#DUMP_VARIABLES NAME=stepper: Возвращает все переменные, в имени которых есть строка stepper.
|
||||
#DUMP_VARIABLES VALUE=extruder : Возвращает все переменные, в значении которых есть строка extruder.
|
||||
#DUMP_VARIABLES NAME=stepper VALUE=extruder : Возвращает все переменные, в названии которых есть строка stepper и в значении которых есть строка extruder.
|
||||
#DUMP_VARIABLES SHOW_CFG=1 : Возвращает все переменные, включая конфигурацию.
|
||||
|
||||
[gcode_macro DUMP_VARIABLES]
|
||||
gcode:
|
||||
{% set filter_name = params.NAME|default('')|string|lower %}
|
||||
{% set filter_value = params.VALUE|default('')|string|lower %}
|
||||
{% set show_cfg = params.SHOW_CFG|default(0)|int %}
|
||||
|
||||
{% set out = [] %}
|
||||
|
||||
{% for key1 in printer %}
|
||||
{% for key2 in printer[key1] %}
|
||||
{% if (show_cfg or not (key1|lower == 'configfile' and key2|lower in ['config', 'settings'])) and (filter_name in key1|lower or filter_name in key2|lower) and filter_value in printer[key1][key2]|string|lower %}
|
||||
{% set dummy = out.append("printer['%s'].%s = %s" % (key1, key2, printer[key1][key2])) %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if filter_name in key1|lower and filter_value in printer[key1]|string|lower %}
|
||||
{% set dummy = out.append("printer['%s'] = %s" % (key1, printer[key1])) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{action_respond_info(out|join("\n"))}
|
||||
|
||||
|
||||
#Аргументы
|
||||
#NAME (строка) (обязательно) — укажите имя переменной, которую вы хотите получить.
|
||||
#Примеры
|
||||
#GET_VARIABLE NAME=toolhead: Возвращает значение и тип переменной printer.toolhead.
|
||||
#GET_VARIABLE NAME=bed_mesh.profiles.default.points.1.0: Возвращает значение и тип переменной printer.bed_mesh.profiles.default.points[1][0].
|
||||
[gcode_macro GET_VARIABLE]
|
||||
gcode:
|
||||
{% set names = (params.NAME).split('.')|list %}
|
||||
{% set join = (params.JOIN)|default(1)|int %}
|
||||
|
||||
{% set _dummy0 = namespace( break = 0 ) %}
|
||||
{% set _dummy1 = namespace( out = printer[names|first] ) %}
|
||||
|
||||
{% for name in names if _dummy0.break == 0 %}
|
||||
{% if loop.index > 1 %}
|
||||
{% if name in _dummy1.out %}
|
||||
{% set _dummy1.out = _dummy1.out[name] %}
|
||||
{% elif name[0] in '0123456789' and _dummy1.out is iterable and _dummy1.out is not string and _dummy1.out is not mapping and _dummy1.out|length > name[0]|int %}
|
||||
{% set _dummy1.out = _dummy1.out[name|int] %}
|
||||
{% else %}
|
||||
{% set _dummy0.break = loop.index0 %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if _dummy1.out is boolean %}
|
||||
{ action_respond_info('Type: boolean') }
|
||||
{% elif _dummy1.out is float %}
|
||||
{ action_respond_info('Type: float') }
|
||||
{% elif _dummy1.out is integer %}
|
||||
{ action_respond_info('Type: integer') }
|
||||
{% elif _dummy1.out is mapping %}
|
||||
{ action_respond_info('Type: mapping') }
|
||||
{% elif _dummy1.out is string %}
|
||||
{ action_respond_info('Type: string') }
|
||||
{% elif _dummy1.out is iterable %}
|
||||
{ action_respond_info('Type: iterable') }
|
||||
{% elif _dummy1.out is none %}
|
||||
{ action_respond_info('Type: none') }
|
||||
{% elif _dummy1.out is undefined %}
|
||||
{ action_respond_info('Type: undefined') }
|
||||
{% elif _dummy1.out is callable %}
|
||||
{ action_respond_info('Type: callable') }
|
||||
{% else %}
|
||||
{ action_respond_info('Type: unknown') }
|
||||
{% endif %}
|
||||
|
||||
{% if join and _dummy1.out is iterable and _dummy1.out is not string and _dummy1.out is not mapping %}
|
||||
{ action_respond_info('%s' % _dummy1.out|join("\n")) }
|
||||
{% else %}
|
||||
{ action_respond_info('%s' % _dummy1.out) }
|
||||
{% endif %}
|
||||
|
||||
{% if _dummy0.break != 0 %}
|
||||
{ action_respond_info('"printer.%s" does not contain "%s"!' % (names[0:_dummy0.break]|join('.'), names[_dummy0.break])) }
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user