Switching between extruders

Now that “shared_heater” is deprecated, how do you change extruders between “extruder” and [‘extruder_stepper second_extruder’]?

Using: ACTIVATE_EXTRUDER EXTRUDER=extruder_stepper belted_extruder or ACTIVATE_EXTRUDER EXTRUDER=belted_extruder
Errors: Malformed command 'ACTIVATE_EXTRUDER EXTRUDER=extruder_stepper belted_extruder'

Hardware:
1 Hot End (heater/thermister) part of the extruder
2nd extruder being used to test with.
Hot end can be considered as 2 in/1 out non-mixing.

Using: extruder/extruder1 with shared_heater works, I can easily switch extruder steppers.

New Config:

[extruder]  
step_pin: PC1 #ar36
dir_pin: PC3 #ar34
enable_pin: !PC7 #!ar30
microsteps: 16
rotation_distance: 22.024  #7.392   21.1765 is very close to 360/17teeth
full_steps_per_rotation: 200
gear_ratio: 50:17
nozzle_diameter: 0.400
filament_diameter: 1.750
max_extrude_only_distance: 950.0
max_extrude_only_velocity: 250
max_extrude_only_accel: 2750
heater_pin: PB4 #ar10
sensor_type: ATC Semitec 104GT-2 
sensor_pin: PK5 #analog13
control: pid
pid_Kp: 28.114
pid_Ki: 1.562
pid_Kd: 126.511
min_temp: 170
max_temp: 300

[gcode_macro T0]
gcode:
    ACTIVATE_EXTRUDER EXTRUDER=extruder


[extruder_stepper belted_extruder]
extruder:
#   The extruder this stepper is synchronized to. If this is set to an
#   empty string then the stepper will not be synchronized to an
#   extruder. The default is "extruder".
step_pin = PA4 #ar26
dir_pin = PA6 #ar28
enable_pin = !PA2 #!ar24
microsteps: 16
rotation_distance: 22.5
full_steps_per_rotation: 200
gear_ratio: 4:1


[gcode_macro T1]
gcode:
    ACTIVATE_EXTRUDER EXTRUDER=belted_extruder

I have a 2 in 1 hotend and also need to figure this out!

After updating and connecting no errors were reported so I think we have time still. It seems the MOTION_QUEUE is now how you turn on and off extruders. It would be nice to have an example 2 in 1 hotend cfg in the documentation.

2 Likes

I believe I have the Klipper config working, but there is a couple things in the slicer that needs some updates, and I’m working on that.

I’m using Super Slicer right now.

I’ll try to wrap up and share my settings tomorrow. I’ve been modeling most of today, so I haven’t been printing

-James

I don’t actually have a multi-extruder printer, so I can’t give any tested examples.

The current “shared_heater” support is a bit “goofy” - it exports an interface with two heaters even though there is only one actual heater. The idea going forward is that an “extruder” config section would represent a single “hotend”.

So, I’d expect a config to contain something like:

[extruder]  
step_pin: PC1
dir_pin: PC3
enable_pin: !PC7
...
control: pid
pid_Kp: 28.114
pid_Ki: 1.562
pid_Kd: 126.511

[extruder_stepper belted_extruder]
extruder:
step_pin: PA4
dir_pin: PA6
enable_pin: !PA2
...

That is, only one “hotend” would be defined, but there would still be two extruder motors defined. (One in an extruder config section and one in an extruder_stepper config section.) This has the advantage that only one actual heater is defined and exported.

This does make switching to the alternate stepper motor a little more complex. I’d expect the switching macros to look something like:

[gcode_macro T0]
gcode:
    # Deactivate second extruder stepper
    SYNC_EXTRUDER_MOTION EXTRUDER=belted_extruder MOTION_QUEUE=
    # Activate first extruder stepper
    SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=extruder

[gcode_macro T1]
gcode:
    # Deactivate first extruder stepper
    SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=
    # Activate second extruder stepper
    SYNC_EXTRUDER_MOTION EXTRUDER=belted_extruder MOTION_QUEUE=extruder

The above should allow one to logically switch which extruder motor moves on a T0/T1 request. To be clear, since there is only one hotend, there is never a reason to call ACTIVATE_EXTRUDER, as that command changes the active “hotend” and does not alter the active “steppers”.

Unfortunately, if the slicer is setup to emit M104 Tx Sy commands then the above may not work well. I suspect the best solution would be to not define two hotends in the slicer (that is, somehow convince the slicer to only send the temperature for one hotend). If that can’t be done, it should be possible to override the M104 via a gcode_macro in Klipper. This would not be ideal, but I guess it would look something like (totally untested):

