Firmware Retraction for multiple extruders with Z Hop and Swap (Long Retraction)

Use:

G10 [(Retraction)] [S1 (Long Retraction)]
G11 [(Recover)]
M207 [T extruder no.] [F retract feedrate] [S retract length] [W swap retract length] [Z z hop height>]
M208 [T extruder no.] [F recover feedrate] [R swap recover feedrate] [S recover extra length] [w swap recover extra length]

In addition, M207 and M208 without a parameter will output a parameter.
In addition, there are two macros that are used when switching extruders:
gcode_macro switch_t0 and gcode_macro switch_t1, which must either be renamed or called from T0 (T1).
For more than 2 extruders, the variables in G11, M207 and M208 must be expanded. And create more gcode_macro switch_t(x)
I am interested in constructive feedback.

# tore1887

[gcode_macro P3]                                                       ; Firmware retraction, resett
gcode:
    M117
    SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e0_gog10 VALUE=True
    SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e1_gog10 VALUE=True
    SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e0_zhop VALUE=0.000
    SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e0_zhop VALUE=0.000

[gcode_macro G10]                                                                           ; Firmware retraction, retract
description: G10 [S1 (Long Retraction)]
gcode:
    {% set extruderc = printer["gcode_macro switch_t0"].current %}                          ; Current extruder as a number
    {% if printer[printer.toolhead.extruder].can_extrude and printer.toolhead.homed_axes == "xyz" %}    ; Is Printer/Extruder ready
        {% if printer["gcode_macro G11"]["e"~extruderc|string~"_gog10"] %}                  ; Can current extruder retract
            {% set pose = printer.gcode_move.gcode_position.e %}                            ; Get current extruder position
            {% if 'S' in params and params.S == "1" %}                                      ; Swap retraction
                {% set retr = printer["gcode_macro M207"]["e"~extruderc|string~"_w"] %}     ; Get swap retraction amount
                SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_swap VALUE=True          ; Save swap status for retraction
            {% else %}
                {% set retr = printer["gcode_macro M207"]["e"~extruderc|string~"_s"] %}     ; Get retraction amount
                SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_swap VALUE=False         ; Save swap status for retraction
            {% endif %}
            G1 E{pose - retr} F{printer["gcode_macro M207"]["e"~extruderc|string~"_f"] }    ; Retract
            G92 E{pose}                                                                     ; Set position
            {% set posr = printer["gcode_macro M207"]["e"~extruderc|string~"_s"] %}         ; Amount of retract
            SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_retr VALUE={retr}            ; Amount of retract save for unretract
            {% set posz = printer.gcode_move.gcode_position.z %}                            ; Get current Z height
            {% set posh = printer["gcode_macro M207"]["e"~extruderc|string~"_z"] %}         ; Height to jump
            {% set posj = (posz + posh)|round(5) %}                                         ; Add
            G0 Z{posj}                                                                      ; Jump
            G92 Z{posz}                                                                     ; Set new position
            SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_zhop VALUE={posh}            ; Save for recovering
            SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_gog10 VALUE=False            ; Extruder E0 not ready to G10
        {% endif %}
    {% else %}
        M118 Extruder too cold or printer not homed!
    {% endif %}

