X-In/1-Out Non-Mixing Extruder - Automate SuperSlicer & PrusaSlicer Filament Swaps

The following is basic documentation on how to setup SuperSlicer/Prusa Slicer/Slic3r to automatically change filaments though extruder stepper changes during a print.

I am not expert with Klipper, SuperSlicer, Prusa Slicer, and/or Slic3r. I will note any challenges that I’ve experienced during my setup and testing. I will also address any input provided in order to enhance this document for others to benefit from.

This builds upon the Config: X-In/1-Out Non-Mixing Extruder Config

Doc. Started: 08-dec-2022
Initial Completion: 09-dec-2022
Last Updated: 14-apr-2023 - added PrusaSlicer 2.6.0-alpha6 WIP

Klipper Version(s) this is working with:
v0.11.0-5
v0.11.0-6
v0.11.0-14
v0.11.0-30
v0.11.0-41
v0.11.0-173

SuperSlicer Version(s):
v2.4.58.5

PrusaSlicer Version(s):
v2.6.0-alpha6 [WIP - has only been visually compared to SS and not tested on a printer]

Assumptions:

Printer is operational using the above noted Config and using Klipper’s [extruder_stepper] to provide additional stepper inputs to your hot-end.

Definitions:

  • Extruder - The complete system of a combination of a Hot End, one or more Extruder Stepper(s), and connection system (typically PTFE tubing) that drives and directs filament though the printer
  • Hot End - the device that melts the filament to be delivered to the print surface.
  • Extruder Stepper - The drive system that pushes the filament into the Hot End, typically comprised of an stepper motor, drive gears, and some type of containment system (typically PTFE tubing).

Hardware and Dimensions:

My printer is a Piper2 Core-XY using a Phaetus Dragon SF hot end and a 4-in/1-out SCP Splitter. Adjusting dimensions provided will be necessary and may reduce some issues related to my specific setup.

I’m currently using a dual-drive BMG extruder and a self designed 4:1 compact belt driven extruder. however the extruders as well as their location are not necessary for this document.

This is the gantry image of a Piper2 Core-XY. there are three areas to be aware of:

  1. Cool Zone - The area in the hot end that filament travels and should be ‘cool’.
  2. Cooling Tube Position - a dimension from tip of the hot end to about the middle of the Cool Zone. This position, in the Cool Zone, is used by the slicer to cool and shape the filament before removing during a filament swap.
    a) 45mm for E3D v6 (approx)
    b) 32mm for Dragon SF (approx)
    c) 36mm for Dragon HF (approx)
    d) 25mm for Mosquito (approx)
  3. Filament Park Position - a dimension from the tip of the hot end to where another filament can easily enter the filament path to hot end from another entry point. This will vary greatly from printer to printer. The slicer uses this dimension to remove one filament and load another. The shorter this distance, the less issues will be seen during printing.
    a) 140mm for my Piper2 Core-XY - Due to the length of this dimension, a Klipper error is induced and will be noted/address later in the document.

Klipper Configuration - printer.cfg options used:

The following additions are used during the filament change / Tool Change routine. Further explanation will be provided in the SuperSlicer Setup section.

[gcode_macro PARK]
description: Park the head to change tool
gcode:
    M117 Parking Head...
    ##### set defaults #####
    {% set x = params.X|default(-15) %}      #edit to your park position
    {% set y = params.Y|default(0) %}      #edit to your park position
    {% set z = params.Z|default(10)|float %} #edit to your park position
    {% set e = params.E|default(4) %}        #edit to your retract length
    ##### save current x and y position ####
    SAVE_GCODE_STATE NAME=park_state
    ##### calculate save lift position #####
    {% set max_z = printer.toolhead.axis_maximum.z|float %}
    {% set act_z = printer.toolhead.position.z|float %}
    {% set lift_z = z|abs %}
    {% if act_z < (max_z - lift_z) %}
        {% set z_safe = lift_z %}
    {% else %}
        {% set z_safe = max_z - act_z %}
    {% endif %}
    ##### end of definitions #####
    G91
    {% if printer.extruder.can_extrude|lower == 'true' %}
      G1 E-{e} F2100
    {% else %}
      {action_respond_info("Extruder not hot enough")}
    {% endif %}
    {% if "xyz" in printer.toolhead.homed_axes %}    
      G1 Z{z_safe}
      G90
      G1 X{x} Y{y} F6000
    {% else %}
      {action_respond_info("Printer not homed")}
    {% endif %}
    M117 Head Parked...

