Skip to content

Commit

Permalink
filament: Improved loading/unloading (and parking)
Browse files Browse the repository at this point in the history
* M701 and M702 now use PAUSE or PARK if needed.
* M701 and M702 now use the default load length is none is provided.
* Added default lazy mode to park, which moves only when not parked and
  will home any unhomed axes if needed.
  • Loading branch information
jschuh committed Feb 20, 2022
1 parent 8098089 commit de3172b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 72 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,13 @@ Loads or unloads filament to the nozzle.
or unload.
* `SPEED` *(default: `variable_load_speed`)* - Speed (in mm/m) to feed the
filament.
* `TARGET` *(optional: `min_extrude_temp`)* - Ensures the extruder is heated
* `MINIMUM` *(default: `min_extrude_temp` + 5)* - Ensures the extruder is heated
to at least the specified temperature.

#### Marlin Compatibility

* The `M701` and `M702` commands are implemented.
* The `M701` and `M702` commands are implemented with a default filament length
of `variable_load_length`.

### Heaters

Expand Down Expand Up @@ -381,6 +382,8 @@ Parks the toolhead.
* `Y` *(default: `variable_park_y`)* - Absolute Y parking coordinate.
* `Z` *(default: `variable_park_z`)* - Z parking coordinate applied according
to the `P` parameter.
* `LAZY` *(default: 1)* - Will home any unhomed axes if needed and will not
move any axis if already homed and parked (even if `P=2`).
* Note: If a print is in progress the larger of the tallest printed layer or the
current Z position will be used as the current Z position, to avoid collisions
with already printed objects during a sequential print.
Expand Down
106 changes: 63 additions & 43 deletions filament.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
# This file may be distributed under the terms of the GNU GPLv3 license.