[gcode_macro G11]                                                                           ; Firmware retraction, recover
variable_e0_gog10: True                                                                     ; Extruder0 ready to retract
variable_e1_gog10: True                                                                     ; Extruder1 ready to retract
variable_e0_swap: False                                                                     ; Extruder0 last retraction a swap retraction
variable_e1_swap: False                                                                     ; Extruder1 last retraction a swap retraction
variable_e0_zhop: 0.0                                                                       ; Last Extruder0 jump height
variable_e1_zhop: 0.0                                                                       ; Last Extruder1 jump height
variable_e0_retr: 0.0                                                                       ; Last Extruder0 retraction
variable_e1_retr: 0.0                                                                       ; Last Extruder1 retraction
description: G11
gcode:                                                                                      ;
    {% set extruderc = printer["gcode_macro switch_t0"].current %}                          ; Current extruder as a number
    {% if printer[printer.toolhead.extruder].can_extrude and printer.toolhead.homed_axes == "xyz" %}    ; Is Printer/Extruder ready
        {% if printer[printer.toolhead.extruder].can_extrude %}                             ; Extruder warm
            {% if not printer["gcode_macro G11"]["e"~extruderc|string~"_gog10"] %}          ; If we are retracted, continue
                {% set posz = printer.gcode_move.gcode_position.z %}                        ; Get current Z height
                {% set posh = printer["gcode_macro G11"]["e"~extruderc|string~"_zhop"] %}   ; Height of the previous z hop
                G0 Z{(posz - posh)|round(5)}                                                ; Subtract, and jump down
                G92 Z{posz}                                                                 ; Set new position
                SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_zhop VALUE=0             ; Current extruder zero Z-hop
                {% set pose = printer.gcode_move.gcode_position.e %}                        ; Get current extruder position
                {% set retr = printer["gcode_macro G11"]["e"~extruderc|string~"_retr"] %}   ; Get last retraction amount
                {% if printer["gcode_macro G11"]["e"~extruderc|string~"_swap"] %}           ; Was last retraction a swap retraction
                    {% set extr = printer["gcode_macro M208"]["e"~extruderc|string~"_w"] %} ; Get swap additional recover lenght
                    {% set sped = printer["gcode_macro M208"]["e"~extruderc|string~"_r"] %} ; Get swap recover speed
                {% else %}                                                                  ;
                    {% set extr = printer["gcode_macro M208"]["e"~extruderc|string~"_s"] %} ; Get normal additional recover lenght
                    {% set sped = printer["gcode_macro M208"]["e"~extruderc|string~"_f"] %} ; Get recover speed
                {% endif %}
                SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_swap VALUE=False         ; Reset swap status for retraction
                G1 E{pose + retr + extr} F{sped}                                            ; Retract recover (unretract)
                G92 E{pose}                                                                 ; Set position
                SET_GCODE_VARIABLE MACRO=G11 VARIABLE=e{extruderc}_gog10 VALUE=True         ; Current extruder ready to G10
            {% endif %}
        {% endif %}
    {% else %}
        M118 Extruder too cold or printer not homed!
    {% endif %}

[gcode_macro M207] 													; Firmware Retraction - retract setting
variable_e0_f: 2700			; Retract feedrate
variable_e1_f: 2400
variable_e0_s: 2.0			; Retract lenght
variable_e1_s: 4.0
variable_e0_w: 3.0			; Retract swap lenght (multiextruder)
variable_e1_w: 5.0
variable_e0_z: 0.10			; Z lift on retraction
variable_e1_z: 0.25

description: M207 [T extruder nr.] [F retract feedrate] [S retract length] [W swap retract length] [Z z hop height>]
gcode:                                                                                      ;
    {% set extruderc = printer["gcode_macro switch_t0"].current %}                          ; Current extruder as a integer
	{% if 'T' in params %}                                                                  ;
	    {% set extrudert = params.T %}                                                      ;
	{% endif %}                                                                             ;
    {% if 'F' in params %}
        {% if (params.F|int <= 7200) and (params.F|int >= 300) %}                           ; Max 7200mm/min min 300mm/min
			{% if 'T' in params %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extrudert}_f VALUE={params.F}      ; Update M207 Tx F
			{% else %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extruderc}_f VALUE={params.F}      ; Update M207 F for current extruder
			{% endif %}
        {% else %}
            M118 Parameter 'F' out of range
        {% endif %}
    {% endif %}	
    {% if 'S' in params %}
        {% if (params.S|int <= 10) and (params.S|int >= 0) %}                               ; Max 7200mm/min min 300mm/min
			{% if 'T' in params %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extrudert}_s VALUE={params.S}      ; Update M207 Tx S
			{% else %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extruderc}_s VALUE={params.S}      ; Update M207 S for current extruder
			{% endif %}
        {% else %}
            M118 Parameter 'S' out of range
        {% endif %}
    {% endif %}	
	{% if 'W' in params%}
	    {% if (params.W|float <= 10) and (params.W|float >= 0) %}                           ; Max 4mm min -2mm
	        {% if 'T' in params %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extrudert}_w VALUE={params.W}      ; Update M207 Tx W
	        {% else %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extruderc}_w VALUE={params.W}      ; Update M207 W for current extruder
	        {% endif %}
	    {% else %}
	        M118 Parameter 'W' out of range
        {% endif %}
	{% endif %}
	{% if 'Z' in params %}
	    {% if (params.Z|float <= 1) and (params.Z|float >= 0) %}                            ; Max 1mm min 0
			{% if 'T' in params %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extrudert}_z VALUE={params.Z}      ; Update M207 Tx Z
		    {% else %}
				SET_GCODE_VARIABLE MACRO=M207 VARIABLE=e{extruderc}_z VALUE={params.Z}      ; Update M207 Z for current extruder
		    {% endif %}
    	{% else %}
	        M118 Parameter 'Z' out of range
        {% endif %}
	{% endif %}
	{% if rawparams == "" %}
		M118 Active extruder is {printer.toolhead.extruder}
		M118 M207 T0 Speed {printer["gcode_macro M207"].e0_f}   Lenght {printer["gcode_macro M207"].e0_s}   Z-Hop {printer["gcode_macro M207"].e0_z}
		M118                 SWAP-Lenght {printer["gcode_macro M207"].e0_w}
		M118 M208 T0 Speed {printer["gcode_macro M208"].e0_f}        Recover-Extra {printer["gcode_macro M208"].e0_s}
		M118    SWAP-Speed {printer["gcode_macro M208"].e0_r}   SWAP-Recover-Extra {printer["gcode_macro M208"].e0_w}
		M118
		M118 M207 T1 Speed {printer["gcode_macro M207"].e1_f}   Lenght {printer["gcode_macro M207"].e1_s}   Z-Hop {printer["gcode_macro M207"].e1_z}
		M118                 SWAP-Lenght {printer["gcode_macro M207"].e1_w}
		M118 M208 T1 Speed {printer["gcode_macro M208"].e1_f}        Recover-Extra {printer["gcode_macro M208"].e1_s}
		M118    SWAP-Speed {printer["gcode_macro M208"].e1_r}   SWAP-Recover-Extra {printer["gcode_macro M208"].e1_w}
    {% endif %}

