A while back I upgraded my Ender 5 Pro with a BigTreeTech Octopus V1.1 and added four extruders to utilize all eight stepper drivers available. The extruders are attached with a 5-in-1-out PTFE tube adapter so they all feed into a single nozzle. When I installed the new control board, I also switched to the Klipper firmware. I already had an OctoPi and continued running that for a bit.
Well, the other day I finally took the plunge and gave Fluidd a try. Once I got it up and running, I was greeted with a whole bunch of errors — one of them being that the shared_heater
option is deprecated and will be removed soon.
The shared_heater Method
We’ll start with a little background info on how it was configured before. Skip down a bit if you just want to see the new working config.
In my Klipper configuration (printer.cfg) I had defined the first extruder section as usual with the stepper and heater values.
# Driver3 - Extruder #1 (T0)
[extruder]
step_pin: PG4
dir_pin: !PC1
enable_pin: !PA0
microsteps: 16
rotation_distance: 32.68
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PA2 # HE0
sensor_pin: PF4 # T0
sensor_type: EPCOS 100K B57560G104F
control: pid
pid_Kp: 21.527
pid_Ki: 1.063
pid_Kd: 108.982
min_temp: 0
max_temp: 260
min_extrude_temp: 180
max_extrude_only_distance: 150
pressure_advance: 0.60
pressure_advance_smooth_time: 0.080
The additional four extruders were configured using the shared_heater
parameter as shown below.
# Driver4 - Extruder #2 (T1)
[extruder1]
step_pin: PF9
dir_pin: !PF10
enable_pin: !PG2
microsteps: 16
rotation_distance: 32.68
nozzle_diameter: 0.400
filament_diameter: 1.750
shared_heater: extruder
max_extrude_only_distance: 150
pressure_advance: 0.60
pressure_advance_smooth_time: 0.080
My tool change gcode macros looked like this.
[gcode_macro T0]
gcode:
ACTIVATE_EXTRUDER EXTRUDER=extruder
SAVE_VARIABLE VARIABLE=currentextruder VALUE='"extruder"'
[gcode_macro T1]
gcode:
ACTIVATE_EXTRUDER EXTRUDER=extruder1
SAVE_VARIABLE VARIABLE=currentextruder VALUE='"extruder1"'
# ...and so on...
Finally, I had a startup gcode macro that would activate the last used extruder after a reboot. That way it can still retract the filament before switching to another extruder and loading its filament.
[delayed_gcode STARTUP_GCODE]
initial_duration: 0.1
gcode:
{% set svv = printer.save_variables.variables %}
ACTIVATE_EXTRUDER extruder={svv.currentextruder}
{ action_respond_info("Current extruder: " + svv.currentextruder) }
This method worked great while I was still running OctoPrint on my Pi.
The extruder_stepper Method
The Klipper configuration documentation recommends replacing any shared_heater
extruder with an [extruder_stepper]
section.
It took me a bit of trial and error to figure out what options were needed and in what sections. Maybe it’s just me, but I found the Klipper documentation to be a little confusing… perhaps it was because I had a solid mental image of how the shared_heater
works and the new method approaches the problem from a different angle.
In this new approach, only one “real” [extruder]
needs to be defined (including all the heater, sensor, pressure advance, etc. definitions). The other extruders are defined in an [extruder_stepper]
section and then those are either synchronized (or not synchronized to) to the “real” extruder
. Hopefully this makes more sense in a minute. My extruder #1 configuration is shown below.
# Driver3 (Extruder 1 / T0)
[extruder]
step_pin: PG4
dir_pin: !PC1
enable_pin: !PA0
full_steps_per_rotation: 200
microsteps: 16
rotation_distance: 32.68
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PA2 # HE0
sensor_pin: PF4 # T0
sensor_type: EPCOS 100K B57560G104F
control: pid
pid_Kp: 21.527
pid_Ki: 1.063
pid_Kd: 108.982
min_temp: 0
max_temp: 260
min_extrude_temp: 180
max_extrude_only_distance: 150
pressure_advance: 0.60
pressure_advance_smooth_time: 0.080
The [extruder_stepper]
section defines a stepper motor and nothing else — no heater or sensor, no nozzle size, no pressure advance value. The only new option is extruder
to specify another extruder to synchronize this stepper to. I left these empty in the config file so that at startup none of the extra steppers are synchronized. Extruders #2 through #4 are shown below.
# Driver4 (Extruder 2 / T1)
[extruder_stepper extruder1]
extruder:
step_pin: PF9
dir_pin: !PF10
enable_pin: !PG2
full_steps_per_rotation: 200
microsteps: 16
rotation_distance: 32.68
# Driver5 (Extruder 3 / T2)
[extruder_stepper extruder2]
extruder:
step_pin: PC13
dir_pin: !PF0
enable_pin: !PF1
full_steps_per_rotation: 200
microsteps: 16
rotation_distance: 32.68
# ...and so on...
If I command the extruder to move at this point (G1 E5
), only extruder #1 (extruder
) will move. The next step is to add the tool change macros to switch which extruder is active (synchronized). I defined my T0/T1/T2/T3/T4 macros as shown below. Basically each macro synchronizes the desired extruder (or extruder_stepper) to extruder
(extruder #1, the “real” extruder) and sets all other extruders to synchronize to nothing. Finally each Tn
macro saves the tool to a variable named active_tool
(I renamed it from currentextruder
before).
[gcode_macro T0]
gcode:
SYNC_EXTRUDER_MOTION EXTRUDER="extruder" MOTION_QUEUE="extruder"
SYNC_EXTRUDER_MOTION EXTRUDER="extruder1" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder2" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder3" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder4" MOTION_QUEUE=""
SAVE_VARIABLE VARIABLE=active_tool VALUE='"T0"'
[gcode_macro T1]
gcode:
SYNC_EXTRUDER_MOTION EXTRUDER="extruder" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder1" MOTION_QUEUE="extruder"
SYNC_EXTRUDER_MOTION EXTRUDER="extruder2" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder3" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder4" MOTION_QUEUE=""
SAVE_VARIABLE VARIABLE=active_tool VALUE='"T1"'
[gcode_macro T2]
gcode:
SYNC_EXTRUDER_MOTION EXTRUDER="extruder" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder1" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder2" MOTION_QUEUE="extruder"
SYNC_EXTRUDER_MOTION EXTRUDER="extruder3" MOTION_QUEUE=""
SYNC_EXTRUDER_MOTION EXTRUDER="extruder4" MOTION_QUEUE=""
SAVE_VARIABLE VARIABLE=active_tool VALUE='"T2"'
# ...and so on...
Now my STARTUP_GCODE
macro looks like this. It is also where I set the pressure advance of each extruder since the pressure_advance
definition is not valid in extruder_stepper
sections.
[delayed_gcode STARTUP_GCODE]
initial_duration: 0.1
gcode:
{% set svv = printer.save_variables.variables %}
{% if svv.active_tool != "" %}
{ svv.active_tool }
{% else %}
T0
{% endif %}
{ action_respond_info("Active Tool: " + svv.active_tool) }
set_pressure_advance extruder=extruder advance=0.60 smooth_time=0.08
set_pressure_advance extruder=extruder1 advance=0.60 smooth_time=0.08
set_pressure_advance extruder=extruder2 advance=0.60 smooth_time=0.08
set_pressure_advance extruder=extruder3 advance=0.60 smooth_time=0.08
set_pressure_advance extruder=extruder4 advance=0.60 smooth_time=0.08
Just for completeness, below is my configuration for the TMC2209 drivers when using extruder_stepper
sections.
[tmc2209 extruder]
uart_pin: PC7
run_current: 0.750
[tmc2209 extruder_stepper extruder1]
uart_pin: PF2
run_current: 0.750
[tmc2209 extruder_stepper extruder2]
uart_pin: PE4
run_current: 0.750
# ...and so on...
With all of that in place I was finally able to programmatically switch between extruders. Of course there are additional macros for loading and unloading filament and everything else, but regarding the shared_heater to extruder_stepper migration, I hope this helps!
Hello , First off I want to thank you for posting this information . I am running a custom build with a 2 in 1 out extruder setup . I have been trying for days to get my config file working . I copy and pasted your code and it instantly started working . Well almost . I can manually control each of the extruders just fine but when I run a program I get an error that says “Extruder Not Configured ” . im not sure if there is an issue with the config file or if it is the gcode coming from the slicer . i was wondering if you would be will to take a look at my config file and see if something stands out to you .
Hey there, glad I could be somewhat helpful! I wish I saw your comment sooner (apparently I never setup email notifications for this website, doh!).
Anyway, if you’re still having troubles with this, I would look at the gcode to see what tool the slicer is telling the printer to use. Usually that’s a “T0” or “T1” command. This needs to correspond with the tool change gcode macros that should be defined in your config — otherwise klipper won’t know what tool the gcode is referring to.
Did you find a solution for “Extruder not configured” fault code? I am running into the same problem
Thank’s a lot for the help. Had toolchange working before shared heater was marked as deprecared. This gave me the recipe to maake it work again. It’s a little funny that the hotend has to be referred to as a MOTION_QUEUE but it works.
so love the documentation its really informative. Im currently rebuilding a Ender 3 pro. I have a biqu manta m5p board with a CB1 and running klipper. I have a hermit crab tool changer and I have everything beutifullly setup for my H2v2s Revo hotend. So I Have used your documentation to start setting up a bowden original creality extruder since it is on hermit crab uses the same hot end pins and a separate extruder. my question is I have on each hotend a Bl touch and the hotend is in different location. would something like this work under the start gcode?
set_pressure_advance extruder=extruder1 advance=0.60 smooth_time=0.08
SET_GCODE_OFFSET extruder=extruder1 Z=0.100 MOVE=1 # Adjust z-height
SET_GCODE_OFFSET extruder=extruder1 X=5 y=5 # Account for different X and y offset
Also would want to set the pid for the different hotends
#control = pid
#pid_kp = 41.287
#pid_ki = 4.915
#pid_kd = 86.703
#min_temp: 0
#max_temp: 250
Thank you! I’m glad you found it useful!
You ask a good question. I might not do it on my current printer, but I would like to build another printer that has a quick-change hotend — something similar to the hermit crab. If I understand correctly, you need to set the gcode offset (and probably the BLtouch offset) for each hotend that you have. Looking at the command reference for SET_GCODE_OFFSET, that command is used to “virtually” change where the hotend is. It does not work for the extruders, so you can remove that argument. Something like this should be all you need:
SET_GCODE_OFFSET Z=0.100 MOVE=1 # Adjust z-height
SET_GCODE_OFFSET X=5 y=5 MOVE=1 # Account for different X and y offset
You would need to run this with different X/Y/Z values for each of your hotends.
I’m not entirely sure how to handle the BLtouch. The BLtouch offset would need to be changed each time you swap out your hotend. I briefly looked through the BLtouch commands and don’t see any commands to alter the offset from gcode. I suppose you could define multiple BLtouch sensors (one for each hotend) where each one has the appropriate offsets.
Without having a hermit crab myself, I’m mostly speculating on how you could configure it. Hopefully this at least points you in the right direction.
Hi Zero Theory,
I used your “shared_heater” macro on my DELTA printer with 4 extruders single hot end, it works well, Thanks.
Would you be able to create a Macro for running 4 extruders at the same time divided by variable percentage levels for each extruder?
For example: “T0” would be 1 percentage variation = 100%, T1 would be different percentage variation = 100% and so on.
I was able to do this in RepRap firmware but I can’t find anything for Klippr. Help would be much appreciated.
Thanks
Hi Ambroz,
I’m not sure that Klipper has anything built in that could do what you are asking. The only thing I can think of would be to sync all the extruders simultaneously. Instead of having tool change macros un-sync the extruders, something like this would sync all of them at once:
SYNC_EXTRUDER_MOTION EXTRUDER=”extruder” MOTION_QUEUE=”extruder”
SYNC_EXTRUDER_MOTION EXTRUDER=”extruder1″ MOTION_QUEUE=”extruder”
SYNC_EXTRUDER_MOTION EXTRUDER=”extruder2″ MOTION_QUEUE=”extruder”
SYNC_EXTRUDER_MOTION EXTRUDER=”extruder3″ MOTION_QUEUE=”extruder”
SYNC_EXTRUDER_MOTION EXTRUDER=”extruder4″ MOTION_QUEUE=”extruder”
In order to achieve a different speed for each extruder, I think you may have to adjust the “rotation_distance” parameter to trick klipper outputting more or less steps to each motor driver. Or perhaps the “gear_ratio” parameter may achieve the same thing more easily.
Regardless, I think what you are asking for would require some non-trivial macros to it pull off. Probably do-able, but not that easily.
Marc (Zero Theory)
Option ‘filename’ is not valid in section ‘delayed_gcode startup_gcode’
i cant figur this out im realy new to klipper working on a biqu b1 with the “b2 ” upgrade using a pi4b
I don’t know anything about Biqu printers, but it sounds like your Klipper config file is formatted wrong or you need to remove the ‘filename’ line from your startup_gcode. The ‘filename’ parameter belongs in the [save_variables] section. It is documented in the Klipper config reference here https://www.klipper3d.org/Config_Reference.html#save_variables
Thank You very very much. I just slammed hard into this problem as the most recent update to Klipper has finally completely removed support for shared_heater. After updating my print was no longer responding. Your examples made it fairly easy to update my configuration and get it back to working.
hi,
thank you for posting this. i’ve added it to my printer.cfg however when the printer receives the change tool head to T1 i receive an error
//extruder value is being passed
!! the value ‘T1’ is not valid for extruder
!! the value ‘T1’ is not valid for extruder
I have kept your macro for t0 and t1 but removed the lines for the other steppers.
I feel its something to do with my config which runs
[extruder]
step
dir_pin
enable
[extruder_stepper extruder_1]
extruder =
step
dir_pin
enable
when I add motion_queue = extruder both extruders run in sync so I know the board has the correct address
Im sure its something incredibly silly i have missed.
Any help would be awesome.
Thank you very much. Your explanation should go on the documentation. I even tried v Voron forums since they seem to be a more active there but could not find anything that was referring to the deprecated shared heater.