diff --git a/config/sample-idex.cfg b/config/sample-idex.cfg index d6c70a2ffbe0..c75501fa9b9e 100644 --- a/config/sample-idex.cfg +++ b/config/sample-idex.cfg @@ -1,7 +1,13 @@ -# This file contains a configuration snippet for a dual extruder +# This file contains configuration snippets for a dual extruder # printer using dual carriages (an "IDEX" printer). +# The most common IDEX setup is to have 2 X carraiges, but 2 Y +# carraiges is also possible on a cartesian printer. You will need +# to update the macros and stepper definitions accordingly to do this. + # See docs/Config_Reference.md for a description of parameters. +# See docs/Dual_Carriage.md for further details on certain modules in +# this document. # Definition for the primary carriage (holding the primary extruder) [stepper_x] @@ -44,13 +50,30 @@ gcode: # Activate the primary extruder [gcode_macro T0] +variable_offset_applied: 0 gcode: - PARK_{printer.toolhead.extruder} + {% set svv = printer.save_variables.variables %} + {% if "x" in printer.toolhead.homed_axes %} # this check ensures compatibility with Cura + PARK_{printer.toolhead.extruder} + {% endif %} + {% set fan_speed = printer["gcode_macro M106"].swap_speed %} + {% if fan_speed != -1 %} + SET_FAN_SPEED FAN=fan_extruder SPEED={fan_speed} + {% else %} + # Update core Klipper's fan speed to the fan speed of the active toolhead + # Only do this if you have a sacrificial [fan] section + M106.1 S{printer["fan_generic fan_extruder"].speed * 255} + {% endif %} ACTIVATE_EXTRUDER EXTRUDER=extruder SET_DUAL_CARRIAGE CARRIAGE=0 - SET_GCODE_OFFSET Y=0 + {% if printer["gcode_macro T0"].offset_applied == 1 %} + SET_GCODE_OFFSET X_ADJUST={ -(svv.xoffset) } Y_ADJUST={ -(svv.yoffset) } + SET_GCODE_OFFSET Z_ADJUST={ -(svv.zoffset) } MOVE=1 + SET_GCODE_VARIABLE MACRO=T0 VARIABLE=offset_applied VALUE=0 + {% endif %} +# SET_INPUT_SHAPER if nessesary, reset the input shaper after using the second extruder -# Definition for the secondary carriage and extruder1 +# Definition for the secondary carriage (holding the secondary extruder) [dual_carriage] axis: x step_pin: ar16 @@ -63,6 +86,7 @@ position_endstop: 200 position_max: 200 homing_speed: 50 +# The definition for the secondary extruder [extruder1] step_pin: ar36 dir_pin: ar34 @@ -90,7 +114,149 @@ gcode: [gcode_macro T1] gcode: - PARK_{printer.toolhead.extruder} + {% set svv = printer.save_variables.variables %} + {% if "x" in printer.toolhead.homed_axes %} # this check ensures compatibility with Cura + PARK_{printer.toolhead.extruder} + {% endif %} + {% set fan_speed = printer["gcode_macro M106"].swap_speed %} + {% if fan_speed != -1 %} + SET_FAN_SPEED FAN=fan_extruder1 SPEED={fan_speed} + {% else %} + # Update core Klipper's fan speed to the fan speed of the active toolhead + # Only do this if you have a sacrificial [fan] section + M106.1 S{printer["fan_generic fan_extruder1"].speed * 255} + {% endif %} ACTIVATE_EXTRUDER EXTRUDER=extruder1 SET_DUAL_CARRIAGE CARRIAGE=1 - SET_GCODE_OFFSET Y=15 + {% if printer["gcode_macro T0"].offset_applied == 0 %} + SET_GCODE_OFFSET X_ADJUST={ svv.xoffset } Y_ADJUST={ svv.yoffset } + SET_GCODE_OFFSET Z_ADJUST={ svv.zoffset } MOVE=1 + SET_GCODE_VARIABLE MACRO=T0 VARIABLE=offset_applied VALUE=1 + {% endif %} +# SET_INPUT_SHAPER if nessesary, update input shaping for the second carraige + +# YOU MUST CALIBRATE YOUR ROTATION_DISTANCE BEFORE THIS IS USEFUL!!! +# Configure this to draw 2 line segments perpendicular to the dual_carraige axis +# that meet in the middle of the bed. Both lines should have the same coordinate +# on the axis of the dual_carraige. If they don't print inline, adjust your endstop +# settings. +[gcode_macro set_separation] +gcode: + {% set svv = printer.save_variables.variables %} + + {% set oldX = svv.xoffset|float %} + {% set oldY = svv.yoffset|float %} + {% set oldZ = svv.zoffset|float %} + + {% if params.X is defined %} + SAVE_VARIABLE VARIABLE=xoffset VALUE={ params.X|float } + {% endif %} + + {% if params.Y is defined %} + SAVE_VARIABLE VARIABLE=yoffset VALUE={ params.Y|float } + {% endif %} + + {% if params.Z is defined %} + SAVE_VARIABLE VARIABLE=zoffset VALUE={ params.Z|float } + {% endif %} + + {% if params.X_ADJUST is defined %} + {% set newX = params.X_ADJUST|float + oldX %} + SAVE_VARIABLE VARIABLE=xoffset VALUE={ newX|float } + {% endif %} + + {% if params.Y_ADJUST is defined %} + {% set newY = params.Y_ADJUST|float + oldY %} + SAVE_VARIABLE VARIABLE=yoffset VALUE={ newY|float } + {% endif %} + + {% if params.Z_ADJUST is defined %} + {% set newZ = params.Z_ADJUST|float + oldZ %} + SAVE_VARIABLE VARIABLE=yoffset VALUE={ newZ|float } + {% endif %} + +[gcode_macro calibrate_separation] +gcode: + G28 + G90 + M83 + T0 ; test T0 + G1 X120 Y150 Z.2 F4800 + G1 Y75 E10 + T1 ; test T1 + G1 X120 Y0 Z.2 + G1 Y75 E10 + +# The following is for if your carraiges have their own part cooling fans. +# Since this macro overrides M106, you cannot also have a [fan] section defined. +# If your printer only has one part cooling fan, don't copy this section +[fan_generic part_fan_0] +pin: PE5 + +[fan_generic part_fan_1] +pin: PD13 + +# For completeness, you can add a [fan] section with an unused pin +[fan] +pin: rpi:gpio20 + +[gcode_macro M106] +# Only rename_existing if you have a sacrificial [fan] section +rename_existing: M106.1 +# The variable that controls fan speed swopping if not specifying P parameter +# -1 means the control is disabled, a value of 0-1 is the requested fan speed. +# Access via {printer["gcode_macro M106"].swap_speed} +variable_swap_speed: -1 +gcode: + {% set s = [[params.S|default(255)|int, 255]|min, 0]|max %} + {% set p = params.P|default(-1)|int %} + {% set speed = s / 255 %} + + # Set speed to -1 by default + SET_GCODE_VARIABLE MACRO=M106 VARIABLE=swap_speed VALUE=-1 + + {% if p == -1 %} + # Set current active extruder fan + {% if speed == 0 %} + # Always turn off al fans if S0 is specified without a specific fan + SET_FAN_SPEED FAN=fan_extruder SPEED=0 + SET_FAN_SPEED FAN=fan_extruder1 SPEED=0 + {% else %} + # Opt into fan speed swop control + SET_GCODE_VARIABLE MACRO=M106 VARIABLE=swap_speed VALUE={speed} + SET_FAN_SPEED FAN=fan_{printer.toolhead.extruder} SPEED={speed} + {% endif %} + {% else %} + # Set specified active extruder fan + {% if p == 0 %} + SET_FAN_SPEED FAN=fan_extruder SPEED={speed} + {% else %} + SET_FAN_SPEED FAN=fan_extruder1 SPEED={speed} + {% endif %} + {% endif %} + + # Update core Klipper's fan speed + # Only do this if you have a sacrificial [fan] section + M106.1 S{s} + +[gcode_macro M107] +rename_existing: M107.1 +gcode: + {% set p = params.P|default(-1)|int %} + M106 S0 P{p} + +[gcode_macro M107] +rename_existing: M107.1 +gcode: + {% set p = params.P|default(-1)|int %} + M106 S0 P{p} + +[save_variables] +filename: ~/klipper_config/variables.klip +# this is used for saving and restoring the idex offsets +# create the file and insert the folloring content (without the #) to start +# +# [Variables] +# xoffset = 0.0 +# yoffset = 0.0 +# zoffset = 0.0 diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index 1ae5a5c62c96..387b074459c8 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -1781,11 +1781,11 @@ for an example configuration. ### [dual_carriage] -Support for cartesian printers with dual carriages on a single -axis. The active carriage is set via the SET_DUAL_CARRIAGE extended -g-code command. The "SET_DUAL_CARRIAGE CARRIAGE=1" command will -activate the carriage defined in this section (CARRIAGE=0 will return -activation to the primary carriage). Dual carriage support is +Support for cartesian, hybrid-corexy, and hybrid-corexz printers with +dual carriages on a single axis. The active carriage is set via the +SET_DUAL_CARRIAGE extended g-code command. The "SET_DUAL_CARRIAGE CARRIAGE=1" +command will activate the carriage defined in this section (CARRIAGE=0 +will return activation to the primary carriage). Dual carriage support is typically combined with extra extruders - the SET_DUAL_CARRIAGE command is often called at the same time as the ACTIVATE_EXTRUDER command. Be sure to park the carriages during deactivation. diff --git a/docs/Dual_Carriage.md b/docs/Dual_Carriage.md new file mode 100644 index 000000000000..73d42b26ad2e --- /dev/null +++ b/docs/Dual_Carriage.md @@ -0,0 +1,135 @@ +This document provides **general** information on configuring and +calibrating a standard IDEX printer. Klipper has support for very +complex IDEX configurations, with multiple hotends and extruders on a +single carriage, independent or grouped cooling fans, and much more, +which are not covered in this document. + +# General configuration +Start with studying, and possibly using parts of the [example config](../config/sample-idex.cfg) +for IDEX printers. It has some distinct items that you may or may not +wish to use. +* Definition for `dual_carriage` on the X-axis, which you can change to +be on the Y axis if that is how your printer is configured. +* Sample macros for parking and switching toolheads. You should check +these to make sure they make sense for your setup and update the +position values with those that match your printer +* Fan configurations mentioned later. +* A macro for calibrating carriage separation described later in this +document. + +# Tuning +If you want to use both extruders to print different features of a +single object, Klipper will need to know the positions of the extruders +relative to each other. + +Because Klipper configures this by the endstop position, you will +need to calibrate your [rotation distance](Rotation_Distance.md) first. + +For the finest accuracy, you should consider calibrating the homing +[endstop phase](endstop_phase.md) of your dual_carraige axis motors. + +## Step 1 (~5mm) +Start by literally eyeballing it. Put a piece of tape on your bed or +use a line or other graphic already on your bed as a reference point. + +Move the first carriage to this point and note it's position. Then, +park carriage 1, and move carriage 2 to the same physical position. +Note it's position (where Klipper "thinks" it is) and calculate the +difference. + +In a standard setup where the carriages home to the sides with the +primary on the left, you move the logical coordinate system for the +secondary extruder to the right by lowering it's `position_endstop` +value. + +Run `SET_SEPARATION Y={your calculated value}` to set the Y offset. + +Once you are within a few mm of accuracy, proceed to step 2 + +## Step 2 (~1mm) +Configure the `calibrate_separation` macro in [the sample config](../config/sample-idex.cfg) +for your bed size and dual_carriage axis, and add heating commands to +it for the filament you'll be using. + +Load filament in both extruders, and run the macro. + +The test with the standard axis configuration should look as follows: + +![measuring print](img/separation-lines.png) + +Note the lines should be colinear. If they are not, adjust your +`position_endstop` setting as noted in step 1. Once they are visually +aligned, proceed to step 3. + +At this point you should re-tune your mins and maxes for each axis when +the other is parked by issuing slow, small movements until they +collide. + +## Step 3 (~.1 - .025mm) +While the measuring process of this step accounts for symmetric +horizontal expansion, you will likely achieve better results by +calibrating the flow, temperature, and pressure advance for the +filament you'll be using first. You'll also do better with a filament +that is known to have better dimensional stability. Look for filaments +that can be printed without a heated bed. + +Use a slicer to generate g-code for the multi-part print found in +[docs/prints/calibrate_idex.stl](prints/calibrate_idex.stl). +Align the long direction of the print perpendicular to the axis of your +`dual_carriage`. Configure your slicer to print the upper part using +the right extruder. I highly recommend using identical filaments printed with +the same temperature, etc. Use a rather coarse layer height since you +have not yet calibrated your Z offset. Print the object. + +Use calipers or better, a micrometer to measure the 2 measureing points +(refer to the image below). Complete the following table: + +| Part | Measurement | Calculation | +|:--:|:--:|:--:| +| Front | (mm) | 20 - (mm) | +| Back | (mm) | (mm) - 20 | +| Offset | | ^ Average ^ | + +![measuring print](img/separation-block.png) + +You should be left with the adjustment that should be made to compensate +for any alignment error. Save this to the printer by running: +``` +SET_SEPARATION X_ADJUST={your calculated value} +``` + +Repeat this step if nessesary until you are happy with the alignment. Rotate +the object 90 degrees and repeat with the Y axis. + +## Step 4 (required for high quality printing) +To print with low layer thicknesses, you'll probably find that the error +between your nozzles in the Z axis is more than your layer height itself. + +Start with a piece of paper and switch between the extruders until the pressure +feels roughly the same on both extruders. Make sure you're testing the exact +same point on your bed. + +Prepare to print a square about 10x10x5mm. Slice the object twice with the only +difference being which extruder is used. MAKE SURE IT IS IN THE SAME PLACE ON YOUR BED. + +Use calipers or better, a micrometer to measure the height of the two samples and +adjust the Z offset as nessesary. + +# Next steps +Configure a homing override to make sure that the inactive carriage is +fully parked in all scenarios. + +If you want to use [input shaping](Resonance_compensation.md), +calibrate the input shaper for each carriage separately and add g-code +to your `T0` and `T1` etc commands to configure the input shaper when +the active carriage changes. + +For support with Fluidd, SuperSlicer, consider overriding the `ACTIVATE_EXTRUDER` +command to run T0, T1. + +If your printer has multiple part cooling fans, create `[fan_generic]` sections +for each of them. For support with Klipper's default LCD resdout, consider using the +`[fan]` section and macro elements in the sample. Otherwise, write your own M106 +and M107 macros. + +Print a few objects to ensure everything is working as expected! diff --git a/docs/Overview.md b/docs/Overview.md index a758a991b281..812aeccd8acf 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -54,6 +54,8 @@ communication with the Klipper developers. perfectly square. - [PWM tools](Using_PWM_Tools.md): Guide on how to use PWM controlled tools such as lasers or spindles. +- [IDEX printers](Dual_Carriage.md): Guide on setting up and calibrating + an IDEX printer. ## Developer Documentation diff --git a/docs/img/separation-block.png b/docs/img/separation-block.png new file mode 100644 index 000000000000..e5b5c89360b9 Binary files /dev/null and b/docs/img/separation-block.png differ diff --git a/docs/img/separation-lines.png b/docs/img/separation-lines.png new file mode 100644 index 000000000000..73064043a312 Binary files /dev/null and b/docs/img/separation-lines.png differ diff --git a/docs/prints/calibrate_idex.stl b/docs/prints/calibrate_idex.stl new file mode 100644 index 000000000000..335cf28cbf0e Binary files /dev/null and b/docs/prints/calibrate_idex.stl differ