[gcode_macro M208]          ; Firmware Retraction - unretract settingd
variable_e0_f: 2400			; Recover feedrate
variable_e1_f: 2100
variable_e0_r: 2200			; Swap recover feedrate (multiextruder)
variable_e1_r: 1900
variable_e0_s: 0.00			; Additional recover lenght. Can be negativ to reduse recover lenght
variable_e1_s: 0.00
variable_e0_w: 0.00			; Additional recover swap lenght. Can be negativ to reduse recover lenght (multiextruder)
variable_e1_w: 0.00
description: M208 [T extruder nr.] [F recover feedrate] [R swap recover feedrate] [S recover extra length] [w swap recover extra length]
gcode:                                                                                      ;
    {% set extruderc = printer["gcode_macro switch_t0"].current %}                          ; Current extruder as a integer
	{% if 'T' in params %}                                                                  ;
	    {% set extrudert = params.T %}                                                      ;
	{% endif %}                                                                             ;
	{% if extrudert == "2" %}                                                               ; Extra code because I'm changing the second
		{% set extrudert = "1" %}                                                           ; extruder between bowden and direct drive on my printer.
	{% endif %}                                                                             ; In Cura I have 3 extruders, and here I have to then correct T2 to T1.
    {% if 'F' in params %}
        {% if (params.F|int <= 7200) and (params.F|int >= 300) %}                           ; Max 7200mm/min min 300mm/min
			{% if 'T' in params %}
				SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extrudert}_f VALUE={params.F}      ; Update M208 Tx F
			{% else %}
				SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extruderc}_f VALUE={params.F}      ; Update M208 F for current extruder
			{% endif %}
        {% else %}
            M118 Parameter 'F' out of range, M208 {params.F}
        {% endif %}
	{% endif %}
	{% if 'R' in params %}
        {% if (params.R|int <= 7200) and (params.R|int >= 300) %}                           ; Max 7200mm/min min 300mm/min
            {% if 'T' in params %}
                SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extrudert}_r VALUE={params.R}      ; Update M208 Tx R
            {% else %}
                SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extruderc}_r VALUE={params.R}      ; Update M208 R for current extruder
            {% endif %}
        {% else %}
            M118 Parameter 'R' out of range
        {% endif %}
    {% endif %}	
	{% if 'S' in params%}
	    {% if (params.S|float <= 4) and (params.S|float >= -2) %}                           ; Max 4mm min -2mm
			{% if 'T' in params %}
				SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extrudert}_s VALUE={params.S}      ; Update M208 Tx R
			{% else %}
				SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extruderc}_s VALUE={params.S}      ; Update M208 S for current extruder
			{% endif %}
	    {% else %}
	        M118 Parameter 'S' out of range
        {% endif %}
	{% endif %}
	{% if 'W' in params%}
	    {% if (params.W|float <= 4) and (params.W|float >= -2) %}                           ; Max 4mm min -2mm
	        {% if 'T' in params %}
				SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extrudert}_w VALUE={params.W}      ; Update M208 Tx W
	        {% else %}
				SET_GCODE_VARIABLE MACRO=M208 VARIABLE=e{extruderc}_w VALUE={params.W}      ; Update M208 S for current extruder
	        {% endif %}
	    {% else %}
	        M118 Parameter 'W' out of range
        {% endif %}
	{% endif %}
	{% if rawparams == "" %}
		M118 Active extruder is {printer.toolhead.extruder}
		M118 M207 T0 Speed {printer["gcode_macro M207"].e0_f}   Lenght {printer["gcode_macro M207"].e0_s}   Z-Hop {printer["gcode_macro M207"].e0_z}
		M118                 SWAP-Lenght {printer["gcode_macro M207"].e0_w}
		M118 M208 T0 Speed {printer["gcode_macro M208"].e0_f}        Recover-Extra {printer["gcode_macro M208"].e0_s}
		M118    SWAP-Speed {printer["gcode_macro M208"].e0_r}   SWAP-Recover-Extra {printer["gcode_macro M208"].e0_w}
		M118
		M118 M207 T1 Speed {printer["gcode_macro M207"].e1_f}   Lenght {printer["gcode_macro M207"].e1_s}   Z-Hop {printer["gcode_macro M207"].e1_z}
		M118                 SWAP-Lenght {printer["gcode_macro M207"].e1_w}
		M118 M208 T1 Speed {printer["gcode_macro M208"].e1_f}        Recover-Extra {printer["gcode_macro M208"].e1_s}
		M118    SWAP-Speed {printer["gcode_macro M208"].e1_r}   SWAP-Recover-Extra {printer["gcode_macro M208"].e1_w}
    {% endif %}

