Klipper Dual Extrusion Macro

Basic Information:

Ender5 - heavily modified:
BTT Octopus v1.1:
Pi 3B+
N/A

Fill out above information and in all cases attach your klippy.log file (use zip to compress it, if too big). Pasting your printer.cfg is not needed
Be sure to check our “Knowledge Base” Category first. Most relevant items, e.g. error messages, are covered there

Describe your issue:

Probably an incredibly easy question - but searching hasn’t helped me find the answer.

I’m DIY-ing a dual extruder - same carriage, separate hotends. In terms of the T0/T1 switching macro, I think I understand that…but what I can’t figure out is how to link the two independent parts cooling fans to their respective hotend.

I have the heater fan on PA8 and have linked that to both hot ends in the config - so that’s working.

Can someone point me in the right direction for dealing with my two part cooling fans? I can either parallel them to the board and have them both on regardless of which hot end is in use, or they can be separate on the board - I don’t care which.

Thanks!

If you have independent heaters/thermistors
and as a result extruders - you can bind each fan to desired extruder.

[heater_fan extruder0_fan]
pin: gpio0_2
heater: extruder
heater_temp: 50

[heater_fan extruder1_fan]
pin: gpio0_3
heater: extruder1
heater_temp: 50

P.S. these setting will keep them off until your extruder is higher than 50 degree.

Forgive me if I don’t understand - but I think what you posted was for the heater fan - i.e. the cooling fan for the heatbreak. I have one heater fan and that is working with this config:
[heater_fan fan1]
pin: PA8
heater: extruder, extruder1
heater_temp: 50.0

What I am asking regards the part cooling fans, which are independent. I currently have this (which doesn’t work):

[fan] #this is part cooling fan 1
pin: PE5

[fan1] #this is part cooling fan 2
pin: PD12

But I don’t know how to bind [fan] to extruder, and [fan1] to extruder1 - clearly something simple I am missing.

Thanks,

Klipper doesn’t currently support that (I’m working on a fix for it). You’ll have to use [fan_generic] with a SET_FAN_SPEED.

There’s also some details here…

https://www.klipper3d.org/Config_Reference.html#dual_carriage

Watch the “Features” category in the next few days, I’ll be posting a Klipper patch for users to test out potential new fan features/fixes/upgrades.

One of the things I’ve added a fix for is that functionality for users with multiple extruders. I’m putting the finishing touches on some last minute things today so HOPEFULLY should be out this evening or tomorrow at the latest.

Edit: Let me be clear. Klipper currently doesn’t support defining two or more part cooling fans as [fan]. I didn’t mean it doesn’t support multiple extruders.

I haven’t done this specifically but it should be fairly easy to override M106 and M107 to relay the parameters to a SET_FAN_SPEED command targeted to the desired generic fan, which can be tracked with a variable that is updated by whatever macros you use to switch extruders.

M106/M107 is solely linked to the [fan], it doesn’t even take any variables/fan numbers/ etc.
It does take a gcode command though, so it MIGHT work, but I’d be super surprised.

M106 takes an S parameter. You just override M106, intercept the S parameter, convert it to a float, and use that with SET_FAN_SPEED on whatever the current extruder’s fan is. M107 is even easier because you just override that to SET_FAN_SPEED SPEED=0 on the current extruder’s fan.

I’ve got these macros for my IDEX printer with two hotends.
Maybe it works:

# ======================= F A N S =========================


# X1 print cooling fan
[fan_generic fan]
pin: PH6
cycle_time: 0.0100
#hardware_pwm: True
kick_start_time: 1.00

# X2 print cooling fan
[fan_generic fan1]
pin: PB6
cycle_time: 0.0100
#hardware_pwm: True
kick_start_time: 1.000

[gcode_macro M207]
gcode:
    {% if params.S is defined %}
      SET_RETRACTION RETRACT_LENGTH={params.S|int}
    {% endif %}
    {% if params.R is defined %}
      set printer.firmware_retraction.unretract_length VALUE={params.R|int}
    {% endif %}
    {% if params.F is defined %}
      set printer.firmware_retraction.retract_speed VALUE={params.F|int*60}
    {% endif %}
    {% if params.T is defined %}
      set printer.firmware_retraction.unretract_speed VALUE={params.T|int*60}
    {% endif %}

