############################### # ERCF module ############################### [ercf] # Encoder encoder_pin: ^mcu2:PA0 encoder_resolution: 1.365188 # in mm # Speeds and accels # Long moves are faster than the small ones # 100mm/s should be "quiet" with the NEMA14 motor or a NEMA17 pancake, but you can go lower if your really want it to be low noise # Tested without any issue at 200mm/s, but it's noisy. I'm running mine at 170mm/s for long moves and 50mm/s for short moves. long_moves_speed: 100 # mm/s. Default value is 100mm/s. long_moves_accel: 400 # mm/s². Default value is 400mm/s² short_moves_speed: 25 # mm/s. Default value is 25mm/s. short_moves_accel: 400 # mm/s². Default value is 400mm/s² [gcode_macro ERCF_VAR] # ======================================================= # ================== VALUES TO ADJUST =================== # ======================================================= # # ==== Toolhead specific values ==== # # Distance between the end of the reverse bowden and the toolhead sensor. Value is toolhead specific. # Tested values : # Galileo Clockwork with ERCF V1.1 sensor (hall effect) : 27.0 # LGX on AfterBurner with ERCF V1.1 sensor (hall effect) : 44.0 # AfterBurner Clockwork with ERCF V1.1 sensor (hall effect) : 36.0 variable_end_of_bowden_to_sensor: 36.0 # Length from the sensor to the nozzle melt pool. # Reduce this value if there are blobs of filament on each load, before the purge on the tower. # Increase this value if there are big gaps on the purge tower (i.e. if it takes time for the filament to get pushed out after a swap) # Tested values : # Galileo Clockwork with ERCF 1.1 sensor (hall effect) & Dragon Normal Flow : 60.5 # LGX on AfterBurner with ERCF 1.1 sensor (hall effect) & Dragon Normal Flow : 55.6 # AfterBurner Clockwork with ERCF 1.1 sensor (hall effect) & Dragon Normal Flow : 54.0 variable_sensor_to_nozzle: 54.0 # # ==== Values to tune ==== # # Tool position for the selector. This has to be tuned manually. Please scale this array to the number of tools you have variable_colorselector = [2.4, 24.0, 44.8, 71.2, 92.0, 113.6, 139.2, 160.8, 181.6] # Base value for the loading length used by the auto-calibration macro # Please use a value SMALLER than the real reverse bowden length (like 50mm less) variable_min_bowden_length: 750.0 # Servo angle for the Up position (i.e. tool disengaged). Refer to the manual to know how to properly tune this value # Default values: # MG90S servo : 30 # SAVOX SH0255MG : 140 variable_servo_up_angle: 30 # Servo angle for the Down position (i.e. tool engaged). Refer to the manual to know how to properly tune this value # Default values: # MG90S servo : 140 # SAVOX SH0255MG : 30 variable_servo_down_angle: 140 # Options to use or not # Beware that the clog detection and endless spool mode are in BETA mode for now # Use at your own risk (beware of the involved macros and the pause(s) and resume ones) # Put 0 to disable, 1 to enable variable_clog_detection: 0 variable_endless_spool_mode: 0 # ======================================================= # ============ END OF VALUES TO ADJUST ================== # ======================================================= # You shouldn't have to change anything below this point # Things that you shouldn't have to change variable_unload_modifier: 9.0 # Modifier to adjust the ERCF park position (where the filament ends when doing an unload) variable_min_temp_extruder: 180 # Temp used during the auto-calibration macro, to ensure we can move the extruder (but not really extruding) variable_extruder_eject_temp: 240 # Temp used during filament ejection (in the ERCF_HOME macro, if a filament is detected in the toolhead) variable_timeout_pause: 72000 # Time out used by the ERCF_PAUSE variable_disable_heater: 600 # Delay after which the hotend heater is disabled in the ERCF_PAUSE state gcode: [save_variables] filename: /home/pi/klipper_config/ercf_vars.cfg ############################### # ERCF Calibration macros ############################### [gcode_macro ERCF_CALIB_SELECTOR] description: Calibration of the selector position for a defined Tool gcode: ERCF_SERVO_UP {% set move_length=(20.0 + (params.TOOL|int + 1)*21.0 + ((params.TOOL|int + 1)/3)*5.0) %} M118 Measuring the selector position for tool {params.TOOL} ERCF_GET_SELECTOR_POS REF={move_length|int} ERCF_MOTORS_OFF [gcode_macro ERCF_CALIBRATE] description: Complete calibration of all ERCF Tools gcode: SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=0 M118 Start the complete auto calibration... M118 First home the ERCF ERCF_HOME {% for chan in range(printer["gcode_macro ERCF_VAR"].colorselector|length) %} ERCF_CALIBRATE_SINGLE TOOL={chan|int} {% endfor %} M118 End of the complete auto calibration! M118 Please reload the firmware for the calibration to be active! [gcode_macro ERCF_CALIBRATE_SINGLE] description: Calibration of a single ERCF Tool gcode: SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=0 {% if params.TOOL|int >= 0 and params.TOOL|int < printer["gcode_macro ERCF_VAR"].colorselector|length %} {% if printer["gcode_macro ERCF_HOME"].home == -1 %} M118 First home the ERCF ERCF_HOME {% endif %} ERCF_SELECT_TOOL TOOL={params.TOOL} ERCF_SET_STEPS RATIO=1.0 {% if params.TOOL|int == 0 %} {% if printer['extruder'].temperature < printer["gcode_macro ERCF_VAR"].min_temp_extruder %} M109 S{printer["gcode_macro ERCF_VAR"].min_temp_extruder|int} {% endif %} M118 Calibrating reference tool {params.TOOL} ERCF_LOAD LENGTH={printer["gcode_macro ERCF_VAR"].min_bowden_length} ERCF_HOME_EXTRUDER TOTAL_LENGTH=400 STEP_LENGTH=0.5 ERCF_CALIB_SAVE_VAR TOOL={params.TOOL} G91 G92 E0 MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=gear_stepper MOVE=-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float} SPEED=25 ACCEL=0 SYNC=0 G1 E-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float} F1500.0 ERCF_CALIB_UNLOAD ERCF_BUZZ_GEAR_MOTOR ERCF_IS_FILAMENT_STUCK_IN_ERCF ERCF_UNSELECT_TOOL {% else %} M118 Calibrating tool {params.TOOL} ERCF_LOAD LENGTH={printer["gcode_macro ERCF_VAR"].min_bowden_length|float - 100.0} ERCF_CALIB_SAVE_VAR tool={params.TOOL} ERCF_CALIB_UNLOAD LENGTH={printer["gcode_macro ERCF_VAR"].min_bowden_length|float - 100.0 + 27.0} {% endif %} {% else %} M118 Tool out of range {% endif %} [gcode_macro ERCF_CALIB_SAVE_VAR] description: Saving ERCF calibration values gcode: {% if params.TOOL|int == 0 %} M118 Tool {params.TOOL} calibration value is {printer['ercf'].encoder_pos|float} SAVE_VARIABLE VARIABLE=ercf_calib_ref VALUE={printer['ercf'].encoder_pos|float} # this is the reference value SAVE_VARIABLE VARIABLE=ercf_calib_{params.TOOL|int} VALUE=1.0 SET_GCODE_VARIABLE MACRO=ERCF_CALIB_UNLOAD VARIABLE=ref VALUE={printer['ercf'].encoder_pos|float} SET_GCODE_VARIABLE MACRO=ERCF_CALIB_UNLOAD VARIABLE=ratio VALUE=1.0 {% else %} {% set ratio = (printer["gcode_macro ERCF_VAR"].min_bowden_length|float - 100.0) / printer['ercf'].encoder_pos|float %} M118 Tool {params.TOOL} ratio is {ratio|float} SAVE_VARIABLE VARIABLE=ercf_calib_{params.TOOL|int} VALUE={ratio|float} SET_GCODE_VARIABLE MACRO=ERCF_CALIB_UNLOAD VARIABLE=ratio VALUE={ratio|float} {% endif %} [gcode_macro ERCF_CALIB_UNLOAD] description: Filament unload during ERCF calibration variable_ratio: 0.0 variable_ref: 0.0 gcode: {% set unload_length = params.LENGTH|default(0.0)|float %} {% if unload_length|float == 0.0 %} ERCF_UNLOAD LENGTH={(ref|float)*(ratio|float) - printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float + 27.0} {% else %} {% if ratio|float < 1.0 %} # No correction move is done in case of "over targeting", hence the correction ratio is not applied during this unload sequence ERCF_UNLOAD LENGTH={(unload_length|float)} {% else %} ERCF_UNLOAD LENGTH={(unload_length|float)*(ratio|float)} {% endif %} {% endif %} [respond] default_type: command ############################### # ERCF servo ############################### # Push the top hat down (enable the bondtech gears) while "buzzing" the gear motor to ensure proper BMG gear meshing [gcode_macro ERCF_SERVO_DOWN] description: Engage the ERCF gear gcode: MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=gear_stepper MOVE=0.5 SPEED=25 ACCEL=0 SYNC=0 SET_SERVO SERVO=ercf_servo ANGLE={printer["gcode_macro ERCF_VAR"].servo_down_angle} G4 P200 MANUAL_STEPPER STEPPER=gear_stepper MOVE=0.0 SPEED=25 ACCEL=0 SYNC=0 G4 P100 MANUAL_STEPPER STEPPER=gear_stepper MOVE=-0.5 SPEED=25 ACCEL=0 SYNC=0 G4 P100 MANUAL_STEPPER STEPPER=gear_stepper MOVE=0.0 SPEED=25 ACCEL=0 SET_SERVO SERVO=ercf_servo WIDTH=0.0 # Pull the top hat up (disengage the bondtech gears) [gcode_macro ERCF_SERVO_UP] description: Disengage the ERCF gear gcode: SET_SERVO SERVO=ercf_servo ANGLE={printer["gcode_macro ERCF_VAR"].servo_up_angle} G4 P250 SET_SERVO SERVO=ercf_servo WIDTH=0.0 ############################### # ERCF motors ############################### [gcode_macro ERCF_MOTORS_OFF] description: Turn off both ERCF motors gcode: MANUAL_STEPPER STEPPER=gear_stepper ENABLE=0 MANUAL_STEPPER STEPPER=selector_stepper ENABLE=0 ############################### # PAUSE MACROS # ERCF_PAUSE is called when an human intervention is needed # use ERCF_UNLOCK to start the manual intervention # and use RESUME when the intervention is over to resume the current print ############################### # Stop the delayed stop of the heater [gcode_macro ERCF_UNLOCK] description: Unlock ERCF operations gcode: M118 Unlock the ERCF SET_GCODE_VARIABLE MACRO=ERCF_PAUSE VARIABLE=is_paused VALUE=0 UPDATE_DELAYED_GCODE ID=disable_heater DURATION=0 {% if printer['filament_switch_sensor toolhead_sensor'].filament_detected == False %} ERCF_UNSELECT_TOOL {% else %} ERCF_UNSELECT_TOOL FORCED=0 {% endif %} M104 S{printer["gcode_macro ERCF_PAUSE"].extruder_temp} RESTORE_GCODE_STATE NAME=ERCF_state M118 Refer to the manual before resuming the print [delayed_gcode disable_heater] gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int != 0 %} M118 Disable extruder heater M104 S0 {% endif %} # Pause the ERCF, park the extruder at the parking position # Save the current state and start the delayed stop of the heated # modify the timeout of the printer accordingly to timeout_pause [gcode_macro ERCF_PAUSE] description: Pause the current print and lock the ERCF operations variable_is_paused: 0 variable_extruder_temp: 0 gcode: SET_GCODE_VARIABLE MACRO=ERCF_PAUSE VARIABLE=extruder_temp VALUE={printer.extruder.target} SET_GCODE_VARIABLE MACRO=ERCF_PAUSE VARIABLE=is_paused VALUE=1 SET_IDLE_TIMEOUT TIMEOUT={printer["gcode_macro ERCF_VAR"].timeout_pause} UPDATE_DELAYED_GCODE ID=disable_heater DURATION={printer["gcode_macro ERCF_VAR"].disable_heater} M118 An issue with the ERCF has been detected and the ERCF has been PAUSED M118 When you intervene to fix the issue, first call the "ERCF_UNLOCK" Gcode M118 Refer to the manual before resuming the print SAVE_GCODE_STATE NAME=ERCF_state SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=0 PAUSE ############################################ # Changing tool macros # ERCF_CHANGE_TOOL_STANDALONE TOOL=XX to change filament outside of a print # ERCF_CHANGE_TOOL_SLICER TOOL=XX will be called automatically (from the ACTIVATE_EXTRUDER gcode from SuperSlicer), don't use that for "manual" filament swap # if the new extruder is different from the current extruder : # eject the filament if needed # load the new one ########################################### [gcode_macro T0] gcode: ERCF_CHANGE_TOOL TOOL=0 [gcode_macro T1] gcode: ERCF_CHANGE_TOOL TOOL=1 [gcode_macro T2] gcode: ERCF_CHANGE_TOOL TOOL=2 [gcode_macro T3] gcode: ERCF_CHANGE_TOOL TOOL=3 [gcode_macro T4] gcode: ERCF_CHANGE_TOOL TOOL=4 [gcode_macro T5] gcode: ERCF_CHANGE_TOOL TOOL=5 [gcode_macro T6] gcode: ERCF_CHANGE_TOOL TOOL=6 [gcode_macro T7] gcode: ERCF_CHANGE_TOOL TOOL=7 [gcode_macro T8] gcode: ERCF_CHANGE_TOOL TOOL=8 [gcode_macro ERCF_CHANGE_TOOL] description: Perform a tool swap gcode: {% if printer.idle_timeout.state == "Printing" %} ERCF_CHANGE_TOOL_SLICER TOOL={params.TOOL|int} {% else %} ERCF_CHANGE_TOOL_STANDALONE TOOL={params.TOOL|int} {% endif %} [gcode_macro ERCF_CHANGE_TOOL_SLICER] description: Perform a tool swap during a print gcode: SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=0 {% if printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int != params.TOOL|int %} # Add a variable 'SwapCounter' in your PRINT_START macro to display this info # {% set newcounter = (printer["gcode_macro PRINT_START"].swapcounter|int + 1) %} # SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=swapcounter VALUE={newcounter} # M118 Swap {newcounter|int} M117 Change Tool T{params.TOOL|int} ERCF_UNLOAD_TOOL ERCF_LOAD_TOOL TOOL={params.TOOL|int} ERCF_CHANGE_TOOL_SLICER_END {% endif %} [gcode_macro ERCF_CHANGE_TOOL_SLICER_END] gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer["gcode_macro ERCF_VAR"].clog_detection|int == 1 %} SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=1 {% endif %} {% endif %} [gcode_macro ERCF_CHANGE_TOOL_STANDALONE] description: Perform a tool swap out of a print gcode: SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=0 {% if printer["gcode_macro ERCF_HOME"].home == -1 %} M118 ERCF not homed, homing it... ERCF_HOME M117 Change Tool T{params.TOOL|int} ERCF_LOAD_TOOL TOOL={params.TOOL|int} {% elif printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int != params.TOOL|int %} M117 Change Tool T{params.TOOL|int} {% if printer['filament_switch_sensor toolhead_sensor'].filament_detected == True %} M118 Unloading current filament {% if printer['extruder'].temperature < 178 %} M118 Preheat Nozzle M109 S{printer["gcode_macro ERCF_VAR"].extruder_eject_temp} {% endif %} ERCF_EJECT {% endif %} ERCF_LOAD_TOOL TOOL={params.TOOL|int} {% endif %} ############################################ # Unloading/Loading Macros ############################################ # Load filament from ERCF to nozzle [gcode_macro ERCF_LOAD_TOOL] description: Load the filament from the ERCF to the toolhead gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer["gcode_macro ERCF_HOME"].home == -1 %} M118 ERCF not homed, homing it... ERCF_HOME {% endif %} M118 Loading tool {params.TOOL|int} ... ERCF_SELECT_TOOL TOOL={params.TOOL|int} {% set ercf_params = printer.save_variables.variables %} ERCF_SET_STEPS RATIO={ercf_params['ercf_calib_%s' % (params.TOOL|string)]} M118 Loading filament from ERCF to extruder ... {% set ercf_params = printer.save_variables.variables %} ERCF_LOAD LENGTH={ercf_params.ercf_calib_ref|float - printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float} ERCF_LOAD_FILAMENT_IN_EXTRUDER {% endif %} # Unload filament from nozzle to ERCF, using built-in tip forming macro [gcode_macro ERCF_EJECT] description: Eject the filament out of a print and park it into the ERCF gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int != -1 %} M118 Unloading tool {printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int} ... {% if printer['filament_switch_sensor toolhead_sensor'].filament_detected == True %} ERCF_UNLOAD_FILAMENT_IN_EXTRUDER_WITH_TIP_FORMING {% set ercf_params = printer.save_variables.variables %} ERCF_SET_STEPS RATIO={ercf_params['ercf_calib_%s' % (printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|string)]} ERCF_UNLOAD LENGTH={ercf_params.ercf_calib_ref|float - printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float + printer["gcode_macro ERCF_VAR"].unload_modifier|float} ERCF_UNSELECT_TOOL {% else %} ERCF_EJECT_UNKNOW_STATE {% endif %} {% else %} ERCF_EJECT_UNKNOW_STATE {% endif %} {% endif %} # Unload filament from nozzle to ERCF, using SuperSlicer ramming [gcode_macro ERCF_UNLOAD_TOOL] description: Eject the filament during a print and park it into the ERCF gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int != -1 %} M118 Unload tool {printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int} ... ERCF_HOME_EXTRUDER ERCF_SELECT_TOOL TOOL={printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int} {% set ercf_params = printer.save_variables.variables %} ERCF_SET_STEPS RATIO={ercf_params['ercf_calib_%s' % (printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|string)]} G91 G92 E0 MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=gear_stepper MOVE=-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float + 20.0} SPEED=25 ACCEL=0 SYNC=0 G1 E-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float + 20.0} F1500.0 {% set ercf_params = printer.save_variables.variables %} ERCF_UNLOAD LENGTH={ercf_params.ercf_calib_ref|float - printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float + printer["gcode_macro ERCF_VAR"].unload_modifier|float - 20.0} ERCF_UNSELECT_TOOL {% endif %} {% endif %} ############################################ # Select/Unselect a tool # move the selector (if needed) to the requested tool ############################################ # Select a tool. move the idler and then move the color selector (if needed) [gcode_macro ERCF_SELECT_TOOL] description: Move the selector to the Tool and select it variable_tool_selected: -1 variable_color_selected: -1 gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer["gcode_macro ERCF_HOME"].home != -1 %} M118 Select Tool {params.TOOL} ... ERCF_SERVO_UP MANUAL_STEPPER STEPPER=selector_stepper MOVE={printer["gcode_macro ERCF_VAR"].colorselector[params.TOOL|int]} SET_GCODE_VARIABLE MACRO=ERCF_SELECT_TOOL VARIABLE=tool_selected VALUE={params.TOOL} SET_GCODE_VARIABLE MACRO=ERCF_SELECT_TOOL VARIABLE=color_selected VALUE={params.TOOL} ERCF_SERVO_DOWN M118 Tool {params.TOOL} Enabled {% else %} M118 Could not select tool, ERCF is not homed {% endif %} {% endif %} # Unselect a tool [gcode_macro ERCF_UNSELECT_TOOL] description: Unselect current Tool gcode: {% set unselect_color = params.FORCED|default(1)|int %} {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer["gcode_macro ERCF_HOME"].home != -1 %} ERCF_SERVO_UP SET_GCODE_VARIABLE MACRO=ERCF_SELECT_TOOL VARIABLE=tool_selected VALUE=-1 {% if unselect_color == 1 %} SET_GCODE_VARIABLE MACRO=ERCF_SELECT_TOOL VARIABLE=color_selected VALUE=-1 {% endif %} ERCF_SET_STEPS RATIO=1.0 {% else %} M118 Could not unselect tool, ERCF is not homed {% endif %} {% endif %} ############################################ # Loading/Unloading part FROM/TO EXTRUDER TO/FROM NOZZLE ############################################ # Load the filament into the extruder # Call ERCF_PAUSE if the filament is not detected by the toolhead sensor [gcode_macro ERCF_LOAD_FILAMENT_IN_EXTRUDER] description: Load filament from the toolhead entrance to the nozzle gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer.extruder.temperature > printer["gcode_macro ERCF_VAR"].min_temp_extruder %} M118 Loading Filament... G91 G92 E0 MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=gear_stepper MOVE={printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float - 7} SPEED=25 ACCEL=0 SYNC=0 G1 E{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float - 7} F1500.0 G4 P100 ERCF_HOME_EXTRUDER TOTAL_LENGTH=30.0 STEP_LENGTH=0.5 ERCF_UNSELECT_TOOL FORCED=0 ERCF_FINALIZE_LOAD LENGTH={printer["gcode_macro ERCF_VAR"].sensor_to_nozzle|float} G92 E0 G90 M118 Load Complete {% else %} M118 Extruder too cold ERCF_PAUSE {% endif %} {% endif %} # StandAlone cooling moves to extract proper filament tip [gcode_macro ERCF_FORM_TIP_STANDALONE] description: Generic tip forming macro gcode: {% set COOLING_TUBE_LENGTH = params.COOLING_TUBE_LENGTH|default(15) %} # Dragon ST: 15, Dragon HF: 10, Mosquito: 20 {% set COOLING_TUBE_RETRACTION = params.COOLING_TUBE_RETRACTION|default(35) %} # Dragon ST: 35, Dragon HF: 30, Mosquito: 38 {% set INITIAL_COOLING_SPEED = params.INITIAL_COOLING_SPEED|default(10) %} {% set FINAL_COOLING_SPEED = params.FINAL_COOLING_SPEED|default(50) %} {% set COOLING_MOVES = params.COOLING_MOVES|default(5) %} {% set TOOLCHANGE_TEMP = params.TOOLCHANGE_TEMP|default(0) %} {% set USE_SKINNYDIP = params.USE_SKINNYDIP|default(1) %} {% set USE_FAST_SKINNYDIP = params.USE_FAST_SKINNYDIP|default(1) %} {% set SKINNYDIP_DISTANCE = params.SKINNYDIP_DISTANCE|default(26) %} {% set DIP_INSERTION_SPEED = params.DIP_INSERTION_SPEED|default(33) %} {% set DIP_EXTRACTION_SPEED = params.DIP_EXTRACTION_SPEED|default(70) %} {% set MELT_ZONE_PAUSE = params.MELT_ZONE_PAUSE|default(0) %} {% set COOLING_ZONE_PAUSE = params.COOLING_ZONE_PAUSE|default(0) %} {% set UNLOADING_SPEED_START = params.UNLOADING_SPEED_START|default(199) %} {% set UNLOADING_SPEED = params.UNLOADING_SPEED|default(20) %} {% set RAMMING_VOLUME = params.RAMMING_VOLUME|default(0) %} # in mm3 {% set INITIAL_RETRACT = params.INITIAL_RETRACT|default(0) %} # Use an initial retract or not. Don't use it if you want to ram the filament {% set FINAL_EJECT = params.FINAL_EJECT|default(0) %} # Fully eject the filament afterwards, default is no G91 G92 E0 SET_PRESSURE_ADVANCE ADVANCE=0 {% set OLD_TEMP = printer.extruder.target %} # Ramming with SuperSlicer standard setting {% if INITIAL_RETRACT|int == 1 %} G1 E-8.5000 F3000 {% endif %} {% set RATIO = (RAMMING_VOLUME|float) /23.0 %} G1 E{0.5784 * RATIO|float} F299 #7 G1 E{0.5834 * RATIO|float} F302 #3 G1 E{0.5918 * RATIO|float} F306 #6 G1 E{0.6169 * RATIO|float} F319 #6 G1 E{0.3393 * RATIO|float} F350 #0 G1 E{0.3363 * RATIO|float} F350 #0 G1 E{0.7577 * RATIO|float} F392 #6 G1 E{0.8382 * RATIO|float} F434 #3 G1 E{0.7776 * RATIO|float} F469 #9 G1 E{0.1293 * RATIO|float} F469 #9 G1 E{0.9673 * RATIO|float} F501 #2 G1 E{1.0176 * RATIO|float} F527 #2 G1 E{0.5956 * RATIO|float} F544 #6 G1 E{0.4555 * RATIO|float} F544 #6 G1 E{1.0662 * RATIO|float} F552 #4 # set toolchange temperature just prior to filament being extracted from melt zone and wait for set point # (SKINNYDIP--normal mode only) {% if TOOLCHANGE_TEMP|float > 0 and USE_FAST_SKINNYDIP|int == 0 %} M109 S{TOOLCHANGE_TEMP} {% endif %} # Retraction {% set TOTAL_RETRACTION_DISTANCE = COOLING_TUBE_RETRACTION|float + COOLING_TUBE_LENGTH|float / 2 - 15 %} G1 E-15 F{1.0 * UNLOADING_SPEED_START|float * 60} G1 E-{0.7 * TOTAL_RETRACTION_DISTANCE} F{1.0 * UNLOADING_SPEED|float * 60} G1 E-{0.2 * TOTAL_RETRACTION_DISTANCE} F{0.5 * UNLOADING_SPEED|float * 60} G1 E-{0.1 * TOTAL_RETRACTION_DISTANCE} F{0.3 * UNLOADING_SPEED|float * 60} {% if TOOLCHANGE_TEMP|float > 0 and USE_FAST_SKINNYDIP|int == 1 %} M104 S{TOOLCHANGE_TEMP} {% endif %} # Generate Cooling Moves {% set SPEED_INC = (FINAL_COOLING_SPEED|float - INITIAL_COOLING_SPEED|float) / (2 * COOLING_MOVES|float - 1) %} {% for move in range(COOLING_MOVES|int) %} G1 E{COOLING_TUBE_LENGTH} F{(INITIAL_COOLING_SPEED|float + SPEED_INC*move*2) * 60} G1 E-{COOLING_TUBE_LENGTH} F{(INITIAL_COOLING_SPEED|float + SPEED_INC*(move*2+1)) * 60} {% endfor %} # wait for extruder to reach toolchange temperature after cooling moves complete (SKINNYDIP--fast mode only) {% if TOOLCHANGE_TEMP|float > 0 and USE_FAST_SKINNYDIP|int == 1 %} M109 S{TOOLCHANGE_TEMP} {% endif %} # Generate a skinnydip move {% if USE_SKINNYDIP|int == 1 %} G1 E{SKINNYDIP_DISTANCE} F{DIP_INSERTION_SPEED|float * 60} G4 P{MELT_ZONE_PAUSE} G1 E-{SKINNYDIP_DISTANCE} F{DIP_EXTRACTION_SPEED|float * 60} G4 P{COOLING_ZONE_PAUSE} {% endif %} {% if TOOLCHANGE_TEMP|float > 0 %} M104 S{OLD_TEMP} {% endif %} {% if FINAL_EJECT|int == 1 %} G92 E0 G1 E-80 F3000 {% endif %} G92 E0 # Unload from extruder with tip forming sequence [gcode_macro ERCF_UNLOAD_FILAMENT_IN_EXTRUDER_WITH_TIP_FORMING] description: Unload filament from the nozzle to the toolhead entrance using generic tip forming macro gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} {% if printer.extruder.temperature > printer["gcode_macro ERCF_VAR"].min_temp_extruder %} {% if printer["gcode_macro ERCF_SELECT_TOOL"].tool_selected|int == -1 %} M118 Forming filament tip and Unloading Filament... G91 ERCF_FORM_TIP_STANDALONE G1 E-4.00 F1200.0 G1 E-15.00 F2000 ERCF_HOME_EXTRUDER ERCF_SERVO_DOWN G91 G92 E0 MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=gear_stepper MOVE=-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float} SPEED=25 ACCEL=0 SYNC=0 G1 E-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float} F1500.0 M118 Filament removed {% else %} M118 Tool selected, UNSELECT it ERCF_PAUSE {% endif %} {% else %} M118 Extruder too cold ERCF_PAUSE {% endif %} {% endif %} ############################################ # Endstop check macros ############################################ # Call ERCF_PAUSE if the filament is not detected by the toolhead sensor [gcode_macro ERCF_IS_FILAMENT_IN_EXTRUDER] gcode: {% if printer['filament_switch_sensor toolhead_sensor'].filament_detected == True %} M118 Filament is in extruder {% else %} M118 Filament not in extruder ERCF_PAUSE {% endif %} # Call ERCF_PAUSE if the filament is stuck in the ERCF [gcode_macro ERCF_IS_FILAMENT_STUCK_IN_ERCF] gcode: {% if printer.ercf.encoder_pos|float != 0 %} M118 Filament stuck in ERCF ERCF_PAUSE {% else %} M118 Filament not in ERCF {% endif %} ############################################ # Macros called during homing to try to eject the filament if loaded ############################################ # Eject from extruder gear to the ERCF [gcode_macro ERCF_EJECT_UNKNOW_STATE] description: Unload filament from an unknown position gcode: M118 Eject Filament if loaded ... {% if printer['filament_switch_sensor toolhead_sensor'].filament_detected == True %} M118 Filament in extruder, trying to eject it .. {% if printer['extruder'].temperature < 178 %} M118 Preheat Nozzle M109 S{printer["gcode_macro ERCF_VAR"].extruder_eject_temp} {% endif %} ERCF_UNLOAD_FILAMENT_IN_EXTRUDER_WITH_TIP_FORMING ERCF_UNLOAD LENGTH={printer["gcode_macro ERCF_VAR"].min_bowden_length - 50} UNKNOWN=1 {% else %} ERCF_SERVO_DOWN {% endif %} ERCF_BUZZ_GEAR_MOTOR G4 P200 ERCF_EJECT_FROM_BOWDEN # Eject from the bowden to the ERCF [gcode_macro ERCF_EJECT_FROM_BOWDEN] description: Unload filament from the reverse bowden gcode: {% if printer.ercf.encoder_pos|float != 0 %} ERCF_UNLOAD HOMING=1 M118 Filament ejected ! {% else %} M118 Filament already ejected ! {% endif %} ERCF_SERVO_UP ############################################ # Homing macros # ERCF_HOME must be called before using the ERCF ############################################ # Home the ERCF # eject filament if loaded with ERCF_EJECT_UNKNOW_STATE # next home the ERCF with ERCF_HOME_ONLY [gcode_macro ERCF_HOME] description: Home the ERCF variable_home: -1 gcode: SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=0 SET_GCODE_VARIABLE MACRO=ERCF_HOME VARIABLE=home VALUE=1 {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 1 %} ERCF_UNLOCK {% endif %} M118 Homing ERCF ... QUERY_ENDSTOPS ERCF_EJECT_UNKNOW_STATE ERCF_HOME_SELECTOR ERCF_HOME_ONLY [gcode_macro ERCF_HOME_SELECTOR] description: Home the ERCF selector gcode: M118 Homing selector ERCF_SERVO_UP {% set number_of_chan=printer["gcode_macro ERCF_VAR"].colorselector|length %} {% set selector_length=(20.0 + number_of_chan*21.0 + (number_of_chan/3)*5.0) %} MANUAL_STEPPER STEPPER=selector_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=selector_stepper SPEED=100 MOVE=-{selector_length|float} STOP_ON_ENDSTOP=1 MANUAL_STEPPER STEPPER=selector_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=selector_stepper SPEED=100 MOVE=5.0 MANUAL_STEPPER STEPPER=selector_stepper SPEED=10 MOVE=-10.0 STOP_ON_ENDSTOP=1 MANUAL_STEPPER STEPPER=selector_stepper SET_POSITION=0 SET_GCODE_VARIABLE MACRO=ERCF_SELECT_TOOL VARIABLE=tool_selected VALUE=-1 SET_GCODE_VARIABLE MACRO=ERCF_SELECT_TOOL VARIABLE=color_selected VALUE=-1 # Home the ERCF: # 1) home the color selector (if needed) # 2) try to load filament 0 to ERCF and then unload it. Used to verify the ERCF gear # if all is ok, the ERCF is ready to be used [gcode_macro ERCF_HOME_ONLY] gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} M118 Test load filament 1 ERCF_SELECT_TOOL TOOL=0 ERCF_SET_STEPS RATIO=1.0 M118 Loading filament to ERCF... ERCF_LOAD LENGTH=45 G4 P50 ERCF_UNLOAD LENGTH=68 ERCF_UNSELECT_TOOL SET_GCODE_VARIABLE MACRO=ERCF_HOME VARIABLE=home VALUE=1 M118 Homing ERCF ended ... {% else %} M118 Homing ERCF failed, ERCF is paused, run "ERCF_UNLOCK" to unlock it ... {% endif %} ############################################### # Test Macros ############################################### [gcode_macro ERCF_DISPLAY_ENCODER_POS] description: Display current value of the ERCF encoder gcode: M118 Encoder value is {printer['ercf'].encoder_pos|float} [gcode_macro ERCF_TEST_MOVE_GEAR] description: Move the ERCF gear gcode: {% set move_length = params.LENGTH|default(200.0)|float %} {% set move_speed = params.SPEED|default(50.0)|float %} {% set move_accel = params.ACCEL|default(200.0)|float %} MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=gear_stepper MOVE={move_length|float} SPEED={move_speed|float} ACCEL={move_accel|float} [gcode_macro ERCF_TEST_SERVO] description: Test the servo angle gcode: SET_SERVO SERVO=ercf_servo ANGLE={params.VALUE|float} G4 P250 SET_SERVO SERVO=ercf_servo WIDTH=0.0 [gcode_macro ERCF_TEST_GRIP] description: Test the ERCF grip for a Tool gcode: ERCF_SERVO_DOWN ERCF_MOTORS_OFF [gcode_macro ERCF_TEST_LOAD_SEQUENCE] description: Test sequence gcode: {% set loop_number = params.LOOP|default(10)|int %} {% set use_rand = params.RAND|default(0)|int %} {% for iteration in range(loop_number|int) %} {% for load in range((printer["gcode_macro ERCF_VAR"].colorselector|length)|int) %} {% if use_rand|int == 1 %} ERCF_SELECT_TOOL TOOL={range(0, printer["gcode_macro ERCF_VAR"].colorselector|length)|random} {% else %} ERCF_SELECT_TOOL TOOL={load|int} {% endif %} ERCF_LOAD LENGTH=100 G4 P50 ERCF_UNLOAD LENGTH=100 ERCF_UNSELECT_TOOL G4 P200 {% endfor %} {% endfor %} ############################################### # Endless spool mode and clog detection ############################################### [gcode_macro ERCF_ENCODER_MOTION_ISSUE] description: Perform a test when the encoder sense an issue (clog or runout) gcode: M118 Issue on tool {printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int} M118 Checking if this is a clog or a runout... SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=0 ERCF_SERVO_DOWN ERCF_BUZZ_GEAR_MOTOR ERCF_SERVO_UP ERCF_CLOG_OR_RUNOUT [gcode_macro ERCF_CLOG_OR_RUNOUT] description: Actions taken if a clog or a runout is detected by the ERCF encoder gcode: {% if printer.ercf.encoder_pos|float != 0 %} M118 Clog detected, please check the ERCF and the printer {% else %} M118 Runout detected ! {% if printer["gcode_macro ERCF_VAR"].endless_spool_mode|int == 1 %} {% if printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int >= (printer["gcode_macro ERCF_VAR"].colorselector|length -1) %} {% set nexttool = 0 %} {% else %} {% set nexttool = (printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|int + 1) %} {% endif %} M118 Loading tool {nexttool|int} SAVE_GCODE_STATE NAME=ERCF_Pre_Brush_init # Adapt the example below to your own setup # The goal is just to clean the nozzle after the change # In my case I have a purge bucket with a brush # G0 X45 Y300 F18000 # G0 X45 Y310 Z1 F3000 # Custom unload sequence M118 Forming filament tip and Unloading Filament... G91 ERCF_FORM_TIP_STANDALONE ERCF_HOME_EXTRUDER TOTAL_LENGTH={printer["gcode_macro ERCF_VAR"].sensor_to_nozzle} STEP_LENGTH=2.0 ERCF_SERVO_DOWN G91 G92 E0 MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0 MANUAL_STEPPER STEPPER=gear_stepper MOVE=-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float} SPEED=25 ACCEL=0 SYNC=0 G1 E-{printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float} F1500.0 {% set ercf_params = printer.save_variables.variables %} ERCF_SET_STEPS RATIO={ercf_params['ercf_calib_%s' % (printer["gcode_macro ERCF_SELECT_TOOL"].color_selected|string)]} ERCF_UNLOAD LENGTH={ercf_params.ercf_calib_ref|float - printer["gcode_macro ERCF_VAR"].end_of_bowden_to_sensor|float + printer["gcode_macro ERCF_VAR"].unload_modifier|float} ERCF_UNSELECT_TOOL ERCF_LOAD_TOOL TOOL={nexttool|int} ERCF_CHECK_IF_RESUME {% else %} M118 EndlessSpool mode not enabled, please do something {% endif %} {% endif %} [gcode_macro ERCF_CHECK_IF_RESUME] description: Safety checks before resuming the print after an encoder event gcode: {% if printer["gcode_macro ERCF_PAUSE"].is_paused|int == 0 %} # Adapt the example below to your own setup # The goal is just to clean the nozzle after the change # In my case I have a purge bucket with a brush # BRUSH_PURGE LENGTH=50 # BRUSH_CLEAN RESTORE_GCODE_STATE NAME=ERCF_Pre_Brush_init RESUME {% if printer["gcode_macro ERCF_VAR"].clog_detection|int == 1 %} SET_FILAMENT_SENSOR SENSOR=encoder_sensor ENABLE=1 {% endif %} {% endif %}