[gcode_macro switch_t0] 	; Called from macro T0
variable_current: 0         ; Current extruder
gcode:
    {% set old = printer["gcode_macro switch_t0"].current %}                          			; Current extruder as a number
    {% set new = "0" %}
    SET_GCODE_VARIABLE MACRO=switch_t0 VARIABLE=current VALUE={new}                             ; Set current extruder
 	{% if printer["gcode_macro G11"]["e"~old|string~"_zhop"] > 0 or printer["gcode_macro G11"]["e"~new|string~"_zhop"] > 0 %}
	    
		{% set posz = printer.gcode_move.gcode_position.z %}
		M118 T0 Jumping OLd hight {posz}
		;            Remove any old extruder z_hop                        Add any new E1 z_hop
        G0 Z{posz - printer["gcode_macro G11"]["e"~old|string~"_zhop"] + printer["gcode_macro G11"]["e"~new|string~"_zhop"]}
        M118 New Hight 
        G92 Z{posz}	
    {% endif %}

[gcode_macro switch_t1] 	; Called from macro from T1	
gcode:
	{% set old = printer["gcode_macro switch_t0"].current %}                          			; Current extruder as a number
    {% set new = "1" %}
    SET_GCODE_VARIABLE MACRO=switch_t0 VARIABLE=current VALUE={new}                             ; Set current extruder
	{% if printer["gcode_macro G11"]["e"~old|string~"_zhop"] > 0 or printer["gcode_macro G11"]["e"~new|string~"_zhop"] > 0 %}
	    M118 T1 Jumping
		{% set posz = printer.gcode_move.gcode_position.z %}
		;            Remove any old extruder z_hop                        Add any new E1 z_hop
        G0 Z{posz - printer["gcode_macro G11"]["e"~old|string~"_zhop"] + printer["gcode_macro G11"]["e"~new|string~"_zhop"]}
        G92 Z{posz}	
    {% endif %}

And here’s what I use in Menu, LCD screen.

[menu __main __Firmware_Retraction]
type: list
name: Retraction
enable: {printer.idle_timeout.state != "Printing" or printer.idle_timeout.state == "Printing"}

[menu __main __Firmware_Retraction __Swap]
type: list
name: SwapRet
enable: {printer.idle_timeout.state != "Printing" or printer.idle_timeout.state == "Printing"}

[menu __main __Firmware_Retraction __Swap __Swap_Retract_Lenght]
type: input
name: Sw_Lenght:{'%0.1f' % menu.input}
input: {printer["gcode_macro M207"]["e"~(printer["gcode_macro switch_t0"].current)~"_w"]}
input_min: 0
input_max: 10
input_step: 0.1
gcode:
    M207 T{printer["gcode_macro switch_t0"].current} W{menu.input}