[gcode_macro M104]
rename_existing: M104.1
gcode:
    {% set temp = params.S|default(0.0)|float %}
    {% if 'T' in params %}
        {% set req_hotend = params.T|int %}
        {% set hotend_map = {0: 0, 1: 0} %}
        {% set new_hotend = hotend_map.get(hotend, 9999) %}
        M104.1 T{new_hotend} S{temp}
    {% else %}
        M104.1 S{temp}
    {% endif %}

-Kevin

1 Like

I finished my modeling project did some test prints last night and found a few challenges and solutions in both Klipper and Slicers to the new configuration options.

Klipper - Stepper Main Config:

[extruder] 
step_pin: PC1 
dir_pin: PC3 
enable_pin: !PC7 
microsteps: 16
rotation_distance: 22.024
full_steps_per_rotation: 200
gear_ratio: 50:17
nozzle_diameter: 0.400
filament_diameter: 1.750

[extruder_stepper belted_extruder]
extruder: extruder
#   The extruder this stepper is synchronized to. If this is set to an
#   empty string then the stepper will not be synchronized to an
#   extruder. The default is "extruder".
step_pin = PA4
dir_pin = PA6
enable_pin = !PA2
microsteps: 16
rotation_distance: 22.5
full_steps_per_rotation: 200
gear_ratio: 4:1

[extruder] is NOT my full config, but there just for reference.
[extruder_stepper] is a full config for this stepper.

  1. extruder_stepper is synchronized with extruder. This is not what we want for a X-in/1-out extruder. Only one stepper should be rotating at a time. To get around this, use a gcode macro such as @koconnor posted to break the sync and activate/deactivate each stepper individually:
[gcode_macro T0]
gcode:
    # Deactivate stepper in my_extruder_stepper
    SYNC_STEPPER_TO_EXTRUDER STEPPER=belted_extruder EXTRUDER=
    # Activate stepper in extruder
    SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER=extruder

[gcode_macro T1]
gcode:
    # Deactivate stepper in extruder
    SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER=
    # Activate stepper in my_extruder_stepper
    SYNC_STEPPER_TO_EXTRUDER STEPPER=belted_extruder EXTRUDER=extruder

T0 will activate [stepper] and deactivate [extruder_stepper].
T1 will deactivate [stepper] and activate [extruder_stepper].

  1. Klipper built-in gcode_macro [ACTIVATE_EXTRUDER] no longer functions as previous. We only have one extrusion system with multiple extruder steppers. Also, SuperSlicer with Klipper G-Code flavor inserts a ACTIVATE_EXTRUDER method whenever there is a change in the extruder, so this is also broken. To get around this, gcode_macro to the rescue:
[gcode_macro ACTIVATE_EXTRUDER]
description: Replaces built-in macro for a X-in, 1-out extruder configuration SuperSlicer fix
rename_existing: ACTIVATE_EXTRUDER_BASE
gcode:
    {% if 'EXTRUDER' in params %}
      {% set ext = params.EXTRUDER|default(EXTRUDER) %}
      {% if ext == "extruder"%}
        {action_respond_info("Switching to extruder0.")}
        T0
      {% elif ext == "extruder1" %}
        {action_respond_info("Switching to extruder1.")}
        T1
      {% else %}
        {action_respond_info("EXTRUDER value being passed.")}
        ACTIVATE_EXTRUDER_BASE EXTRUDER={ext}
      {% endif %}
    {% endif %}

Expand this macro to cover additional [extruder_steppers] if you have a 3-in or 4-in hotend or a secondary hotend.

@koconnor can we skip extruder#? ie: [extruder], [extruder2], or do we need [extruder1] in the config? This would make a difference on how the macro is built and in a multi-hotend / tool changer printer, where the x-in/1-out or mixing extruder is placed in the system. (just thinking forward here).

  1. When Klipper starts, both steppers are sync’d. You need to remember to switch to a single stepper or you could get Klipper errors. I heated up my hotend to change filament and during the fast retract, I got a timer too close because BOTH steppers were reversing at an extreme rate the MCU could not keep up with. To help with this, I used a delayed_gcode_macro to deactivate [stepper_extruder] on start-up.
