So I was waiting for updates on Klipper macros from a number of posts, and eventually decided that I'd take my own crack at making klipper macros for the chameleon unit.
Now, disclaimer: I'm a bit of a hardcore geek, and really just wanted to get the physical filament switching unit from the 3D Chameleon with the PTFE Y plugs. I got my kit direclty from Bill in the online auction at SMRRF in December, and I don't think it was a MK3 unit? Anyway, driving the filament swap from outside electronics with a US plug when I'm not in the US was... suboptimal for me.
So I connected both of the steppers to my control board and am not using the electronics that Bill built with a lot of effort. (sorry! I'm just a huge nerd that way). Even though Bill said all of it is available, I don't think I've seen his hardware kits available outside his webshop, and that's perfectly fine. Happy to throw my $$ at a good product, which this clearly is.
So in Klipper, I setup the selector and extruder motors
of the chameleon unit as manual steppers. I'm including a snippet of what the config for that looks like for me, just remember to check your MCU pins and run_current values if you want to use those:
#S6
[tmc2209 manual_stepper selector]
uart_pin: ar100:PD2
uart_address: 3
run_current: 0.3
stealthchop_threshold: 0
#S7
[tmc2209 manual_stepper chameleon]
uart_pin: ar100:PD3
uart_address: 2
run_current: 0.8
stealthchop_threshold: 0
#S6
[manual_stepper selector]
step_pin: ar100:PL10
dir_pin: !ar100:PE14
microsteps: 1
rotation_distance: 2
#S7
[manual_stepper chameleon]
step_pin: ar100:PL11
dir_pin: !ar100:PE15
microsteps: 16
rotation_distance: 34.408602151 # reverse engineered from the ESteps value
Now for the really complicated bit.
These macros are going to behave like a regular toolchange. Meaning T0, T1, T2, T3 will do what we need them to do before the slicer creates the color purge.
I tried to build them like a good programmer would, to reuse code as much as possible. TS0, TS1, TS2 and TS3 are meant to facilitate filament selection after a boot if you're not on T0 being loaded into the nozzle (just shorthand for KlipperScreen calling TOOL_SELECT TOOL=[0-3]). TOOL_INIT does the initial homing sequence.
So, make sure you include TOOL_INIT in your PRINT_START macro if you have one, or your start gcode otherwise, and remember it defaults to setting the tool to T0.
This is still under construction to a certain extent, as there are ways to modify the printer.cfg to make it save variables, so the printer would remember what filament is loaded between reboots. I just didn't want to futz with that until I get some basic multi-color prints done.
To make the macros appear, put the chameleon.cfg file in the config directory on mainsail, and add a line near the top or bottom to include it with [include chameleon.cfg].
In the chameleon.cfg file, you will need to double check a couple of values before getting started.
The first is on the 4th line of the file. This is the distance in millimeters you want to retract the filament to clear the Y joint. The same distance is used to push it back in.
The WIPE macro on lines 16 through 22 is directing my printer's toolhead to a nozzle cleaning brush and making two swipes across it to clean the nozzle before going to print on the purge block. This catches ooze that could otherwise get caught elsewhere.
The TOOL_INIT macro is the last place to check. This was what I had a number of difficulties with, until I re-watched Bill's setup video and he talks about the selector motor's position to determine where each filament is properly selected. The setup for the selector is such that each filament selection's position is 0.5 away from the other. You can see this below in the TOOL_SELECT macro. On line 9 you'll notice I have this weird value of movement:
MANUAL_STEPPER STEPPER=selector MOVE=0.12
This is because the hard stop of my chameleon isn't exactly when T0 is selected. The selector's slot in the bearing wasn't aligned with the perpendicular of the frame. This value will probably differ from one unit to the next.
How do you calibrate this? Run the following commands in the console until you find the value that you need:
MANUAL_STEPPER STEPPER=selector SET_POSITION=0
MANUAL_STEPPER STEPPER=selector MOVE=-1.65
MANUAL_STEPPER STEPPER=selector SET_POSITION=0
Now the selector thinks it's in position 0. This should be parallel to the long edge of the unit's frame.
If it's not (it wasn't exactly right on mine), slowly move the stepper by small increments with a command like this:
MANUAL_STEPPER STEPPER=selector MOVE=0.05
If 0.05 isn't enough, increase it. Remember, the value you're setting in MOVE= is a position for the stepper. Not an increment. When the slot is properly aligned, you've found what the value is that you want to put in for the MOVE= on line 9.
With this, you're left with simply setting up your slicer for multi-material color, just make sure that your TOOL_CHANGE custom gcode simply calls.
T{next_extruder}
This will depend on the slicer you use, but hopefully it will bring the needed controls you were looking for.
If there's interest, I can put this up on Github for folks to contribute and make this a community resource with continuous improvement.
Multi-colored cheers from Switzerland!
Jon
EDIT: Forgot to share the Github Repo where the code will likely be updated: https://github.com/goeland86/3DChameleon_Klipper_macros
I added a filament cutter to the software and added a switch for each filament for the 4+1 filament hub. The hub design is available in the link below. Although there are some minor issues with the system at the moment, I have come a long way. I am sharing the code with those who want to do it.
4+1 hub
https://www.thingiverse.com/thing:6992668
#############################
# Manual Stepper Tanımlamaları
#############################
[manual_stepper selector]
step_pin: nano:PE0
dir_pin: nano:PB9
microsteps: 1
rotation_distance: 2
enable_pin: !nano:PE1
endstop_pin: !nano:PA2 # PA2 pini limit switch olarak tanımlandı
position_endstop: 15
[manual_stepper chameleon]
step_pin: nano:PB5
dir_pin: nano:PB4
microsteps: 16
rotation_distance: 41
enable_pin: !nano:PB8
#endstop_pin: !nano:PA11
#position_endstop: 0
#############################
# Filament Sensör Tanımlamaları
#############################
[filament_switch_sensor tool_0_sensor]
switch_pin: !nano:PA15
pause_on_runout: True
runout_gcode: M117 "Filament Runout on Tool 0!"
[filament_switch_sensor tool_1_sensor]
switch_pin: !nano:PA12
pause_on_runout: True
runout_gcode: M117 "Filament Runout on Tool 1!"
[filament_switch_sensor tool_2_sensor]
switch_pin: !nano:PA11
pause_on_runout: True
runout_gcode: M117 "Filament Runout on Tool 2!"
[filament_switch_sensor tool_3_sensor]
switch_pin: !nano:PC4
pause_on_runout: True
runout_gcode: M117 "Filament Runout on Tool 3!"
#############################
# CHECK_FILAMENT
#############################
[gcode_macro CHECK_FILAMENT]
description: "Filament sensörlerini kontrol eder"
gcode:
{% set t0 = printer["input_pin tool_0_sensor"].value %}
{% set t1 = printer["input_pin tool_1_sensor"].value %}
{% set t2 = printer["input_pin tool_2_sensor"].value %}
{% set t3 = printer["input_pin tool_3_sensor"].value %}
{% if t0 == 0 %}
M117 "Tool 0: Filament Var"
{% else %}
M117 "Tool 0: Filament Yok! Baskı durduruldu!"
M600
{% endif %}
{% if t1 == 0 %}
M117 "Tool 1: Filament Var"
{% else %}
M117 "Tool 1: Filament Yok! Baskı durduruldu!"
M600
{% endif %}
{% if t2 == 0 %}
M117 "Tool 2: Filament Var"
{% else %}
M117 "Tool 2: Filament Yok! Baskı durduruldu!"
M600
{% endif %}
{% if t3 == 0 %}
M117 "Tool 3: Filament Var"
{% else %}
M117 "Tool 3: Filament Yok! Baskı durduruldu!"
M600
{% endif %}
#############################
# G-Code Makroları
#############################
[gcode_macro TOOL_INIT]
description: Homes the tool selector. Needed before any tool change.
variable_tool: 0
variable_ysplit_distance: 426
variable_chameleon_speed: 60
variable_chameleon_acc: 100
gcode:
MANUAL_STEPPER STEPPER=selector SET_POSITION=0
MANUAL_STEPPER STEPPER=selector MOVE=-1.42
MANUAL_STEPPER STEPPER=selector SET_POSITION=0
MANUAL_STEPPER STEPPER=selector MOVE=0.12
MANUAL_STEPPER STEPPER=selector SET_POSITION=0
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
{% if printer["gcode_macro TOOL_INIT"].tool == -1 %}
M117 "Mevcut takım korunuyor"
{% else %}
M117 "Aktif takım: {printer["gcode_macro TOOL_INIT"].tool}"
{% endif %}
[gcode_macro WIPE]
gcode:
G1 X300 Y300 Z5 F5000 ; Wipe konumuna git (arka taraf)
G1 E10 F300 ; Bir miktar filament akıt
{% for _ in range(3) %} ; 3 kez tekrarla
G1 X300 Y235 F5000 ; Hafif sola hareket et
G1 X300 Y280 F5000 ; Tekrar sağa hareket et
G1 X300 Y235 F5000 ; Orta noktada dur
G1 X300 Y280 F5000
{% endfor %}
G1 Z0.2 F500 ; Z eksenini tekrar baskı konumuna getir
G92 E0 ; Ekstrüderi sıfırla
[gcode_macro FILAMENT_CUT]
description: "Filamenti X ekseninde uygun konumda keser"
gcode:
G1 X250 Y300 Z5 F6000 ; Kesim konumuna git
G1 E-70 F500 ; Filamenti geri çek
G1 X300 Y300 F6000 ; Kesme işlemi için X ekseninde küçük hareket
G1 X250 Y300 F6000
G1 X300 Y280
M117 "Filament kesildi"
G92 E0 ; Ekstrüderi sıfırla
[gcode_macro TS0]
gcode:
TOOL_SELECT TOOL=0
[gcode_macro TS1]
gcode:
TOOL_SELECT TOOL=1
[gcode_macro TS2]
gcode:
TOOL_SELECT TOOL=2
[gcode_macro TS3]
gcode:
TOOL_SELECT TOOL=3
[gcode_macro TOOL_SELECT]
gcode:
{% set TOOL = params.TOOL|int %}
M117 "Setting tool to TOOL{TOOL}"
{% if TOOL == 0 %}
MANUAL_STEPPER stepper=selector MOVE=0
{% elif TOOL == 1 %}
MANUAL_STEPPER stepper=selector MOVE=-4.5
{% elif TOOL == 2 %}
MANUAL_STEPPER stepper=selector MOVE=-13
{% elif TOOL == 3 %}
MANUAL_STEPPER stepper=selector MOVE=-8
{% endif %}
SET_GCODE_VARIABLE MACRO=TOOL_INIT VARIABLE=tool VALUE={TOOL}
[gcode_macro TOOL_FREE]
gcode:
{% set TOOL = params.TOOL|int %}
M117 "Free filament path for tool {TOOL}"
{% if TOOL == 0 %}
MANUAL_STEPPER stepper=selector MOVE=-13
{% elif TOOL == 1 %}
MANUAL_STEPPER stepper=selector MOVE=-8
{% elif TOOL == 2 %}
MANUAL_STEPPER stepper=selector MOVE=0
{% elif TOOL == 3 %}
MANUAL_STEPPER stepper=selector MOVE=-4.5
{% endif %}
[gcode_macro CHAMELEON_UNLOAD]
description: Unloads the filament from the tubing
gcode:
{% set TOOL=printer["gcode_macro TOOL_INIT"].tool %}
{% set YSPLIT_DIST=printer["gcode_macro TOOL_INIT"].ysplit_distance %}
{% set SPEED=printer["gcode_macro TOOL_INIT"].chameleon_speed %}
{% set ACC=printer["gcode_macro TOOL_INIT"].chameleon_acc %}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
{% if TOOL == 0 or TOOL == 1 %}
M117 "Move tool {TOOL} by -{YSPLIT_DIST}"
MANUAL_STEPPER stepper=chameleon MOVE=-{YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
MANUAL_STEPPER stepper=chameleon MOVE=-{YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
{% else %}
M117 "Move tool {TOOL} by {YSPLIT_DIST}"
MANUAL_STEPPER stepper=chameleon MOVE={YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
MANUAL_STEPPER stepper=chameleon MOVE={YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
{% endif %}
[gcode_macro CHAMELEON_LOAD]
description: Loads the filament into the extruder bowden
gcode:
{% set TOOL=printer["gcode_macro TOOL_INIT"].tool %}
{% set YSPLIT_DIST=printer["gcode_macro TOOL_INIT"].ysplit_distance %}
{% set SPEED=printer["gcode_macro TOOL_INIT"].chameleon_speed %}
{% set ACC=printer["gcode_macro TOOL_INIT"].chameleon_acc %}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
{% if TOOL == 0 or TOOL == 1 %}
M117 "Move tool {TOOL} by {YSPLIT_DIST}"
MANUAL_STEPPER stepper=chameleon MOVE={YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
MANUAL_STEPPER stepper=chameleon MOVE={YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
{% else %}
M117 "Move tool {TOOL} by -{YSPLIT_DIST}"
MANUAL_STEPPER stepper=chameleon MOVE=-{YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
MANUAL_STEPPER stepper=chameleon MOVE=-{YSPLIT_DIST} SPEED={SPEED} ACCEL={ACC}
MANUAL_STEPPER STEPPER=chameleon SET_POSITION=0
{% endif %}
G92 E0
[gcode_macro EXTRUDER_UNLOAD]
description: Unloads the filament from the extruder before a tool change
gcode:
G92 E0
G1 E-2 F300
G1 E-90 F3000
G92 E0
[gcode_macro EXTRUDER_LOAD]
description: Loads the filament in the extruder after a tool change
gcode:
G92 E0
G1 E30 F400
G1 E80 F400
G92 E0
[gcode_macro T0]
description: Changes the filament to that loaded in tool 0
gcode:
FILAMENT_CUT ; **Filament kesme işlemi burada yapılır**
G92 E0
G1 E-2 F300
G1 E-90 F1500 ; Geri çekme hızını düşürdük
{% if printer["gcode_macro TOOL_INIT"].tool != 0 %}
TOOL_SELECT TOOL={printer["gcode_macro TOOL_INIT"].tool}
CHAMELEON_UNLOAD
{% endif %}
{% set TOOL=0 %}
SET_GCODE_VARIABLE MACRO=TOOL_INIT VARIABLE=tool VALUE={TOOL}
TOOL_SELECT TOOL={TOOL}
CHAMELEON_LOAD
TOOL_FREE TOOL={TOOL}
G1 E20 F500 ; 20mm filament iterek nozula ilerlet
G1 X300 Y300 Z5 F6000 ; Wipe konumuna git ve Z'yi 5mm kaldır
G1 E110 F400 ; Filamenti burada yükle
G1 Z0.2 F400 ; Z eksenini tekrar baskı konumuna getir
WIPE
G92 E0
[gcode_macro T1]
description: Changes the filament to that loaded in tool 1
gcode:
FILAMENT_CUT ; **Filament kesme işlemi burada yapılır**
G92 E0
G1 E-2 F300
G1 E-90 F1500
{% if printer["gcode_macro TOOL_INIT"].tool != 1 %}
TOOL_SELECT TOOL={printer["gcode_macro TOOL_INIT"].tool}
CHAMELEON_UNLOAD
{% endif %}
{% set TOOL=1 %}
SET_GCODE_VARIABLE MACRO=TOOL_INIT VARIABLE=tool VALUE={TOOL}
TOOL_SELECT TOOL={TOOL}
CHAMELEON_LOAD
TOOL_FREE TOOL={TOOL}
G1 E20 F500
G1 X300 Y300 Z5 F6000
G1 E110 F400
G1 Z0.2 F500
WIPE
G92 E0
[gcode_macro T2]
description: Changes the filament to that loaded in tool 2
gcode:
FILAMENT_CUT ; **Filament kesme işlemi burada yapılır**
G92 E0
G1 E-2 F300
G1 E-90 F1500
{% if printer["gcode_macro TOOL_INIT"].tool != 2 %}
TOOL_SELECT TOOL={printer["gcode_macro TOOL_INIT"].tool}
CHAMELEON_UNLOAD
{% endif %}
{% set TOOL=2 %}
SET_GCODE_VARIABLE MACRO=TOOL_INIT VARIABLE=tool VALUE={TOOL}
TOOL_SELECT TOOL={TOOL}
CHAMELEON_LOAD
TOOL_FREE TOOL={TOOL}
G1 E20 F500
G1 X300 Y300 Z5 F6000
G1 E110 F400
G1 Z0.2 F500
WIPE
G92 E0
[gcode_macro T3]
description: Changes the filament to that loaded in tool 3
gcode:
FILAMENT_CUT ; **Filament kesme işlemi burada yapılır**
G92 E0
G1 E-2 F300
G1 E-90 F1500
{% if printer["gcode_macro TOOL_INIT"].tool != 3 %}
TOOL_SELECT TOOL={printer["gcode_macro TOOL_INIT"].tool}
CHAMELEON_UNLOAD
{% endif %}
{% set TOOL=3 %}
SET_GCODE_VARIABLE MACRO=TOOL_INIT VARIABLE=tool VALUE={TOOL}
TOOL_SELECT TOOL={TOOL}
CHAMELEON_LOAD
TOOL_FREE TOOL={TOOL}
G1 E20 F500
G1 X300 Y300 Z5 F6000
G1 E110 F400
G1 Z0.2 F500
WIPE
G92 E0