[gcode_macro _load_unload]
variable_is_printing: 1
gcode:
# Klipper think we're printing if parking homed first, so this is a hack to
# prevent that from happening. The caller sets the value and we clear it.
SET_GCODE_VARIABLE MACRO=_load_unload VARIABLE=is_printing VALUE="{1}"
{% set saved_extruder = printer.toolhead.extruder %}
{% set EXTRUDER = params.EXTRUDER|default(saved_extruder)|lower %}
{% set TARGET = params.TARGET|default(
printer.configfile.settings[EXTRUDER].min_extrude_temp) %}
{% if TARGET < printer.configfile.settings[EXTRUDER].min_extrude_temp %}
{ action_raise_error("Extrude below minimum temp") }
{% elif printer.idle_timeout.state == "Printing" and
{% set MINIMUM = params.MINIMUM|default(
printer.configfile.settings[EXTRUDER].min_extrude_temp + 5.0) %}
{% if MINIMUM < printer.configfile.settings[EXTRUDER].min_extrude_temp %}
{ action_raise_error("Extrude below minimum temp.") }
{% elif printer.idle_timeout.state == "Printing" and is_printing and
not printer.pause_resume.is_paused %}
{ action_raise_error("Command not valid during printing.") }
{% endif %}
Expand All @@ -26,8 +30,8 @@ gcode:
{% if EXTRUDER != saved_extruder%}
ACTIVATE_EXTRUDER EXTRUDER={EXTRUDER}
{% endif %}
{% if printer[EXTRUDER].target < TARGET %}
M109 S{TARGET}
{% if printer[EXTRUDER].target < MINIMUM %}
M109 S{MINIMUM}
{% endif %}
M83
{% if params.LOAD|int %}
Expand All @@ -40,71 +44,87 @@ gcode:
G1 E{'%.4f' % -priming_length} F{(km.load_priming_speed, SPEED)|min}
G1 E{'%.4f' % -LENGTH} F{SPEED}
{% endif %}
M400
RESTORE_GCODE_STATE NAME=_LOAD_UNLOAD

[gcode_macro load_filament]
description: Loads filament to the extruder.
Usage: LOAD_FILAMENT [LENGTH=<distance>] [SPEED=<speed>]
[EXTRUDER=<extruder>] [TARGET=<temperature>]
[EXTRUDER=<extruder>] [MINIMUM=<temperature>]
gcode:
_LOAD_UNLOAD LOAD=1{% for k in params
%}{' '~k~'="'~params[k]~'"'}{% endfor %}

# Dummy argument block for Mainsail
{% set dummy = None if True else "
{% set dummy = params.LENGTH|default(variable_load_length)|float %}
{% set dummy = params.SPEED|default(variable_load_speed)|float %}
{% set dummy = params.EXTRUDER|default(current extruder) %}
{% set dummy = params.TARGET|default(current temp)|int %}
{% set dummy = params.MINIMUM|default(min_extrude_temp)|int %}
" %} # End argument block for Mainsail
{% set extruder = printer["extruder" ~ params.T]
if params.T|default(0)|int != 0 else printer.toolhead.extruder %}
_LOAD_UNLOAD LOAD=1 EXTRUDER={extruder}{% for k in params|reject("==", "T")
%}{' '~k~'="'~params[k]~'"'}{% endfor %}

[gcode_macro unload_filament]
description: Unloads filament from the extruder.
Usage: UNLOAD_FILAMENT [LENGTH=<distance>] [SPEED=<speed>]
[EXTRUDER=<extruder>] [TARGET=<temperature>]
[EXTRUDER=<extruder>] [MINIMUM=<temperature>]
gcode:
_LOAD_UNLOAD LOAD=0{% for k in params
%}{' '~k~'="'~params[k]~'"'}{% endfor %}

# Dummy argument block for Mainsail
{% set dummy = None if True else "
{% set dummy = params.LENGTH|default(variable_load_length)|float %}
{% set dummy = params.SPEED|default(variable_load_speed)|float %}
{% set dummy = params.EXTRUDER|default(default extruder) %}
{% set dummy = params.TARGET|default(current temp)|int %}
{% set dummy = params.MINIMUM|default(min_extrude_temp)|int %}
" %} # End argument block for Mainsail
_LOAD_UNLOAD LOAD=0{% for k in params|reject("==", "T")
%}{' '~k~'="'~params[k]~'"'}{% endfor %}

[gcode_macro _lift_m700]
[gcode_macro _pause_inner_m700]
gcode:
{% if printer.toolhead.homed_axes != 'xyz' %}
{ action_raise_error("Must home axis first.") }
{% set extruder = printer["extruder" ~ params.T|int]
if params.T|default(0)|int != 0 else printer.toolhead.extruder %}
{% if extruder != printer.toolhead.extruder%}
ACTIVATE_EXTRUDER EXTRUDER={extruder}
{% endif %}

{% set z_param = (' Z="%f"' % params.Z) if 'Z' in params else "" %}

{% if printer.idle_timeout.state|string == "Printing" %}
PAUSE P=2{z_param}
{% elif not printer.pause_resume.is_paused%}
SET_GCODE_VARIABLE MACRO=_load_unload VARIABLE=is_printing VALUE="{0}"
PARK P=2{z_param}
{% endif %}
SAVE_GCODE_STATE NAME=_LIFT_M700
G91
G0 Z{params.Z}
RESTORE_GCODE_STATE NAME=_LIFT_M700

[gcode_macro m701]
description: Loads filament to the extruder.
Usage: M701 L<distance> [Z<pos>] [T<extruder>]
description: Pauses/parks the toolhead then loads filament to the extruder.
Usage: M701 [L<distance>] [Z<pos>] [T<extruder>]
gcode:
{% set extruder = printer["extruder" ~ params.T|int]
if params.T|default(0)|int != 0 else printer.toolhead.extruder %}
{% if 'Z' in params %}_LIFT_M700 Z={params.Z}{%endif%}
LOAD_FILAMENT LENGTH={params.L} EXTRUDER={extruder
}{% if not printer[printer.toolhead.extruder].can_extrude %} TARGET={
printer.configfile.settings[extruder].min_extrude_temp
}{% endif %}
{% if 'U' in params %}
{% if not 'L' in params %}
RESPOND TYPE=error MSG="Argument \"U\" substituted for missing \"L\"."
{% set dummy = params.__setitem__("L", params.U) %}
{% else %}
RESPOND TYPE=error MSG="Invalid argument \"U\" ignored."
{% endif %}
{% endif %}

_PAUSE_INNER_M700 {% for k in params %}{' '~k~'="'~params[k]~'"'}{% endfor %}
LOAD_FILAMENT LENGTH={
params.L|default(printer["gcode_macro _km_globals"].load_length)|float}

[gcode_macro m702]
description: Unloads filament from the extruder.
Usage: M701 U<distance> [Z<pos>] [T<extruder>]
description: Pauses/parks the toolhead then unloads filament from the extruder.
Usage: M702 [U<distance>] [Z<pos>] [T<extruder>]
gcode:
{% set extruder = printer["extruder" ~ params.T|int]
if params.T|default(0)|int != 0 else printer.toolhead.extruder %}
{% if 'Z' in params %}_LIFT_M700 Z={params.Z}{%endif%}
UNLOAD_FILAMENT LENGTH={params.U} EXTRUDER={extruder
}{% if not printer[printer.toolhead.extruder].can_extrude %} TARGET={
printer.configfile.settings[extruder].min_extrude_temp
}{% endif %}
{% if 'L' in params %}
{% if not 'U' in params %}
RESPOND TYPE=error MSG="Argument \"L\" substituted for missing \"U\"."
{% set dummy = params.__setitem__("U", params.L) %}
{% else %}
RESPOND TYPE=error MSG="Invalid argument \"L\" ignored."
{% endif %}
{% endif %}

_PAUSE_INNER_M700 {% for k in params %}{' '~k~'="'~params[k]~'"'}{% endfor %}
UNLOAD_FILAMENT LENGTH={
params.U|default(printer["gcode_macro _km_globals"].load_length)|float}
67 changes: 43 additions & 24 deletions park.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,51 @@

[gcode_macro park]
description: Park the toolhead
Usage: PARK [P=<0|1|2>] [X=<pos>] [Y=<pos>] [Z=<pos>]
Usage: PARK [P=<0|1|2>] [X=<pos>] [Y=<pos>] [Z=<pos>] [LAZY=<1|0>]
gcode:
{% set toolhead = printer.toolhead %}
{% if toolhead.homed_axes != "xyz" %}
{action_respond_info("Must home axes first.")}
{% endif %}

{% set km = printer["gcode_macro _km_globals"] %}
{% set max_z = toolhead.axis_maximum.z %}
{% set min_z = toolhead.axis_minimum.z %}
{% set travel_speed_xy = km.travel_speed_xy %}
{% set travel_speed_z = km.travel_speed_z %}
{% set LAZY = params.LAZY|default(1)|int %}
{% if printer.toolhead.homed_axes != "xyz" %}
{% if LAZY %}
G28 O
{% else %}
{action_raise_error("Must home axes first.")}
{% endif %}
{% endif %}

# Z position type from G27 (if below, absolute, relative)
{% set P = (params.P|default(2))|int %} # Default to 2 because it's sanest.
{% set X = params.X|default(km.park_x)|float %}
{% set Y = params.Y|default(km.park_x)|float %}
{% set Z = params.Z|default(km.park_z)|float %}

_CHECK_KINEMATIC_LIMITS X="{X}" Y="{Y}" Z="{Z}"
_PARK_INNER X="{X}" Y="{Y}" Z="{Z}" P="{P}" LAZY="{LAZY}"
# Dummy argument block for Mainsail
{% set dummy = None if True else "
{% set dummy = params.P|default(mode=<0|1|2>)|int %}
{% set dummy = params.X|default(X position)|int %}
{% set dummy = params.Y|default(Y position)|int %}
{% set dummy = params.Z|default(Z position)|int %}
" %} # End argument block for Mainsail

[gcode_macro _park_inner]
gcode:
{% set km = printer["gcode_macro _km_globals"] %}
{% set travel_speed_xy = km.travel_speed_xy %}
{% set travel_speed_z = km.travel_speed_z %}

{% set position = printer.gcode_move.gcode_position %}

# Use the taller of the highest printed layer or the current Z height, which
# should helps crashes e.g. when a sequential print in progress.
{% set clearance_z = (printer["gcode_macro _km_layer_run"].clearance_z,
printer.gcode_move.gcode_position.z) | max %}
position.z) | max %}
{% set P = params.P|int %}
{% set X = params.X|float %}
{% set Y = params.Y|float %}
{% set Z = params.Z|float %}
{% set LAZY = params.LAZY|int %}

# Convert everything to absolute coordinates.
# P == 1 is absolute, so needs no adjustment.
Expand All @@ -43,21 +64,19 @@ gcode:
{% endif %}

# Clamp to the printer limits.
{% set Z = ((Z, max_z)|min, min_z)|max %}
{% set Z = ((Z, printer.toolhead.axis_maximum.z)|min,
printer.toolhead.axis_minimum.z)|max %}

SAVE_GCODE_STATE NAME=PARK
G90
G0 Z{Z} F{travel_speed_z}
G0 X{X} Y{Y} F{travel_speed_xy}
RESTORE_GCODE_STATE NAME=PARK MOVE=0
# Don't move if it's a lazy park and we're already in position.
{% if (not LAZY) or P != 2 or X != position.x or Y != position.y
or Z < clearance_z %}
SAVE_GCODE_STATE NAME=PARK
G90
G0 Z{Z} F{travel_speed_z}
G0 X{X} Y{Y} F{travel_speed_xy}
RESTORE_GCODE_STATE NAME=PARK MOVE=0
{% endif %}

# Dummy argument block for Mainsail
{% set dummy = None if True else "
{% set dummy = params.P|default(mode=<0|1|2>)|int %}
{% set dummy = params.X|default(X position)|int %}
{% set dummy = params.Y|default(Y position)|int %}
{% set dummy = params.Z|default(Z position)|int %}
" %} # End argument block for Mainsail

[gcode_macro g27]
description: Parks the toolhead.
Expand Down
5 changes: 2 additions & 3 deletions pause_resume_cancel.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ gcode:
SET_GCODE_VARIABLE MACRO=resume VARIABLE=saved_e VALUE="{E}"
SAVE_GCODE_STATE NAME=PAUSE_override_state
_KM_PAUSE_BASE
G91
M83
G1 E{'%.4f' % -E} F{km.load_speed}
PARK P=2{% for k in params|select("in", "XYZ") %}
{' '~k~'="'~params[k]~'"'}
Expand All @@ -44,8 +44,7 @@ description: Pauses the current print.
[Z<pos>]
gcode:
PAUSE P=2{% for k in params|select("in", "BEXYZ") %}{
' '~k~'="'~params[k]~'"'
}{% endfor %}
' '~k~'="'~params[k]~'"'}{% endfor %}
UNLOAD_FILAMENT{% if 'U' in params %} LENGTH={params.U}{% endif %}
{% if 'R' in params %}M109 S{params.R}{% endif %}
# Clear the saved E so we don't unretract on return.
Expand Down

0 comments on commit de3172b

Please sign in to comment.