PARK is used to move the print head off the purge block to a safe area for unloading and loading. This was done to remove heat from the printed objects.

[gcode_macro CONTINUE]
description: Continue's printing after tool change
gcode:
    M117 Print Continuing...
    ##### set defaults #####
    {% set speed = params.SPEED|default(180) %} #edit to your travel speed in mm^2
    ##### end of definitions #####
    RESTORE_GCODE_STATE NAME=park_state MOVE=1 MOVE_SPEED={speed}
    M117

CONTINUE (updated) - used to move the print head back to the purge block after loading filament. Will be adding the MOVE_SPEED option in the near future.

[gcode_macro FILAMENT_LOAD2]
description: Loads filament from splitter to hot end
gcode =
	M117 LOADING...
	G91
	G1 E110.0 F900
	G4 P900
	G1 E30.0 F150
	G90
    M117

FILAMENT_LOAD2 will extend the filament 140mm, from the Filament Park Position back to the Tip of the Hot End. This will be explained further and may not be needed if you have a shorter Filament Park Position dimension.

NOTE: I have a FILAMENT_LOAD1 gcode_macro that load filament from the stepper extruder gears to the Filament Park Position. It is not needed for the purpose of this document.

SuperSlicer Setup:

Printer Settings → General

  1. Set the number of Extruder Steppers configured in Klipper. This should be the total number of steppers in [extruder] and [extruder_stepper] objects. My printer has one extruder and one extruder_stepper = 2 extruders in SuperSlicer
  2. Check the Single Extruder Multi Material check box. This should enable additional features
  3. Confirm that the new menu object Single extruder MM setup is visible along with the number of extruder(s). If the new menu is not available, un-check the Single Extruder Multi Material, increase Extruders, an then re-check Single Extruder Multi Material. Once the new menu is visible, adjust Extruders to the correct number of your printer.

Printer Settings → Custom G-code

Add in the appropriate Tool change G-code. Mine is as follows:

;Tool Change g-code
PARK
ACTIVATE_EXTRUDER EXTRUDER=[tool_name]
FILAMENT_LOAD2
CONTINUE

During a filament swap, I decided to add some extra G-code that provides the following functions:

  1. PARK - Moves head off the printing area. This also removes hot end heat from the wipe tower during the loading process
  2. ACTIVATE_EXTRUDER EXTRUDER=[tool_name] - This does the physical switch between extruder_steppers in FW.
  3. FILAMENT_LOAD2 - loads the filament the needed 140mm from Filament Park Position to Tip. This may not be needed for shorter Filament Park Position dimensions.
  4. CONTINUE - Moves the print head back to the wipe tower so purging can take place.

General → Single extruder MM setup

Insert the value you determined from the first image above for Cooling tube position and Filament parking position. These values will be explained later on and how they work along with the Extra loading distance value.

General → Extruder (x)
These settings were explained in detail under my previous Confg post, link above.

Filament Settings
Reminder: Filament Settings are unique per filament selected. Make sure that you make changes to this section that is appropriate for each specific filament to be used.

Filament Settings → Multimaterial

This section is fairly long. Review and adjust as needed settings in the temperature, string reduction, and wipe tower settings.

Toolchange parameters…
These settings will be explained a bit more when we look at the generated g-code later in this document.

Adjust the Load and Unload speeds if you’d like. The image is more conservative than the defaults.

Change Number of cooling moves down to 1.

