================================================================ System Information ================================================================ Distro: PRETTY_NAME="Debian GNU/Linux 12 (bookworm)" NAME="Debian GNU/Linux" VERSION_ID="12" VERSION="12 (bookworm)" VERSION_CODENAME=bookworm ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/" Kernel: Linux v202 6.12.25+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.12.25-1+rpt1 (2025-04-30) aarch64 GNU/Linux Uptime: 21:18:36 up 11 min, 2 users, load average: 0.74, 0.96, 0.61 ================================================================ Versions ================================================================ AFC Version: 1410-6ba66e6 Klipper Version: v0.13.0-91-gca83c13f3 ================================================================ lsusb output ================================================================ Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 007: ID 04d8:e72b Microchip Technology, Inc. Beacon RevH Bus 001 Device 005: ID 1d50:614e OpenMoko, Inc. rp2040 Bus 001 Device 004: ID 1d50:614e OpenMoko, Inc. stm32h743xx Bus 001 Device 008: ID 1d50:614e OpenMoko, Inc. stm32h723xx Bus 001 Device 006: ID a108:2240 Ingenic Semiconductor Co.,Ltd UVC Camera Bus 001 Device 003: ID 14cd:8601 Super Top 4-Port hub Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub ================================================================ Serial IDs ================================================================ total 0 lrwxrwxrwx 1 root root 13 May 31 17:27 usb-Beacon_Beacon_RevH_E2A2B07F5157355957202020FF11170A-if00 -> ../../ttyACM2 lrwxrwxrwx 1 root root 13 May 31 17:27 usb-Klipper_rp2040_4E363334320B2A7A-if00 -> ../../ttyACM1 lrwxrwxrwx 1 root root 13 May 31 17:27 usb-Klipper_stm32h723xx_boxturt1-if00 -> ../../ttyACM3 lrwxrwxrwx 1 root root 13 May 31 17:27 usb-Klipper_stm32h743xx_21001F000751333038333637-if00 -> ../../ttyACM0 ================================================================ CAN Bus IDs ================================================================ No CAN devices found. ================================================================ AFC.var.unit ================================================================ { "Turtle_1": { "lane1": { "name": "lane1", "unit": "Turtle_1", "hub": "Turtle_1", "extruder": "extruder", "buffer": "Turtle_1", "buffer_status": "Advancing", "lane": 1, "map": "T0", "load": false, "prep": false, "tool_loaded": false, "loaded_to_hub": false, "material": null, "spool_id": "", "color": "", "weight": "", "extruder_temp": null, "runout_lane": "NONE", "filament_status": "Not Ready", "filament_status_led": "#ff0000", "status": null }, "lane2": { "name": "lane2", "unit": "Turtle_1", "hub": "Turtle_1", "extruder": "extruder", "buffer": "Turtle_1", "buffer_status": "Advancing", "lane": 2, "map": "T1", "load": false, "prep": false, "tool_loaded": false, "loaded_to_hub": false, "material": null, "spool_id": "", "color": "", "weight": "", "extruder_temp": null, "runout_lane": "NONE", "filament_status": "Not Ready", "filament_status_led": "#ff0000", "status": null }, "lane3": { "name": "lane3", "unit": "Turtle_1", "hub": "Turtle_1", "extruder": "extruder", "buffer": "Turtle_1", "buffer_status": "Advancing", "lane": 3, "map": "T2", "load": false, "prep": false, "tool_loaded": false, "loaded_to_hub": false, "material": null, "spool_id": null, "color": null, "weight": null, "extruder_temp": null, "runout_lane": "NONE", "filament_status": "Not Ready", "filament_status_led": "#ff0000", "status": null }, "lane4": { "name": "lane4", "unit": "Turtle_1", "hub": "Turtle_1", "extruder": "extruder", "buffer": "Turtle_1", "buffer_status": "Advancing", "lane": 4, "map": "T3", "load": false, "prep": false, "tool_loaded": false, "loaded_to_hub": false, "material": null, "spool_id": "", "color": "", "weight": "", "extruder_temp": null, "runout_lane": "NONE", "filament_status": "Not Ready", "filament_status_led": "#ff0000", "status": null } }, "system": { "current_load": null, "num_units": 1, "num_lanes": 4, "num_extruders": 1, "extruders": { "extruder": { "lane_loaded": null } }, "bypass": { "enabled": false } } } ================================================================ AFC_macros.cfg ================================================================ # Eject Loaded Lane [gcode_macro BT_TOOL_UNLOAD] description: Unloads the currently loaded lane gcode: TOOL_UNLOAD [gcode_macro BT_CHANGE_TOOL] description: Switch to a new lane by ejecting the previously loaded one and then load the lane specified by LANE parameter. Lane parameter is an integer and defaults to 1. ex. `BT_CHANGE_TOOL LANE=2` gcode: {% set lane_num = params.LANE|default(1)|int %} {% set stepper = printer['gcode_macro _AFC_GLOBAL_VARS'].stepper_name|string %} CHANGE_TOOL LANE={stepper ~ lane_num} [gcode_macro BT_LANE_EJECT] description: Fully eject the filament from the lane so spool can be removed. Lane parameter is an integer and defaults to 1. ex. `BT_LANE_EJECT LANE=2` gcode: {% set lane_num = params.LANE|default(1)|int %} {% set stepper = printer['gcode_macro _AFC_GLOBAL_VARS'].stepper_name|string %} LANE_UNLOAD LANE={stepper ~ lane_num} [gcode_macro BT_LANE_MOVE] description: Move the specified lane the specified amount. Lane parameter is an integer and defaults to 1. Distance parameter is and integer and defaults to 20. Distance over 200 uses long load speeds. ex `BT_LANE_MOVE LANE=2 DISTANCE=100` gcode: {% set lane_num = params.LANE|default(1)|int %} {% set dist_str = params.DISTANCE|default('20')|string %} {% set stepper = printer['gcode_macro _AFC_GLOBAL_VARS'].stepper_name|string %} {% set valid_chars = '0123456789' %} {% set is_valid = true %} {% if dist_str|length > 0 %} {% if dist_str[-1] not in valid_chars %} {% set is_valid = false %} {% endif %} {% else %} {% set is_valid = false %} {% endif %} {% if is_valid %} {% set dist = dist_str|float %} LANE_MOVE LANE={stepper ~ lane_num} DISTANCE={dist} {% else %} { action_respond_info("Error: Invalid DISTANCE parameter: " ~ dist_str) } {% endif %} [gcode_macro BT_RESUME] description: Resume the print after an error, using normal resume will also call AFC_RESUME gcode: {% if not printer.pause_resume.is_paused %} RESPOND MSG="Print is not paused. Resume ignored" {% else %} AFC_RESUME {% endif %} [gcode_macro BT_PREP] description: Run the AFC PREP sequence gcode: PREP ================================================================ Brush.cfg ================================================================ [gcode_macro AFC_BRUSH] description: Wipe the nozzle on the brush gcode: {% set gVars = printer['gcode_macro _AFC_GLOBAL_VARS'] %} {% set accel = gVars['accel']|float %} {% set travel_speed = gVars['travel_speed'] * 60|float %} {% set z_travel_speed = gVars['z_travel_speed'] * 60|float %} {% set verbose = gVars['verbose']|int %} {% set vars = printer['gcode_macro _AFC_BRUSH_VARS'] %} {% set Bx, By, Bz = vars.brush_loc|map('float') %} {% set brush_clean_accel = vars['brush_clean_accel']|float %} {% set y_brush = vars['y_brush']|default(false)|lower == 'true' %} {% set brush_clean_speed = vars['brush_clean_speed'] * 60|float %} {% set brush_width = vars['brush_width']|float %} {% set brush_depth = vars['brush_depth']|float %} {% set brush_count = vars['brush_count']|int %} {% set z_move = vars['z_move'] |float %} # Get printer bounds to make sure none of our cleaning moves fall outside of them # Check for IDEX {% if printer.dual_carriage is defined %} {% if printer.dual_carriage.carriage_0 == "INACTIVE" %} # Carriage_1 is active, use its axis limits {% set x_max = printer.configfile.config.dual_carriage.position_max|float|round(3) %} {% set x_min = printer.configfile.config.dual_carriage.position_min|float|round(3) %} {% else %} # Carriage_0 is active, use its axis limits {% set x_max = printer.toolhead.axis_maximum.x %} {% set x_min = printer.toolhead.axis_minimum.x %} {% endif %} {% else %} # Non-IDEX printer, grab the X axis limits {% set x_max = printer.toolhead.axis_maximum.x %} {% set x_min = printer.toolhead.axis_minimum.x %} {% endif %} {% set y_max = printer.toolhead.axis_maximum.y %} {% set y_min = printer.toolhead.axis_minimum.y %} # Get min and max positions for brush moves {% set brush_x_max = Bx + brush_width / 2 %} {% set brush_x_min = Bx - brush_width / 2 %} {% set brush_y_max = By + brush_depth / 2 %} {% set brush_y_min = By - brush_depth / 2 %} # Set the cleaning acceleration prior to any movement {% set saved_accel = printer.toolhead.max_accel %} # Check if macro accel is defined {% if brush_clean_accel > 0 %} {% set selected_accel = brush_clean_accel %} {% else %} {% set selected_accel = accel %} {% endif %} SET_VELOCITY_LIMIT ACCEL={selected_accel} {% if verbose > 0 %} RESPOND TYPE=command MSG='AFC_Brush: Clean Nozzle' {% endif %} # Move to center of the brush {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Brush: Move to Brush.' {% endif %} G90 G1 X{Bx} Y{By} F{travel_speed} {% if Bz >= 0 %} G1 Z{Bz} F{z_travel_speed} {% endif %} # Wipe procedure {% if y_brush %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Brush: Y Brush Moves' {% endif %} {% for wipe in range(brush_count) %} {% if brush_y_min >= y_min %} G1 Y{brush_y_min} F{brush_clean_speed} {% endif %} {% if brush_y_max <= y_max %} G1 Y{brush_y_max} F{brush_clean_speed} {% endif %} G1 Y{By} F{brush_clean_speed} {% endfor %} {% endif %} # Brush procedure {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Brush: X Brush Moves' {% endif %} {% for wipe in range(brush_count) %} {% if brush_x_min >= x_min %} G1 X{brush_x_min} F{brush_clean_speed} {% endif %} {% if brush_x_max <= x_max %} G1 X{brush_x_max} F{brush_clean_speed} {% endif %} G1 X{Bx} F{brush_clean_speed} {% endfor %} {% if z_move >= 0 %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Brush: Finish z_move.' {% endif %} G91 G1 Z{z_move} F{z_travel_speed} G90 {% endif %} G90 # Reset acceleration values to what it was before SET_VELOCITY_LIMIT ACCEL={saved_accel} ================================================================ Kick.cfg ================================================================ [gcode_macro AFC_KICK] gcode: {% set gVars = printer['gcode_macro _AFC_GLOBAL_VARS'] %} {% set accel = gVars['accel']|float %} {% set travel_speed = gVars['travel_speed'] * 60|float %} {% set z_travel_speed = gVars['z_travel_speed'] * 60|float %} {% set verbose = gVars['verbose']|int %} {% set vars = printer['gcode_macro _AFC_KICK_VARS'] %} {% set kick_start_x, kick_start_y, kick_start_z = vars.kick_start_loc|map('float') %} {% set kick_z = vars['kick_z']|float %} {% set kick_direction = vars['kick_direction']|default('')|lower %} {% set kick_move_dist = vars['kick_move_dist']|float %} {% set z_after_kick = vars['z_after_kick']|float %} {% set kick_speed = vars['kick_speed'] * 60|float %} {% set kick_accel = vars['kick_accel']|float %} # Get printer bounds to make sure none of our kick moves fall outside of them # Check for IDEX {% if printer.dual_carriage is defined %} {% if printer.dual_carriage.carriage_0 == "INACTIVE" %} # Carriage_1 is active, use its axis limits {% set x_max = printer.configfile.config.dual_carriage.position_max|float|round(3) %} {% set x_min = printer.configfile.config.dual_carriage.position_min|float|round(3) %} {% else %} # Carriage_0 is active, use its axis limits {% set x_max = printer.toolhead.axis_maximum.x %} {% set x_min = printer.toolhead.axis_minimum.x %} {% endif %} {% else %} # Non-IDEX printer, grab the X axis limits {% set x_max = printer.toolhead.axis_maximum.x %} {% set x_min = printer.toolhead.axis_minimum.x %} {% endif %} {% set y_max = printer.toolhead.axis_maximum.y %} {% set y_min = printer.toolhead.axis_minimum.y %} # Save current Accel {% set saved_accel = printer.toolhead.max_accel %} # Check if macro accel is defined {% if kick_accel > 0 %} {% set selected_accel = kick_accel %} {% else %} {% set selected_accel = accel %} {% endif %} SET_VELOCITY_LIMIT ACCEL={selected_accel} {% if verbose > 0 %} RESPOND TYPE=command MSG='AFC_Kick: Starting Filament Kick' {% endif %} # Kick macro expects absolute mode, so make sure we are in that G90 {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Kick: Move to Start Position' {% endif %} G1 Z{kick_start_z} F{z_travel_speed} G1 X{kick_start_x} Y{kick_start_y} F{travel_speed} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Kick: Drop Z For Kick Move' {% endif %} {% if kick_z > 0 %} G1 Z{kick_z} F{z_travel_speed} {% else %} RESPOND TYPE=command MSG='AFC-KICK: kick_z value to low. Please adjust in AFC_Macro_Vars.cfg. Defaulting to 0.5mm z-height' G1 Z0.5 F{z_travel_speed} {% endif %} {% set location_factor = { 'left' : { 'x': -1, 'y': 0 }, 'right' : { 'x': 1, 'y': 0 }, 'front' : { 'x': 0, 'y': -1 }, 'back' : { 'x': 0, 'y': 1 } } %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Kick: Kick filament' {% endif %} {% if kick_direction == "left" or kick_direction == "right" %} {% if (kick_start_x + location_factor[kick_direction].x * kick_move_dist) > x_max or (kick_start_x + location_factor[kick_direction].x * kick_move_dist) < x_min %} { action_raise_error("X Kick move is outside your printer bounds. Check the kick_move_dist in your AFC_Macro_Vars.cfg file!") } {% else %} G1 X{kick_start_x + location_factor[kick_direction].x * kick_move_dist} F{kick_speed} {% endif %} {% elif kick_direction == "front" or kick_direction == "back" %} {% if (kick_start_y + location_factor[kick_direction].y * kick_move_dist) > y_max or (kick_start_y + location_factor[kick_direction].y * kick_move_dist) < y_min %} { action_raise_error("Y Kick move is outside your printer bounds. Check the kick_move_dist in your AFC_Macro_Vars.cfg file!") } {% else %} G1 Y{kick_start_y + location_factor[kick_direction].y * kick_move_dist} F{kick_speed} {% endif %} {% else %} { action_raise_error("Error in kick movement. Check the directions in your AFC_Macro_Vars.cfg file!") } {% endif %} G1 Z{z_after_kick} F{z_travel_speed} # Reset acceleration values to what it was before SET_VELOCITY_LIMIT ACCEL={saved_accel} ================================================================ Cut.cfg ================================================================ [gcode_macro AFC_CUT] description: Cut filament by pressing the cutter on a pin gcode: {% set gVars = printer['gcode_macro _AFC_GLOBAL_VARS'] %} {% set accel = gVars['accel']|float %} {% set travel_speed = gVars['travel_speed'] * 60|float %} {% set verbose = gVars['verbose']|int %} {% set vars = printer['gcode_macro _AFC_CUT_TIP_VARS'] %} {% set pin_loc_x, pin_loc_y = vars.pin_loc_xy|map('float') %} {% set pin_park_dist = vars['pin_park_dist']|float %} {% set retract_length = vars['retract_length']|float %} {% set quick_tip_forming = vars['quick_tip_forming']|default(true)|lower == 'true' %} {% set rip_length = vars['rip_length']|float %} {% set cut_direction = vars['cut_direction']|default('')|lower %} {% set cut_accel = vars['cut_accel']|float %} {% set pushback_length = vars['pushback_length']|float %} {% set pushback_dwell_time = vars['pushback_dwell_time']|int %} {% set extruder_move_speed = vars['extruder_move_speed'] * 60|float %} {% set restore_position = vars['restore_position']|default(true)|lower == 'true' %} {% set cut_count = vars['cut_count']|int %} {% set y_cut = vars['y_cut']|default(false)|lower == 'true' %} {% set awd = vars['awd']|default(false)|lower == 'true' %} {% set cut_current_x = vars['cut_current_stepper_x']|default(0)|float %} {% set cut_current_dc = vars['cut_current_dual_carriage']|default(0)|float %} {% set cut_current_y = vars['cut_current_stepper_y']|default(0)|float %} {% set cut_current_z = vars['cut_current_stepper_z']|default(0)|float %} {% if verbose > 0 %} RESPOND TYPE=command MSG='AFC_Cut: Cut Filament' {% endif %} {% set location_factor = { 'left' : { 'x': 1, 'y': 0 }, 'right' : { 'x': -1, 'y': 0 }, 'front' : { 'x': 0, 'y': 1 }, 'back' : { 'x': 0, 'y': -1 } } %} # Add safe move distance to x or y depending on cut type {% if cut_direction == "left" or cut_direction == "right" %} {% set pin_park_x_loc = pin_loc_x + location_factor[cut_direction].x * pin_park_dist %} {% set pin_park_y_loc = pin_loc_y %} {% elif cut_direction == "front" or cut_direction == "back" %} {% set pin_park_x_loc = pin_loc_x %} {% set pin_park_y_loc = pin_loc_y + location_factor[cut_direction].y * pin_park_dist %} {% else %} { action_raise_error("Invalid cut direction. Check the cut_direction in your AFC_Macro_Vars.cfg file!") } {% endif %} # Track total extruder move dist for future use {% set _extruder_moved_dist = 0 %} {% if "xy" not in printer.toolhead.homed_axes %} G28 X Y {% endif %} SAVE_GCODE_STATE NAME=_AFC_CUT # Save current Accel {% set saved_accel = printer.toolhead.max_accel %} # Check if macro accel is defined {% if cut_accel > 0 %} {% set selected_accel = cut_accel %} {% else %} {% set selected_accel = accel %} {% endif %} SET_VELOCITY_LIMIT ACCEL={selected_accel} {% set prev_pa = printer.extruder.pressure_advance %} # Save current PA SET_PRESSURE_ADVANCE ADVANCE=0 # Temporarily disable PA G90 # Absolute positioning M83 # Relative extrusion G92 E0 {% if retract_length > 0 %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Cut: Retract Filament for Cut' {% endif %} # Retract to save filament waste, repeat to allow some cooling G1 E-{retract_length} F{extruder_move_speed} {% if quick_tip_forming %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Cut: Performing Quick Tip Form' {% endif %} G1 E{retract_length / 2} F{extruder_move_speed} G1 E-{retract_length / 2} F{extruder_move_speed} {% endif %} {% set _extruder_moved_dist = _extruder_moved_dist + retract_length %} {% endif %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Cut: Move to Cut Pin Location' {% endif %} _MOVE_TO_CUTTER_PIN PIN_PARK_X_LOC={pin_park_x_loc} PIN_PARK_Y_LOC={pin_park_y_loc} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Cut: Cut Move...' {% endif %} {% if cut_current_x > 0 or cut_current_dc > 0 %} # Check for IDEX {% if printer.dual_carriage is defined %} {% if printer.dual_carriage.carriage_0 == "INACTIVE" %} # Second toolhead in use {% set conf_name = vars['conf_name_dual_carriage']|default('tmc2209 dual_carriage') %} {% set conf_current_dc = printer.configfile.settings[conf_name].run_current|float %} SET_TMC_CURRENT STEPPER=dual_carriage CURRENT={cut_current_dc} {% else %} # First toolhead in use {% set conf_name = vars['conf_name_stepper_x']|default('tmc2209 stepper_x') %} {% set conf_current_x = printer.configfile.settings[conf_name].run_current|float %} SET_TMC_CURRENT STEPPER=stepper_x CURRENT={cut_current_x} {% endif %} {% else %} # Not running on IDEX, do normal things {% set conf_name = vars['conf_name_stepper_x']|default('tmc2209 stepper_x') %} {% set conf_current_x = printer.configfile.settings[conf_name].run_current|float %} SET_TMC_CURRENT STEPPER=stepper_x CURRENT={cut_current_x} {% if awd %} SET_TMC_CURRENT STEPPER=stepper_x1 CURRENT={cut_current_x} {% endif %} {% endif %} {% endif %} {% if cut_current_y > 0 %} {% set conf_name = vars['conf_name_stepper_y']|default('tmc2209 stepper_y') %} {% set conf_current_y = printer.configfile.settings[conf_name].run_current|float %} SET_TMC_CURRENT STEPPER=stepper_y CURRENT={cut_current_y} {% if awd %} SET_TMC_CURRENT STEPPER=stepper_y1 CURRENT={cut_current_y} {% endif %} {% endif %} {% if cut_current_z > 0 %} {% set conf_name = vars['conf_name_stepper_z']|default('tmc2209 stepper_z') %} {% set conf_current_z = printer.configfile.settings[conf_name].run_current|float %} SET_TMC_CURRENT STEPPER=stepper_z CURRENT={cut_current_z} {% endif %} {% for cut in range(cut_count - 1) %} _DO_CUT_MOTION PIN_PARK_X_LOC={pin_park_x_loc} PIN_PARK_Y_LOC={pin_park_y_loc} RIP_LENGTH=0 {% endfor %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Cut: Final Cut...' {% endif %} # Do a rip on final cut pass _DO_CUT_MOTION PIN_PARK_X_LOC={pin_park_x_loc} PIN_PARK_Y_LOC={pin_park_y_loc} RIP_LENGTH={rip_length} {% if cut_current_x > 0 or cut_current_dc > 0 %} # Check for IDEX {% if printer.dual_carriage is defined %} {% if printer.dual_carriage.carriage_0 == "INACTIVE" %} # Second toolhead in use SET_TMC_CURRENT STEPPER=dual_carriage CURRENT={conf_current_dc} {% else %} # First toolhead in use SET_TMC_CURRENT STEPPER=stepper_x CURRENT={conf_current_x} {% endif %} {% else %} # Not running on IDEX, do normal things SET_TMC_CURRENT STEPPER=stepper_x CURRENT={conf_current_x} {% if awd %} SET_TMC_CURRENT STEPPER=stepper_x1 CURRENT={conf_current_x} {% endif %} {% endif %} {% endif %} {% if cut_current_y > 0 %} SET_TMC_CURRENT STEPPER=stepper_y CURRENT={conf_current_y} {% if awd %} SET_TMC_CURRENT STEPPER=stepper_y1 CURRENT={conf_current_y} {% endif %} {% endif %} {% if cut_current_z > 0 %} SET_TMC_CURRENT STEPPER=stepper_z CURRENT={conf_current_z} {% endif %} {% set _extruder_moved_dist = _extruder_moved_dist + rip_length %} # Optionally pushback of the cut piece into the hotend to avoid potential clog {% if pushback_length > 0 %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Cut: Push cut tip back into hotend' {% endif %} G1 E{pushback_length} F{extruder_move_speed} G4 P{pushback_dwell_time} G1 E-{pushback_length} F{extruder_move_speed} {% set _extruder_moved_dist = _extruder_moved_dist - pushback_length %} {% endif %} SET_PRESSURE_ADVANCE ADVANCE={prev_pa} # Restore PA # Reset acceleration values to what it was before SET_VELOCITY_LIMIT ACCEL={saved_accel} # Restore state and optionally position RESTORE_GCODE_STATE NAME=_AFC_CUT MOVE={1 if restore_position else 0} MOVE_SPEED={travel_speed} #--=================================================================================- #------- Helper macro for tip cutting ----------------------------------------------- #--=================================================================================- [gcode_macro _MOVE_TO_CUTTER_PIN] description: Helper to move the toolhead to the target pin in either safe or faster way, depending on toolhead clearance gcode: {% set pin_park_x_loc = params.PIN_PARK_X_LOC|float %} {% set pin_park_y_loc = params.PIN_PARK_Y_LOC|float %} {% set gVars = printer['gcode_macro _AFC_GLOBAL_VARS'] %} {% set travel_speed = gVars['travel_speed'] * 60|float %} {% set vars = printer['gcode_macro _AFC_CUT_TIP_VARS'] %} {% set safe_margin_x, safe_margin_y = vars.safe_margin_xy|map('float') %} {% if ((printer.gcode_move.gcode_position.x - pin_park_x_loc)|abs < safe_margin_x) or ((printer.gcode_move.gcode_position.y - pin_park_y_loc)|abs < safe_margin_y) %} # Make a safe but slower travel move G1 X{pin_park_x_loc} F{travel_speed} G1 Y{pin_park_y_loc} F{travel_speed} {% else %} G1 X{pin_park_x_loc} Y{pin_park_y_loc} F{travel_speed} {% endif %} #--=================================================================================- #------- Helper macro for tip cutting ----------------------------------------------- #--=================================================================================- [gcode_macro _DO_CUT_MOTION] description: Helper to do a single horizontal cut movement gcode: {% set pin_park_x_loc = params.PIN_PARK_X_LOC|float %} {% set pin_park_y_loc = params.PIN_PARK_Y_LOC|float %} {% set rip_length = params.RIP_LENGTH|float %} {% set vars = printer['gcode_macro _AFC_CUT_TIP_VARS'] %} {% set cut_move_dist = vars['cut_move_dist']|float %} {% set cut_direction = vars['cut_direction']|default('')|lower %} {% set cut_fast_move_fraction = vars['cut_fast_move_fraction']|float %} {% set pin_park_dist = vars['pin_park_dist']|float %} {% set cut_fast_move_speed = vars['cut_fast_move_speed'] * 60|float %} {% set cut_slow_move_speed = vars['cut_slow_move_speed'] * 60|float %} {% set cut_dwell_time = vars['cut_dwell_time']|float %} {% set evacuate_speed = vars['evacuate_speed'] * 60|float %} {% set rip_speed = vars['rip_speed'] * 60|float %} # Get printer bounds to make sure none of our cut moves fall outside of them # Check for IDEX {% if printer.dual_carriage is defined %} {% if printer.dual_carriage.carriage_0 == "INACTIVE" %} # Carriage_1 is active, use its axis limits {% set x_max = printer.configfile.config.dual_carriage.position_max|float|round(3) %} {% set x_min = printer.configfile.config.dual_carriage.position_min|float|round(3) %} {% else %} # Carriage_0 is active, use its axis limits {% set x_max = printer.toolhead.axis_maximum.x %} {% set x_min = printer.toolhead.axis_minimum.x %} {% endif %} {% else %} # Non-IDEX printer, grab the X axis limits {% set x_max = printer.toolhead.axis_maximum.x %} {% set x_min = printer.toolhead.axis_minimum.x %} {% endif %} {% set y_max = printer.toolhead.axis_maximum.y %} {% set y_min = printer.toolhead.axis_minimum.y %} # Add the safe park distance to the cut move {% set cut_dist = cut_move_dist + pin_park_dist %} {% set location_factor = { 'left' : { 'x': -1, 'y': 0 }, 'right' : { 'x': 1, 'y': 0 }, 'front' : { 'x': 0, 'y': -1 }, 'back' : { 'x': 0, 'y': 1 } } %} {% if cut_direction == "left" or cut_direction == "right" %} {% set fast_slow_transition_loc_x = pin_park_x_loc + location_factor[cut_direction].x * (cut_dist * cut_fast_move_fraction)| float %} {% set full_cut_loc_x = pin_park_x_loc + location_factor[cut_direction].x * cut_dist| float %} {% if full_cut_loc_x > x_max or full_cut_loc_x < x_min %} { action_raise_error("X Cut move is outside your printer bounds. Check the cut_move_dist in your AFC_Macro_Vars.cfg file!") } {% else %} G1 X{fast_slow_transition_loc_x} F{cut_fast_move_speed} # Fast move to initiate contact of the blade with filament G1 X{full_cut_loc_x} F{cut_slow_move_speed} # Do the cut in slow move G4 P{cut_dwell_time} {% if rip_length > 0 %} G1 E-{rip_length} F{rip_speed} {% endif %} G4 P200 G1 X{pin_park_x_loc} F{evacuate_speed} # Evacuate G4 P200 {% endif %} {% elif cut_direction == "front" or cut_direction == "back" %} {% set fast_slow_transition_loc_y = pin_park_y_loc + location_factor[cut_direction].y * (cut_dist * cut_fast_move_fraction)| float %} {% set full_cut_loc_y = pin_park_y_loc + location_factor[cut_direction].y * cut_dist| float %} {% if full_cut_loc_y > y_max or full_cut_loc_y < y_min %} { action_raise_error("Y Cut move is outside your printer bounds. Check the cut_move_dist in your AFC_Macro_Vars.cfg file!") } {% else %} G1 Y{fast_slow_transition_loc_y} F{cut_fast_move_speed} # Fast move to initiate contact of the blade with filament G1 Y{full_cut_loc_y} F{cut_slow_move_speed} # Do the cut in slow move G4 P{cut_dwell_time} {% if rip_length > 0 %} G1 E-{rip_length} F{rip_speed} {% endif %} G4 P200 G1 Y{pin_park_y_loc} F{evacuate_speed} # Evacuate G4 P200 {% endif %} {% else %} { action_raise_error("Invalid cut direction. Check the cut_direction in your AFC_Macro_Vars.cfg file!") } {% endif %} ================================================================ Park.cfg ================================================================ [gcode_macro AFC_PARK] gcode: {% set gVars = printer['gcode_macro _AFC_GLOBAL_VARS'] %} {% set travel_speed = gVars['travel_speed'] * 60|float %} {% set verbose = gVars['verbose']|int %} {% set z_travel_speed = gVars['z_travel_speed'] * 60|float %} {% set vars = printer['gcode_macro _AFC_PARK_VARS'] %} {% set Px, Py = vars.park_loc_xy|map('float') %} {% set Px = params.X|default(Px)|float %} {% set Py = params.Y|default(Py)|float %} {% set z_hop = vars['z_hop']|float %} {% set z_hop = params.Z_HOP|default(z_hop)|float %} {% set max_z = printer.toolhead.axis_maximum.z - printer.gcode_move.homing_origin.z |float %} {% set cur_z = printer.toolhead.position.z|float %} {% set z_safe = cur_z + z_hop %} {% if z_safe > max_z %} {% set z_safe = max_z %} {% endif %} {% if verbose > 0 %} RESPOND TYPE=command MSG='AFC_Park: Park Toolhead' {% endif %} G90 G1 Z{z_safe} F{z_travel_speed} G1 X{Px} Y{Py} F{travel_speed} ================================================================ Poop.cfg ================================================================ [gcode_macro AFC_POOP] variable_max_iteration_length: 40 variable_iteration_z_raise: 6 variable_iteration_z_change: 0.6 variable_max_iterations_per_blob: 3 variable_pressure_release_time: 1000 variable_purge_z: 0 gcode: {% set gVars = printer['gcode_macro _AFC_GLOBAL_VARS'] %} {% set travel_speed = gVars['travel_speed'] * 60|float %} {% set z_travel_speed = gVars['z_travel_speed'] * 60|float %} {% set verbose = gVars['verbose']|int %} {% set vars = printer['gcode_macro _AFC_POOP_VARS'] %} {% set purge_x, purge_y = vars.purge_loc_xy|map('float') %} {% set purge_spd = vars['purge_spd'] * 60|float %} {% set z_poop = vars['z_purge_move']|default(true)|lower == 'true' %} {% set fast_z = vars['fast_z'] * 60|float %} {% set z_lift = vars['z_lift']|float %} {% set part_cooling_fan = vars['part_cooling_fan']|default(true)|lower == 'true' %} {% set part_cooling_fan_speed = vars['part_cooling_fan_speed']|default(1.0)|float %} {% set purge_cool_time = vars['purge_cool_time'] * 1000|float %} {% set purge_length = vars['purge_length']|float %} {% set purge_length_minimum = vars['purge_length_minimum']|float %} {% set purge_start = vars['purge_start']|float %} {% set restore_position = vars['restore_position']|default(true)|lower == 'true' %} {% if verbose > 0 %} RESPOND TYPE=command MSG='AFC_Poop: Starting poop' {% endif %} SAVE_GCODE_STATE NAME=_AFC_POOPING {% if part_cooling_fan %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Poop: Set Cooling Fan to Full Speed' {% endif %} {% set backup_fan_speed = printer.fan.speed %} M106 S{(part_cooling_fan_speed * 255)|int} {% endif %} {% set backup_feedrate = printer.gcode_move.speed_factor %} M220 S100 {% if params.PURGE_LENGTH %} {% set purge_len = params.PURGE_LENGTH|float %} {% else %} {% set purge_len = purge_length %} {% endif %} # Apply purge minimum {% set purge_len = [purge_len, purge_length_minimum]|max %} G90 {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Poop: Move To Purge Location' {% endif %} G1 X{purge_x} Y{purge_y} F{travel_speed} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Poop: z_poop {z_poop}' {% endif %} {% if z_poop %} G1 Z{purge_z + purge_start} F{z_travel_speed} {% endif %} {% set iterations = (purge_len / max_iteration_length)|round(0, 'ceil')|int %} # Repeat the process until purge_len is reached {% for n in range(iterations) %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Poop: Purge Iteration {n}' {% endif %} # Calculate current iteration in current blob {% set step = n % max_iterations_per_blob %} {% if step == 0 %} {% if z_poop %} G1 Z{purge_z + purge_start} F{z_travel_speed} {% endif %} {% endif %} {% set purge_amount_left = purge_len - (max_iteration_length * n) %} {% set extrude_amount = [purge_amount_left, max_iteration_length]|min %} {% set extrude_ratio = extrude_amount / max_iteration_length %} G91 M83 {% set step_triangular = step * (step + 1) / 2 %} {% set z_raise_substract = purge_start if step == 0 else step_triangular * iteration_z_change %} {% set raise_z = (iteration_z_raise - z_raise_substract) * extrude_ratio %} {% set raise_z = [raise_z, 0]|max %} {% set duration = extrude_amount / purge_spd %} {% if z_poop %} {% set speed = raise_z / duration %} G1 Z{raise_z} E{extrude_amount} F{speed} {% else %} G1 E{extrude_amount} F{purge_spd} {% endif %} {% set max_iterations_reached = step == max_iterations_per_blob - 1 %} {% set purge_length_reached = purge_len - max_iteration_length * (n + 1) <= 0 %} {% if max_iterations_reached or purge_length_reached %} M83 G4 P{purge_cool_time} # Pause {% endif %} {% endfor %} G90 {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Poop: Fast Z Lift to keep poop from sticking' {% endif %} {% if z_poop %} G1 Z{z_lift} F{fast_z}21000 {% endif %} {% if verbose > 1 %} RESPOND TYPE=command MSG='AFC_Poop: Restore fan speed and feedrate' {% endif %} {% if part_cooling_fan %} M106 S{(backup_fan_speed * 255)|int} {% endif %} M220 S{(backup_feedrate * 100)|int} RESTORE_GCODE_STATE NAME=_AFC_POOPING MOVE={1 if restore_position else 0} ================================================================ AFC.cfg ================================================================ [AFC] VarFile: /home/pi/printer_data/config/AFC/AFC.var # Path to the variables file for AFC configuration. #--=================================================================================- #------- Speed ---------------------------------------------------------------------- #--=================================================================================- long_moves_speed: 150 # mm/s. Default value is 150mm/s. long_moves_accel: 250 # mm/s². Default value is 250mm/s². short_moves_speed: 50 # mm/s. Default value is 50mm/s. short_moves_accel: 300 # mm/s². Default value is 300mm/s². short_move_dis: 10 # Move distance for failsafe moves. Default is 10mm. #global_print_current: 0.6 # Uncomment to set stepper motors to a lower current while printing # This value can also be set per stepper with print_current: 0.6 enable_sensors_in_gui: True # Uncomment to show all sensor switches as filament sensors in mainsail/fluidd gui # this can also be set at individual levels in your config file default_material_temps: default: 235, PLA:210, ABS:235, ASA:235 # Default temperature to set extruder when loading/unloading lanes. # Material needs to be either manually set or uses material from spoolman if extruder temp is not # set in spoolman. Follow current format to add more #default_material_type: PLA # Default material type to assign to a spool once loaded into a lane load_to_hub: True # Fast loads filament to hub when inserted, set to False to disable. This is a global setting and can be overridden at AFC_stepper #moonraker_port: 7125 # Port to connect to when interacting with moonraker. Used when there are multiple moonraker/klipper instances on a single host assisted_unload: True # If True, the unload retract is assisted to prevent loose windings, especially on full spools. This can prevent loops from slipping off the spool. This is a global setting and can be overridden at the unit and stepper level. #pause_when_bypass_active: True # When True AFC pauses print when change tool is called and bypass is loaded #unload_on_runout: True # When True AFC will unload lane and then pause when runout is triggered and spool to swap to is not set(infinite spool) #debug: True # Setting to True turns on more debugging to show on console #--=================================================================================- #------- TRSYNC Values -------------------------------------------------------------- #--=================================================================================- #trsync_update: True # Uncomment this value to update Klipper's trsync value automatically #trsync_timeout: 0.05 # Uncomment this value if timeout needs to be greater than the default of 0.05 #trsync_single_timeout: 0.250 # Uncomment this value if single_timeout needs to be greater than the default of 0.250 #--=================================================================================- #------- Pause/Resume --------------------------------------------------------------- #--=================================================================================- z_hop: 5 # Height to move up before and after a tool change completes resume_speed: 120 # Speed mm/s of resume move. Set to 0 to use gcode speed resume_z_speed: 30 # Speed mm/s of resume move in Z. Set to 0 to use gcode speed #--=================================================================================- #------- LED Settings --------------------------------------------------------------- #--=================================================================================- led_name: AFC_Indicator # LED name from the [AFC_led] section in AFC_Hardware.cfg. led_fault: 1,0,0,0 # Fault color (R,G,B,W) 0 = off, 1 = full brightness. led_ready: 0,0.8,0,0 # Ready color (R,G,B,W) 0 = off, 1 = full brightness. led_not_ready: 1,0,0,0 # Not ready color (R,G,B,W) 0 = off, 1 = full brightness. led_loading: 1,1,1,0 # Loading color (R,G,B,W) 0 = off, 1 = full brightness. led_tool_loaded: 0,0,1,0 # Loaded color (R,G,B,W) 0 = off, 1 = full brightness. led_buffer_advancing: 0,0,1,0 # Buffer advancing color (R,G,B,W) 0 = off, 1 = full brightness. led_buffer_trailing: 0,1,0,0 # Buffer trailing color (R,G,B,W) 0 = off, 1 = full brightness. led_buffer_disable: 0,0,0,0.25 # Buffer disable color (R,G,B,W) 0 = off, 1 = full brightness. #--=================================================================================- #------- Macro Config --------------------------------------------------------------- #--=================================================================================- # Macro order of operation # - Load | - Unload # - Load Filament | - Cut # - Poop | - Park # - Wipe | or # - Kick | - Park # - Wipe | - Tip Form # - Print | # TOOL Cutting Settings tool_cut: True # Enable Cut macro. tool_cut_cmd: AFC_CUT # Cut macro name. # Park Settings park: True # Enable Park. park_cmd: AFC_PARK # Park macro name. # Poop Settings poop: True # Enable Poop. poop_cmd: AFC_POOP # Poop macro name. # Kick Settings kick: True # Enable Kick. kick_cmd: AFC_KICK # Kick macro name. # Wipe Settings wipe: True # Enable Wipe. wipe_cmd: AFC_BRUSH # Wipe macro name. # Form Tip Settings form_tip: False # Enable Tip Form. form_tip_cmd: AFC # AFC is default routine. Name to custom macro if you prefer #--=================================================================================- #------- Start-up ------------------------------------------------------------------- #--=================================================================================- [AFC_prep] enable: True # Enable the AFC Prep routine. [delayed_gcode welcome] initial_duration: 0.5 gcode: PREP [AFC_form_tip] #--=================================================================================- #------- Tip Forming --------------------------------------------------------------- #--=================================================================================- # This is the initial press of the filament into the tip before any cooling moves. ramming_volume: 0 # Volume of filament to press into the nozzle during tip formation in mm³. # Set this if you would like a temperature reduction during the tip formation. # If using skinny_dip, this change will happen before. toolchange_temp: 0 # This step is split into two different movements. First, a fast move to separate the filament # from the hot zone. Next, a slower movement over the remaining distance of the cooling tube. unloading_speed_start: 40 # Speed in mm/s (fast pull). unloading_speed: 15 # Speed in mm/s (cooling tube move). # This stage moves the filament back and forth in the cooling tube section of the hotend. # It helps keep the tip shape uniform with the filament path to prevent clogs. cooling_tube_position: 35 # Start of the cooling tube in mm. cooling_tube_length: 10 # Length of the move in mm. initial_cooling_speed: 10 # Initial movement speed to start solidifying the tip in mm/s. final_cooling_speed: 50 # Fast movement speed in mm/s. cooling_moves: 4 # Number of back and forth moves in the cooling tube. # This is a final move to burn off any hairs possibly on the end of stringy materials like PLA. # If you use this, it should be the last thing you tune after achieving a solid tip shape. use_skinnydip: False # Enable skinny dip moves (for burning off filament hairs). skinnydip_distance: 30 # Distance to reinsert the filament, starting at the end of the cooling tube in mm. dip_insertion_speed: 30 # Insertion speed for burning off filament hairs in mm/s. dip_extraction_speed: 70 # Extraction speed (set to around 2x the insertion speed) in mm/s. melt_zone_pause: 0 # Pause time in the melt zone in seconds. cooling_zone_pause: 0 # Pause time in the cooling zone after the dip in seconds. ================================================================ AFC_Turtle_1.cfg ================================================================ [include mcu/AFC_Lite.cfg] [mcu Turtle_1] #canbus_uuid: serial: /dev/serial/by-id/usb-Klipper_stm32h723xx_boxturt1-if00 [AFC_BoxTurtle Turtle_1] type: 'Box Turtle' hub: Turtle_1 extruder: extruder # buffer: # If not defined below from the install script, uncomment and add buffer name if using a buffer buffer: Turtle_1 [temperature_sensor Turtle_1] sensor_type: temperature_mcu sensor_mcu: Turtle_1 [AFC_stepper lane1] unit: Turtle_1:1 step_pin: Turtle_1:M1_STEP dir_pin: !Turtle_1:M1_DIR enable_pin: !Turtle_1:M1_EN microsteps: 16 rotation_distance: 4.65 dist_hub: 155.0 park_dist: 10 led_index: AFC_Indicator:1 afc_motor_rwd: Turtle_1:MOT1_RWD afc_motor_fwd: Turtle_1:MOT1_FWD afc_motor_enb: Turtle_1:MOT1_EN rwd_speed_multiplier: 0.5 fwd_speed_multiplier: 0.5 pwm: True prep: ^!Turtle_1:TRG1 load: ^Turtle_1:EXT1 [tmc2209 AFC_stepper lane1] uart_pin: Turtle_1:M1_UART uart_address: 0 run_current: 0.8 sense_resistor: 0.110 [AFC_stepper lane2] unit: Turtle_1:2 step_pin: Turtle_1:M2_STEP dir_pin: !Turtle_1:M2_DIR enable_pin: !Turtle_1:M2_EN microsteps: 16 rotation_distance: 4.65 dist_hub: 80 park_dist: 10 led_index: AFC_Indicator:2 afc_motor_rwd: Turtle_1:MOT2_RWD afc_motor_fwd: Turtle_1:MOT2_FWD afc_motor_enb: Turtle_1:MOT2_EN rwd_speed_multiplier: 0.5 fwd_speed_multiplier: 0.5 pwm: True prep: ^!Turtle_1:TRG2 load: ^Turtle_1:EXT2 [tmc2209 AFC_stepper lane2] uart_pin: Turtle_1:M2_UART uart_address: 0 run_current: 0.8 sense_resistor: 0.110 [AFC_stepper lane3] unit: Turtle_1:3 step_pin: Turtle_1:M3_STEP dir_pin: !Turtle_1:M3_DIR enable_pin: !Turtle_1:M3_EN microsteps: 16 rotation_distance: 4.65 dist_hub: 90.0 park_dist: 10 led_index: AFC_Indicator:3 afc_motor_rwd: Turtle_1:MOT3_RWD afc_motor_fwd: Turtle_1:MOT3_FWD afc_motor_enb: Turtle_1:MOT3_EN rwd_speed_multiplier: 0.5 fwd_speed_multiplier: 0.5 pwm: True prep: ^!Turtle_1:TRG3 load: ^Turtle_1:EXT3 [tmc2209 AFC_stepper lane3] uart_pin: Turtle_1:M3_UART uart_address: 0 run_current: 0.8 sense_resistor: 0.110 [AFC_stepper lane4] unit: Turtle_1:4 step_pin: Turtle_1:M4_STEP dir_pin: !Turtle_1:M4_DIR enable_pin: !Turtle_1:M4_EN microsteps: 16 rotation_distance: 4.65 dist_hub: 145.0 park_dist: 10 led_index: AFC_Indicator:4 afc_motor_rwd: Turtle_1:MOT4_RWD afc_motor_fwd: Turtle_1:MOT4_FWD afc_motor_enb: Turtle_1:MOT4_EN rwd_speed_multiplier: 0.5 fwd_speed_multiplier: 0.5 pwm: True prep: ^!Turtle_1:TRG4 load: ^Turtle_1:EXT4 [tmc2209 AFC_stepper lane4] uart_pin: Turtle_1:M4_UART uart_address: 0 run_current: 0.8 sense_resistor: 0.110 [AFC_hub Turtle_1] switch_pin: ^Turtle_1:HUB # Pin for the hub switch afc_bowden_length: 1725 # Length of the Bowden tube from the hub to the toolhead sensor in mm. move_dis: 50 # Distance to move the filament within the hub in mm. #hub_clear_move_dis: 25 # Distance after hub switch becomes fast to retract to insure hub is clear cut: False # Hub cutter installed (e.g. Snappy) #--=================================================================================--# ######### Hub Cut ##################################################################### #--=================================================================================--# assisted_retract: False # If True, retracts are assisted to prevent loose windows on the spool cut_cmd: AFC #CMD to use cut_dist: 50 # How much filament to cut off (in mm). cut_clear: 120 # How far the filament should retract back from the hub (in mm). cut_min_length: 300.0 cut_servo_pass_angle: 10 # Servo angle to align the Bowden tube with the hole for loading the toolhead. cut_servo_clip_angle: 180 # Servo angle for cutting the filament. cut_servo_prep_angle: 80 # Servo angle to prepare the filament for cutting (aligning the exit hole). #[AFC_screen Turtle_1] #mac_address: None [AFC_led AFC_Indicator] pin: Turtle_1:RGB1 chain_count: 4 color_order: GRBW #[neopixel Extra2] #pin: Turtle_1:RGB2 #chain_count: 6 #color_order: GRB #[neopixel Extra3] #pin: Turtle_1:RGB3 #chain_count: 6 #color_order: GRB #[neopixel Extra4] #pin: Turtle_1:RGB4 #chain_count: 4 #color_order: GRB ================================================================ AFC_Macro_Vars.cfg ================================================================ [include macros/*.cfg] #--=================================================================================- #------- Global --------------------------------------------------------------------- #--=================================================================================- [gcode_macro _AFC_GLOBAL_VARS] description: Global variables used in multiple macros gcode: # Leave Empty # Set this to match your AFC_stepper base naming in AFC_Hardware.cfg variable_stepper_name : 'lane' # [AFC_stepper lane1] [AFC_stepper lane2]... variable_travel_speed : 120 # Speed mm/s variable_z_travel_speed : 30 # Speed mm/s variable_accel : 2000 # Move accel for all macro moves variable_verbose : 1 # Console Output for macros # 0 - None # 1 - Limited # 2 - All #--=================================================================================- #------- Cut ----------------------------------------------------------------------- #--=================================================================================- [gcode_macro _AFC_CUT_TIP_VARS] description: Toolhead tip cutting macro configuration variables gcode: # Leave empty # This should be the position of the toolhead where the cutter arm just # lightly touches the depressor pin variable_pin_loc_xy : -1, -1 # x,y coordinates of depressor pin # Accel during cut. This will overwrite the global accel for this macro. Set to 0 to use global accel variable_cut_accel : 0 # Direction to make the cut move (left, right, front, back) variable_cut_direction : "left" # This distance is used to move toolhead to cut filament # and to create a small saftely distance that aids in generating momentum variable_pin_park_dist : 6.0 # Distance in mm # Position of the toolhead when the cutter is fully compressed. # Distance the toolhead needs to travel to compress the cutter arm. # To calculate this distance start at the pin_loc_xy position and move # your toolhead till the cutter arm is completely compressed. Take 0.5mm off this distance # as a buffer. # Ex pin_loc_x : 9, 310 fully compressed at 0, 310 set cut_move_dist to 8.5 variable_cut_move_dist : 8.5 # Distance in mm # Speed related settings for tip cutting # Note that if the cut speed is too fast, the steppers can lose steps. # Therefore, for a cut: # - We first make a fast move to accumulate some momentum and get the cut # blade to the initial contact with the filament # - We then make a slow move for the actual cut to happen variable_cut_fast_move_speed : 32 # Speed mm/s variable_cut_slow_move_speed : 10 # Speed mm/s variable_evacuate_speed : 150 # Speed mm/s variable_cut_dwell_time : 50 # Time to dwell at the cut point in ms variable_cut_fast_move_fraction : 0.85 # Fraction of the move that uses fast move 0.0 - 1.0 variable_extruder_move_speed : 25 # Speed mm/s for all extruder movement # If the toolhead returns to initial position after the cut is complete. variable_restore_position : False # True = return to initial position, False = don't return # Distance to retract prior to making the cut, this reduces wasted filament but might cause clog # if set too large and/or if there are gaps in the hotend assembly # *This must be less than the distance from the nozzle to the cutter variable_retract_length : 20 # This can help prevent clogging of some toolheads by doing a quick tip from to reduce stringing variable_quick_tip_forming : False # Number of times to run the cut movement variable_cut_count : 2 # Retract length and speed after the cut so that the cutter can go back # into its origin position variable_rip_length : 1.0 # Distance in mm to retract to aid lever decompression (>= 0) variable_rip_speed : 3 # Speed mm/s # Pushback of the remaining tip from the cold end into the hotend # *Must be less then retract_length variable_pushback_length : 15 # Distance in mm variable_pushback_dwell_time : 20 # Time to dwell between the pushback # Safety margin for fast vs slow travel. When traveling to the pin location # we make a safer but longer move if we are closer to the pin than this # specified margin. Usually setting these to the size of the toolhead # (plus a small margin) should be good enough variable_safe_margin_xy : 30, 30 # Approx toolhead width +5mm, height +5mm) # Some printers may need a boost of power to complete the cut without skipping steps. # One option is to increase the current for thost steppers in printer.cfg. Another # option is to use these variables to set a current that is only used during the # cut motion. Different combinations of kinematics and cutter configurations engage # different combinations of steppers for that motion. Set the needed variables. # The override is skipped if the current is 0. # Enable if layer shifts occur when cutting # variable_cut_current_stepper_x: 0 # variable_cut_current_dual_carriage: 0 # This is the value that is used to define the current for the dual carriage stepper (2nd x) for an IDEX printer during the cut. # variable_cut_current_stepper_y: 0 # variable_cut_current_stepper_z: 0 # Change these to match the entries in printer.cfg if needed # variable_conf_name_stepper_x: "tmc2209 stepper_x" # variable_conf_name_dual_carriage: "tmc2209 dual_carriage" # variable_conf_name_stepper_y: "tmc2209 stepper_y" # variable_conf_name_stepper_z: "tmc2209 stepper_z" # variable_awd: True #--=================================================================================- #------- Poop ---------------------------------------------------------------------- #--=================================================================================- [gcode_macro _AFC_POOP_VARS] description: Poop macro configuration variables gcode: # Leave empty variable_purge_loc_xy : -1, -1 # (x,y) Location of where to purge variable_purge_spd : 6.5 # Speed, in mm/s, of the purge. variable_z_purge_move : True # Set to False to not move in Z during poop # Speed, in mm/s to lift z after the purge is completed. Its a faster lift to keep it from # sticking to the toolhead variable_fast_z : 200 variable_z_lift : 20 # Z height to raise to after the purge is completed as part of the fast z move # If the toolhead returns to initial position after the poop is complete. variable_restore_position : False # True = return to initial position, False = don't return # The height to raise the nozzle above the tray before purging. This allows any built up # pressure to escape before the purge. variable_purge_start : 0.6 # Set the part cooling fan speed. Disabling can help prevent the nozzle from cooling down # and stimulate flow, Enabling it can prevent blobs from sticking together. variable_part_cooling_fan : True # Run it at full speed variable_part_cooling_fan_speed : 1.0 # Speed to run fan when enabled above. 0 - 1.0 variable_purge_cool_time : 2 # Time to pause after purge to allow fan to cool the poop in seconds # ==================== PURGE LENGTH TUNING # Default purge length to fall back on when neither the tool map purge_volumes or # parameter PURGE_LENGTH is set. variable_purge_length : 72.111 # The absolute minimum to purge, even if you don't changed tools. This is to prime the # nozzle before printing variable_purge_length_minimum : 60.999 # The slicer values often are a bit too wasteful. Tune it here to get optimal values. 0.6 # is a good starting point. #variable_purge_length_modifier : 1 # Length of filament to add after the purge volume. Purge volumes don't always take # cutters into account and therefor a swap from red to white might be long enough, but # from white to red can be far too short. When should you alter this value: # INCREASE: When the dark to light swaps are good, but light to dark aren't. # DECREASE: When the light to dark swaps are good, but dark to light aren't. Don't # forget to increase the purge_length_modifier #variable_purge_length_addition : 0 #--=================================================================================- #------- Kick ---------------------------------------------------------------------- #--=================================================================================- [gcode_macro _AFC_KICK_VARS] description: Kick macro configuration variables gcode: # Leave empty variable_kick_start_loc : -1,-1,10 # Location to move before kick variable_kick_z : 1.5 # Height to drop to for kick move variable_kick_speed : 150 # Speed of kick movement variable_kick_accel : 0 # Accel of kick moves. This will overwrite the global accel for this macro. Set to 0 to use global accel variable_kick_direction : "right" # Direction to make the kick move (left, right, front, back) variable_kick_move_dist : 45 # How far to move to kick poop off variable_z_after_kick : 10 # Height of z after kick move #--=================================================================================- #------- Brush --------------------------------------------------------------------- #--=================================================================================- [gcode_macro _AFC_BRUSH_VARS] description: Brush macro configuration variables gcode: # Leave empty variable_brush_loc : -1,-1,-1 # Position of the center of the brush (Set z to -1 if you dont want a z move) variable_brush_clean_speed : 150 # Speed of cleaning moves when brushing # Accel of cleaning moves when brushing. This will overwrite the global accel for this macro. Set to 0 to use global accel variable_brush_clean_accel : 0 variable_brush_width : 30 # Total width in mm of the brush in the X direction variable_brush_depth : 10 # Total depth in mm of the brush in the Y direction variable_y_brush : True # True - Brush along Y axis first then X. False - Only brush along x variable_brush_count : 4 # Number of passes to make on the brush. # Move in Z after brush to avoid bed if brush is at Z0 (Set z to -1 if you dont want a z move) variable_z_move : -1 #--=================================================================================- #------- Park ---------------------------------------------------------------------- #--=================================================================================- [gcode_macro _AFC_PARK_VARS] description: Park macro configuration variables gcode: # Leave empty variable_park_loc_xy : -1, -1 # Position to park the toolhead # If you want z_hop during toolchanges please set the value in the AFC.cfg variable_z_hop : 0 # Height to raise Z when moving to park. Leave 0 to disable ================================================================ TurtleNeckv2.cfg ================================================================ [mcu turtleneck] serial: /dev/serial/by-id/**YOUR SERIAL HERE** [board_pins tn_v2] mcu: turtleneck aliases: TRAILING = PB1, ADVANCE = PB2, ES1 = PB5, ES2 = PB6, ES3 = PB7, ES4 = PB8, ES5 = PB9, RGB = PD3, ================================================================ MMB_1.1.cfg ================================================================ [board_pins mmb_1.1] mcu: AFC aliases: M1_STEP=PB15 , M1_DIR=PB14 , M1_EN=PB8 , M1_UART=PA10 , # M1_DIAG=PA3 , M2_STEP=PD2 , M2_DIR=PB13 , M2_EN=PD1 , M2_UART=PC7 , # M2_DIAG=PA4 , M3_STEP=PD0 , M3_DIR=PD3 , M3_EN=PA15 , M3_UART=PC6 , # M3_DIAG=PB9 , M4_STEP=PB6 , M4_DIR=PB7 , M4_EN=PB5 , M4_UART=PA9 , # M4_DIAG=PB8 , HUB=PB11 , TRG1=PA3 , TRG2=PA4 , TRG3=PB9 , TRG4=PA8 , EXT1=PC15 , EXT2=PC13 , EXT3=PC14 , EXT4=PB12 , MOT1_RWD=PA0 , MOT2_RWD=PA1 , MOT3_RWD=PB10 , MOT4_RWD=PB2 , RGB1=PA2 , ================================================================ HTLF_ERB.cfg ================================================================ [board_pins erb_htlf] mcu: ERB aliases: M1_STEP=gpio16 , M1_DIR=gpio15 , M1_EN=gpio14 , M1_UART=gpio17 , # M1_DIAG=PA3 , M2_STEP=gpio10 , M2_DIR=gpio9 , M2_EN=gpio8 , M2_UART=gpio11 , # M2_DIAG=PA4 , HUB=gpio25 , HOME_POS=gpio24 , LOAD1=gpio12 , LOAD2=gpio3 , LOAD3=gpio6 , LOAD4=gpio27 , SPARE1=PC13 , SPARE2=PC14 , SPARE3=PB12 , SPARE4=PA0 , SPARE5=PA1 , SPARE6=PB3 , SPARE7=PB4 , SPARE8=PB11 , SPARE9=PB10 , SPARE10=PB2 , RGB1=gpio21 , ================================================================ MMB_1.0.cfg ================================================================ [board_pins mmb_1.0] mcu: AFC aliases: M1_STEP=PB15 , M1_DIR=PB14 , M1_EN=PA8 , M1_UART=PA10 , # M1_DIAG=PA3 , M2_STEP=PD2 , M2_DIR=PB13 , M2_EN=PD1 , M2_UART=PC7 , # M2_DIAG=PA4 , M3_STEP=PD0 , M3_DIR=PD3 , M3_EN=PA15 , M3_UART=PC6 , # M3_DIAG=PB9 , M4_STEP=PB6 , M4_DIR=PB7 , M4_EN=PB5 , M4_UART=PA9 , # M4_DIAG=PB8 , HUB=PB11 , TRG1=PA3 , TRG2=PA4 , TRG3=PB9 , TRG4=PB8 , EXT1=PC15 , EXT2=PC13 , EXT3=PC14 , EXT4=PB12 , MOT1_RWD=PA0 , MOT2_RWD=PA1 , MOT3_RWD=PB10 , MOT4_RWD=PB2 , RGB1=PA2 , ================================================================ AFC_Lite.cfg ================================================================ [board_pins Turtle_1] mcu: Turtle_1 aliases: M1_STEP=PD4 , M1_DIR=PD3 , M1_EN=PD6 , M1_UART=PD5 , # M1_DIAG=PD2 , M2_STEP=PC12 , M2_DIR=PC11 , M2_EN=PD1 , M2_UART=PD0 , # M2_DIAG=PC10 , M3_STEP=PE2 , M3_DIR=PE3 , M3_EN=PE0 , M3_UART=PE1 , # M3_DIAG=PE4 , M4_STEP=PD15 , M4_DIR=PD14 , M4_EN=PC7 , M4_UART=PC6 , # M4_DIAG=PC8 , # suggested switch pin configurations HUB=PC4 , TRG1=PC5 , TRG2=PB0 , TRG3=PB1 , TRG4=PB2 , EXT1=PE8 , EXT2=PE9 , EXT3=PE10 , EXT4=PE11 , TN_ADV=PE12 , TN_TRL=PE13 , # alternate names for endstop ports SW1=PC4 , SW2=PC5 , SW3=PB0 , SW4=PB1 , SW5=PB2 , SW6=PE7 , SW7=PE8 , SW8=PE9 , SW9=PE10 , SW10=PE11 , SW11=PE12 , SW12=PE13 , MOT1_RWD=PA0 , MOT1_FWD=PA1 , MOT1_EN=PA2 , MOT2_RWD=PA6 , MOT2_FWD=PA7 , MOT2_EN=PA5 , MOT3_RWD=PB14 , MOT3_FWD=PB15 , MOT3_EN=PB13 , MOT4_RWD=PD12 , MOT4_FWD=PD13 , MOT4_EN=PD11 , RGB1=PE14 , RGB2=PE15 , RGB3=PB10 , RGB4=PB11 , ================================================================ HTLF_MMB_1.1.cfg ================================================================ [board_pins mmb_1.1_htlf] mcu: MMB_HTLF aliases: M1_STEP=PB15 , M1_DIR=PB14 , M1_EN=PB8 , M1_UART=PA10 , # M1_DIAG=PA3 , M2_STEP=PD2 , M2_DIR=PB13 , M2_EN=PD1 , M2_UART=PC7 , # M2_DIAG=PA4 , M3_STEP=PD0 , M3_DIR=PD3 , M3_EN=PA15 , M3_UART=PC6 , # M3_DIAG=PB9 , M4_STEP=PB6 , M4_DIR=PB7 , M4_EN=PB5 , M4_UART=PA9 , # M3_DIAG=PB8 , HUB=PC13 , HOME_POS=PA3 , LOAD1=PA4 , LOAD2=PB9 , LOAD3=PA8 , LOAD4=PC15 , SPARE1=PC14 , SPARE2=PB12 , SPARE3=PA0 , SPARE4=PA1 , SPARE5=PB3 , SPARE6=PB4 , SPARE7=PB11 , SPARE8=PB10 , SPARE9=PB2 , RGB1=PA2 , ================================================================ HTLF_MMB_1.0.cfg ================================================================ [board_pins mmb_1.0_htlf] mcu: MMB_HTLF aliases: M1_STEP=PB15 , M1_DIR=PB14 , M1_EN=PA8 , M1_UART=PA10 , # M1_DIAG=PA3 , M2_STEP=PD2 , M2_DIR=PB13 , M2_EN=PD1 , M2_UART=PC7 , # M2_DIAG=PA4 , M3_STEP=PD0 , M3_DIR=PD3 , M3_EN=PA15 , M3_UART=PC6 , # M3_DIAG=PB9 , M4_STEP=PB6 , M4_DIR=PB7 , M4_EN=PB5 , M4_UART=PA9 , # M3_DIAG=PB8 , HUB=PC13 , HOME_POS=PA3 , LOAD1=PA4 , LOAD2=PB9 , LOAD3=PB8 , LOAD4=PC15 , # LOAD3=PA8 => PB8 SPARE1=PC14 , SPARE2=PB12 , SPARE3=PA0 , SPARE4=PA1 , SPARE5=PB3 , SPARE6=PB4 , SPARE7=PB11 , SPARE8=PB10 , SPARE9=PB2 , RGB1=PA2 , ================================================================ ERB_2.0.cfg ================================================================ [board_pins NightOwl] #fysetc erb2.0 mcu: NightOwl # Assuming using an external / extra mcu dedicated to MMU aliases: LANE1_UART=gpio17, LANE1_STEP=gpio16, LANE1_DIR=gpio15, LANE1_EN=gpio14, LANE1_DIAG=gpio19, LANE1_ENDSTOP=gpio24, LANE2_UART=gpio11, LANE2_STEP=gpio10, LANE2_DIR=gpio9, LANE2_EN=gpio8, LANE2_DIAG=gpio13, MMU_SERVO=gpio23, MMU_ENCODER=gpio22, MMU_GATE_SENSOR=, MMU_NEOPIXEL=gpio21, LANE1_TRIG=gpio3, LANE2_TRIG=gpio5, LANE1_EXT=gpio4, LANE2_EXT=gpio6, NT_HUB=gpio12, TN_ADV=gpio2, TN_TRL=gpio18 ================================================================ AFC_Hardware.cfg ================================================================ [force_move] enable_force_move: True [AFC_extruder extruder] pin_tool_start: nhk:gpio13 #pin_tool_end: None tool_stn: 72 # Distance in mm from the toolhead sensor to the tip of the nozzle in mm, if `tool_end` is defined then distance is from this sensor tool_stn_unload: 100 # Distance to move in mm while unloading toolhead tool_sensor_after_extruder: 0 # Extra distance to move in mm once pre/post sensors are clear. Useful for when only using post sensor, so this distance can be the amout to move to clear extruder gears tool_unload_speed: 25 # Unload speed in mm/s when unloading toolhead. Default is 25mm/s. tool_load_speed: 25 # Load speed in mm/s when unloading toolhead. Default is 25mm/s. #[filament_switch_sensor bypass] #switch_pin: turtleneck:PB5 #pause_on_runout: False [AFC_buffer Turtle_1] advance_pin: ^Turtle_1:TN_ADV # set advance pin trailing_pin: ^Turtle_1:TN_TRL # set trailing pin multiplier_high: 1.05 # default 1.05, factor to feed more filament multiplier_low: 0.95 # default 0.95, factor to feed less filament velocity: 0 ================================================================ Uploaded Extracted Klippy Configuration and Shutdown Logs ================================================================ AFC.log: https://termbin.com/casp AFC.log.2025-05-29_12-02-31: https://termbin.com/ohdq AFC.log.2025-05-29_12-19-03: https://termbin.com/7ptev AFC.log.2025-05-29_13-28-03: https://termbin.com/j82i AFC.log.2025-05-31_17-07-36: https://termbin.com/ulgd AFC.log.2025-05-31_17-27-30: https://termbin.com/2j6y klippy.log: https://termbin.com/ez9t klippy.log.config0001.cfg: https://termbin.com/tu8u