Toolchangers support

Have been working on making toplchanging work well and configurations making sense for a while. The status quo has issues all over the place.

So I’m trying to attack te toplchanging in the broadest sense - idex, dual heads, tool docks, mmus, nozzle swappers, combination of those. A rough list of steps I’m working on:

Improve semantics for basic objects like extruder, fan, heater to be able to reflect the realities of the hardware.
Some pull requests out: 1 2.

Add tools support in core Klipper, integrating closely with other core elements. Something that is minimalistic and provides a shared structure to all those macro systems out there. And allows hardware makers to provide reasonably structured example configs that can be plugged in existing configuration. So far have a Klipper branch that I’m reasonably enjoying using and improving gradually.

Finally, work with slicers (prusa and cura) to bridge the remaining gaps. Prusa is the bigger offender currently.
Establish what is controller by Klipper and what by slicer during tool change. IE fans, temps, pressure advance.

Thoughts on this? Any favorite extensions/slicers you are currently using In a multi tool setup?

1 Like

IDEX already works fine for a recent time.

This is expandable for more tools and a docking station.

Idex is probably the simplest case.
Still, how do you handle part cooling fans?

One more aspect: Basic UI support.

I’m using macros for that and a special fan naming:

#BTL fan heater 0 - fan0
[fan_generic BTL_Fan0]
pin: PA8
cycle_time: 0.0100
hardware_pwm: false

#Coldend fan heater 0
[heater_fan CE_Fan0] #fan1
pin: PE5
heater: extruder
heater_temp: 50.0
fan_speed: 1.0


#BTL fan heater 1 - fan2
[fan_generic BTL_Fan1]
pin: PD12
cycle_time: 0.0100
hardware_pwm: false

#Coldend fan heater 1
[heater_fan CE_Fan1] #fan3
pin: PD13
heater: extruder1
heater_temp: 50.0
fan_speed: 1.0

#[controller_fan fan4]
#pin: PD14
#cycle_time: 0.01
#kick_start_time: 0.200
#max_power: 1

#[controller_fan fan5]
#pin: PD15
#cycle_time: 0.01
#kick_start_time: 0.200
#max_power: 1



[gcode_macro FAN_VARIABLE]
gcode:
variable_active_fan: 0
#--- Carriages print cooling FANs ---
variable_fan: 'BTL_Fan0'    # carriage X1
variable_fan1: 'BTL_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 = ('BTL_Fan0', 'BTL_Fan1')[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 %}

Due to WIP I did not test it with actual gcode yet.

1 Like

I use these fan controls:


BTW: @Viesturz does your fork support mirror and copy mode for IDEX?

Also see: Support of COPY and MIRROR modes for IDEX

2 Likes

No, my fork is adding a basic tool selection layer. Primarily providing extensible Tn commands and eliminating need to override basic gcodes.

You could use it to define something like:
T0 - left tool
T1 - right tool
T2 - mirror mode
T3 - copy mode
With tool activation macros doing the necessary setup.

Viesturs

That can lead to inconsistency in Gcode coding.
I think, Tx should be exclusivity for tool selection. E.g. Prusa’s MMU works with T0 up to T4
It also limits the use to a maximum of 2 tools.

I’ve seen that RepRap firmware (Duet3D) uses your attempt.

To select normal/mirror/copy mode I would prefer a Gcode command.
On my T-Rex 3 M420 was formerly used for that purpose. M420 now is used differently.
Like it is described in the link above.

Good point.

It seems there are quite a few ways you could configure an Idex:

  • A Basic tools: T0, T1
  • B Mirror, duplicate mode.
  • C Tools with MMU: T0 left, T1 right+mmu1, T2 right+mmu2, etc.
  • D Duplicate mode with dual MMU: T0 - first filament for both mmus, T1 - second color,…

Would you even want to switch between then mid print? Seems to be no, unless I’m missing something.

My code can support A and C but not the others, def something to consider. This seems to call for a separate idex mode.

Could be similar to colour mixing extruders. Will take a look at the idex PR.

It seems it gets hard to decide what solution to use.

I would hope for a toolchange that is controller by the printer exclusively. Slicers should only issue a T0, T1,…,Tx. All other parameters to be controller by the firmware.

Totally agree. Still idex presents some unique configuration challenges.

All the commercial idexes control the mode from slicer. That makes some sense since the build plate dimensions change as well.