[delayed_gcode activate_default_extruder]
initial_duration: 1
gcode:
    ACTIVATE_EXTRUDER EXTRUDER=extruder
  1. M104 Temperature errors. This can be corrected in slicer or via gcode_macro. Basically, when a temp change is made, some slicers insert a tool# to the M104 command like: M104 S200 T1. The T1 or T0 in the temp would cause an issue with Klipper extruder motion control. gcode_macro to compensate:
[gcode_macro M104]
description: Replaces built-in gcode to not specify Tx due to single extruder
rename_existing: M104.1
gcode:
    {% set s = params.S|default(0)|float %}
    {% set t = params.T|default(0)|int %}
    {% if 'S' in params %}
      {%  if 'T' in params %}
        M104.1 S{s}
      {% else %}
        M104.1 S{s}
      {% endif %}
    {% endif %}

I’ll post my Slicer modifications next.

1 Like

Slicer Modifications - SuperSlicer.

Printer Settings

  1. Name your extruders in the slicer similar to Klipper; extruder, extruder1, etc.


  2. Modify custom start g-code to include: ACTIVATE_EXTRUDER EXTRUDER=[tool_name] This will make sure that you have the correct stepper extruder chosen when printing starts. [tool_name] is linked to #1 above.

  3. Check-box for Single Extruder Multi Material. This will remove the T# in the M104 commands.

The above works in SuperSlicer with Klipper G-Code flavor. Using Prusa Slicer/Slic3r or SuperSlicer with other G-Code flavors will probably need additional tweaks like:
[tool_name] being 0, 1, 2, etc., and the Start G-Code being changed to T[tool_name] instead of ACTIVATE_EXTRUDER EXTRUDER=[tool_name]

1 Like

@koconnor
Since updating to v0.10.0-293-ge3beafbd, I see that the SYNC_STEPPER_TO_EXTRUDER has be depreciated for SYNC_EXTRUDER_MOTION, however I cannot get a similar function to work.

Configured:
[extruder] and [extruder_stepper belted_extruder]

I only want to operate one stepper at a time, either [extruder] or [extruder_stepper belted_extruder].

I upgraded my macro’s to be as such:

[gcode_macro T0]
gcode:
    # Deactivate stepper in my_extruder_stepper
    #SYNC_STEPPER_TO_EXTRUDER STEPPER=belted_extruder EXTRUDER=
    SYNC_EXTRUDER_MOTION EXTRUDER=belted_extruder MOTION_QUEUE=
    # Activate stepper in extruder
    #SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER=extruder
    SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=extruder
[gcode_macro T1]
gcode:
    # Deactivate stepper in extruder
    #SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER=
    SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=
    # Activate stepper in my_extruder_stepper
    #SYNC_STEPPER_TO_EXTRUDER STEPPER=belted_extruder EXTRUDER=extruder
    SYNC_EXTRUDER_MOTION EXTRUDER=belted_extruder MOTION_QUEUE=extruder

When I execute the T0/T1 command, it operates as expected, however when gcode is run from mainsail, I get this error in the console: Unable to infer active extruder stepper

Klippy.log does not show anything really useful as far as errors and it’s larger than the 4gb size to attach un-zipped.
klippy(2).zip (2.4 MB)

Here is my extruder and belted_extruder config sections.

[extruder]
step_pin = PC1
dir_pin = PC3
enable_pin = !PC7
microsteps = 16
rotation_distance = 22.024
full_steps_per_rotation = 200
gear_ratio = 50:17
nozzle_diameter = 0.400
filament_diameter = 1.750
max_extrude_only_distance = 950.0
max_extrude_only_velocity = 250
max_extrude_only_accel = 2750
heater_pin = PB4
sensor_type = ATC Semitec 104GT-2
sensor_pin = PK5
control = pid
pid_kp = 28.114
pid_ki = 1.562
pid_kd = 126.511
min_temp = 0
max_temp = 300

[extruder_stepper belted_extruder]
extruder = extruder
step_pin = PA4
dir_pin = PA6
enable_pin = !PA2
microsteps = 16
rotation_distance = 22.5
full_steps_per_rotation = 200
gear_ratio = 4:1

Even if the deprecated commands are used, the same issue exists:

13:41:30 Unable to infer active extruder stepper

13:41:29 File selected

13:41:29 File opened:cloak.gcode Size:13052276

13:41:10 Extruder stepper now syncing with 'extruder'

13:41:10 SYNC_STEPPER_TO_EXTRUDER STEPPER=belted_extruder EXTRUDER=extruder

13:40:41 Extruder stepper now syncing with ''

13:40:41 SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER

For manual extrusion commands, it functions, but when initiating motion + extrusion, then Klipper is lost.