Pigment Percentage should be adjusted from 0 to 1 based on the filament pigment. 0 = natural/clear. 1 = black. This should be taken into consideration for how much purging is necessary to clean out the nozzle during the wipe tower moves. example: Light to Dark = less purging, Dark to Light = more purging needed.

Filament Settings → Custom G-code

Nothing out of the ordinary here. Great place to set PA values (based on filament selected and may be different for each extruder. I had to move the Z_ADJUST logic to the Printer Settings → Custom G-code → Start G-code so that the Z_ADJUST is not changed every time a tool is changed.

Print Settings
Reminder: Print Settings are unique per configuration selected. Make sure that you make changes to this section that is appropriate for each specific Printer Settings to be used.

Print Settings → Multiple extruders

Extruders, Ooze prevention, and Advanced sections will not be addressed in this document. Adjust as you see fit.

Wipe Tower needs to be Enabled and uncheck the Prime all printing extruders for starters. Feel free to adjust the default location of the Wipe tower position. It can be dynamically moved around on the 3D View before slicing. The remaining settings can be adjusted if/as needed.

PrusaSlicer Setup:

Note: PrusaSlicer configurations are based on the 2.6.0 release due to Klipper support and added macro functionallity
Printer Settings → General

  1. Set the G-Code Flavor to Klipper.
  2. Set the number of Extruder Steppers configured in Klipper. This should be the total number of steppers in [extruder] and [extruder_stepper] objects. My printer has one extruder and one extruder_stepper = 2 extruders in SuperSlicer
  3. Check the Single Extruder Multi Material check box. This should enable additional features
  4. Confirm that the new menu object Single extruder MM setup is visible along with the number of extruder(s). If the new menu is not available, un-check the Single Extruder Multi Material, increase Extruders, an then re-check Single Extruder Multi Material. Once the new menu is visible, adjust Extruders to the correct number of your printer.

Printer Settings → Custom G-code*

In order to maintain similar G-code settings between SuperSlicer and PrusaSlicer, I used some new PrusaSlicer v2.6.0 custom variable functionality.

Start G-Code - This creates a custom variable called tool_name that will call set the Klipper configured stepper name based on Tx tool numbering that PrusaSlicer uses.

;Tool: [current_extruder]
{if current_extruder == 0 then
  global tool_name="extruder" 
elsif current_extruder == 1 then
  global tool_name="belted_extruder"
else
  global tool_name="unknown"
endif}

{
"ACTIVATE_EXTRUDER EXTRUDER=" + tool_name + "
";
"SET_PRESSURE_ADVANCE ADVANCE=0 EXTRUDER="+ tool_name + "
";
}

.
*End G-code -

{
"SET_PRESSURE_ADVANCE ADVANCE=0 EXTRUDER="+ tool_name + "
";
}

{if total_toolchanges==0}
  ; Unloads filament to Filament Park Position - 140mm from tip.  
  ; Only needed for non-multi-material prints.
  FILAMENT_UNLOAD
{endif}

.
Tool change G-code -

;Tool Change G-code
{if layer_num > 1 then
  "PARK
  ";
 
  if next_extruder == 0 then
    global tool_name="extruder" 
  elsif next_extruder == 1 then
    global tool_name="belted_extruder"
  else
    global tool_name="unknown"
  endif

  "ACTIVATE_EXTRUDER EXTRUDER=" + tool_name + "
  ";

  "FILAMENT_LOAD2
  ";
  "CONTINUE
  ";
else

endif}

During a filament swap, I decided to add some extra G-code that provides the following functions:

  1. PARK - Moves head off the printing area. This also removes hot end heat from the wipe tower during the loading process
  2. ACTIVATE_EXTRUDER EXTRUDER=[tool_name] - This does the physical switch between extruder_steppers in FW.
  3. FILAMENT_LOAD2 - loads the filament the needed 140mm from Filament Park Position to Tip. This may not be needed for shorter Filament Park Position dimensions.
  4. CONTINUE - Moves the print head back to the wipe tower so purging can take place.

General → Single extruder MM setup

Insert the value you determined from the first image above for Cooling tube position and Filament parking position. These values will be explained later on and how they work along with the Extra loading distance value.

General → Extruder (x)
These settings were explained in detail under my previous Confg post, link above.

Filament Settings → Advanced

This section is fairly long. Review and adjust as needed settings in the temperature, string reduction, and wipe tower settings.

Toolchange parameters…
These settings will be explained a bit more when we look at the generated g-code later in this document.

Adjust the Load and Unload speeds if you’d like. The image is more conservative than the defaults.

Change Number of cooling moves down to 3 (updated from original SuperSlicer settings).

Filament Settings → Custom G-code

Nothing out of the ordinary here. Great place to set PA values (based on filament selected and may be different for each extruder. I had to move the Z_ADJUST logic to the Printer Settings → Custom G-code → Start G-code so that the Z_ADJUST is not changed every time a tool is changed.

Start G-code -

; Filament specific Start G-code
;
;Tool: [current_extruder]
{if current_extruder == 0 then
  global tool_name="extruder" 
elsif current_extruder == 1 then
  global tool_name="belted_extruder"
else
  global tool_name="unknown"
endif}
;
;
{ if tool_name == "extruder" then
  "; PLA PA
  ";
  "SET_PRESSURE_ADVANCE ADVANCE=0.653 SMOOTH_TIME=0.040 EXTRUDER=" + tool_name + "
  ";
elsif tool_name == "belted_extruder" then
  "SET_PRESSURE_ADVANCE ADVANCE=0.4176 SMOOTH_TIME=0.040 EXTRUDER=" + tool_name + "
  ";
else
endif }
;

Print Settings
Reminder: Print Settings are unique per configuration selected. Make sure that you make changes to this section that is appropriate for each specific Printer Settings to be used.

Print Settings → Multiple extruders

Extruders, Ooze prevention, and Advanced sections will not be addressed in this document. Adjust as you see fit.

Wipe Tower needs to be Enabled and uncheck the Prime all printing extruders for starters. Feel free to adjust the default location of the Wipe tower position. PrusaSlicer allows for dynamically moving the prime tower around on the 3D View before slicing. The remaining settings can be adjusted if/as needed.

Toolchange Workflow:

The following steps are a basic toolchange workflow in SuperSlicer.

  1. Ramming procedure - This is little positive extrustion moves and the print head moves back and fourth over the purge block to try to shape the end of the filament
  2. Retract to Cooling Tube Position - Four retraction sequence used to move and form the tip of the filament into the Cool Zone. Speed is controlled under Filament Settings and Unloading speed at the start value.
  3. Cooling Move - Configured by (Filament Settings) Number of Cooling Moves, Speed of Cooling Moves, and (Printer Settings) Cooling Tube Length. This too is done as the print head moves back and fourth over the purge block.
  4. Retract to Filament Park Position (140mm from Tip). Speed is controlled under Filament Settings and Unloading Speed value.
  5. Filament End G-code, if configured
  6. Tool Change G-code
  7. Filament Start G-code, if configured
  8. Tool Change Filament Load sequence - This is 3-step filament load process where the filament move the complete distance of the Filament Park Position dimension (140mm-ish) by 20%, then 70% and finally 10% of the total distance
    Distance = Filament Park Position + Extra Loading Distance configured in Printer Settings.
    Speed = Speed is controlled under Filament Settings and Loading speed at the start and Loading speed values.
  9. Purge (print) new filament on the wipe tower
  10. Continue printing part with new filament.

Example Sliced Model with Tool Change at Layer:

This image is of the sliced model. a simple logo with a color change at a layer. Purge/Wipe block is just to the top.

Generated G-code and explanation of settings:



Challenges & Issues:

Due to the long length of 140mm, this process, Klipper kept throwing a Move exceeds maximum extrusion (3.963mm^2 vs 0.640mm^2) error.
The G-code causing the issue is under the Tool Change Filament Load section:


Specifically the two X-moves in combination with the long E-moves.

To compensate, I decided to use SuperSlicer G-Code Substitution under Print Settings.

I needed three rules, one for each load distance, that would comment out the G-code. As long as I don’t change my Filament Park Position and Extra loading distance values, the configured regex will comment out any lines found in the created G-code.

; CP TOOLCHANGE LOAD
G1 E27.6 F180
G1  X194.375  E96.6 F650
G1  X136.250  E13.8 F455

Find Regex 1: (G1\s*E27.6\sF[0-9]*) - Finds a G1(space)E27.6(space)F(any speed)
Find Regex 2: (G1\s*X[\0-9]*E96.6\sF[0-9]*) - Finds a G1(space)X(any value)E96.6(space)F(any speed)
Find Regex 3: (G1\s*X[\0-9]*E13.8\sF[0-9]*) - Finds a G1(space)X(any value)E13.8(space)F(any speed)

Corresponding Replace value can be anything. I added a semi-colon (comment character) followed by something so I would remember what was modified.

UPDATE -
using at ${1} within the Replace with section will insert the original found text back into the saved g-code file.
example:
; ${1} - G-code substitution since it causes Klipper Move exceeds maximum extrusion (3.963mm^2 vs 0.640mm^2)

Result G-code looks like:

; CP TOOLCHANGE LOAD
; G1 E27.6 F180 - G-code substitution since it causes Klipper Move exceeds maximum extrusion 3.963mm^2 vs 0.640mm^2
; G1  X194.375  E96.6 F650 - G-code substitution since it causes Klipper Move exceeds maximum extrusion 3.963mm^2 vs 0.640mm^2
; G1  X136.250  E13.8 F455 - G-code substitution since it causes Klipper Move exceeds maximum extrusion 3.963mm^2 vs 0.640mm^2

Finally, to get the filament to load from Filament Park Position to Tip, I added in the FILAMENT_LOAD2 gcode_maco in the Tool change G-code section.

Printed Results:

To-Do Item(s):

I still need to adjust the Custom G-code in several areas by using {if wipe_tower == 1} logic to enable/disable mutli-color/single color print specific g-code.

UPDATE:
I was unable to use the wipe_tower variable to key off of for g-code needed for non-toolchaning printing. I found a total_toolchanges variable was available and used that in my End G-code section in SuperSlicer to retract the filament at the end of a print:

{if total_toolchanges == 0}
; Unloads filament to Filament Park Position - 140mm from tip.  
; Only needed for non-multi-material prints.
FILAMENT_UNLOAD
{endif}

Toolchanging printing routines have a built in final retract to Filament Park Position, so adding a similar final retract for non-toolchanging printing keeps the workflow consistent.

Filament Unload g-code_macro -
This was created to mimic the same process used during toolchanging printing. The retract to Cooling Tube Position, Cooling moves, and retract to Filament Park Position routine does not form a tail on the end of the filament.

[gcode_macro FILAMENT_UNLOAD]
description: Unloads filament from hot end to Filament Park Position
gcode =
	G91
#   Retract to Cooling Tube Position
    G1 E-15 F4800
    G1 E-13.65
    G1 E-3.9 F2400
    G1 E-1.95 F1440  ;-34.5mm retraction
#   Cooling Move 
    G1  E5 F1531
    G1  E-5 F2366
#   Retract to Filament Park Position
    G1 E-105.5 F2000  ;-140mm retraction total
	G90
5 Likes

This needs to be added to the klipper docs !

2 Likes

Outside of the Tool Change G-code and the issue I had with filament load, this document is more “slicer” than Klipper.

Bad part is, there isn’t even clear documentation on how to do filament swaps in the slicer documents either.

1 Like

Has anyone made any progress regarding this lately???

What additional progress are you looking for?

This was very helpful. With this information, along with similar discussions/videos, I’m starting to understand how multi-material printing is configured.

My setup is similar to what is described here, with one extruder per spool, a combiner at the hotend, and a single primary extruder/hotend. It’s currently working very well with single color printing, with a mostly manual process of loading/unloading. The biggest problem is with the filament getting stuck unloading and/or reloading.

I use superslicer, and have gathered that it allows for quite a bit of configurability on refining the process of shaping the tip of the filament on removal, which I’m very interested in trying. I’m wondering, though, if that configuration is in the right place.

One of the problems that I’ve had with trying to automate the loading/unloading process is figuring out what to do in the case of canceling a print, or, worse case, an emergency shutdown when things go south.

If, for whatever reason, you have the filament loaded into the hotend and you’re not printing, it seems like you need a macro to do the whole clean unload process, which means the macro really needs to be in the klipper config. The problem is that the filament unloading process can be filament dependent, which is why it makes sense in the slicer.

Am I missing something here? Could/should, at least, the filament unloading macros be in klipper?

Yes, you have to deal with filament still loaded during a cancel or E-Stop situation.

If you E-Stop the printer, that is just a “kill” and you will have to manage filament unloading manually or after the fact.

If you cancel, then you can automate with a macro. This is where the “UNLOAD_FILAMENT” macro comes in. It will perform the ramming cycle the same way as the filament swap. Should it be the same for all filaments? YES, I think you can make it the same since it’s the same hot end, even if you have different extruders, which I do on my printer.

Both my End and Cancel gcode macros call the UNLOAD_FILAMENT macro to extract the currently loaded filament.

@jjarosz Can you explain the FILAMENT_LOAD2 in Tool Change G-Code?

I tried to use it, but what was happening is that at the first filament change, after purging the old color, the hotend was just sitting in place and making a giant blob of filament, which then caught the nozzle and caused a layer shift.

I removed it and now it is working correctly.

Also: why does Klipper turn off pressure advance when changing extruders? I didn’t include any of the SET_PRESSURE_ADVANCE code on purpose in the macros, because I wanted to keep the same value all the time, but it turns out it just gets set to 0 after 1st tool change…

Other than that, it worked very well

This G-code is used to move the filament from the Park Position to the nozzle tip in the hot end.

If you have a short park position, you might not need it as the slicer adds that move in. I had to remove it due the long load length via g-code substitution.

Ohhh I get it now, this is used with the combination of commenting out the extrusions that cause klipper error.

I just upped the limit in the config a bit, so I didn’t run into that.

One more thing, I finished the first print, and at the end it unloaded the filament to park position. I loaded up the next one, but I don’t see any code to load it back it. Do I need to add that manually?

@Asalas88 Yes, I used the same FILAMENT_LOAD2 G-code macro to load the filament from the chosen extruder into the hot end.

Here is a snippet of my start G-code:

; Start G-code
; https://github.com/Klipper3d/klipper/pull/5726
; "Start G-code" (above of your start_print gcode)
SET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]
;
ACTIVATE_EXTRUDER EXTRUDER=[tool_name]

;Tool: [tool_name]
SET_PRESSURE_ADVANCE ADVANCE=0 EXTRUDER=[tool_name]
;
G21 ;metric values
G90 ;absolute positioning
M82 ;set extruder to absolute mode
M107 ;start with the fan off
M117 Heating Bed...
M190 S[first_layer_bed_temperature] ; set bed temperature and wait for it to be reached
M117 Home & Mesh...
HOME_ALL ;Performs a G28 if the machine is not already homed.
BED_MESH_CALIBRATE ;auto level
G1 Z25 F4000
M117 Heat Hotend...
M104 S[first_layer_temperature] ; set the first layer temp so hot end is heating up while doing the bed mesh
M109 S[first_layer_temperature] ; set hot end temp and wait
G1 Z15.0 F9000 ;move the platform down 15mm
FILAMENT_LOAD2

Note, I set PA to 0 in the start G-code, mainly for the purge line. In the Filament start G-code, I set it to the correct value for that specific filament and extruder combination.