[menu __main __Firmware_Retraction __Swap __Swap_Recover_Lenght]
type: input
name: Sw_Ek_Len:{'%0.2f' % menu.input}
input: {printer["gcode_macro M208"]["e"~(printer["gcode_macro switch_t0"].current)~"_w"]}
input_min: -2
input_max: 2
input_step: 0.01
gcode:
    M208 T{printer["gcode_macro switch_t0"].current} W{menu.input}

[menu __main __Firmware_Retraction __Swap __Swap_Recover_Speed]
type: input
name: Sw_Rec_Sp:{'%d' % menu.input}
input: {printer["gcode_macro M208"]["e"~(printer["gcode_macro switch_t0"].current)~"_r"]}
input_min: 300
input_max: 7200
input_step: 60
gcode:
    M208 T{printer["gcode_macro switch_t0"].current} R{menu.input}

[menu __main __Firmware_Retraction __Retract_Speed]
type: input
name: Ret_Speed:{'%d' % menu.input}
input: {printer["gcode_macro M207"]["e"~(printer["gcode_macro switch_t0"].current)~"_f"]}
input_min: 300
input_max: 7200
input_step: 60
gcode:
    M207 T{printer["gcode_macro switch_t0"].current} F{'%d' % menu.input}
    
[menu __main __Firmware_Retraction __Unretract__Speed]
type: input
name: Unr_Speed:{'%d' % menu.input}
input: {printer["gcode_macro M208"]["e"~(printer["gcode_macro switch_t0"].current)~"_f"]}
input_min: 300
input_max: 7200
input_step: 60
gcode:
    M208 T{printer["gcode_macro switch_t0"].current} F{'%d' % menu.input}
    
[menu __main __Firmware_Retraction __Retract_Length]
type: input
name: RetLenght:{'%0.1f' % menu.input}
input: {printer["gcode_macro M207"]["e"~(printer["gcode_macro switch_t0"].current)~"_s"]}
input_min: 0
input_max: 10
input_step: 0.1
gcode:
    M207 T{printer["gcode_macro switch_t0"].current} S{'%.1f' % menu.input}
    
[menu __main __Firmware_Retraction __Unretract_Extra_Lenght]
type: input
name: Ex_Unretr:{'%.2f' % menu.input}
input: {printer["gcode_macro M208"]["e"~(printer["gcode_macro switch_t0"].current)~"_s"]}
input_min: -2
input_max: 2
input_step: 0.01
gcode:
    M208 T{printer["gcode_macro switch_t0"].current} S{'%.2f' % menu.input}
    
[menu __main __Firmware_Retraction __Retract__Zhop]
type: input
name: Z_hop____:{'%.2f' % menu.input}
input: {printer["gcode_macro M207"]["e"~(printer["gcode_macro switch_t0"].current)~"_z"]}
input_min: 0
input_max: 2
input_step: 0.01
gcode:
    M207 Z{menu.input}

Edit: Removed som old lines.

" Menu, LCD screen. "

Hi… as a novice user. in some macro packages. i see macro app in the architecture you have written. and i don’t know what these macros do and where to install them. can you give some details about this subject for reference to users like me who are just starting and have no knowledge of software. thanks…

Well, I’m not a teacher.

1: You can copy - paste both parts into your printer.cfg.
2: Or you can create a separate file and e.g. call it retraction.cfg. Then you need to add a line in printer.cfg printer.cfg [include retraction.cfg]. And then copy - paste everything into it.
3: Or you can create two files retraction.cfg and retraction-menu.cfg. Then you need two lines in your printer.cfg. [include retraction.cfg] and [include retraction-menu.cfg]. And then copy - paste the code from my first post into the first file, and the code from my second post into the second file.

That was the easy part. The bottom two macros ([gcode_macro switch_t0] and [gcode_macro switch_t1]) in the first post are meant as an addition to your [gcode_macro t0] and [gcode_macro t1] macros. In my [gcode_macro t0] the last line is switch_t0, and similarly for t1.
As mentioned before I am no teacher. If you want to learn more about macros, printer.cfg etc. I am sure others can do it much better than me.

1 Like

thank you very much … for the information you have given … I have some knowledge about those topics. if I need to express myself more accurately, what I want to understand is that after installing the macro packages, when we install the lcd menu macro … is a menu added that we can control from the clipper screen (physical lcd panel).

Small note. Since I use translate when writing and reading my messages, sometimes there may be translation errors and misunderstandings. Please excuse me for that.

I also use translate.
One thing. If you have more than 2 extruders, you have to add variables.