I also tried:
SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=belted_extruder DISTANCE=0
but rotation_distance cannot be zero or null.

Could this be a viable option and allow for X-In/1-Out and mixing extruders to set a specific sync’d extruder to have a zero rotation distance?

1 Like

The Unable to infer active extruder stepper error occurs if a SET_PRESSURE_ADVANCE command is sent without an EXTRUDER parameter and Klipper can’t determine which stepper to apply the pressure settings to.

In Klipper, the pressure advance settings are applied to a stepper and not to a hotend. So, if you want to use pressure advance when “belted_extruder” is active it is necessary to issue a SET_PRESSURE_ADVANCE EXTRUDER=belted_extruder ... command.

So, it looks like you need to update the commands in your gcode file.

-Kevin

That makes sense…

Gcode being executed start off with:

M73 P0 R223
;TYPE:Custom
ACTIVATE_EXTRUDER EXTRUDER=extruder1


;Textruder1
SET_PRESSURE_ADVANCE ADVANCE=0
G21 ;metric values

I’ll update the slicer to accommodate along with updating my M900 macro.

@koconnor Has the TUNING_TOWER command been extended to accept an EXTRUDER= value?

I validated that switching to second extruder and adjusting Pressure Advance command with will allow printing to proceed without receiving Unable to infer active extruder stepper:

Updated gcode:

# deactivate stepper on extruder
SYNC_EXTRUDER_MOTION EXTRUDER=extruder MOTION_QUEUE=
# activate second stepper
SYNC_EXTRUDER_MOTION EXTRUDER=belted_extruder MOTION_QUEUE=extruder

SET_PRESSURE_ADVANCE ADVANCE=0 EXTRUDER=belted_extruder

When running a PA test with TUNING_TOWER COMMAND=SET_PRESSURE_ADVANCE PARAMETER=ADVANCE START=0 FACTOR=.020 will fail with Unable to infer active extruder stepper.

There is no updated documentation regarding TUNING TOWER and I did not see any extension in tuning_tower.py for specifying an extruder.

Thank you.

PA Testing - Short term, I used a function in the slicer to get a quick PA test done.

Today, I did a bit more testing using the TUNING_TOWER function and found that this will work, with no changes to code:

TUNING_TOWER COMMAND="SET_PRESSURE_ADVANCE [EXTRUDER=<config_name>]" PARAMETER=<name> START=<value> FACTOR=<value>

Basically, putting SET_PRESSURE_ADVANCE [EXTRUDER=<config_name>] between double quotes so the COMMAND will be passed as one value.

I will create a new CONFIG topic or X-In/1-Out Hot End’s here on discourse (Klipper Config and Slicer Settings) and maintain it though future upgrades.

1 Like

@jjarosz the only difference with my setup is I have two hotends, not 2-in-1-out as you have. I have my extruders setup, aligned, printing fine and my start g-code preps both nozzles successfully.
My challenge is oozing; the inactive hotend going along for the ride oozes all over my print. I tried a simple retract after nozzle prep but it does not work all that well and I have an ‘empty’ nozzle for the first part of extruder1’s print since I have not figured out how to get that prep-time retract taken into account. No servo’s, additional belted extruders noting. Just a chimera hotend with two nozzles.

I was thinking I need a tool change macro but for the life of me I cannot find an example to match my setup. This is as close as I get but you are not using a tool change macro… am I being thick?

@vNate the tool changing piece is something I have yet to configure. I’m going to have to use it to pull the filament back out about 80mm from the nozzle so the change-to filament can load. Basically an activate and deactivate macro.

For your setup, I would do something like:

  • Deactivate - retracting filament 10-15mm, then lower hot-end temp maybe 20-40C (depending on filament). Maybe a dd a wait/dwell.
  • Activate - raise temp to print temp and wait. Advance filament 8-13mm

Have you thought about seeing if your slicer can add a purge shield around the model?

Thanks @jjarosz. I use SuperSlicer as well and tried the shield but it still oozes from the first layer, shield and all. Nozzle offset on X is only ~17mm so the second nozzle is inside the print most of the time.
I retracted 5mm and dropped the standby temp by 20C (PLA) so I will try your higher retraction and dropping the temp even more.

What I am still not clear on; when do I use G600 vs T0/T1 macros vs activate/ deactivate? Or is it a case of dealers choice? SuperSlicer is set to Klipper output format and works just fine without T0/T1 Macro’s so I am thinking these macro’s are only required if your slicer outputs RepRap or Marlin that uses T0/T1. And M600 is when you need to do a physical tool change or deploy a servo or summin.