[gcode_macro FAN_VARIABLE]
gcode:

variable_active_fan: 0

#--- Carriages print cooling FANs ---
variable_fan: 'fan'    # carriage X1
variable_fan1: 'fan1'   # carriage X2
#--- Other user define FANs ---
variable_fan2: 'fan2'     
variable_fan3: 'fan3'
variable_fan4: 'fan4'  
variable_fan5: 'fan5'


##########################################################
# PRINTER FANS MANAGEMENT
# Redefine G-code command M106 and M107 
##########################################################

[gcode_macro M106]
description: Override "M106" to allow multiple extruders.
gcode:
    {% set fan_vars = printer["gcode_macro FAN_VARIABLE"] %}
    {% set raw_speed = params.S|default(0)|float %}
    {% set fan_speed = (raw_speed / 255.0)|round(2) %}     
        
    {% set target_fan = params.P|default(fan_vars.active_fan)|int %}
    {% set default_fan = ('fan', 'fan1', 'fan2', 'fan3', 'fan4', 'fan5')[target_fan] %}     
    
    {% if target_fan in [0,1] %}
       ### carriages print cooling FAN   
        CARRIAGE_PRINT_FAN SPEED={fan_speed}
    {% else %}
       ### other user define FAN
        SET_FAN_SPEED FAN={default_fan} SPEED={fan_speed}
    {% endif %}

[gcode_macro M107]
description: Override "M107" to allow multiple extruders.
gcode:
    M106 S0
     
[gcode_macro CARRIAGE_PRINT_FAN]
description: Set automatically the print fan speed for dual carriages modes 
gcode:
    {% set fan_vars = printer["gcode_macro FAN_VARIABLE"] %}      
    
    {% if params.SPEED is defined %}
        {% set fan_speed = params.SPEED|float %}
    {% else %}
        ### read print fan speed from active carriage/extruder
        {% set fan_speed = printer["fan_generic " + fan_vars.fan].speed|float %}
        {% set fan1_speed = printer["fan_generic " + fan_vars.fan1].speed|float %}
        {% set fan_speed = [fan_speed, fan1_speed]|max %}
    {% endif %}
        
    {% if fan_vars.active_fan == 0 %}
        ### FAN on carriage X1
        SET_FAN_SPEED FAN={fan_vars.fan} SPEED={fan_speed}
        SET_FAN_SPEED FAN={fan_vars.fan1} SPEED=0
    {% elif fan_vars.active_fan == 1 %}
        ### FAN on carriage X2
        SET_FAN_SPEED FAN={fan_vars.fan} SPEED=0
        SET_FAN_SPEED FAN={fan_vars.fan1} SPEED={fan_speed}
    {% endif %}

[heater_fan my_nozzle0_fan]
pin: PH3
heater: extruder
heater_temp: 50.0
fan_speed: 1.0

[heater_fan my_nozzle1_fan]
pin: PL4
heater: extruder1
heater_temp: 50.0
fan_speed: 1.0

Ah, I was thinking of it the other way around like you were trying to feed the M106 a “T” parameter, you’re just intercepting the S parameter and using it with Fan set speed.

The fix I mentioned a few comments above is for this very thing, where Klipper would support “M106 T1 S255” or whatever straight from the slicer so there is no need to jump through these hoops.

It will need testing though, I don’t have an IDEX printer, I’ve just been renaming fans to cooling fans and trying it out that way.

Thanks all - so, my understanding is that M106 turns on [fan] - and that is true regardless of the active extruder. So for now I have physically parallel-ed the two fans so both are on in response to an M106 - that’ll work fine for my use case.

you can keep the fans separate, but link the control of them together like this:

`[multi_pin my_fan]
pins:PA8,PE5

[fan]
pin: multi_pin:my_fan`

that way your wiring wouldn’t need to be changed in future when klipper is able to support controlling them independently.

1 Like