If I am reading you I need to go for activate/ deactivate inside my [extruder]definition and then do something like this to the second [exturder1]:

activate_gcode:  
SET_GCODE_OFFSET X=17.55 Y=0.25
G1 E8 F100
M104 S{EXTR_TEMP}  
deactivate_gcode:
G1 E-8 F100
M104 S{EXTR_SB_TEMP}  

[extruder] will be the same without the offset.

Correct?

@vNate yes, the T0/T1 is more for the RepRap output, but also very helpful to manually change tools. I find it easier to type 2 characters over a string of options.

Yes, I forgot about the activate/deactivate gcode options in the [extruder] object give that a try for your retract/advance, cool/heat changes.

Since I’m using a splitter and a single heater block that probably wouldn’t be used…… unless??? I’ll have to check into that myself now to see if it contained gcode would be triggered when swapping steppers, otherwise I’ll have to come up with something else.

@vNate not sure if after your final retract you are getting a nub and string on the filament or not. I’m using this with good results:
G1 E-10 F900
The higher retract speed seems to reduce issues and make feeding back into the hot end easier.

Thanks @jjarosz . Will give it a try!

Oops… Seems I have been looking at old configs.

20191210: The builtin T0, T1, T2, … commands have been removed. The extruder activate_gcode and deactivate_gcode config options have been removed. If these commands (and scripts) are needed then define individual [gcode_macro T0] style macros that call the ACTIVATE_EXTRUDER command. See the config/sample-idex.cfg and sample-multi-extruder.cfg files for examples.

@jjarosz I sincerely thank you for having given all these explanations, I would never have been able to setup my second extruder on my Sovol SV02 without you.

For people who would like to switch to klipper with their SOVOL SV02, here are my settings :

Klipper Config : Klipper for SOVOL SV02 with BLTOUCH - Pastebin.com

Cura

; machine start code >>
G21 ;metric values
G28 ;home all
G90 ;absolute positioning
M107 ;start with the fan off
;G1 F2400 Z15.0 ;raise the nozzle 15mm
M140 S{material_bed_temperature}; Heat bed but do not wait
M109 S{material_print_temperature} ;Set Extruder Temperature and Wait
M190 S{material_bed_temperature}; Wait for bed temperature to reach target temp
G92 E0 ;reset extrusion distance
ACTIVATE_EXTRUDER EXTRUDER=extruder
; << machine start code
; machine end code >>
M104 S0; hotend off
M140 S0; bed off
G92 E0 ; reset extrusion distance
G1 F3000 E-5 ; retract
G91 ; relative positioning
G1 Z10 ; lift Z-axis
G90 ; absolute positioning
G92 E0 ; reset extrusion distance
G1 F3000 E-90; unload filament
G1 F3000 X0 Y240; move bed for easy part removal
M84; disable steppers
; << machine end code
; extruder start code >>
T0
G0 F4500 X{prime_tower_position_x} Y{prime_tower_position_y} ; move nozzle to prime tower center
#M211 X1 S0 ; disable SW endstop
G0 F3600 X310 ; move nozzle to purge position
G92 E0 ; reset extrusion distance
G1 F3000 E88 ; load filament
G92 E0 ; reset extrusion distance
G1 F250 E25 ; purge nozzle
G92 E0 ; reset extrusion distance
G1 F3000 E-3 ; retract
;G92 E0 ; reset extrusion distance
;M400 ; wait for everything to settle
G0 F3600 X{prime_tower_position_x} Y{prime_tower_position_y} ; move nozzle to prime tower center
#M211 X1 S1 ; enable SW endstop
; << extruder start code
; extruder end code >>
G92 E0 ; reset extrusion distance
G1 F1200 E-5 ;short retract
G0 F4500 X{prime_tower_position_x} Y{prime_tower_position_y} E-93; move nozzle to prime tower center
;G1 F3000 E-85 ; unload filament
G92 E0 ; reset extrusion distance
; << extruder end code

Extruder 2 is identical except T0 that must be changed to T1

Final important note : these scripts are adapted from ThKu’s and work with the excellent Purge Bucket designed by him here : Clip-On Purge Bucket / Wipe for Sovol SV02 by ThKu - Thingiverse

1 Like

I forgot to give my Cura machine settings for the SOVOL SV02 : https://img001.prntscr.com/file/img001/YS1Rv98DTXSkEIoaUTrTUw.png