From a523b7ff69d1c965f9172c05b408a83c3fe0d11a Mon Sep 17 00:00:00 2001 From: Martyn Date: Wed, 23 Apr 2025 15:35:32 +0100 Subject: [PATCH] Automatic commit of config from 2025-04-23 --- martyn_macros.cfg | 30 +- mmu-20250423_130617/addons/blobifier.cfg | 924 ++++++++++++++++++ mmu-20250423_130617/addons/blobifier_hw.cfg | 28 + .../addons/dc_espooler.cfg | 0 .../addons/dc_espooler_hw.cfg | 0 .../addons/mmu_eject_buttons.cfg | 31 + .../addons/mmu_eject_buttons_hw.cfg | 21 + .../addons/mmu_erec_cutter.cfg | 91 ++ .../addons/mmu_erec_cutter_hw.cfg | 10 + mmu-20250423_130617/base/mmu.cfg | 154 +++ mmu-20250423_130617/base/mmu_cut_tip.cfg | 1 + mmu-20250423_130617/base/mmu_form_tip.cfg | 1 + mmu-20250423_130617/base/mmu_hardware.cfg | 368 +++++++ mmu-20250423_130617/base/mmu_leds.cfg | 1 + mmu-20250423_130617/base/mmu_macro_vars.cfg | 506 ++++++++++ mmu-20250423_130617/base/mmu_parameters.cfg | 613 ++++++++++++ mmu-20250423_130617/base/mmu_sequence.cfg | 1 + mmu-20250423_130617/base/mmu_software.cfg | 1 + mmu-20250423_130617/base/mmu_state.cfg | 1 + mmu-20250423_130617/mmu_vars.cfg | 38 + .../optional/client_macros.cfg | 1 + mmu-20250423_130617/optional/mmu_menu.cfg | 1 + mmu-20250423_131125/addons/blobifier.cfg | 924 ++++++++++++++++++ mmu-20250423_131125/addons/blobifier_hw.cfg | 28 + .../addons/mmu_eject_buttons.cfg | 31 + .../addons/mmu_eject_buttons_hw.cfg | 21 + .../addons/mmu_erec_cutter.cfg | 91 ++ .../addons/mmu_erec_cutter_hw.cfg | 10 + mmu-20250423_131125/base/mmu.cfg | 154 +++ mmu-20250423_131125/base/mmu_cut_tip.cfg | 1 + mmu-20250423_131125/base/mmu_form_tip.cfg | 1 + mmu-20250423_131125/base/mmu_hardware.cfg | 368 +++++++ mmu-20250423_131125/base/mmu_leds.cfg | 1 + mmu-20250423_131125/base/mmu_macro_vars.cfg | 535 ++++++++++ mmu-20250423_131125/base/mmu_parameters.cfg | 685 +++++++++++++ mmu-20250423_131125/base/mmu_purge.cfg | 1 + mmu-20250423_131125/base/mmu_sequence.cfg | 1 + mmu-20250423_131125/base/mmu_software.cfg | 1 + mmu-20250423_131125/base/mmu_state.cfg | 1 + mmu-20250423_131125/mmu_vars.cfg | 38 + .../optional/client_macros.cfg | 1 + mmu-20250423_131125/optional/mmu_menu.cfg | 1 + mmu/addons/blobifier.cfg | 24 +- mmu/base/mmu_macro_vars.cfg | 59 +- mmu/base/mmu_parameters.cfg | 92 +- mmu/base/mmu_purge.cfg | 1 + mmu/mmu_vars.cfg | 4 +- printer.cfg | 107 +- 48 files changed, 5869 insertions(+), 134 deletions(-) create mode 100644 mmu-20250423_130617/addons/blobifier.cfg create mode 100644 mmu-20250423_130617/addons/blobifier_hw.cfg rename {mmu => mmu-20250423_130617}/addons/dc_espooler.cfg (100%) rename {mmu => mmu-20250423_130617}/addons/dc_espooler_hw.cfg (100%) create mode 100644 mmu-20250423_130617/addons/mmu_eject_buttons.cfg create mode 100644 mmu-20250423_130617/addons/mmu_eject_buttons_hw.cfg create mode 100644 mmu-20250423_130617/addons/mmu_erec_cutter.cfg create mode 100644 mmu-20250423_130617/addons/mmu_erec_cutter_hw.cfg create mode 100644 mmu-20250423_130617/base/mmu.cfg create mode 120000 mmu-20250423_130617/base/mmu_cut_tip.cfg create mode 120000 mmu-20250423_130617/base/mmu_form_tip.cfg create mode 100644 mmu-20250423_130617/base/mmu_hardware.cfg create mode 120000 mmu-20250423_130617/base/mmu_leds.cfg create mode 100644 mmu-20250423_130617/base/mmu_macro_vars.cfg create mode 100644 mmu-20250423_130617/base/mmu_parameters.cfg create mode 120000 mmu-20250423_130617/base/mmu_sequence.cfg create mode 120000 mmu-20250423_130617/base/mmu_software.cfg create mode 120000 mmu-20250423_130617/base/mmu_state.cfg create mode 100644 mmu-20250423_130617/mmu_vars.cfg create mode 120000 mmu-20250423_130617/optional/client_macros.cfg create mode 120000 mmu-20250423_130617/optional/mmu_menu.cfg create mode 100644 mmu-20250423_131125/addons/blobifier.cfg create mode 100644 mmu-20250423_131125/addons/blobifier_hw.cfg create mode 100644 mmu-20250423_131125/addons/mmu_eject_buttons.cfg create mode 100644 mmu-20250423_131125/addons/mmu_eject_buttons_hw.cfg create mode 100644 mmu-20250423_131125/addons/mmu_erec_cutter.cfg create mode 100644 mmu-20250423_131125/addons/mmu_erec_cutter_hw.cfg create mode 100644 mmu-20250423_131125/base/mmu.cfg create mode 120000 mmu-20250423_131125/base/mmu_cut_tip.cfg create mode 120000 mmu-20250423_131125/base/mmu_form_tip.cfg create mode 100644 mmu-20250423_131125/base/mmu_hardware.cfg create mode 120000 mmu-20250423_131125/base/mmu_leds.cfg create mode 100644 mmu-20250423_131125/base/mmu_macro_vars.cfg create mode 100644 mmu-20250423_131125/base/mmu_parameters.cfg create mode 120000 mmu-20250423_131125/base/mmu_purge.cfg create mode 120000 mmu-20250423_131125/base/mmu_sequence.cfg create mode 120000 mmu-20250423_131125/base/mmu_software.cfg create mode 120000 mmu-20250423_131125/base/mmu_state.cfg create mode 100644 mmu-20250423_131125/mmu_vars.cfg create mode 120000 mmu-20250423_131125/optional/client_macros.cfg create mode 120000 mmu-20250423_131125/optional/mmu_menu.cfg create mode 120000 mmu/base/mmu_purge.cfg diff --git a/martyn_macros.cfg b/martyn_macros.cfg index 25e2236..4f1142c 100644 --- a/martyn_macros.cfg +++ b/martyn_macros.cfg @@ -3,7 +3,8 @@ gcode: {% set BED_TEMP = params.BED|default(60)|float %} {% set EXTRUDER_TEMP = params.EXTRUDER|default(190)|float %} {% set STANDBY_TEMP = params.STANDBY|default(190)|float %} - {% set CHAMBER_TEMP = params.CHAMBER|default(45)|float %} + {% set CHAMBER_TEMP = params.CHAMBER|default(40)|float %} + {% set CLEAN_TEMP = params.CLEAN|default(170)|float %} G90 ; ensure absolute positioning STATUS_HOMING G92 E0 ; Reset Extruder @@ -15,10 +16,16 @@ gcode: M190 S{BED_TEMP} ; Start heating the bed, wait until target temperature reached M4 P120000 ; Wait 2 minutes TEMPERATURE_WAIT SENSOR="temperature_sensor chamber_temp" MINIMUM={CHAMBER_TEMP} ; Wait for chamber temp - M140 S0 ; turn off power to the bed, interference with probe? - G28 Z0 ; Heatsoaked, validate that z + + QUAD_GANTRY_LEVEL + M109 S{CLEAN_TEMP} + CLEAN_NOZZLE + G1 X175 Y175 Z2 + PROBE_EDDY_NG_TAP + STATUS_MESHING BED_MESH_CALIBRATE ;Well, this is fine and dandy... + STATUS_HEATING M190 S{BED_TEMP} ; Start heating the bed, wait until target temperature reached M109 S{EXTRUDER_TEMP} ; Finish heating the nozzle CLEAN_NOZZLE @@ -30,7 +37,7 @@ gcode: G92 E0 ; Reset Extruder G1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed G1 X5 Y20 Z0.3 F5000.0 ; Move over to prevent blob squish - G1 E-1 ; Retract before cleaning, or we will still have stringing + G1 E-2 ; Retract before cleaning, or we will still have stringing CLEAN_NOZZLE ; doing this again is probably gonna make it work! SKEW_PROFILE LOAD=calilantern_skew_profile G1 E0 ; "UnRetract" (I forgot we were in absolutes!) @@ -45,6 +52,8 @@ gcode: {% set y_safe = th.position.y + 20 * (1 if th.axis_maximum.y - th.position.y > 20 else -1) %} {% set z_safe = [th.position.z + 2, th.axis_maximum.z]|min %} SET_SKEW CLEAR=1 + BED_MESH_CLEAR + PROBE_EDDY_NG_SET_TAP_OFFSET VALUE=0 SAVE_GCODE_STATE NAME=STATE_PRINT_END @@ -56,7 +65,7 @@ gcode: G90 ; absolute positioning G0 X{x_safe} Y{y_safe} Z{z_safe} F20000 ; move nozzle to remove stringing - G0 X{th.axis_maximum.x//2} Y25 F3600 ; park nozzle at rear but avoid the drag chain + G0 X{th.axis_maximum.x//2} Y275 F3600 ; park nozzle at rear but avoid the drag chain M107 ; turn off fan RESTORE_GCODE_STATE NAME=STATE_PRINT_END @@ -69,12 +78,6 @@ gcode: TURN_OFF_HEATERS CANCEL_PRINT_BASE -[delayed_gcode start_with_mmu_off] -initial_duration: .01 -gcode: - SET_LED_EFFECT EFFECT=MMU_PURPLE_SLOW - MMU ENABLE=0 - [gcode_macro G32] gcode: SAVE_GCODE_STATE NAME=STATE_G32 @@ -160,11 +163,6 @@ gcode: G0 E{E} F600 ;retract additional filament to move out of melt zone G92 E0 -[delayed_gcode bed_mesh_init] -initial_duration: .01 -gcode: - BED_MESH_PROFILE LOAD=default - [gcode_macro TEST_SPEED] # from ellis # Home, get position, throw around toolhead, home again. diff --git a/mmu-20250423_130617/addons/blobifier.cfg b/mmu-20250423_130617/addons/blobifier.cfg new file mode 100644 index 0000000..e86d62d --- /dev/null +++ b/mmu-20250423_130617/addons/blobifier.cfg @@ -0,0 +1,924 @@ +# Include servo hardware definition separately to allow for automatic upgrade +[include blobifier_hw.cfg] + +########################################################################################## + +# Sample config to be used in conjunction with Blobifier Purge Tray, Bucket & Nozzle +# Scrubber mod. Created by Dendrowen (dendrowen on Discord). The Macro is based on a +# version, and Nozzle Scrubber is made by Hernsl (hernsl#8860 on Discord). The device is +# designed around a Voron V2.4 300mm, but should work for 250mm and 350mm too. This +# version only supports the assembly on the rear-left of the bed. If you decide to change +# that, please consider contributing to the project by creating a pull request with the +# needed changes. + +# IMPORTANT: The rear-left part of your bed becomes unusable by this mod because the +# toolhead needs to lower down to 0. Be sure not to use the left-rear 130x35mm. + +# The goals of this combination of devices is to dispose of purged filament during a +# multicolored print without the need of a purge block and without the flurries of +# filament poops consuming your entire 3D printer room. The Blobifier achieves that by +# purging onto a retractable tray which causes the filament to turn into a tiny blob +# rather then a large spiral. This keeps the waste relatively small. The bucket should be +# able to account for up to 200 filament swaps (for the 300mm V2). + +# The Blobifier uses some room at the back-left side of your printer, depending on your +# printer limits and positions. (usually max_pos.y - toolhead_y and brush_start + +# brush_width + toolhead_x). If you do place objects within this region, Blobifier will +# skip purging automatically. It does this by extending the EXCLUDE_OBJECT_* macro's, so +# make sure you have exclude objects enabled in your slicer. + +# If your using Blobifier in conjunction with the filament cutter on the stealthburner +# toolhead, you can place the pin at max_pos.y - 7 (e.g., max pos y is 307, place it at +# 300). The pin will then poke through the cavity in your toolhead. (Be careful with +# manually moving the toolhead. I have broken many filament cutter pins) + +# It is advised to use the start_gcode from Happy Hare. Then you will be able to fully +# and efficiently use this mod. Check the Happy Hare document at gcode_preprocessing.md +# in the Happy Hare github for more details. + +###################################### DISCLAIMER ######################################## + +# You, and you alone, are responsible for the correct execution of these macros and +# gcodes. Any damage that may occur to your machine remains your responsibility. +# Especially when executing this macro for the first few times, keep an eye on your +# printer and the +# emergency stop. + +########################################################################################## + +########################################################################################## +# Main macro. Usually you should only need to call this one or place it in the Happy Hare +# _MMU_POST_LOAD macro using the variable_user_post_load_extension: +# +# variable_user_post_load_extension : `BLOBIFIER` +# +# Notes on parameters: +# PURGE_LENGTH=[float] (optional) The length to purge. If omitted (default) it will check +# the purge_volumes matrix or variable_purge_length. This can be used +# to override and for testing. +# +[gcode_macro BLOBIFIER] +# These parameters define your filament purging. +# Note that the control of retraction is set in 'mmu_macro_vars.cfg' which can be increased +# if you experience excessive oozing. +variable_purge_spd: 400 # Speed, in mm/min, of the purge. +variable_purge_temp_min: 200 # Minimum nozzle purge temperature. +variable_toolhead_x: 70 # From the nozzle to the left of your toolhead +variable_toolhead_y: 50 # From the nozzle to the front of your toolhead + +# This macro will prevent a gcode movement downward while 'blobbing' if there might be a +# print in the way (e.g. You print something large and need the area where Blobifier does +# its... 'business'). However, at low heights (or at print start) this might not be +# desireable. You can force a 'safe descend' with this variable. Keep in mind that the +# height of the print is an estimation based on previous heights and certain assumptions +# so it might be wise to include a safety margin of 0.2mm +variable_force_safe_descend_height_until: 1.0 + +# Adjust this so that your nozzle scrubs within the brush. Be careful not to go too low! +# Start out with a high value (like, 6) and go +# down from there. +variable_brush_top: 6 + +# These parameters define your scrubbing, travel speeds, safe z clearance and how many +# times you want to wipe. Update as necessary. +variable_clearance_z: 2 # When traveling, but not cleaning, the + # clearance along the z-axis between nozzle + # and brush. +variable_wipe_qty: 2 # Number of complete (A complete wipe: left, + # right, left OR right, left, right) wipes. +variable_travel_spd_xy: 10000 # Travel (not cleaning) speed along x and + # y-axis in mm/min. +variable_travel_spd_z: 1000 # Travel (not cleaning) speed along z axis + # in mm/min. +variable_wipe_spd_xy: 10000 # Nozzle wipe speed in mm/min. + +# The acceleration to use when using the brush action. If set to 0, it uses the already +# set acceleration. However, in some cases this is not desirable for the last motion +# could be an 'outer contour' acceleration which is usually lower. +variable_brush_accel: 0 + +# Blobifier sends the toolhead to the maximum y position during purge operations and +# minimum x position during shake operations. This can cause issues when skew correction +# is set up. If you have skew correction enabled and get 'move out of range' errors +# regarding blobifier while skew is enabled, try increasing this value. Keep the +# adjustments small though! (0.1mm - 0.5mm) and increase it until it works. +variable_skew_correction: 0.1 + +# These parameters define the size of the brush. Update as necessary. A visual reference +# is provided below. +# +# ← brush_width → +# _________________ +# | | ↑ Y position is acquired from your +# brush_start (x) | | brush_depth stepper_y position_max. Adjust +# |_________________| ↓ your brush physically in Y so +# (y) that the nozzle scrubs within the +# brush_front brush. +# __________________________________________________________ +# PRINTER FRONT +# +# +# Start location of the brush. Defaults for 250, 300 and 350mm are provided below. +# Uncomment as necessary +#variable_brush_start: 34 # For 250mm build +variable_brush_start: 67 # For 300mm build +#variable_brush_start: 84 # for 350mm build + +# width of the brush +variable_brush_width: 35 + +# Location of where to purge. The tray is 15mm in length, so if you assemble it against +# the side of the bed (default), 10mm is a good location +variable_purge_x: 10 + +# Height of the tray. If it's below your bed, give this a negative number equal to the +# difference. If it's above your bed, give it a positive number. You can find this number +# by homing, optional QGL or equivalent, and moving you toolhead above the tray, and +# lowering it with the paper method. +variable_tray_top: 0.7 + +# Servo angles for tray positions +variable_tray_angle_out: 0 +variable_tray_angle_in: 180 + +# Increase this value if the servo doesn't have enough time to fully retract or extend +variable_dwell_time: 200 + +# ======================================================================================== +# ==================== BLOB TUNING ======================================================= +# ======================================================================================== + +# The following section defines how the purging sequence is executed. This is where you +# tune the purging to create pretty blobs. Refer to the visual reference for a better +# understanding. The visual is populated with example values. Below are some guides +# provided to help with tuning. +# +# \_____________/ +# |___|___| +# \_/ ______________ < End of third iteration. +# / \ HEIGHT: 3 x iteration_z_raise - (2 + 1) x iteration_z_change (3 x 5 - 2 x 1.2 = 11.4) +# | | EXTRUDED: 3 x max_iteration_length (3 x 50 = 150) +# / \ ______________ < End of second iteration. +# | \ HEIGHT: 2 x iteration_z_raise - 1 x iteration_z_change (2 x 5 - 1 x 1.2 = 8.8) +# / | EXTRUDED: 2 x max_iteration_length (2 x 50 = 100) +# | \ ______________ < End of first iteration. +# / \ HEIGHT: 1 x iteration_z_raise (1 x 5 = 5) +# | | EXTRUDED: 1 x max_iteration_length (1 x 50 = 50) +#___________ \ / ______________ < Start height of the nozzle. default value: 1.5mm +# |_______________\___________/_ ______________ < Bottom of the tray +# |_____________________________| +# | +# +########################### BLOB TUNING ############################## +# +-------------------------------------+----------------------------+ +# | Filament sticks to the nozzle at | Incr. purge start | +# | initial purge (first few mm) | | +# +-------------------------------------+----------------------------+ +# | Filament scoots out from under | Incr. temperature | +# | the nozzle at the first iteration | Decr. z_raise | +# | | Incr. purge_length_maximum | +# +-------------------------------------+----------------------------+ +# | Filament scoots out from under the | Decr. purge_spd | +# | the nozzle at later iterations | Decr. z_raise_exp | +# | | Decr. z_raise | +# | | Incr. purge_length_maximum | +# +-------------------------------------+----------------------------+ +# | Filament sticks to the nozzle at | Incr. z_raise_exp | +# | later iterations | (Not above 1) | +# +-------------------------------------+----------------------------+ +# + +# 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.2 + +# The amount to raise Z +variable_z_raise: 12 + +# As the nozzle gets higher and the blob wider, the Z raise needs to be reduced, this +# follows the following formula: +# (extruded_amount/max_purge_length)^z_raise_exp * z_raise +# 1 is linear, below 1 will cause z to raise less quickly over time, above 1 will make it +# raise quicker over time. 0.85 is a good starting point and you should not have it above 1 +variable_z_raise_exp: 0.85 + +# Lift the nozzle slightly after creating the blob te release pressure on the tray. +variable_eject_hop: 1.0 + +# Dwell time (ms) after purging and before cleaning to relieve pressure from the nozzle. +variable_pressure_release_time: 1000 + +# 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. Values range +# from 0 .. 1, or -1 if you don't want it changed. +#variable_part_cooling_fan: -1 # Leave it unchanged +#variable_part_cooling_fan: 0 # Disable the fan +variable_part_cooling_fan: 1 # Run it at full speed + +# Define the part fan name if you are using a fan other than [fan] +# Applies to [fan_generic] or other fan definitons +# Example would be if you are using auxiliary fan control in Orcaslicer (https://github.com/SoftFever/OrcaSlicer/wiki/Auxiliary-fan) +# If you are unsure if you need this, then probably just leave it commented out. + +#variable_fan_name: "fan_generic fan0" + + + +# ======================================================================================== +# ==================== PURGE LENGTH TUNING =============================================== +# ======================================================================================== + +# The absolute minimum to purge, even if you don't changed tools. This is to prime the +# nozzle before printing +variable_purge_length_minimum: 30 + +# The maximum amount of filament (in mm¹) to purge in a single blob. Blobifier will +# automatically purge multiple blobs if the purge amount exceeds this. +variable_purge_length_maximum: 150 + +# Default purge length to fall back on when neither the tool map purge_volumes or +# parameter PURGE_LENGTH is set. +variable_purge_length: 150 + +# The slicer values often are a bit too wasteful. Tune it here to get optimal values. +# 0.6 (60%) is a good starting point. +variable_purge_length_modifier: 0.6 + +# Fixed length of filament to add after the purge volume calculation. Happy Hare already +# shares info on the extra amount of filament to purge based on known residual filament, +# tip cutting fragment and initial retraction setting. However this setting can add a fixed +# amount on top on that if necessary although it is recommended to start with 0 and tune +# slicer purge matrix first. +# 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 + +# ======================================================================================== +# ==================== BUCKET ============================================================ +# ======================================================================================== + +# Maximum number of blobs that fit in the bucket. Pauses the print if it exceeds this +# number. +variable_max_blobs: 400 +# Enable the bucket shaker. You need to have the shaker.stl installed +variable_enable_shaker: 1 +# The number of back-and-forth motions of one shake +variable_bucket_shakes: 10 +# During shaking acceleration can often be higher because you don't need to keep print +# quality in mind. Higher acceleration helps better with dispersing the blobs. +variable_shake_accel: 10000 + +# The frequency at which to shake the bucket. A decimal value ranging from 0 to 1, where 0 +# is never, and 1 is every time. This way the shaking occurs more often as the bucket +# fills up. Sensible values range from 0.75 to 0.95 +variable_bucket_shake_frequency: 0.95 + +# Height of the shaker arm. If your hotend hits your tray during shaking, increase. +variable_shaker_arm_z: 2 + +gcode: + + # ====================================================================================== + # ==================== RECORD STATE (INCL. FANS, SPEEDS, ETC...) ======================= + # ====================================================================================== + + # General state + SAVE_GCODE_STATE NAME=BLOBIFIER_state + + + # ====================================================================================== + # ==================== CHECK HOMING STATUS ============================================= + # ====================================================================================== + + {% if "xyz" not in printer.toolhead.homed_axes %} + RESPOND MSG="BLOBIFIER: Not homed! Home xyz before blobbing" + {% elif printer.quad_gantry_level and printer.quad_gantry_level.applied == False %} + RESPOND MSG="BLOBIFIER: QGL not applied! run quad_gantry_level before blobbing" + {% else %} + + # Part cooling fan + {% if part_cooling_fan >= 0 %} + {% set fan = fan_name|string %} + # Save the part cooling fan speed to be enabled again later + {% set backup_fan_speed = (printer[fan].speed if printer[fan] is defined else printer.fan.speed) %} + # Set part cooling fan speed + M106 S{part_cooling_fan * 255} + {% endif %} + + # Set feedrate to 100% for correct speed purging + {% set backup_feedrate = printer.gcode_move.speed_factor %} + M220 S100 + + # ====================================================================================== + # ==================== DEFINE BASIC VARIABLES ========================================== + # ====================================================================================== + + {% set sequence_vars = printer['gcode_macro _MMU_SEQUENCE_VARS'] %} + {% set park_vars = printer['gcode_macro _MMU_PARK'] %} + {% set filament_diameter = printer.configfile.config.extruder.filament_diameter|float %} + {% set filament_cross_section = (filament_diameter/2) ** 2 * 3.1415 %} + {% set from_tool = printer.mmu.last_tool %} + {% set to_tool = printer.mmu.tool %} + {% set bl_count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% set pos = printer.gcode_move.gcode_position %} + {% set safe = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'] %} + {% set ignore_safe = safe.print_height < force_safe_descend_height_until %} + {% set restore_z = [printer['gcode_macro BLOBIFIER_PARK'].restore_z,pos.z]|max %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - skew_correction %} + + # Get purge volumes from the slicer (if set up right. see + # https://github.com/moggieuk/Happy-Hare/wiki/Gcode-Preprocessing) + {% set pv = printer.mmu.slicer_tool_map.purge_volumes %} + + # ====================================================================================== + # ==================== DETERMINE PURGE LENGTH ========================================== + # ====================================================================================== + + {% if params.PURGE_LENGTH %} # =============== PARAM PURGE LENGTH ====================== + {action_respond_info("BLOBIFIER: param PURGE_LENGTH provided")} + {% set purge_len = params.PURGE_LENGTH|float %} + {% elif from_tool == to_tool and to_tool >= 0 %} # ==== TOOL DIDN'T CHANGE ============= + {action_respond_info("BLOBIFIER: Tool didn't change (T%s > T%s), %s" % (from_tool, to_tool, "priming" if purge_length_minimum else "skipping"))} + {% set purge_len = 0 %} + + {% elif pv %} # ============== FETCH FROM HAPPY HARE (LIKELY FROM SLICER) ============== + {% if from_tool < 0 and to_tool >= 0%} + {action_respond_info("BLOBIFIER: from tool unknown. Finding largest value for T? > T%d" % to_tool)} + {% set purge_vol = pv|map(attribute=to_tool)|max %} + {% elif to_tool < 0 %} + {action_respond_info("BLOBIFIER: tool(s) unknown. Finding largest value")} + {% set purge_vol = pv|map('max')|max %} + {% else %} + {% set purge_vol = pv[from_tool][to_tool]|float * purge_length_modifier %} + {action_respond_info("BLOBIFIER: Swapped T%s > T%s" % (from_tool, to_tool))} + {% endif %} + {% set purge_len = purge_vol / filament_cross_section %} + + {% set purge_len = purge_len + printer.mmu.extruder_filament_remaining + park_vars.retracted_length + purge_length_addition %} + + {% else %} # ========================= USE CONFIG VARIABLE ============================= + {action_respond_info("BLOBIFIER: No toolmap or PURGE_LENGTH. Using default")} + {% set purge_len = purge_length|float + printer.mmu.extruder_filament_remaining + park_vars.retracted_length %} + {% endif %} + + # ==================================== APPLY PURGE MINIMUM ============================= + {% set purge_len = [purge_len,purge_length_minimum]|max|round(0, 'ceil')|int %} + {action_respond_info("BLOBIFIER: Purging %dmm of filament" % (purge_len))} + + # ====================================================================================== + # ==================== PURGING SEQUENCE ================================================ + # ====================================================================================== + + # Set to absolute positioning. + G90 + + # Check for purge length and purge if necessary. + {% if purge_len|float > 0 %} + + # ==================================================================================== + # ==================== POSITIONING =================================================== + # ==================================================================================== + + # Retract the tray so it is not in the way + BLOBIFIER_SERVO POS=in + + # Move to the assembly, first a bit more to the right (brush_start) to avoid a + # potential filametrix pin if it's not already on the same Y coordinate. + {% if printer.toolhead.position.y != position_y %} + G1 X{[brush_start - 20, 30]|max} Y{position_y} F{travel_spd_xy} + {% endif %} + + # ==================================================================================== + # ==================== BUCKET SHAKE ================================================== + # ==================================================================================== + + {% if enable_shaker and (safe.shake or ignore_safe) %} + {% if (bl_count.current_blobs + 1) >= bl_count.next_shake %} + BLOBIFIER_SHAKE_BUCKET SHAKES={bucket_shakes} + _BLOBIFIER_CALCULATE_NEXT_SHAKE + {% endif %} + {% endif %} + + # ==================================================================================== + # ==================== POSITIONING ON TRAY =========================================== + # ==================================================================================== + {% if safe.tray or ignore_safe %} + G1 Z{tray_top + purge_start} F{travel_spd_z} + {% endif %} + + # Move over to the tray after z change (For cases when the tool is lower than the tray) + G1 X{purge_x} F{travel_spd_xy} + + # Extend the tray + BLOBIFIER_SERVO POS=out + + # ==================================================================================== + # ==================== HEAT HOTEND =================================================== + # ==================================================================================== + + {% if printer.extruder.temperature < purge_temp_min %} + {% if printer.extruder.target < purge_temp_min %} + M109 S{purge_temp_min} + {% else %} + TEMPERATURE_WAIT SENSOR=extruder MINIMUM={purge_temp_min} + {% endif %} + {% endif %} + + # ==================================================================================== + # ==================== START ITERATING =============================================== + # ==================================================================================== + + # Calculate total number of iterations based on the purge length and the max_iteration + # length. + {% set blobs = (purge_len / purge_length_maximum)|round(0, 'ceil')|int %} + {% set purge_per_blob = purge_len|float / blobs %} + {% set retracts_per_blob = (purge_per_blob / 40)|round(0, 'ceil')|int %} + {% set purge_per_retract = (purge_per_blob / retracts_per_blob)|int %} + {% set pulses_per_retract = (purge_per_blob / retracts_per_blob / 5)|round(0, 'ceil')|int %} + {% set pulses_per_blob = (purge_per_blob / 5)|round(0, 'ceil')|int %} + {% set purge_per_pulse = purge_per_blob / pulses_per_blob %} + {% set pulse_time_constant = purge_per_pulse * 0.95 / purge_spd / (purge_per_pulse * 0.95 / purge_spd + purge_per_pulse * 0.05 / 50) %} + {% set pulse_duration = purge_per_pulse / purge_spd %} + + # Repeat the process until purge_len is reached + {% for blob in range(blobs) %} + RESPOND MSG={"'BLOBIFIER: Blob %d of %d (%.1fmm)'" % (blob + 1, blobs, purge_per_blob)} + + {% if safe.tray or ignore_safe %} + G1 Z{tray_top + purge_start} F{travel_spd_z} + {% endif %} + + # relative positioning + G91 + # relative extrusion + M83 + + # Purge filament in a pulsating motion to purge the filament quicker and better + {% for pulse in range(pulses_per_blob) %} + # Calculations to determine z-speed + {% set purged_this_blob = pulse * purge_per_pulse %} + {% set z_last_pos = purge_start + ((purged_this_blob)/purge_length_maximum)**z_raise_exp * z_raise %} + {% set z_pos = purge_start + ((purged_this_blob + purge_per_pulse)/purge_length_maximum)**z_raise_exp * z_raise %} + {% set z_up = z_pos - z_last_pos %} + {% set speed = z_up / pulse_duration %} + + # Purge quickly + G1 Z{z_up * pulse_time_constant} E{purge_per_pulse * 0.95} F{speed} + # Purge a tiny bit slowly + G1 Z{z_up * (1 - pulse_time_constant)} E{purge_per_pulse * 0.05} F{speed} + + # retract and unretract filament every now and then for thorough cleaning + {% if pulse % pulses_per_retract == 0 and pulse > 0 %} + G1 E-2 F1800 + G1 E2 F800 + {% endif %} + + {% endfor %} + + # Retract to match what Happy Hare is expecting + G1 E-{park_vars.retracted_length} F{sequence_vars.retract_speed * 60} + + # ================================================================================== + # ==================== DEPOSIT BLOB ================================================ + # ================================================================================== + {% if safe.tray or ignore_safe %} + # Raise z a bit to relieve pressure on the blob preventing it to go sideways + G1 Z{eject_hop} F{travel_spd_z} + # Retract the tray + BLOBIFIER_SERVO POS=in + # Move the toolhead down to purge_start height lowering the blob below the tray + G90 # absolute positioning + G1 Z{tray_top} F{travel_spd_z} + # Extend the tray to 'cut off' the blob and prepare for the next blob + BLOBIFIER_SERVO POS=out + BLOBIFIER_SERVO POS=in + BLOBIFIER_SERVO POS=out + # Keep track of the # of blobs + _BLOBIFIER_COUNT + {% endif %} + {% endfor %} + {% endif %} + {% if safe.tray or ignore_safe %} + G1 Z{tray_top + 1} F{travel_spd_z} + G4 P{pressure_release_time} + {% endif %} + {% if safe.brush or ignore_safe %} + BLOBIFIER_CLEAN + {% else %} + G1 X{brush_start} F{travel_spd_xy} + {% endif %} + + # ====================================================================================== + # ==================== RESTORE STATE =================================================== + # ====================================================================================== + G90 # absolute positioning + G1 Z{restore_z} F{travel_spd_z} + + {% if part_cooling_fan >= 0 %} + # Reset part cooling fan if it was changed + M106 S{(backup_fan_speed * 255)|int} + {% endif %} + + M220 S{(backup_feedrate * 100)|int} + {% endif %} + + # Retract the tray + BLOBIFIER_SERVO POS=in + + RESTORE_GCODE_STATE NAME=BLOBIFIER_state + + +########################################################################################## +# Wipes the nozzle on the brass brush +# +[gcode_macro BLOBIFIER_CLEAN] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + {% set original_accel = printer.toolhead.max_accel %} + {% set original_minimum_cruise_ratio = printer.toolhead.minimum_cruise_ratio %} + {% set pos = printer.gcode_move.gcode_position %} + + SAVE_GCODE_STATE NAME=BLOBIFIER_CLEAN_state + + G90 + + {% if bl.brush_accel > 0 %} + SET_VELOCITY_LIMIT ACCEL={bl.brush_accel} MINIMUM_CRUISE_RATIO=0.1 + {% endif %} + + {% if pos.z < bl.brush_top + bl.clearance_z %} + G1 Z{bl.brush_top + bl.clearance_z} F{bl.travel_spd_z} + {% endif %} + G1 X{bl.brush_start} F{bl.travel_spd_xy} + G1 Y{position_y} + G1 Z{bl.brush_top + bl.clearance_z} F{bl.travel_spd_z} + + # Move nozzle down into brush. + G1 Z{bl.brush_top} F{bl.travel_spd_z} + + SET_VELOCITY_LIMIT ACCEL={original_accel} MINIMUM_CRUISE_RATIO={original_minimum_cruise_ratio} + + # Perform wipe. Wipe direction based off bucket_pos for cool random scrubby routine. + {% for wipes in range(1, (bl.wipe_qty + 1)) %} + G1 X{bl.brush_start + bl.brush_width} F{bl.wipe_spd_xy} + G1 X{bl.brush_start} F{bl.wipe_spd_xy} + {% endfor %} + + # Move away from the brush, but not onto the tray or in front of the filametrix cutter pin + G1 X{[bl.brush_start - 20, 30]|max} F{bl.travel_spd_xy} + + RESTORE_GCODE_STATE NAME=BLOBIFIER_CLEAN_state + + + +########################################################################################## +# Park the nozzle on the tray to prevent oozing during filament swaps. Place this +# extension in the post_form_tip extension in mmu_macro_vars.cfg: +# variable_user_post_form_tip_extension: "BLOBIFIER_PARK" +# +[gcode_macro BLOBIFIER_PARK] +variable_restore_z: 0 +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos = printer.gcode_move.gcode_position %} + {% set safe = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'] %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + + SET_GCODE_VARIABLE MACRO=BLOBIFIER_PARK VARIABLE=restore_z VALUE={pos.z} + + SAVE_GCODE_STATE NAME=blobifier_park_state + + {% if "xyz" in printer.toolhead.homed_axes and printer.quad_gantry_level and printer.quad_gantry_level.applied %} + G90 + + # Retract the tray + BLOBIFIER_SERVO POS=in + + G1 X{[bl.brush_start - 20, 30]|max} Y{position_y} F{bl.travel_spd_xy} + {% if safe.tray or ignore_safe %} + G1 Z{bl.tray_top} F{bl.travel_spd_z} + {% endif %} + G1 X{bl.purge_x} F{bl.travel_spd_xy} + + # Extend the tray + BLOBIFIER_SERVO POS=out + + {% else %} + RESPOND MSG="Please home (and QGL) before parking" + {% endif %} + + RESTORE_GCODE_STATE NAME=blobifier_park_state + +########################################################################################## +# Retract or extend the tray +# POS=[in|out] Retractor extend the tray +# +[gcode_macro BLOBIFIER_SERVO] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos = params.POS %} + {% if pos == "in" %} + SET_SERVO SERVO=blobifier ANGLE={bl.tray_angle_in} + G4 P{bl.dwell_time} + {% elif pos == "out" %} + SET_SERVO SERVO=blobifier ANGLE={bl.tray_angle_out} + G4 P{bl.dwell_time} + {% else %} + {action_respond_info("BLOBIFIER: provide POS=[in|out]")} + {% endif %} + SET_SERVO SERVO=blobifier WIDTH=0 + +########################################################################################## +# Define exclude objects for those who haven't already +# +[exclude_object] + +########################################################################################## +# Overwrite the existing EXCLUDE_OBJECT_DEFINE to also check for safe descend. +# +[gcode_macro EXCLUDE_OBJECT_DEFINE] +rename_existing: _EXCLUDE_OBJECT_DEFINE +gcode: + # only reset on the first object at the beginning of a print + {% if printer.exclude_object.objects|length < 1 %} + _BLOBIFIER_RESET_SAFE_DESCEND + {% endif %} + _EXCLUDE_OBJECT_DEFINE {rawparams} + _BLOBIFIER_SAFE_DESCEND + UPDATE_DELAYED_GCODE ID=BLOBIFIER_SHOW_SAFE_DESCEND DURATION=1 + +[delayed_gcode BLOBIFIER_SHOW_SAFE_DESCEND] +gcode: + {% set safe = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'] %} + {action_respond_info( + "BLOBIFIER: Safe descend possible:\n - tray: %s\n - brush: %s\n - shake: %s" % + ( + "yes" if safe.tray else "no", + "yes" if safe.brush else "no", + "yes" if safe.shake else "no" + ) + )} + +########################################################################################## +# Use the EXCLUDE_OBJECT_START gcode macro to record the current height +# +[gcode_macro EXCLUDE_OBJECT_START] +rename_existing: _EXCLUDE_OBJECT_START +gcode: + _EXCLUDE_OBJECT_START {rawparams} + {% if printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'].first_layer %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=first_layer VALUE=False + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_height VALUE={printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'].print_layer_height} + {% else %} + {% set pos = printer.gcode_move.gcode_position %} + {% set last_height = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'].print_previous_height|float %} + {% if pos.z > last_height %} + {% set last_layer = (pos.z - last_height)|round(2) %} + {% set print_height = (pos.z + last_layer)|round(2) %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_previous_height VALUE={pos.z} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_height VALUE={print_height} + {% endif %} + {% endif %} + +########################################################################################## +# Reset the safe descend variables. +# +[gcode_macro _BLOBIFIER_RESET_SAFE_DESCEND] +gcode: + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=tray VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=brush VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=shake VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=first_layer VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_height VALUE=0 + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_previous_height VALUE=0 + +########################################################################################## +# Determine if it is safe to drop the toolhead (e.g. not hit a print) +# +[gcode_macro _BLOBIFIER_SAFE_DESCEND] +variable_tray: True # Assume it is safe +variable_brush: True +variable_shake: True +variable_first_layer: True +variable_print_height: 0 +variable_print_previous_height: 0 +variable_print_layer_height: 0.3 +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + {% set tray = [bl.purge_x + bl.toolhead_x, position_y - bl.toolhead_y] %} + {% set brush = [bl.brush_start + bl.brush_width + bl.toolhead_x, position_y - bl.toolhead_y] %} + {% set shake = [bl.purge_x + bl.toolhead_x, position_y - bl.toolhead_y - 4] %} + {% set objects = printer.exclude_object.objects | map(attribute='polygon') %} + + {% for polygon in objects %} + {% for point in polygon %} + {% if point[0] < tray[0] and point[1] > tray[1] %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=tray VALUE=False + {% endif %} + {% if point[0] < brush[0] and point[1] > brush[1] %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=brush VALUE=False + {% endif %} + {% if point[0] < shake[0] and point[1] > shake[1] %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=shake VALUE=False + {% endif %} + {% endfor %} + {% endfor %} + +########################################################################################## +# Increment the blob count with 1 and check if the bucket is full. Pause +# the printer if it is. +# +[gcode_macro _BLOBIFIER_COUNT] +# Don't change these variables +variable_current_blobs: 0 +variable_last_shake: 0 +variable_next_shake: 0 +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% if current_blobs >= bl.max_blobs %} + {action_respond_info("BLOBIFIER: Empty purge bucket!")} + M117 Empty purge bucket! + MMU_PAUSE MSG="Empty purge bucket!" + {% else %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=current_blobs VALUE={current_blobs + 1} + _BLOBIFIER_SAVE_STATE + {action_respond_info( + "BLOBIFIER: Blobs in bucket: %s/%s. Next shake @ %s" + % (current_blobs + 1, bl.max_blobs, next_shake) + )} + {% endif %} + +########################################################################################## +# Reset the blob count to 0 +# +[gcode_macro _BLOBIFIER_COUNT_RESET] +gcode: + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=current_blobs VALUE=0 + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=last_shake VALUE=0 + _BLOBIFIER_SAVE_STATE + + _BLOBIFIER_CALCULATE_NEXT_SHAKE + +########################################################################################## +# Shake the blob bucket to disperse the blobs +# +[gcode_macro BLOBIFIER_SHAKE_BUCKET] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% set original_accel = printer.toolhead.max_accel %} + {% set original_minimum_cruise_ratio = printer.toolhead.minimum_cruise_ratio %} + {% set position_x = bl.skew_correction %} + + {% if "xyz" not in printer.toolhead.homed_axes %} + {action_raise_error("BLOBIFIER: Not homed. Home xyz first")} + {% endif %} + + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=last_shake VALUE={count.current_blobs} + _BLOBIFIER_SAVE_STATE + SAVE_GCODE_STATE NAME=shake_bucket + + M400 + M117 (^_^) + + G90 + {% set shakes = params.SHAKES|default(10)|int %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + + # move to save y if not already there + {% if printer.toolhead.position.y != position_y %} + G1 X{bl.brush_start} Y{position_y} F{bl.travel_spd_xy} + {% endif %} + + # Retract the tray + BLOBIFIER_SERVO POS=in + + # move up a bit to prevent oozing on base + G1 Z{bl.shaker_arm_z} F{bl.travel_spd_z} + # slide into the slot + G1 X{position_x} F{bl.travel_spd_xy} + + M400 + M117 (+(+_+)+) + + SET_VELOCITY_LIMIT ACCEL={bl.shake_accel} MINIMUM_CRUISE_RATIO=0.1 + + # Shake away! + {% for shake in range(1, shakes) %} + G1 Y{position_y - 4} + G1 Y{position_y} + {% endfor %} + + SET_VELOCITY_LIMIT ACCEL={original_accel} MINIMUM_CRUISE_RATIO={original_minimum_cruise_ratio} + # move out of slot + G1 X{bl.purge_x} + + M400 + M117 (X_x) + + RESTORE_GCODE_STATE NAME=shake_bucket + +########################################################################################## +# Calculate when the bucket should be shaken. +# +[gcode_macro _BLOBIFIER_CALCULATE_NEXT_SHAKE] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + + {% set remaining_blobs = bl.max_blobs - count.last_shake %} + {% set next_shake = (1 - bl.bucket_shake_frequency) * remaining_blobs + count.last_shake %} + _BLOBIFIER_SAVE_STATE + _BLOBIFIER_SET_NEXT_SHAKE VALUE={next_shake|int} + +########################################################################################## +# Set when the bucket should be shaken next +# VALUE=[int] At what amount of blobs should it be shaken +# +[gcode_macro _BLOBIFIER_SET_NEXT_SHAKE] +gcode: + {% if params.VALUE %} + {% set next_shake = params.VALUE %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=next_shake VALUE={next_shake} + _BLOBIFIER_SAVE_STATE + {% else %} + {action_respond_info("BLOBIFIER: Provide parameter VALUE=")} + {% endif %} + +########################################################################################## +# Some sanity checks +# +[delayed_gcode BLOBIFIER_INIT] +initial_duration: 5.0 +gcode: + _BLOBIFIER_INIT + # Extend and retract the tray to test + BLOBIFIER_SERVO POS=out + BLOBIFIER_SERVO POS=in + +[gcode_macro _BLOBIFIER_INIT] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + + # Valid part cooling fan setting + {% if bl.part_cooling_fan != -1 and (bl.part_cooling_fan < 0 or bl.part_cooling_fan > 1) %} + {action_emergency_stop("BLOBIFIER: Value %f is invalid for variable part_cooling_fan. Either -1 or a value from 0 .. 1 is valid." % (bl.part_cooling_fan))} + {% endif %} + + # Valid bucket shake frequency + {% if bl.bucket_shake_frequency < 0 or bl.bucket_shake_frequency > 1 %} + {action_emergency_stop("BLOBIFIER: Value %f is invalid for variable bucket_shake_frequency. Change it to a value between 0 .. 1" % (bl.bucket_shake_frequency))} + {% endif %} + + # Check if position is on 'next' + {% if printer.mmu %} + {% if printer['gcode_macro _MMU_SEQUENCE_VARS'].restore_xy_pos != 'next' %} + {action_respond_info("BLOBIFIER: If not using a wipe tower, consider setting restore_xy_pos: 'next' in mmu_macro_vars.cfg")} + {% endif %} + {% endif %} + + # Check the z_raise variable for normal values + {% if bl.z_raise < 3 %} + {action_respond_info("BLOBIFIER: variable_z_raise: %f is very low. This is the value z raises in total on a single blob. Make sure the value is correct before continuing." % (bl.z_raise))} + {% endif %} + + # Z raise exponent + {% if bl.z_raise_exp > 1 or bl.z_raise_exp < 0.5 %} + {action_respond_info("BLOBIFIER: variable_z_raise_exp has value: %f. This value is out of spec (0.5 ... 1.0)." % (bl.z_raise_exp))} + {% endif %} + + # cap user defined accels at printer max_accel if greater + {% if bl.shake_accel > printer.configfile.config.printer.max_accel|int %} + {action_respond_info("BLOBIFIER: variable_shake_accel has value: %d which is higher than your printer limit of %d. Reduce this if your printer skips steps." % (bl.shake_accel,printer.configfile.config.printer.max_accel|int))} + {% endif %} + {% if bl.brush_accel > printer.configfile.config.printer.max_accel|int %} + {action_respond_info("BLOBIFIER: variable_brush_accel has value: %d which is higher than your printer limit of %d. Reduce this if your printer skips steps." % (bl.brush_accel,printer.configfile.config.printer.max_accel|int))} + {% endif %} + +[delayed_gcode BLOBIFIER_LOAD_STATE] +initial_duration: 2.0 # Give it some time to boot up +gcode: + {% set sv = printer.save_variables.variables.blobifier %} + + {% if sv %} + # Restore state + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=last_shake VALUE={sv.last_shake} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=current_blobs VALUE={sv.current_blobs} + {% endif %} + _BLOBIFIER_CALCULATE_NEXT_SHAKE + +[gcode_macro _BLOBIFIER_SAVE_STATE] +gcode: + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% set sv = {'current_blobs': count.current_blobs, 'last_shake': count.last_shake} %} + SAVE_VARIABLE VARIABLE=blobifier VALUE="{sv}" diff --git a/mmu-20250423_130617/addons/blobifier_hw.cfg b/mmu-20250423_130617/addons/blobifier_hw.cfg new file mode 100644 index 0000000..5f76ae8 --- /dev/null +++ b/mmu-20250423_130617/addons/blobifier_hw.cfg @@ -0,0 +1,28 @@ + +########################################################################################## +# The servo hardware configuration. Change the values to your needs. +# +[mmu_servo blobifier] +# Pin for the servo. +pin: PG14 +# Adjust this value until a 'BLOBIFIER_SERVO POS=out' extends the tray fully without a +# buzzing sound +minimum_pulse_width: 0.00053 +# Adjust this value until a 'BLOBIFIER_SERVO POS=in' retracts the tray fully without a +# buzzing sound +maximum_pulse_width: 0.0023 +# Leave this value at 180 +maximum_servo_angle: 180 + + +########################################################################################## +# The bucket hardware configuration. Change the pin to whatever pin you've connected the +# switch to. +# +[gcode_button bucket] +pin: ^PG15 # The pullup ( ^ ) is important here. +press_gcode: + M117 bucket installed +release_gcode: + M117 bucket removed + _BLOBIFIER_COUNT_RESET diff --git a/mmu/addons/dc_espooler.cfg b/mmu-20250423_130617/addons/dc_espooler.cfg similarity index 100% rename from mmu/addons/dc_espooler.cfg rename to mmu-20250423_130617/addons/dc_espooler.cfg diff --git a/mmu/addons/dc_espooler_hw.cfg b/mmu-20250423_130617/addons/dc_espooler_hw.cfg similarity index 100% rename from mmu/addons/dc_espooler_hw.cfg rename to mmu-20250423_130617/addons/dc_espooler_hw.cfg diff --git a/mmu-20250423_130617/addons/mmu_eject_buttons.cfg b/mmu-20250423_130617/addons/mmu_eject_buttons.cfg new file mode 100644 index 0000000..59080b6 --- /dev/null +++ b/mmu-20250423_130617/addons/mmu_eject_buttons.cfg @@ -0,0 +1,31 @@ +# Include servo hardware definition separately to allow for automatic upgrade +[include mmu_eject_buttons_hw.cfg] + +########################################################################### +# Optional hardware MMU eject buttons (e.g. QuattroBox) +# +# This is the supplementary macro to support dedicated per-gate eject +# buttons for easy unloading. It is complimentary to the built-in auto +# preload of filament +# +# To configure: +# 1. Add this to your printer.cfg: +# +# [include mmu/addons/mmu_eject_buttons.cfg] +# + +########################################################################### +# Macro to simply call MMU_EJECT for the specified gate +# +# This logic is separated from actual button h/w setup to facilitate upgrades +# and to allow addition of logic (perhaps validation or warning logic) +# +[gcode_macro _MMU_EJECT_BUTTON] +description: Wrapper around ejecting filament via dedicated hardware buttons +gcode: + {% set gate = params.GATE|default(-1)|int %} + {% set mmu = printer['mmu'] %} + {% set current_gate = mmu.gate %} + + # TODO add validation and warning logic + MMU_EJECT GATE={gate} diff --git a/mmu-20250423_130617/addons/mmu_eject_buttons_hw.cfg b/mmu-20250423_130617/addons/mmu_eject_buttons_hw.cfg new file mode 100644 index 0000000..693ee57 --- /dev/null +++ b/mmu-20250423_130617/addons/mmu_eject_buttons_hw.cfg @@ -0,0 +1,21 @@ + +########################################################################################## +# The eject button hardware configuration. Change the values to your needs and number +# of gates +# + +[gcode_button mmu_eject_button_0] +pin: mmu:EJECT_BUTTON_0 +press_gcode: _MMU_EJECT_BUTTON GATE=0 + +[gcode_button mmu_eject_button_1] +pin: mmu:EJECT_BUTTON_1 +press_gcode: _MMU_EJECT_BUTTON GATE=1 + +[gcode_button mmu_eject_button_2] +pin: mmu:EJECT_BUTTON_2 +press_gcode: _MMU_EJECT_BUTTON GATE=2 + +[gcode_button mmu_eject_button_3] +pin: mmu:EJECT_BUTTON_3 +press_gcode: _MMU_EJECT_BUTTON GATE=3 diff --git a/mmu-20250423_130617/addons/mmu_erec_cutter.cfg b/mmu-20250423_130617/addons/mmu_erec_cutter.cfg new file mode 100644 index 0000000..12e1d53 --- /dev/null +++ b/mmu-20250423_130617/addons/mmu_erec_cutter.cfg @@ -0,0 +1,91 @@ +# Include servo hardware definition separately to allow for automatic upgrade +[include mmu_erec_cutter_hw.cfg] + +########################################################################### +# Optional EREC Filament Cutter Support +# +# https://github.com/kevinakasam/ERCF_Filament_Cutter +# +# This is the supplementary macro to support filament cutting at the MMU +# on a ERCF design. +# +# To configure: +# 1. Add this to your printer.cfg: +# +# [include mmu/addons/mmu_erec_cutter.cfg] +# +# 2. In mmu_macro_vars.cfg, change this line: +# +# variable_user_post_unload_extension : "EREC_CUTTER_ACTION" +# +# 3. Tune the servo configuration and macro "variables" below +# + +# EREC CUTTER CONFIGURATION ----------------------------------------------- +# (addons/mmu_erec_cutter.cfg) +# +[gcode_macro _EREC_VARS] +description: Empty macro to store the variables +gcode: # Leave empty + +# These variables control the servo movement +variable_servo_closed_angle : 70 ; Servo angle for closed position with bowden aligned MMU +variable_servo_open_angle : 10 ; Servo angle to open up the cutter and move bowden away from MMU +variable_servo_duration : 1.5 ; Time (s) of PWM pulse train to activate servo +variable_servo_idle_time : 1.8 ; Time (s) to let the servo to reach it's position + +# Controls for feed and cut lengths +variable_feed_length : 48 ; Distance in mm from gate parking position to blade (ERCFv1.1: 58, v2/other: 48) +variable_cut_length : 10 ; Amount in mm of filament to cut +variable_cut_attempts : 1 ; Number of times the cutter tries to cut the filament + + +########################################################################### +# Macro to perform the cutting step. Designed to be included to the +# _MMU_POST_UNLOAD step +# +[gcode_macro EREC_CUTTER_ACTION] +description: Cut off the filament tip at the MMU after the unload sequence is complete +gcode: + {% set vars = printer["gcode_macro _EREC_VARS"] %} + + MMU_LOG MSG="Cutting filament tip..." + + _CUTTER_OPEN + _MMU_STEP_MOVE MOVE={vars.feed_length + vars.cut_length} + {% for i in range(vars.cut_attempts - 1) %} + _CUTTER_CLOSE + _CUTTER_OPEN + {% endfor %} + _MMU_STEP_MOVE MOVE=-1 + _CUTTER_CLOSE + _MMU_EVENT EVENT="filament_cut" # Count as one cut for consumption counter + + _MMU_STEP_SET_FILAMENT STATE=2 # FILAMENT_POS_START_BOWDEN + _MMU_STEP_UNLOAD_GATE # Repeat gate parking move + _MMU_M400 # Wait on both move queues + +[gcode_macro _CUTTER_ANGLE] +description: Helper macro to set cutter servo angle +gcode: + {% set angle = params.ANGLE|default(0)|int %} + SET_SERVO SERVO=cut_servo ANGLE={angle} + +[gcode_macro _CUTTER_CLOSE] +description: Helper macro to set cutting servo the closed position +gcode: + {% set vars = printer["gcode_macro _EREC_VARS"] %} + SET_SERVO SERVO=cut_servo ANGLE={vars.servo_closed_angle} DURATION={vars.servo_duration} + G4 P{vars.servo_idle_time * 1000} + RESPOND MSG="EREC Cutter closed" + M400 + +[gcode_macro _CUTTER_OPEN] +description: Helper macro to set cutting servo the open position +gcode: + {% set vars = printer["gcode_macro _EREC_VARS"] %} + SET_SERVO SERVO=cut_servo ANGLE={vars.servo_open_angle} DURATION={vars.servo_duration} + G4 P{vars.servo_idle_time * 1000} + RESPOND MSG="EREC Cutter open" + M400 + diff --git a/mmu-20250423_130617/addons/mmu_erec_cutter_hw.cfg b/mmu-20250423_130617/addons/mmu_erec_cutter_hw.cfg new file mode 100644 index 0000000..4fec0c1 --- /dev/null +++ b/mmu-20250423_130617/addons/mmu_erec_cutter_hw.cfg @@ -0,0 +1,10 @@ + +########################################################################################## +# The servo hardware configuration. Change the values to your needs. +# +[mmu_servo cut_servo] +pin: mmu:PA7 # Extra Pin on the ERCF easy Board +maximum_servo_angle: 180 # Set this to 60 for a 60° Servo +minimum_pulse_width: 0.0005 # Adapt these for your servo +maximum_pulse_width: 0.0025 # Adapt these for your servo + diff --git a/mmu-20250423_130617/base/mmu.cfg b/mmu-20250423_130617/base/mmu.cfg new file mode 100644 index 0000000..3ff44dc --- /dev/null +++ b/mmu-20250423_130617/base/mmu.cfg @@ -0,0 +1,154 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Happy Hare MMU hardware pin config +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# +# This contains aliases for pins for MCU type MMB11 +# +#[mcu oldmmu] +#canbus_uuid: 214adf7db8eb # Change to `canbus_uuid: 1234567890` for CANbus setups + +[mcu mmu] +canbus_uuid: 029f6dc0d75b + +# PIN ALIASES FOR MMU MCU BOARD ---------------------------------------------------------------------------------------- +# ██████╗ ██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗ ███████╗ +# ██╔══██╗██║████╗ ██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝ +# ██████╔╝██║██╔██╗ ██║ ███████║██║ ██║███████║███████╗ +# ██╔═══╝ ██║██║╚██╗██║ ██╔══██║██║ ██║██╔══██║╚════██║ +# ██║ ██║██║ ╚████║ ██║ ██║███████╗██║██║ ██║███████║ +# ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═╝╚══════╝ +# Section to create alias for pins used by MMU for easier integration into Klippain and RatOS. The names match those +# referenced in the mmu_hardware.cfg file. If you get into difficulty you can also comment out this aliases definition +# completely and configure the pin names directly into mmu_hardware.cfg. However, use of aliases is encouraged. + +# Note: that aliases are not created for TOOLHEAD_SENSOR, EXTRUDER_SENSOR or SYNC_FEEDBACK_SENSORS because those are +# most likely on the printer's main mcu. These should be set directly in mmu_hardware.cfg +# +# [board_pins oldmmu] +# mcu: mmu # Assumes using an external / extra mcu dedicated to MMU +# aliases: +# MMU_GEAR_UART=PA10, +# MMU_GEAR_STEP=PB15, +# MMU_GEAR_DIR=PB14, +# MMU_GEAR_ENABLE=PB8, +# MMU_GEAR_DIAG=PA3, + +# MMU_GEAR_UART_1=, +# MMU_GEAR_STEP_1=, +# MMU_GEAR_DIR_1=, +# MMU_GEAR_ENABLE_1=, +# MMU_GEAR_DIAG_1=, + +# MMU_GEAR_UART_2=, +# MMU_GEAR_STEP_2=, +# MMU_GEAR_DIR_2=, +# MMU_GEAR_ENABLE_2=, +# MMU_GEAR_DIAG_2=, + +# MMU_GEAR_UART_3=, +# MMU_GEAR_STEP_3=, +# MMU_GEAR_DIR_3=, +# MMU_GEAR_ENABLE_3=, +# MMU_GEAR_DIAG_3=, + +# MMU_SEL_UART=PC7, +# MMU_SEL_STEP=PD2, +# MMU_SEL_DIR=PB13, +# MMU_SEL_ENABLE=PD1, +# MMU_SEL_DIAG=PA4, +# MMU_SEL_ENDSTOP=PB2, +# MMU_SEL_SERVO=PA0, + +# MMU_ENCODER=PA1, +# MMU_GATE_SENSOR=, +# MMU_NEOPIXEL=PA2, + +# MMU_PRE_GATE_0=, +# MMU_PRE_GATE_1=PA3, +# MMU_PRE_GATE_2=, +# MMU_PRE_GATE_3=, +# MMU_PRE_GATE_4=, +# MMU_PRE_GATE_5=, +# MMU_PRE_GATE_6=, +# MMU_PRE_GATE_7=, +# MMU_PRE_GATE_8=, +# MMU_PRE_GATE_9=, +# MMU_PRE_GATE_10=, +# MMU_PRE_GATE_11=, + +# MMU_POST_GEAR_0=, +# MMU_POST_GEAR_1=, +# MMU_POST_GEAR_2=, +# MMU_POST_GEAR_3=, +# MMU_POST_GEAR_4=, +# MMU_POST_GEAR_5=, +# MMU_POST_GEAR_6=, +# MMU_POST_GEAR_7=, +# MMU_POST_GEAR_8=, +# MMU_POST_GEAR_9=, +# MMU_POST_GEAR_10=, +# MMU_POST_GEAR_11=, + +[board_pins mmu] +mcu: mmu # Assumes using an external / extra mcu dedicated to MMU +aliases: + MMU_GEAR_UART=gpio9, + MMU_GEAR_STEP=gpio7, + MMU_GEAR_DIR=gpio8, + MMU_GEAR_ENABLE=gpio6, + MMU_GEAR_DIAG=gpio23, + + MMU_SEL_UART=gpio0, + MMU_SEL_STEP=gpio2, + MMU_SEL_DIR=gpio1, + MMU_SEL_ENABLE=gpio3, + MMU_SEL_DIAG=gpio22, + + MMU_SEL_ENDSTOP=gpio20, + MMU_SEL_SERVO=gpio21, + + MMU_ENCODER=gpio15, + MMU_NEOPIXEL=gpio14, + MMU_GATE_SENSOR=, + + MMU_PRE_GATE_0=gpio10, + MMU_PRE_GATE_1=gpio11, + MMU_PRE_GATE_2=gpio12, + MMU_PRE_GATE_3=gpio24, + MMU_PRE_GATE_4=gpio13, + MMU_PRE_GATE_5=gpio26, + MMU_PRE_GATE_6=gpio27, + MMU_PRE_GATE_7=gpio28, + MMU_PRE_GATE_8=, + MMU_PRE_GATE_9=, + MMU_PRE_GATE_10=, + MMU_PRE_GATE_11=, + + MMU_POST_GEAR_0=, + MMU_POST_GEAR_1=, + MMU_POST_GEAR_2=, + MMU_POST_GEAR_3=, + MMU_POST_GEAR_4=, + MMU_POST_GEAR_5=, + MMU_POST_GEAR_6=, + MMU_POST_GEAR_7=, + MMU_POST_GEAR_8=, + MMU_POST_GEAR_9=, + MMU_POST_GEAR_10=, + MMU_POST_GEAR_11=, + +[temperature_sensor MMB] +sensor_type: temperature_mcu +sensor_mcu: mmu diff --git a/mmu-20250423_130617/base/mmu_cut_tip.cfg b/mmu-20250423_130617/base/mmu_cut_tip.cfg new file mode 120000 index 0000000..12b45af --- /dev/null +++ b/mmu-20250423_130617/base/mmu_cut_tip.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_cut_tip.cfg \ No newline at end of file diff --git a/mmu-20250423_130617/base/mmu_form_tip.cfg b/mmu-20250423_130617/base/mmu_form_tip.cfg new file mode 120000 index 0000000..e2b93da --- /dev/null +++ b/mmu-20250423_130617/base/mmu_form_tip.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_form_tip.cfg \ No newline at end of file diff --git a/mmu-20250423_130617/base/mmu_hardware.cfg b/mmu-20250423_130617/base/mmu_hardware.cfg new file mode 100644 index 0000000..fc44d73 --- /dev/null +++ b/mmu-20250423_130617/base/mmu_hardware.cfg @@ -0,0 +1,368 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Happy Hare MMU hardware config file with config for MMB11 MCU board +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# +# Notes about setup of common external MCUs can be found here: +# https://github.com/moggieuk/Happy-Hare/blob/main/doc/mcu_notes.md +# +# Note about "touch" endstops: Happy Hare provides extremely flexible homing options using both single steppers or +# synced steppers. The "touch" option leverages stallguard and thus requires the appropriate 'diag_pin' and stallguard +# parameters set on the TMC driver section. If you have the diag_pin exposed, it is harmless to define this because +# they will only be used when explicitly needed and configured. +# +# Touch option for each stepper provides these benefits / possibilities (experimental): +# - on extruder stepper allows for the automatic detection of the nozzle! +# - on selector stepper allows for the automatic detection of filament stuck in the gate and subsequent recovery +# - on gear stepper allows for the automatic detection of the extruder entrance +# +# These sound wonderful right? They are, but there are caveats: +# - Some external MCUs are terrible at detecting stallguard and often result in an "undervoltage error" +# It is generally possible to get selector touch (TMC2209) tuned especially if you set 'stealthchop_threshold' +# to a value greater than homing speeds and less than move speed. I.e. the stepper runs in stealthchop mode when +# homing. [klipper experts will know that it switches the chip mode automatically to stealthchop and then back for +# Stallguard2 support, however the automatic switching back to spreadcycle at the end homing move seems to provoke +# the error condition and setting 'stealthchop_threshold' appropriately avoids this condition. More than you wanted +# to know I'm sure! +# - I have not had much luck with touch (stallguard) on the gear stepper with EASY-BRD and ERB MCUs and you really +# want the extra torque of spreadcycle so adjusting 'stealthchop_threshold' is not really an option +# - Enabling on the extruder stepper is viable but you will likely have to change jumpers on your main mcu to expose +# the DIAG pin for whichever driver the extruder stepper is connected to. +# +# In summary, "touch" homing with your MMU is an advanced option that requires patience and careful tuning. Everything +# works with regular endstops and there are workaround options for certain homing points (like extruder entry) in +# the absence of any endstop. I'm really interested in creative setups. Ping me on Discord (moggieuk#6538) +# +# See 'mmu.cfg' for serial definition and pins aliases +# +# HOMING CAPABLE EXTRUDER (VERY ADVANCED) ----------------------------------------------------------------------------- +# With Happy Hare installed even the extruder can be homed. You will find the usual 'endstop' parameters can be added +# to your '[extruder]' section. Useless you have some clever load cell attached to your nozzle it only really makes +# sense to configure stallguard style "touch" homing. To do this add lines similar to this to your existing +# '[extruder]' definition in printer.cfg. +# +# [extruder] +# endstop_pin: tmc2209_extruder:virtual_endstop +# +# Also be sure to add the appropriate stallguard config to the TMC section, e.g. +# +# [tmc2209 extruder] +# diag_pin: E_DIAG # Set to MCU pin connected to TMC DIAG pin for extruder +# driver_SGTHRS: 100 # 255 is most sensitive value, 0 is least sensitive +# +# Happy Hare will take care of the rest and add a 'mmu_ext_touch' endstop automatically +# + + +# MMU MACHINE / TYPE --------------------------------------------------------------------------------------------------- +# ███╗ ███╗███╗ ███╗██╗ ██╗ ███╗ ███╗ █████╗ ██████╗██╗ ██╗██╗███╗ ██╗███████╗ +# ████╗ ████║████╗ ████║██║ ██║ ████╗ ████║██╔══██╗██╔════╝██║ ██║██║████╗ ██║██╔════╝ +# ██╔████╔██║██╔████╔██║██║ ██║ ██╔████╔██║███████║██║ ███████║██║██╔██╗ ██║█████╗ +# ██║╚██╔╝██║██║╚██╔╝██║██║ ██║ ██║╚██╔╝██║██╔══██║██║ ██╔══██║██║██║╚██╗██║██╔══╝ +# ██║ ╚═╝ ██║██║ ╚═╝ ██║╚██████╔╝ ██║ ╚═╝ ██║██║ ██║╚██████╗██║ ██║██║██║ ╚████║███████╗ +# ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚══════╝ +[mmu_machine] + +# Number of selectable gate on (each) MMU. Generally this is a single number, but with multi-mmu (type-B) setups +# it can be a comma separated list of the number of gates per unit. +# E.g. 'num_gates: 4,4,2' for a 2xBox Turtle and 1xNight Owl multiplexed setup +# +num_gates: 8 + +# MMU Vendor & Version is used to automatically configure some parameters and validate configuration +# If custom set to "Other" and uncomment the additional parameters below +# +# ERCF 1.1 add "s" suffix for Springy, "b" for Binky, "t" for Triple-Decky +# e.g. "1.1sb" for v1.1 with Springy mod and Binky encoder +# ERCF 2.0 community edition ERCFv2 +# Tradrack 1.0 add "e" if encoder is fitted (assumed to be Binky) +# AngryBeaver 1.0 +# BoxTurtle 1.0 +# NightOwl 1.0 +# 3MS 1.0 +# 3D Chameleon 1.0 +# Prusa 3.0 NOT YET SUPPORTED - COMING SOON +# Other Generic setup that may require further customization of 'cad' parameters. See doc in mmu_parameters.cfg +# +mmu_vendor: ERCF # MMU family +mmu_version: 2.0 # MMU hardware version number (add mod suffix documented above) + +# The following attributes are set internally from vendor/version above. Only uncomment to customize the vendor +# default or for custom ("Other") designs +# +#selector_type: LinearSelector # E.g. LinearSelector (type-A), VirtualSelector (type-B), MacroSelector, RotarySelector, ... +#variable_bowden_lengths: 0 # 1 = If MMU design has different bowden lengths per gate, 0 = bowden length is the same +#variable_rotation_distances: 1 # 1 = If MMU design has dissimilar drive/BMG gears, thus rotation distance, 0 = One drive gear (e.g. Tradrack) +#require_bowden_move: 1 # 1 = If MMU design has bowden move that is included in load/unload, 0 = zero length bowden (skip bowden move) +#filament_always_gripped: 0 # 1 = Filament is always trapped by MMU (most type-B designs), 0 = MMU can release filament +#has_bypass: 0 # 1 = Bypass gate available, 0 = No filament bypass possible + +# Uncomment to change the display name in UI's. Defaults to the vendor name +#display_name: My Precious + +homing_extruder: 1 # CAUTION: Normally this should be 1. 0 will disable the homing extruder capability + + +# FILAMENT DRIVE GEAR STEPPER(S) -------------------------------------------------------------------------------------- +# ██████╗ ███████╗ █████╗ ██████╗ +# ██╔════╝ ██╔════╝██╔══██╗██╔══██╗ +# ██║ ███╗█████╗ ███████║██████╔╝ +# ██║ ██║██╔══╝ ██╔══██║██╔══██╗ +# ╚██████╔╝███████╗██║ ██║██║ ██║ +# ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ +# Note that 'toolhead' & 'mmu_gear' endstops will automatically be added if a toolhead sensor or gate sensor is defined +# +# The default values are tested with the ERCF BOM NEMA14 motor. Please adapt these values to the motor you are using +# Example : for NEMA17 motors, you'll usually use higher current +# +# [tmc2209 stepper_mmu_gear] +# uart_pin: mmu:MMU_GEAR_UART +# run_current: 1.1 # ERCF v2.5 BOM NEMA17 motor +# hold_current: 0.1 # Recommend to be small if not using "touch" or move (TMC stallguard) +# interpolate: True +# sense_resistor: 0.110 # Usually 0.11, 0.15 for BTT TMC2226 +# stealthchop_threshold: 0 # Spreadcycle has more torque and better at speed +# +# Uncomment two lines below if you have TMC and want the ability to use filament "touch" homing with gear stepper +#diag_pin: ^mmu:MMU_GEAR_DIAG # Set to MCU pin connected to TMC DIAG pin for gear stepper +#driver_SGTHRS: 60 # 255 is most sensitive value, 0 is least sensitive + +[stepper_mmu_gear] +step_pin: mmu:MMU_GEAR_STEP +dir_pin: mmu:MMU_GEAR_DIR +enable_pin: !mmu:MMU_GEAR_ENABLE +rotation_distance: 22.7316868 # Bondtech 5mm Drive Gears. Overridden by 'mmu_gear_rotation_distance' in mmu_vars.cfg +#gear_ratio: 80:20 # ERCF v2.5 is direct drive +microsteps: 16 # Recommend 16. Increase only if you "step compress" issues when syncing +full_steps_per_rotation: 200 # 200 for 1.8 degree, 400 for 0.9 degree +# +# Uncomment the two lines below to enable filament "touch" homing option with gear motor +#extra_endstop_pins: tmc2209_stepper_mmu_gear:virtual_endstop +#extra_endstop_names: mmu_gear_touch + + + +# SELECTOR STEPPER ---------------------------------------------------------------------------------------------------- +# ███████╗███████╗██╗ ███████╗ ██████╗████████╗ ██████╗ ██████╗ +# ██╔════╝██╔════╝██║ ██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ +# ███████╗█████╗ ██║ █████╗ ██║ ██║ ██║ ██║██████╔╝ +# ╚════██║██╔══╝ ██║ ██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ +# ███████║███████╗███████╗███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ +# ╚══════╝╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ +# Consult doc if you want to setup selector for "touch" homing instead or physical endstop +# +[tmc2209 stepper_mmu_selector] +uart_pin: mmu:MMU_SEL_UART +run_current: 0.8 # ERCF BOM NEMA17 motor +hold_current: 0.6 # Can be small if not using "touch" movement (TMC stallguard) +interpolate: True +sense_resistor: 0.110 +stealthchop_threshold: 100 # Stallguard "touch" movement (slower speeds) best done with stealthchop +# +# Uncomment two lines below if you have TMC and want to use selector "touch" movement +#diag_pin: ^mmu:MMU_SEL_DIAG # Set to MCU pin connected to TMC DIAG pin for selector stepper +#driver_SGTHRS: 75 # 255 is most sensitive value, 0 is least sensitive + +[stepper_mmu_selector] +step_pin: mmu:MMU_SEL_STEP +dir_pin: !mmu:MMU_SEL_DIR +enable_pin: !mmu:MMU_SEL_ENABLE +rotation_distance: 40 +microsteps: 16 # Don't need high fidelity +full_steps_per_rotation: 200 # 200 for 1.8 degree, 400 for 0.9 degree +endstop_pin: ^mmu:MMU_SEL_ENDSTOP # Selector microswitch +endstop_name: mmu_sel_home +# Uncomment this line only if default endstop above is using stallguard +#homing_retract_dist: 0 +# +# Uncomment two lines below to give option of selector "touch" movement +#extra_endstop_pins: tmc2209_stepper_mmu_selector:virtual_endstop +#extra_endstop_names: mmu_sel_touch + + +# SERVOS --------------------------------------------------------------------------------------------------------------- +# ███████╗███████╗██████╗ ██╗ ██╗ ██████╗ ███████╗ +# ██╔════╝██╔════╝██╔══██╗██║ ██║██╔═══██╗██╔════╝ +# ███████╗█████╗ ██████╔╝██║ ██║██║ ██║███████╗ +# ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║ ██║╚════██║ +# ███████║███████╗██║ ██║ ╚████╔╝ ╚██████╔╝███████║ +# ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ +# Basic servo PWM setup. If these values are changed then the angles defined for different positions will also change +# +# SELECTOR SERVO ------------------------------------------------------------------------------------------------------- +# +[mmu_servo selector_servo] +pin: mmu:MMU_SEL_SERVO +maximum_servo_angle: 180 +minimum_pulse_width: 0.00085 +maximum_pulse_width: 0.00215 +# +# OPTIONAL GANTRY SERVO FOR TOOLHEAD FILAMENT CUTTER ------------------------------------------------------------------ +# +# (uncomment this section if you have a gantry servo for toolhead cutter pin) +#[mmu_servo mmu_gantry_servo] +#pin: +#maximum_servo_angle:180 +#minimum_pulse_width: 0.00075 +#maximum_pulse_width: 0.00225 +#initial_angle: 180 + + +# FILAMENT SENSORS ----------------------------------------------------------------------------------------------------- +# ███████╗███████╗███╗ ██╗███████╗ ██████╗ ██████╗ ███████╗ +# ██╔════╝██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝ +# ███████╗█████╗ ██╔██╗ ██║███████╗██║ ██║██████╔╝███████╗ +# ╚════██║██╔══╝ ██║╚██╗██║╚════██║██║ ██║██╔══██╗╚════██║ +# ███████║███████╗██║ ╚████║███████║╚██████╔╝██║ ██║███████║ +# ╚══════╝╚══════╝╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ +# Define the pins for optional sensors in the filament path. All but the pre-gate sensors will be automatically setup as +# both endstops (for homing) and sensors for visibility purposes. +# +# 'pre_gate_switch_pin_X' .. 'mmu_pre_gate_X' sensor detects filament at entry to MMU. X=gate number (0..N) +# 'gate_switch_pin' .. 'mmu_gate' shared sensor detects filament past the gate of the MMU +# or +# 'post_gear_switch_pin_X' .. 'mmu_gear_X' post gear sensor for each filament +# 'extruder_switch_pin' .. 'extruder' sensor detects filament just before the extruder entry +# 'toolhead_switch_pin' .. 'toolhead' sensor detects filament after extruder entry +# +# Sync motor feedback will typically have a tension switch (most important for syncing) or both tension and compression. +# Note that compression switch is useful for use as a endstop to detect hitting the extruder entrance +# 'sync_feedback_tension_pin' .. pin for switch activated when filament is under tension +# 'sync_feedback_compression_pin' .. pin for switch activated when filament is under compression +# +# Configuration is flexible: Simply define pins for any sensor you want to enable, if pin is not set (or the alias is empty) +# it will be ignored. You can also just comment out what you are not using. +# +[mmu_sensors] +pre_gate_switch_pin_0: ^mmu:MMU_PRE_GATE_0 +pre_gate_switch_pin_1: ^mmu:MMU_PRE_GATE_1 +pre_gate_switch_pin_2: ^mmu:MMU_PRE_GATE_2 +pre_gate_switch_pin_3: ^mmu:MMU_PRE_GATE_3 +pre_gate_switch_pin_4: ^mmu:MMU_PRE_GATE_4 +pre_gate_switch_pin_5: ^mmu:MMU_PRE_GATE_5 +pre_gate_switch_pin_6: ^mmu:MMU_PRE_GATE_6 +pre_gate_switch_pin_7: ^mmu:MMU_PRE_GATE_7 +pre_gate_switch_pin_8: ^mmu:MMU_PRE_GATE_8 +pre_gate_switch_pin_9: ^mmu:MMU_PRE_GATE_9 +pre_gate_switch_pin_10: ^mmu:MMU_PRE_GATE_10 +pre_gate_switch_pin_11: ^mmu:MMU_PRE_GATE_11 + +post_gear_switch_pin_0: ^mmu:MMU_POST_GEAR_0 +post_gear_switch_pin_1: ^mmu:MMU_POST_GEAR_1 +post_gear_switch_pin_2: ^mmu:MMU_POST_GEAR_2 +post_gear_switch_pin_3: ^mmu:MMU_POST_GEAR_3 +post_gear_switch_pin_4: ^mmu:MMU_POST_GEAR_4 +post_gear_switch_pin_5: ^mmu:MMU_POST_GEAR_5 +post_gear_switch_pin_6: ^mmu:MMU_POST_GEAR_6 +post_gear_switch_pin_7: ^mmu:MMU_POST_GEAR_7 +post_gear_switch_pin_8: ^mmu:MMU_POST_GEAR_8 +post_gear_switch_pin_9: ^mmu:MMU_POST_GEAR_9 +post_gear_switch_pin_10: ^mmu:MMU_POST_GEAR_10 +post_gear_switch_pin_11: ^mmu:MMU_POST_GEAR_11 + +# These sensors can be replicated in a multi-mmu, type-B setup (see num_gates comment). +# If so, then use a comma separated list of per-unit pins instead of single pin +gate_switch_pin: ^mmu:MMU_GATE_SENSOR +sync_feedback_tension_pin: +sync_feedback_compression_pin: + +# These sensors are on the toolhead and often controlled by the main printer mcu +extruder_switch_pin: ^ebb36: PB6 +toolhead_switch_pin: ^ebb36: PB5 + + +# ENCODER ------------------------------------------------------------------------------------------------------------- +# ███████╗███╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗ +# ██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗ +# █████╗ ██╔██╗ ██║██║ ██║ ██║██║ ██║█████╗ ██████╔╝ +# ██╔══╝ ██║╚██╗██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗ +# ███████╗██║ ╚████║╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║ +# ╚══════╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ +# Encoder measures distance, monitors for runout and clogging and constantly calculates % flow rate +# Note that the encoder_resolution set here is purely a default to get started. It will be correcly set after calibration +# with the value stored in mmu_vars.cfg +# +# The encoder resolution will be calibrated but it needs a default approximation +# If BMG gear based: +# resolution = bmg_circumfrance / (2 * teeth) +# 24 / (2 * 17) = 0.7059 for TRCT5000 based sensor +# 24 / (2 * 12) = 1.0 for Binky with 12 tooth disc +# +[mmu_encoder mmu_encoder] +encoder_pin: ^mmu:MMU_ENCODER +encoder_resolution: 1.0 # This is just a starter value. Overriden by calibrated 'mmu_encoder_resolution' in mmm_vars.cfg +desired_headroom: 5.0 # The clog/runout headroom that MMU attempts to maintain (closest point to triggering runout) +average_samples: 4 # The "damping" effect of last measurement (higher value means slower automatic clog_length reduction) +flowrate_samples: 20 # How many "movements" of the extruder to measure average flowrate over + + +# MMU OPTIONAL NEOPIXEL LED SUPPORT ------------------------------------------------------------------------------------ +# ██╗ ███████╗██████╗ ███████╗ +# ██║ ██╔════╝██╔══██╗██╔════╝ +# ██║ █████╗ ██║ ██║███████╗ +# ██║ ██╔══╝ ██║ ██║╚════██║ +# ███████╗███████╗██████╔╝███████║ +# ╚══════╝╚══════╝╚═════╝ ╚══════╝ +# Define the led connection, type and length +# +# (comment out this section if you don't have leds or have them defined elsewhere) +[neopixel mmu_leds] +pin: mmu:MMU_NEOPIXEL +chain_count: 9 # Need number gates x1 or x2 + status leds +color_order: GRBW # Set based on your particular neopixel specification (can be comma separated list) + +# MMU LED EFFECT SEGMENTS ---------------------------------------------------------------------------------------------- +# Define neopixel LEDs for your MMU. The chain_count must be large enough for your desired ranges: +# exit .. this set of LEDs, one for every gate, usually would be mounted at the exit point of the gate +# entry .. this set of LEDs, one for every gate, could be mounted at the entry point of filament into the MMU/buffer +# status .. these LED. represents the status of the MMU (and selected filament). More than one status LED is possible +# logo .. these LEDs don't change during operation and are designed for driving a logo. More than one logo LED is possible +# +# Note that all sets are optional. You can opt to just have the 'exit' set for example. The advantage to having +# both entry and exit LEDs is, for example, so that 'entry' can display gate status while 'exit' displays the color +# +# The animation effects requires the installation of Julian Schill's awesome LED effect module otherwise the LEDs +# will be static: +# https://github.com/julianschill/klipper-led_effect +# +# LED's are indexed in the chain from 1..N. Thus to set up LED's on 'exit' and a single 'status' LED on a 4 gate MMU: +# +# exit_leds: neopixel:mmu_leds (1,2,3,4) +# status_leds: neopixel:mmu_leds (5) +# +# In this example no 'entry' set is configured. Note that constructs like "mmu_leds (1-3,4)" are also valid +# +# The range is completely flexible and can be comprised of different led strips, individual LEDs, or combinations of +# both on different pins. In addition, the ordering is flexible based on your wiring, thus (1-4) and (4-1) both represent +# the same LED range but mapped to increasing or decreasing gates respectively. E.g if you have two Box Turtle MMUs, one +# with a chain of LEDs wired in reverse order and another with individual LEDs, to define 8 exit LEDs: +# +# exit_leds: neopixel:bt_1 (4-1) +# neopixel:bt_2a +# neopixel:bt_2b +# neopixel:bt_2c +# neopixel:bt_2d +# +# Note the use of separate lines for each part of the definition, +# +# ADVANCED: Happy Hare provides a convenience wrapper [mmu_led_effect] that not only creates an effect on each of the +# [mmu_leds] specified segments as a whole but also each individual LED for atomic control. See mmu_leds.cfg for examples +# +# (comment out this whole section if you don't have/want leds; uncomment/edit LEDs fitted on your MMU) +[mmu_leds] +exit_leds: neopixel:mmu_leds (8-1) +#entry_leds: neopixel:mmu_leds (9-16) +#status_leds: neopixel:mmu_leds (17) +#logo_leds: neopixel:mmu_leds (18) +frame_rate: 24 diff --git a/mmu-20250423_130617/base/mmu_leds.cfg b/mmu-20250423_130617/base/mmu_leds.cfg new file mode 120000 index 0000000..1a16abe --- /dev/null +++ b/mmu-20250423_130617/base/mmu_leds.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_leds.cfg \ No newline at end of file diff --git a/mmu-20250423_130617/base/mmu_macro_vars.cfg b/mmu-20250423_130617/base/mmu_macro_vars.cfg new file mode 100644 index 0000000..4dc14b7 --- /dev/null +++ b/mmu-20250423_130617/base/mmu_macro_vars.cfg @@ -0,0 +1,506 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Happy Hare supporting MACRO configuration +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# +# Supporting set of macros supplied with Happy Hare can be customized by editing the macro "variables" declared here. +# +# This configuration will automatically retained and upgraded between releases (a backup of previous config files will +# always be made for your reference). If you want to customize macros beyond what is possible through these variables +# it is highly recommended you copy the macro to a new name and change the callback macro name in 'mmu_parameters.cfg' +# That way the default macros can still be upgraded but your customization will be left intact +# + + +# PERSISTED STATE --------------------------------------------------------- +# Happy Hare stores configuration and state in the klipper variables file. +# Since klipper can only be a single 'save_variables' file, if you already +# have one you will need to merge the two and point this appropriately. +# +[save_variables] +filename: ~/printer_data/config/mmu/mmu_vars.cfg + + +# NECESSARY KLIPPER OVERRIDES --------------------------------------------- +# ██╗ ██╗██╗ ██╗██████╗ ██████╗ ███████╗██████╗ +# ██║ ██╔╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗ +# █████╔╝ ██║ ██║██████╔╝██████╔╝█████╗ ██████╔╝ +# ██╔═██╗ ██║ ██║██╔═══╝ ██╔═══╝ ██╔══╝ ██╔══██╗ +# ██║ ██╗███████╗██║██║ ██║ ███████╗██║ ██║ +# ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ +# +# These supplemental settings essentially disable klipper's built in +# extrusion limits and is necessary when using an MMU +[extruder] +max_extrude_only_distance: 200 +max_extrude_cross_section: 50 + +# For dialog prompts and progress in Mainsail. Requires Mainsail version >= v2.9.0 +[respond] + +# Other Happy Hare prerequisites. Harmless if already defined elsewhere in user config +[display_status] +[pause_resume] +[virtual_sdcard] +path: ~/printer_data/gcodes +#on_error_gcode: CANCEL_PRINT + + +# PRINT START/END --------------------------------------------------------- +# ██████╗ ██████╗ ██╗███╗ ██╗████████╗ ███████╗████████╗ █████╗ ██████╗ ████████╗ +# ██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔══██╗╚══██╔══╝ +# ██████╔╝██████╔╝██║██╔██╗ ██║ ██║ ███████╗ ██║ ███████║██████╔╝ ██║ +# ██╔═══╝ ██╔══██╗██║██║╚██╗██║ ██║ ╚════██║ ██║ ██╔══██║██╔══██╗ ██║ +# ██║ ██║ ██║██║██║ ╚████║ ██║ ███████║ ██║ ██║ ██║██║ ██║ ██║ +# ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ +# (base/mmu_software.cfg) +# +[gcode_macro _MMU_SOFTWARE_VARS] +description: Happy Hare optional configuration for print start/end checks +gcode: # Leave empty + +# These variables control the behavior of the MMU_START_SETUP and MMU_START_LOAD_INITIAL_TOOL macros +variable_user_pre_initialize_extension : '' ; Executed at start of MMU_START_SETUP. Commonly G28 to home +variable_home_mmu : False ; True/False, Whether to home mmu before print starts +variable_check_gates : True ; True/False, Whether to check filament is loaded in all gates used +variable_load_initial_tool : True ; True/False, Whether to automatically load initial tool +# +# Automapping strategy to apply slicer tool map to find matching MMU gate (will adjust tool-to-gate map). Options are: +# 'none' - don't automap (i.e. don't update tool-to-gate map) +# 'filament_name' - exactly match on case insensitive filament name +# 'material' - exactly match on material +# 'color' - exactly match on color (with same material) +# 'closest_color' - match to closest available filament color (with same material) +# 'spool_id' - exactly match on spool_id [FUTURE] +variable_automap_strategy : "none" ; none|filament_name|material|color|closest_color|spool_id + +# These variables control the behavior of the MMU_END macro +variable_user_print_end_extension : '' ; Executed at start of MMU_END. Good place to move off print +variable_unload_tool : True ; True/False, Whether to unload the tool at the end of the print +variable_reset_ttg : False ; True/False, Whether reset TTG map at end of print +variable_dump_stats : True ; True/False, Whether to display print stats at end of print + + +# STATE MACHINE CHANGES --------------------------------------------------- +# ███████╗████████╗ █████╗ ████████╗███████╗ ██████╗██╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗ +# ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝ ██╔════╝██║ ██║██╔══██╗████╗ ██║██╔════╝ ██╔════╝ +# ███████╗ ██║ ███████║ ██║ █████╗ ██║ ███████║███████║██╔██╗ ██║██║ ███╗█████╗ +# ╚════██║ ██║ ██╔══██║ ██║ ██╔══╝ ██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║██╔══╝ +# ███████║ ██║ ██║ ██║ ██║ ███████╗ ╚██████╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗ +# ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ +# (base/mmu_state.cfg) +# +[gcode_macro _MMU_STATE_VARS] +description: Happy Hare configuration for state change hooks +gcode: # Leave empty + +# You can extend functionality to all Happy Hare state change or event +# macros by adding a command (or call to your gcode macro). +# E.g for additional LED logic or consumption counters +variable_user_action_changed_extension : '' ; Executed after default logic with duplicate params +variable_user_print_state_changed_extension : '' ; Executed after default logic with duplicate params +variable_user_mmu_event_extension : '' ; Executed after default logic with duplicate params + +# Maintenance warning limits (consumption counters) +variable_servo_down_limit : 5000 ; Set to -1 for no limit / disable warning +variable_cutter_blade_limit : 3000 ; Set to -1 for no limit / disable warning + + +# LED CONTROL ------------------------------------------------------------- +# ██╗ ███████╗██████╗ ███████╗ +# ██║ ██╔════╝██╔══██╗██╔════╝ +# ██║ █████╗ ██║ ██║███████╗ +# ██║ ██╔══╝ ██║ ██║╚════██║ +# ███████╗███████╗██████╔╝███████║ +# ╚══════╝╚══════╝╚═════╝ ╚══════╝ +# Only configure if you have LEDs installed. The led_effects option is +# automatically ignored if led-effects klipper module is not installed +# (base/mmu_led.cfg) +# +[gcode_macro _MMU_LED_VARS] +description: Happy Hare led macro configuration variables +gcode: # Leave empty + +# Default effects for LED segments when not providing action status +# 'off' - LED's off +# 'on' - LED's white +# 'gate_status' - indicate gate availability / status (printer.mmu.gate_status) +# 'filament_color' - display filament color defined in gate map (printer.mmu.gate_color_rgb) +# 'slicer_color' - display slicer defined set color for each gate (printer.mmu.slicer_color_rgb) +# 'r,g,b' - display static r,g,b color e.g. "0,0,0.3" for dim blue +# '_effect_' - display the named led effect +# +variable_led_enable : True ; True = LEDs are enabled at startup (MMU_LED can control), False = Disabled +variable_led_animation : True ; True = Use led-animation-effects, False = Static LEDs +variable_default_exit_effect : "gate_status" ; off|gate_status|filament_color|slicer_color|r,g,b|_effect_ +variable_default_entry_effect : "filament_color" ; off|gate_status|filament_color|slicer_color|r,g,b|_effect_ +variable_default_status_effect : "filament_color" ; on|off|gate_status|filament_color|slicer_color|r,g,b|_effect_ +variable_default_logo_effect : "0,0,.3" ; off |r,g,b|_effect_ +variable_white_light : (1, 1, 1) ; RGB color for static white light +variable_black_light : (.01, 0, .02) ; RGB color used to represent "black" (filament) +variable_empty_light : (0, 0, 0) ; RGB color used to represent empty gate + + +# SEQUENCE MACRO - PARKING MOVEMENT AND TOOLCHANGE CONTROL ---------------- +# ███╗ ███╗ ██████╗ ██╗ ██╗███████╗███╗ ███╗███████╗███╗ ██╗████████╗ +# ████╗ ████║██╔═══██╗██║ ██║██╔════╝████╗ ████║██╔════╝████╗ ██║╚══██╔══╝ +# ██╔████╔██║██║ ██║██║ ██║█████╗ ██╔████╔██║█████╗ ██╔██╗ ██║ ██║ +# ██║╚██╔╝██║██║ ██║╚██╗ ██╔╝██╔══╝ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ +# ██║ ╚═╝ ██║╚██████╔╝ ╚████╔╝ ███████╗██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ +# ╚═╝ ╚═╝ ╚═════╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ +# Configure carefully if you 'enable_park: True' +# (base/mmu_sequence.cfg) +# +[gcode_macro _MMU_SEQUENCE_VARS] +description: Happy Hare sequence macro configuration variables +gcode: # Leave empty + +# Parking and movement controls: +# Happy Hare defines 7 operations that may require parking. You can specify +# whether to park for each of those operations both during a print and +# standalone (not printing) with Happy Hare or when HH is disabled: +# +# enable_park_printing +# This is a list of the operations that should result in toolhead parking +# while in a print. There are really two main starting points from which +# you can customize. If using the slicer to form tips (and toolchange is +# over the wipetower) you don't want to park on "toolchange" but you would +# want to on "runout" which is a forced toolchange unknown by the slicer. +# Typically you would also want to park at least on pause, cancel and +# complete if not done elsewhere +# +# enabled_park_standalone +# List of the operations that should result in toolhead parking when not +# printing, for example, just manipulating the MMU manually or via +# Klipperscreen. Really it is up to you to choose based on personal +# workflow preferences but this defaults to just 'pause,cancel' +# (i.e. disabled for toolchange) +# +# enabled_park_disabled +# List of the operations that should result in toolhead parking when MMU is +# disabled (MMU ENABLE=0) and using Happy Hare client macros. Note that only +# pause and cancel can occur in this mode and would typically be enabled +# +# The operations are as follows: +# toolchange - normal toolchange initiated with Tx or MMU_CHANGE_TOOL command +# runout - when a forced toolchange occurs as a result of runout +# load - individual MMU_LOAD operation +# unload - individual MMU_UNLOAD/MMU_EJECT operation +# complete - when print is complete (Happy Hare enabled) +# pause - a regular klipper PAUSE +# cancel - a regular klipper CANCEL_PRINT +# +# It is possible to call the parking macro manually in this form should you wish +# to include in your macros. +# +# _MMU_PARK FORCE_PARK=1 X=10 Y=10 Z_HOP=5 +# +# restore_xy_pos +# Controls where the toolhead (x,y) is returned to after an operation that +# invokes a parking move: +# last - return to original position before park (frequently the default) +# next - return to next print position if possible else last logic will be applied. +# In print this reduces dwell time at the last position reducing blobbing +# and unnecessary movement. Only applied to "toolchange" operation +# none - the toolhead is left wherever it ends up after change. In a print the +# next gcode command will restore toolhead x,y position +# +# Notes: +# - The starting z-height will always be restored, thus the different between 'next' +# and 'none' is the z-height at which the (x,y) move occurs and the location of +# of any un-retract +# - The default parking logic is a straight line move to the 'park_*' position. +# To implement fancy movement and control you can specify your own +# 'user_park_move_macro' to use instead of default straight line move +# +# Retraction can be used to optimize stringing and blobs that can occur when +# changing tools and are active only during a print. +# IMPORTANT: For toolchanging the config order would be: +# 1. In mmu_parameters.cfg configure extruder dimensions like +# 'toolhead_extruder_to_nozzle',etc. These are based on geometry. +# 2. In mmu_parameters.cfg tweak 'toolhead_ooze_reduction' only if necessary +# so that filament _just_ appears at the nozzle on load +# 3. Only then, adjust retraction to control stringing and blobs when +# changing tool in a print +variable_enable_park_printing : 'toolchange,runout,load,unload,complete,pause,cancel' ; Empty '' to disable parking +variable_enable_park_standalone : 'toolchange,load,unload,pause,cancel' ; Empty '' to disable parking +variable_enable_park_disabled : 'pause,cancel' ; Empty '' to disable parking + +variable_min_toolchange_z : 1.0 ; The absolute minimum safety floor (z-height) for ALL parking moves + +# These specify the parking location, z_hop and retraction for all enabled operation +# types. Each must be 5 values: +# x_coord, y_coord, z_hop(delta), z_hop_ramp, retraction length +# Use -1,-1 for no x,y move (you can just have z_hop). Use 0 for no z_hop +# The z_hop ramp is the horizontal distance in mm to travel during the lift. The +# direction is automatic and only applied if lifting the first time from print. +# This move is useful to help break the filament "string" +variable_park_toolchange : -1, -1, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract for "toolchange" operations (toolchange,load,unload) +variable_park_runout : -1, -1, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract +variable_park_pause : 50, 50, 5, 0, 2 ; x,y,z-hop,z_hop_ramp,retract (park position when mmu error occurs) +variable_park_cancel : -1, -1, 10, 0, 5 ; x,y,z-hop,z_hop_ramp,retract +variable_park_complete : 50, 50, 10, 0, 5 ; x,y,z-hop,z_hop_ramp,retract + +# For toolchange operations, this allows to you to specify additional parking moves +# at various stages of the toolchange. Each must have 3 values: +# x_coord, y_coord, z_hop(delta) +# Use -1,-1,0 for no movement at that stage (no-op). +# All movement will be at the established movement plane (z-height) +variable_pre_unload_position : -1, -1, 0 ; x,y,z-hop position before unloading starts +variable_post_form_tip_position : -1, -1, 0 ; x,y,z-hop position after form/cut tip on unload +variable_pre_load_position : -1, -1, 0 ; x,y,z-hop position before loading starts + +variable_restore_xy_pos : "last" ; last|next|none - What x,y position the toolhead should travel to after a "toolchange" + +variable_park_travel_speed : 200 ; Speed for any travel movement XY(Z) in mm/s +variable_park_lift_speed : 15 ; Z-only travel speed in mm/s +variable_retract_speed : 30 ; Speed of the retract move in mm/s +variable_unretract_speed : 30 ; Speed of the unretract move in mm/s + +# ADVANCED: Normally x,y moves default to 'G1 X Y' to park position. This allows +# you to create exotic movements. Macro will be provided the following parameters: +# YOUR_MOVE_MACRO X= Y= F= +# when restoring the from parked postion the same macro is called but passed a RESTORE=1 parameter, along with co-ordinates to restore to +# YOUR_MOVE_MACRO RESTORE=1 X= Y= F= +variable_user_park_move_macro : '' ; Executed instead of default 'G1 X Y move' to park position + +variable_auto_home : True ; True = automatically home if necessary, False = disable +variable_timelapse : False ; True = take frame snapshot after load, False = disable + +# Instead of completely defining your your own macros you can can extend functionality +# of default sequence macros by adding a command (or call to your gcode macro) +variable_user_mmu_error_extension : '' ; Executed after default logic when mmu error condition occurs +variable_user_pre_unload_extension : '' ; Executed after default logic +variable_user_post_form_tip_extension : '' ; Executed after default logic +variable_user_post_unload_extension : '' ; Executed after default logic +variable_user_pre_load_extension : '' ; Executed after default logic +variable_user_post_load_extension : 'CLEAN_NOZZLE' ; Executed after default logic but before restoring toolhead position + + +# CUT_TIP ----------------------------------------------------------------- +# ██████╗██╗ ██╗████████╗ ████████╗██╗██████╗ +# ██╔════╝██║ ██║╚══██╔══╝ ╚══██╔══╝██║██╔══██╗ +# ██║ ██║ ██║ ██║ ██║ ██║██████╔╝ +# ██║ ██║ ██║ ██║ ██║ ██║██╔═══╝ +# ╚██████╗╚██████╔╝ ██║ ██║ ██║██║ +# ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ +# Don't need to configure if using tip forming +# (base/mmu_cut_tip.cfg) +# +[gcode_macro _MMU_CUT_TIP_VARS] +description: Happy Hare toolhead tip cutting macro configuration variables +gcode: # Leave empty + +# Whether the toolhead tip cutting macro will return toolhead to initial position +# after the cut is complete. If using parking logic it is better to disable this +variable_restore_position : False ; True = return to initial position, False = don't return + +# Distance from the internal nozzle tip to the cutting blade. This dimension +# is based on your toolhead and should not be used for tuning +# Note: If you have a toolhead sensor this variable can be automatically determined! +# Read https://github.com/moggieuk/Happy-Hare/wiki/Blobing-and-Stringing +variable_blade_pos : 37.5 ; TUNE ME: Distance in mm from internal nozzle tip + +# Distance to retract prior to making the cut, measured from the internal nozzle +# tip. This reduces wasted filament (left behind in extruder) but might cause a +# clog if set too large. This must be less than 'blade_pos' +# Note: the residual filament left in nozzle ('toolhead_ooze_reduction') is +# subtracted from this value so make sure toolhead is calibrated +variable_retract_length : 32.5 ; TUNE ME: 5mm less than 'blade_pos' is a good starting point + +# Whether to perform a simple tip forming move after the initial retraction +# Enabling this adds gives some additional cooling time of molten filament and +# may help avoid potential clogging on some hotends +variable_simple_tip_forming : False ; True = Perform simple tip forming, False = skip + +# This should be the position of the toolhead where the cutter arm just +# lightly touches the depressor pin +variable_cutting_axis : "x" ; "x" or "y". Determines cut direction (axis) during cut motion, used for park distance +variable_pin_loc_xy : 16.5, 354.5 ; x,y coordinates of depressor pin + +# This distance is added to "pin_loc_x" or "pin_loc_y" depending on the 'cutting_axis' +# to determine the starting position and to create a small safety distance that aids +# in generating momentum +variable_pin_park_dist : 5.0 ; Distance in mm + +# Position of the toolhead when the cutter is fully compressed. Should leave a small headroom from the +# extremes of your printer edges (e.g. it should be a bit larger than 0, or whatever Xmin is) to avoid +# banging the toolhead or gantry. Typically x position will match x in pin_loc_xy if cutting in y direction +# or y position will match y in pin_loc_xy if cutting in x direction, but diagonal cuts are possible +variable_pin_loc_compressed_xy : 3, 354.5 ; x,y coordinates of fully depressed location (This is 0 actually but skew correction!) + +# Retract length and speed after the cut so that the cutter blade doesn't +# get stuck on return to 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. This does +# not have to push back all the way, just sufficient to ensure filament fragment +# stays in hot end and the "nail head" of the cut is pushed back past the +# PTFE/metal junction so it cannot cause clogging problems on future loads. +# Cannot be larger than 'retract_length' - `toolhead_ooze_reduction` +variable_pushback_length : 15.0 ; TUNE ME: PTFE tube length + 3mm is good starting point +variable_pushback_dwell_time : 0 ; Time in ms to dwell after the pushback + +# 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_travel_speed : 150 ; Speed mm/s +variable_cut_fast_move_speed : 32 ; Speed mm/s +variable_cut_slow_move_speed : 8 ; Speed mm/s +variable_evacuate_speed : 150 ; Speed mm/s +variable_cut_dwell_time : 50 ; Time in ms to dwell at the cut point +variable_cut_fast_move_fraction : 1.0 ; Fraction of the move that uses fast move +variable_extruder_move_speed : 25 ; Speed mm/s for all extruder movement + +# 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) + +# If gantry servo option is installed, enable the servo and set up and down +# angle positions +variable_gantry_servo_enabled : False ; True = enabled, False = disabled +variable_gantry_servo_down_angle: 55 ; Angle for when pin is deployed +variable_gantry_servo_up_angle : 180 ; Angle for when pin is retracted + + +# FORM_TIP ---------------------------------------------------------------- +# ███████╗ ██████╗ ██████╗ ███╗ ███╗ ████████╗██╗██████╗ +# ██╔════╝██╔═══██╗██╔══██╗████╗ ████║ ╚══██╔══╝██║██╔══██╗ +# █████╗ ██║ ██║██████╔╝██╔████╔██║ ██║ ██║██████╔╝ +# ██╔══╝ ██║ ██║██╔══██╗██║╚██╔╝██║ ██║ ██║██╔═══╝ +# ██║ ╚██████╔╝██║ ██║██║ ╚═╝ ██║ ██║ ██║██║ +# ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ +# Don't need to configure if using tip cutting +# (base/mmu_form_tip.cfg) +# +[gcode_macro _MMU_FORM_TIP_VARS] +description: Happy Hare tip forming macro configuration variables +gcode: # Leave empty + +# Step 1 - Ramming +# Ramming is the initial squeeze of filament prior to cooling moves and is +# described in terms of total volume and progression of squeeze intensity +# printing/standalone. This can be separately controlled when printing or +# standalone +variable_ramming_volume : 0 ; Volume in mm^3, 0 = disabled (optionally let slicer do it) +variable_ramming_volume_standalone : 0 ; Volume in mm^3, 0 = disabled + +# Optionally set for temperature change (reduction). The wait will occur +# before nozzle separation if 'use_fast_skinnydip: False' else after cooling +# moves. Temperature will be restored after tip creation is complete +variable_toolchange_temp : 0 ; 0 = don't change temp, else temp to set +variable_toolchange_fan_assist : False ; Whether to use part cooling fan for quicker temp change +variable_toolchange_fan_speed : 50 ; Fan speed % if using fan_assist enabled + +# Step 2 - Nozzle Separation +# The filament is then quickly separated from the meltzone by a fast movement +# before then slowing to travel the remaining distance to cooling tube. The +# initial fast movement should be as fast as extruder can comfortably perform. +# A good starting point# for slower move is unloading_speed_start/cooling_moves. +# Too fast a slower movement can lead to excessively long tips or hairs +variable_unloading_speed_start : 80 ; Speed in mm/s for initial fast movement +variable_unloading_speed : 18 ; Speed in mm/s for slow move to cooling zone + +# Step 3 - Cooling Moves +# The cooling move allows the filament to harden while constantly moving back +# and forth in the cooling tube portion of the extruder to prevent a bulbous +# tip forming. The cooling tube position is measured from the internal nozzle +# to just past the top of the heater block (often it is beneficial to add a +# couple of mm to ensure the tip is in the cooling section. The cooling tube +# length is then the distance from here to top of heatsink (this is the length +# length of the cooling moves). The final cooling move is a fast movement to +# break the string formed. +variable_cooling_tube_position : 35 ; Start of cooling tube. DragonST:35, DragonHF:30, Mosquito:30, Revo:35, RapidoHF:27 +variable_cooling_tube_length : 10 ; Movement length. DragonST:15, DragonHF:10, Mosquito:20, Revo:10, RapidoHF:10 +variable_initial_cooling_speed : 10 ; Initial slow movement (mm/s) to solidify tip and cool string if formed +variable_final_cooling_speed : 50 ; Fast movement (mm/s) Too fast: tip deformation on eject, Too Slow: long string/no separation +variable_cooling_moves : 4 ; Number of back and forth cooling moves to make (2-4 is a good start) + +# Step 4 - Skinnydip +# Skinnydip is an advanced final move that may have benefit with some +# material like PLA to burn off persistent very fine hairs. To work the +# depth of insertion is critical (start with it disabled and tune last) +# For reference the internal nozzle would be at a distance of +# cooling_tube_position + cooling_tube_length, the top of the heater +# block would be cooling_tube_length away. +variable_use_skinnydip : False ; True = enable skinnydip, False = skinnydip move disabled +variable_skinnydip_distance : 30 ; Distance to reinsert filament into hotend starting from end of cooling tube +variable_dip_insertion_speed : 30 ; Medium/Slow insertion speed mm/s - Just long enough to melt the fine hairs, too slow will pull up molten filament +variable_dip_extraction_speed : 70 ; Speed mm/s - Around 2x Insertion speed to prevents forming new hairs +variable_melt_zone_pause : 0 ; Pause if melt zone in ms. Default 0 +variable_cooling_zone_pause : 0 ; Pause if cooling zone after dip in ms. Default 0 +variable_use_fast_skinnydip : False ; False = Skip the toolhead temp change wait during skinnydip move + +# Step 5 - Parking +# Park filament ready to eject +variable_parking_distance : 0 ; Position mm to park the filament at end of tip forming, 0 = leave where filament ends up after tip forming +variable_extruder_eject_speed : 25 ; Speed mm/s used for parking_distance (and final_eject when testing) + + +# CLIENT MACROS ----------------------------------------------------------- +# ██████╗ █████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███████╗███████╗██╗ ██╗███╗ ███╗███████╗ +# ██╔══██╗██╔══██╗██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██║ ██║████╗ ████║██╔════╝ +# ██████╔╝███████║██║ ██║███████╗█████╗ ██████╔╝█████╗ ███████╗██║ ██║██╔████╔██║█████╗ +# ██╔═══╝ ██╔══██║██║ ██║╚════██║██╔══╝ ██╔══██╗██╔══╝ ╚════██║██║ ██║██║╚██╔╝██║██╔══╝ +# ██║ ██║ ██║╚██████╔╝███████║███████╗ ██║ ██║███████╗███████║╚██████╔╝██║ ╚═╝ ██║███████╗ +# ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ +# If using the recommended PAUSE/RESUME/CANCEL_PRINT macros shipped with +# Happy Hare these variables allow for customization and basic extension +# Note that most parameters are pulled from the "movement" (sequence) +# macro above and thus these are supplemental a +# (optional/client_macros.cfg) +# +[gcode_macro _MMU_CLIENT_VARS] +description: Happy Hare client macro configuration variables +gcode: # Leave empty + +variable_reset_ttg_on_cancel : False ; True/False, Whether reset TTG map if print is canceled +variable_unload_tool_on_cancel : False ; True/False, Whether to unload the tool on cancel + +# You can extend functionality by adding a command (or call to your gcode macro) +variable_user_pause_extension : '' ; Executed after the klipper base pause +variable_user_resume_extension : '' ; Executed before the klipper base resume +variable_user_cancel_extension : '' ; Executed before the klipper base cancel_print + + +########################################################################### +# Tool change macros +# This is automatically created on installation but you can increase or +# reduce this list to match your number of tools in operation +# Note: it is annoying to have to do this but interfaces like Mainsail rely +# on real macro definitions for tools to be visible in the UI +# +[gcode_macro T0] +gcode: MMU_CHANGE_TOOL TOOL=0 +[gcode_macro T1] +gcode: MMU_CHANGE_TOOL TOOL=1 +[gcode_macro T2] +gcode: MMU_CHANGE_TOOL TOOL=2 +[gcode_macro T3] +gcode: MMU_CHANGE_TOOL TOOL=3 +[gcode_macro T4] +gcode: MMU_CHANGE_TOOL TOOL=4 +[gcode_macro T5] +gcode: MMU_CHANGE_TOOL TOOL=5 +[gcode_macro T6] +gcode: MMU_CHANGE_TOOL TOOL=6 +[gcode_macro T7] +gcode: MMU_CHANGE_TOOL TOOL=7 + diff --git a/mmu-20250423_130617/base/mmu_parameters.cfg b/mmu-20250423_130617/base/mmu_parameters.cfg new file mode 100644 index 0000000..acbdf55 --- /dev/null +++ b/mmu-20250423_130617/base/mmu_parameters.cfg @@ -0,0 +1,613 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Main configuration parameters for the klipper module +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# Notes: +# Macro configuration is specified separately in 'mmu_macro_vars.cfg'. +# Full details in https://github.com/moggieuk/Happy-Hare/tree/main/doc/configuration.md +# +[mmu] +happy_hare_version: 3.1 # Don't mess, used for upgrade detection + +# MMU Hardware Limits -------------------------------------------------------------------------------------------------- +# ██╗ ██╗███╗ ███╗██╗████████╗███████╗ +# ██║ ██║████╗ ████║██║╚══██╔══╝██╔════╝ +# ██║ ██║██╔████╔██║██║ ██║ ███████╗ +# ██║ ██║██║╚██╔╝██║██║ ██║ ╚════██║ +# ███████╗██║██║ ╚═╝ ██║██║ ██║ ███████║ +# ╚══════╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ +# +# Define the physical limits of your MMU. These settings will be respected regardless of individual speed settings. +# +gear_max_velocity: 300 # Never to be exceeded gear velocity regardless of specific parameters +gear_max_accel: 1500 # Never to be exceeded gear acceleration regardless of specific parameters +selector_max_velocity: 250 # Never to be exceeded selector velocity regardless of specific parameters +selector_max_accel: 1200 # Never to be exceeded selector acceleration regardless of specific parameters + + +# Servo configuration ------------------------------------------------------------------------------------------------- +# ███████╗███████╗██████╗ ██╗ ██╗ ██████╗ +# ██╔════╝██╔════╝██╔══██╗██║ ██║██╔═══██╗ +# ███████╗█████╗ ██████╔╝██║ ██║██║ ██║ +# ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║ ██║ +# ███████║███████╗██║ ██║ ╚████╔╝ ╚██████╔╝ +# ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═════╝ +# +# Angle of the servo in three named positions +# up = tool is selected and filament is allowed to freely move through gate +# down = to grip filament +# move = ready the servo for selector move (optional - defaults to up) +# V2.4.0 on: These positions are only for initial config they are replaced with calibrated servo positions in `mmu_vars.cfg` +# +# Note that leaving the servo active when down can stress the electronics and is not recommended with EASY-BRD or ERB board +# unless the 5v power supply has been improved and it is not necessary with standard ERCF builds +# Make sure your hardware is suitable for the job! +# +servo_up_angle: 140 # ERCF: MG90S: 30 ; SAVOX SH0255MG: 140 ; Tradrack: 145 +servo_down_angle: 30 # ERCF: MG90S: 140 ; SAVOX SH0255MG: 30 ; Tradrack: 1 +servo_move_angle: 109 # Optional angle used when selector is moved (defaults to up position) +servo_duration: 0.4 # Duration of PWM burst sent to servo (default non-active mode, automatically turns off) +servo_dwell: 0.5 # Minimum time given to servo to complete movement prior to next move +servo_always_active: 0 # CAUTION - WILL DAMAGE COMMON SERVOS, PLEASE USE AT YOUR OWN RISK: 1=Force servo to always stay active, 0=Release after movement +servo_active_down: 0 # CAUTION - WILL DAMAGE COMMON SERVOS, PLEASE USE AT YOUR OWN RISK: 1=Force servo to stay active when down only, 0=Release after movement +servo_buzz_gear_on_down: 1 # Whether to "buzz" the gear stepper on down to aid engagement + + +# Logging -------------------------------------------------------------------------------------------------------------- +# ██╗ ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ +# ██║ ██╔═══██╗██╔════╝ ██╔════╝ ██║████╗ ██║██╔════╝ +# ██║ ██║ ██║██║ ███╗██║ ███╗██║██╔██╗ ██║██║ ███╗ +# ██║ ██║ ██║██║ ██║██║ ██║██║██║╚██╗██║██║ ██║ +# ███████╗╚██████╔╝╚██████╔╝╚██████╔╝██║██║ ╚████║╚██████╔╝ +# ╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# log_level & logfile_level can be set to one of (0 = essential, 1 = info, 2 = debug, 3 = trace, 4 = stepper moves) +# Generally you can keep console logging to a minimal whilst still sending debug output to the mmu.log file +# Increasing the console log level is only really useful during initial setup to save having to constantly open the log file +# Note: that it is not recommended to keep logging at level greater that 2 (debug) if not debugging an issue because +# of the additional overhead +# +log_level: 1 +log_file_level: 2 # Can also be set to -1 to disable log file completely +log_statistics: 1 # 1 to log statistics on every toolchange (default), 0 to disable (but still recorded) +log_visual: 1 # 1 log visual representation of filament, 0 = disable +log_startup_status: 1 # Whether to log tool to gate status on startup, 1 = summary (default), 0 = disable + + +# Movement speeds ------------------------------------------------------------------------------------------------------ +# ███████╗██████╗ ███████╗███████╗██████╗ ███████╗ +# ██╔════╝██╔══██╗██╔════╝██╔════╝██╔══██╗██╔════╝ +# ███████╗██████╔╝█████╗ █████╗ ██║ ██║███████╗ +# ╚════██║██╔═══╝ ██╔══╝ ██╔══╝ ██║ ██║╚════██║ +# ███████║██║ ███████╗███████╗██████╔╝███████║ +# ╚══════╝╚═╝ ╚══════╝╚══════╝╚═════╝ ╚══════╝ +# +# Long moves are faster than the small ones and used for the bulk of the bowden movement. You can set two fast load speeds +# depending on whether pulling from the spool or filament buffer (if fitted and not the first time load). This can be helpful +# in allowing faster loading from buffer and slower when pulling from the spool because of the additional friction (prevents +# loosing steps). Unloading speed can be tuning if you have a rewinder system that imposes additional limits. +# NOTE: Encoder cannot keep up much above 450mm/s so make sure 'bowden_apply_correction' is off at very high speeds! +# +gear_from_spool_speed: 80 # mm/s Speed when loading from the spool (for the first time if has_filament_buffer: 1) +gear_from_spool_accel: 100 # Acceleration when loading from spool +gear_from_buffer_speed: 150 # mm/s Speed when loading filament from buffer. Conservative is 100mm/s, Max around 400mm/s +gear_from_buffer_accel: 400 # Normal acceleration when loading filament +gear_unload_speed: 80 # mm/s Use (lower) speed when unloading filament (defaults to "from spool" speed) +gear_unload_accel: 100 # Acceleration when unloading filament (defaults to "from spool" accel) +# +gear_short_move_speed: 80 # mm/s Speed when making short moves (like incremental retracts with encoder) +gear_short_move_accel: 600 # Usually the same as gear_from_buffer_accel (for short movements) +gear_short_move_threshold: 70 # Move distance that controls application of 'short_move' speed/accel +gear_homing_speed: 50 # mm/s Speed of gear stepper only homing moves (e.g. homing to gate or extruder) + +# Speeds of extruder movement. The 'sync' speeds will be used when gear and extruder steppers are moving in sync +# +extruder_load_speed: 16 # mm/s speed of load move inside extruder from homing position to meltzone +extruder_unload_speed: 16 # mm/s speed of unload moves inside of extruder (very initial move from meltzone is 50% of this) +extruder_sync_load_speed: 18 # mm/s speed of synchronized extruder load moves +extruder_sync_unload_speed: 18 # mm/s speed of synchronized extruder unload moves +extruder_homing_speed: 18 # mm/s speed of extruder only homing moves (e.g. to toolhead sensor) + +# Selector movement speeds. (Acceleration is defined by physical MMU limits set above and passed to selector stepper driver) +# +selector_move_speed: 200 # mm/s speed of selector movement (not touch) +selector_homing_speed: 60 # mm/s speed of initial selector homing move (not touch) +selector_touch_speed: 80 # mm/s speed of all touch selector moves (if stallguard configured) + +# Selector touch (stallguard) operation. If stallguard is configured, then this can be used to switch on touch movement which +# can detect blocked filament path and try to recover automatically but it is more difficult to set up +# +selector_touch_enable: 0 # If selector touch operation configured this can be used to disable it 1=enabled, 0=disabled + +# When Happy Hare calls out to a macro for user customization and for parking moves these settings are applied and the previous +# values automatically restored afterwards. This allows for deterministic movement speed regardless of the starting state. +# +macro_toolhead_max_accel: 0 # Default printer toolhead acceleration applied when macros are run. 0 = use printer max +macro_toolhead_min_cruise_ratio: 0.5 # Default printer cruise ratio applied when macros are run + + +# Gate loading/unloading ----------------------------------------------------------------------------------------------- +# ██████╗ █████╗ ████████╗███████╗ ██╗ ██████╗ █████╗ ██████╗ +# ██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝ ██║ ██╔═══██╗██╔══██╗██╔══██╗ +# ██║ ███╗███████║ ██║ █████╗ ██║ ██║ ██║███████║██║ ██║ +# ██║ ██║██╔══██║ ██║ ██╔══╝ ██║ ██║ ██║██╔══██║██║ ██║ +# ╚██████╔╝██║ ██║ ██║ ███████╗ ███████╗╚██████╔╝██║ ██║██████╔╝ +# ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ +# +# These settings control the loading and unloading filament at the gate which is the parking position inside the MMU. +# Typically this would be switch sensor but you can also use an encoder. Even with encoder the endstop can be a switch +# and the encoder used for move verifcation (see advanced 'gate_endstop_to_encoder' option). Note that the `encoder` +# method, due to the nature of its operation will overshoot a little. This is not a problem in practice because the +# overshoot will simply be compensated for in the subsequent move. A +ve parking distance moves towards the MMU, -ve +# moves back through the endstop towards the toolhead. If the MMU has multiple bowden tubes then it is possible to home +# at the extruder sensor and avoid long bowden moves! +# +# Possible gate_homing_endstop names: +# encoder - Detect filament position using movement of the encoder +# mmu_gate - Use gate endstop +# mmu_gear - Use individual per-gate endstop (type-B MMU's) +# extruder - Use extruder entry sensor (Only for some type-B designs, see [mmu_machine] require_bowden_move setting) +# +gate_homing_endstop: encoder # Name of gate endstop, "encoder" forces use of encoder for parking +gate_homing_max: 70 # Maximum move distance to home to the gate (or actual move distance for encoder parking) +gate_preload_homing_max: 70 # Maximum homing distance to the mmu_gear endstop (if MMU is fitted with one) +gate_unload_buffer: 50 # Amount to reduce the fast unload so that filament doesn't overshoot when parking +gate_load_retries: 2 # Number of times MMU will attempt to grab the filament on initial load (type-A designs) +gate_parking_distance: 13 # Parking position in the gate (distance back from homing point, -ve value means move forward) +gate_endstop_to_encoder: 10 # Distance between gate endstop and encoder (IF both fitted. +ve if encoder after endstop) +gate_autoload: 1 # If pre-gate sensor fitted this controls the automatic loading of the gate +gate_final_eject_distance: 0 # Distance to eject filament on MMU_EJECT (Ignored by MMU_UNLOAD) + + +# Bowden tube loading/unloading ---------------------------------------------------------------------------------------- +# ██████╗ ██████╗ ██╗ ██╗██████╗ ███████╗███╗ ██╗ ██╗ ██████╗ █████╗ ██████╗ +# ██╔══██╗██╔═══██╗██║ ██║██╔══██╗██╔════╝████╗ ██║ ██║ ██╔═══██╗██╔══██╗██╔══██╗ +# ██████╔╝██║ ██║██║ █╗ ██║██║ ██║█████╗ ██╔██╗ ██║ ██║ ██║ ██║███████║██║ ██║ +# ██╔══██╗██║ ██║██║███╗██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██║██╔══██║██║ ██║ +# ██████╔╝╚██████╔╝╚███╔███╔╝██████╔╝███████╗██║ ╚████║ ███████╗╚██████╔╝██║ ██║██████╔╝ +# ╚═════╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ +# +# In addition to different bowden loading speeds for buffer and non-buffered filament it is possible to detect missed +# steps caused by "jerking" on a heavy spool. If bowden correction is enabled the driver with "believe" the encoder +# reading and make correction moves to bring the filament to within the 'bowden_allowable_load_delta' of the end of +# bowden position (this does require a reliable encoder and is not recommended for very high speed loading >350mm/s) +# +bowden_apply_correction: 1 # 1 to enable, 0 disabled. Requires Encoder +bowden_allowable_load_delta: 20.0 # How close in mm the correction moves will attempt to get to target. Requires Encoder + +# This test verifies the filament is free of extruder before the fast bowden movement to reduce possibility of grinding filament +bowden_pre_unload_test: 1 # 1 to check for bowden movement before full pull (slower), 0 don't check (faster). Requires Encoder + +# ADVANCED: If pre-unload test is enabled, this controls the detection of successful bowden pre-unload test and represents +# the fraction of allowable mismatch between actual movement and that seen by encoder. Setting to 50% tolerance usually +# works well. Increasing will make test more tolerant. Value of 100% essentially disables error detection +bowden_pre_unload_error_tolerance: 50 + + +# Extruder homing ----------------------------------------------------------------------------------------------------- +# ███████╗██╗ ██╗████████╗ ██╗ ██╗ ██████╗ ███╗ ███╗██╗███╗ ██╗ ██████╗ +# ██╔════╝╚██╗██╔╝╚══██╔══╝ ██║ ██║██╔═══██╗████╗ ████║██║████╗ ██║██╔════╝ +# █████╗ ╚███╔╝ ██║ ███████║██║ ██║██╔████╔██║██║██╔██╗ ██║██║ ███╗ +# ██╔══╝ ██╔██╗ ██║ ██╔══██║██║ ██║██║╚██╔╝██║██║██║╚██╗██║██║ ██║ +# ███████╗██╔╝ ██╗ ██║██╗ ██║ ██║╚██████╔╝██║ ╚═╝ ██║██║██║ ╚████║╚██████╔╝ +# ╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# Happy Hare needs a reference "homing point" close to the extruder from which to accurately complete the loading of +# the toolhead. This homing operation takes place after the fast bowden load and it is anticipated that that load +# operation will leave the filament just shy of the homing point. If using a toolhead sensor this initial extruder +# homing is unnecessary (but can be forced) because the homing will occur inside the extruder for the optimum in accuracy. +# You still should set this homing method because it is also used for the determination and calibration of bowden length. +# +# In addition to an entry sensor "extruder" it is possible for Happy Hare to "feel" for the extruder gear entry +# by colliding with it. This can be done with encoder based collision detection, the compression of the sync-feedback +# (aka buffer) sensor or using "touch" (stallguard) on the gear stepper. Note that encoder collision detection is not +# completely deterministic and you will have to find the sweetspot for your setup by adjusting the TMC current reduction. +# Note that reduced current during collision detection can also prevent unecessary filament griding. +# +# Possible extruder_homing_endtop names: +# collision - Detect the collision with the extruder gear by monitoring encoder movement (Requires encoder) +# Fast bowden load will move to the extruder gears +# mmu_gear_touch - Use touch detection when the gear stepper hits the extruder (Requires stallguard) +# Fast bowden load will move to extruder_homing_buffer distance before extruder gear, then home +# extruder - If you have a "filament entry" endstop configured (Requires 'extruder' endstop) +# Fast bowden load will move to extruder_homing_buffer distance before sensor, then home +# filament_compression - If you have a "sync-feedback" sensor with compression switch configured +# Fast bowden load will move to extruder_homing_buffer distance before extruder gear, then home +# none - Don't attempt to home. Only possibiliy if lacking all sensor options +# Fast bowden load will move to the extruder gears. Option is fine if using toolhead sensor +# Note: The homing_endstop will be ignored ("none") if a toolhead sensor is available unless "extruder_force_homing: 1" +# +extruder_homing_max: 80 # Maximum distance to advance in order to attempt to home the extruder +extruder_homing_endstop: extruder # Filament homing method/endstop name (fallback if toolhead sensor not available) +extruder_homing_buffer: 25 # Amount to reduce the fast bowden load so filament doesn't overshoot the extruder homing point +extruder_collision_homing_current: 30 # % gear_stepper current (10%-100%) to use when homing to extruder homing (100 to disable) + +# If you have a toolhead sensor it will always be used as a homing point making the homing outside of the extruder +# potentially unnecessary. However you can still force this initial homing step by setting this option in which case +# the filament will home to the extruder and then home to the toolhead sensor in two steps +# +extruder_force_homing: 0 + + +# Toolhead loading and unloading -------------------------------------------------------------------------------------- +# ████████╗ ██████╗ ██████╗ ██╗ ██╗ ██╗███████╗ █████╗ ██████╗ ██╗ ██████╗ █████╗ ██████╗ +# ╚══██╔══╝██╔═══██╗██╔═══██╗██║ ██║ ██║██╔════╝██╔══██╗██╔══██╗ ██║ ██╔═══██╗██╔══██╗██╔══██╗ +# ██║ ██║ ██║██║ ██║██║ ███████║█████╗ ███████║██║ ██║ ██║ ██║ ██║███████║██║ ██║ +# ██║ ██║ ██║██║ ██║██║ ██╔══██║██╔══╝ ██╔══██║██║ ██║ ██║ ██║ ██║██╔══██║██║ ██║ +# ██║ ╚██████╔╝╚██████╔╝███████╗██║ ██║███████╗██║ ██║██████╔╝ ███████╗╚██████╔╝██║ ██║██████╔╝ +# ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ +# +# It is possible to define highly customized loading and unloading sequences, however, unless you have a specialized +# setup it is probably easier to opt for the built-in toolhead loading and unloading sequence which already offers a +# high degree of customization. If you need even more control then edit the _MMU_LOAD_SEQUENCE and _MMU_UNLOAD_SEQUENCE +# macros in mmu_sequence.cfg - but be careful! +# +# An MMU must have a known point at the end of the bowden from which it can precisely load the extruder. Generally this +# will either be the extruder entrance (which is controlled with settings above) or by homing to toolhead sensor. If +# you have toolhead sensor it is past the extruder gear and the driver needs to know the max distance (from end of +# bowden move) to attempt homing +# +toolhead_homing_max: 40 # Maximum distance to advance in order to attempt to home to defined homing endstop + +# IMPORTANT: These next three settings are based on the physical dimensions of your toolhead +# Once a homing position is determined, Happy Hare needs to know the final move distance to the nozzle. There is only +# one correct value for your setup - use 'toolhead_ooze_reduction' (which corresponds to the residual filament left in +# your nozzle) to control excessive oozing on load. See doc for table of proposed values for common configurations. +# +# NOTE: If you have a toolhead sensor you can automate the calculation of these parameters! Read about the +# `MMU_CALIBRATE_TOOLHEAD` command (https://github.com/moggieuk/Happy-Hare/wiki/Blobbing-and-Stringing#---calibrating-toolhead) +# +toolhead_extruder_to_nozzle: 72 # Distance from extruder gears (entrance) to nozzle +toolhead_sensor_to_nozzle: 62 # Distance from toolhead sensor to nozzle (ignored if not fitted) +toolhead_entry_to_extruder: 8 # Distance from extruder "entry" sensor to extruder gears (ignored if not fitted) + +# This setting represents how much residual filament is left behind in the nozzle when filament is removed, it is thus +# used to reduce the extruder loading length and prevent excessive blobbing but also in the calculation of purge volume. +# Note that this value can also be measured with the `MMU_CALIBRATE_TOOLHEAD` procedure +# +toolhead_residual_filament: 0 # Reduction in extruder loading length because of residual filament left behind + +# TUNING: Finally, this is the last resort tuning value to fix blobbing. It is expected that this value is NEAR ZERO as +# it represents a further reduction in extruder load length to fix blobbing. If using a wipetower and you experience blobs +# on it, increase this value (reduce the quantity of filament loaded). If you experience gaps, decrease this value. If gaps +# and already at 0 then perhaps the 'toolhead_extruder_to_nozzle' or 'toolhead_residual_filament' settings are incorrect. +# Similarly a value >+5mm also suggests the four settings above are not correct. Also see 'retract' setting in +# 'mmu_macro_vars.cfg' for final in-print ooze tuning. +# +toolhead_ooze_reduction: 0 # Reduction in extruder loading length to prevent ooze (represents filament remaining) + +# Distance added to the extruder unload movement to ensure filament is free of extruder. This adds some degree of tolerance +# to slightly incorrect configuration or extruder slippage. However don't use as an excuse for incorrect toolhead settings +# +toolhead_unload_safety_margin: 10 # Extra movement safety margin (default: 10mm) + +# If not synchronizing gear and extruder and you experience a "false" clog detection immediately after the tool change +# it might be because of a long bowden and/or large internal diameter that causes slack in the filament. This optional +# move will tighten the filament after a load by % of current clog detection length. Gear stepper will run at 50% current +# +toolhead_post_load_tighten: 60 # % of clog detection length, 0 to disable. Ignored if 'sync_to_extruder: 1' + +# ADVANCED: Controls the detection of successful extruder load/unload movement and represents the fraction of allowable +# mismatch between actual movement and that seen by encoder. Setting to 100% tolerance effectively turns off checking. +# Some designs of extruder have a short move distance that may not be picked up by encoder and cause false errors. This +# allows masking of those errors. However the error often indicates that your extruder load speed is too high or the +# friction is too high on the filament and in that case masking the error is not a good idea. Try reducing friction +# and lowering speed first! +# +toolhead_move_error_tolerance: 60 + + +# Tip forming --------------------------------------------------------------------------------------------------------- +# ████████╗██╗██████╗ ███████╗ ██████╗ ██████╗ ███╗ ███╗██╗███╗ ██╗ ██████╗ +# ╚══██╔══╝██║██╔══██╗ ██╔════╝██╔═══██╗██╔══██╗████╗ ████║██║████╗ ██║██╔════╝ +# ██║ ██║██████╔╝ █████╗ ██║ ██║██████╔╝██╔████╔██║██║██╔██╗ ██║██║ ███╗ +# ██║ ██║██╔═══╝ ██╔══╝ ██║ ██║██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██║ ██║ +# ██║ ██║██║ ██║ ╚██████╔╝██║ ██║██║ ╚═╝ ██║██║██║ ╚████║╚██████╔╝ +# ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# Tip forming responsibility can be split between slicer (in-print) and standalone macro (not in-print) or forced to always +# be done by Happy Hare's standalone macro. Since you always need the option to form tips without the slicer so it is +# generally easier to completely turn off the slicer, force "standalone" tip forming and tune only in Happy Hare. +# +# When Happy Hare is asked to form a tip it will run the referenced macro. Two are reference examples are provided but +# you can implement your own: +# _MMU_FORM_TIP .. default tip forming similar to popular slicers like Superslicer and Prusaslicer +# _MMU_CUT_TIP .. for Filametrix (ERCFv2) or similar style toolhead filament cutting system +# +# Often it is useful to increase the extruder current for the rapid movement to ensure high torque and no skipped steps +# +# If opting for slicer tip forming you MUST configure where the slicer leaves the filament in the extruder since +# there is no way to determine this. This can be ignored if all tip forming is performed by Happy Hare +# +force_form_tip_standalone: 1 # 0 = Slicer in print else standalone, 1 = Always standalone tip forming (TURN SLICER OFF!) +form_tip_macro: _MMU_CUT_TIP # Name of macro to call to perform the tip forming (or cutting) operation +extruder_form_tip_current: 100 # % of extruder current (100%-150%) to use when forming tip (100 to disable) +slicer_tip_park_pos: 0 # This specifies the position of filament in extruder after slicer completes tip forming + + +# Synchronized gear/extruder movement ---------------------------------------------------------------------------------- +# ███╗ ███╗ ██████╗ ████████╗ ██████╗ ██████╗ ███████╗██╗ ██╗███╗ ██╗ ██████╗ +# ████╗ ████║██╔═══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╔════╝╚██╗ ██╔╝████╗ ██║██╔════╝ +# ██╔████╔██║██║ ██║ ██║ ██║ ██║██████╔╝ ███████╗ ╚████╔╝ ██╔██╗ ██║██║ +# ██║╚██╔╝██║██║ ██║ ██║ ██║ ██║██╔══██╗ ╚════██║ ╚██╔╝ ██║╚██╗██║██║ +# ██║ ╚═╝ ██║╚██████╔╝ ██║ ╚██████╔╝██║ ██║ ███████║ ██║ ██║ ╚████║╚██████╗ +# ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ +# +# This controls whether the extruder and gear steppers are synchronized during printing operations +# If you normally run with maxed out gear stepper current consider reducing it with 'sync_gear_current' +# If equipped with TMC drivers the current of the gear and extruder motors can be controlled to optimize performance. +# This can be useful to control gear stepper temperature when printing with synchronized motor +# +sync_to_extruder: 1 # Gear motor is synchronized to extruder during print +sync_gear_current: 70 # % of gear_stepper current (10%-100%) to use when syncing with extruder during print +sync_form_tip: 0 # Synchronize during standalone tip formation (initial part of unload) + +# Optionally it is possible to leverage feedback for a "compression/expansion" sensor in the bowden path from MMU to +# extruder to ensure that the two motors are kept in sync as viewed by the filament (the signal feedback state can be +# binary supplied by one or two switches: -1 (expanded) and 1 (compressed) of proportional value between -1.0 and 1.0 +# Requires [mmu_sensors] setting +# +sync_feedback_enable: 0 # 0 = Turn off (even with fitted sensor), 1 = Turn on +sync_multiplier_high: 1.05 # Maximum factor to apply to gear stepper 'rotation_distance' +sync_multiplier_low: 0.95 # Minimum factor to apply + + +# Filament Management Options ---------------------------------------------------------------------------------------- +# ███████╗██╗██╗ ███╗ ███╗ ██████╗ ███╗ ███╗████████╗ +# ██╔════╝██║██║ ████╗ ████║██╔════╝ ████╗ ████║╚══██╔══╝ +# █████╗ ██║██║ ██╔████╔██║██║ ███╗██╔████╔██║ ██║ +# ██╔══╝ ██║██║ ██║╚██╔╝██║██║ ██║██║╚██╔╝██║ ██║ +# ██║ ██║███████╗██╗ ██║ ╚═╝ ██║╚██████╔╝██║ ╚═╝ ██║ ██║ +# ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ +# +# - Clog detection is available when encoder is fitted and it can detect when filament is not moving and pause the print +# - EndlessSpool feature allows detection of runout on one spool and the automatic mapping of tool to an alternative +# gate (spool). Set to '1', this feature requires clog detection or gate sensor or pre-gate sensors. EndlessSpool +# functionality can optionally be extended to attempt to load an empty gate with 'endless_spool_on_load'. On some MMU +# designs (with linear selector) it can also be configured to eject filament remains to a designated gate rather than +# defaulting to current gate. A custom gate will disable pre-gate runout detection for EndlessSpool because filament +# end must completely pass through the gate for selector to move +# +enable_clog_detection: 2 # 0 = disable, 1 = static length clog detection, 2 = automatic length clog detection +enable_endless_spool: 1 # 0 = disable, 1 = enable endless spool +endless_spool_on_load: 0 # 0 = don't apply endless spool on load, 1 = run endless spool if gate is empty +endless_spool_eject_gate: -1 # Which gate to eject the filament remains. -1 = current gate +#endless_spool_groups: # Default EndlessSpool groups (see later in file) +# +# Spoolman support requires you to correctly enable spoolman with moonraker first. If enabled, the gate SpoolId will +# be used to load filament details and color from the spoolman database and Happy Hare will activate/deactivate +# spools as they are used. The enabled variation allows for either the local map or the spoolman map to be the +# source of truth as well as just fetching filament attributes. See this table for explanation: +# +# | Activate/ | Fetch filament attributes | Filament gate | Filament gate | +# spoolman_support | Deactivate | attributes from spoolman | assignment shown | assignment pulled | +# | spool? | based on spool_id? | in spoolman db? | from spoolman db? | +# -----------------+------------+---------------------------+------------------+-------------------+ +# off | no | no | no | no | +# readonly | yes | yes | no | no | +# push | yes | yes | yes | no | +# pull | yes | yes | yes | yes | +# +spoolman_support: off # off = disabled, readonly = enabled, push = local gate map, pull = remote gate map +pending_spool_id_timeout: 20 # Seconds after which this pending spool_id (set with rfid) is voided +# +# Mainsail/Fluid UI can visualize the color of filaments next to the extruder/tool chooser. The color is dynamic and +# can be customized to your choice: +# +# slicer - Color from slicer tool map (what the slicer expects) +# allgates - Color from all the tools in the gate map after running through the TTG map +# gatemap - As per gatemap but hide empty tools +# off - Turns off support +# +# Note: Happy Hare will also add the 'spool_id' variable to the Tx macro if spoolman is enabled +# +t_macro_color: slicer # 'slicer' = default | 'allgates' = mmu | 'gatemap' = mmu without empty gates | 'off' + + +# Print Statistics --------------------------------------------------------------------------------------------------- +# ███████╗████████╗ █████╗ ████████╗███████╗ +# ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝ +# ███████╗ ██║ ███████║ ██║ ███████╗ +# ╚════██║ ██║ ██╔══██║ ██║ ╚════██║ +# ███████║ ██║ ██║ ██║ ██║ ███████║ +# ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ +# +# These parameters determine how print statistic data is shown in the console. This table can show a lot of data, +# probably more than you'd want to see. Below you can enable/disable options to your needs. +# +# +-----------+---------------------+----------------------+----------+ +# | 114(46) | unloading | loading | complete | +# | swaps | pre | - | post | pre | - | post | swap | +# +-----------+------+-------+------+------+-------+-------+----------+ +# | all time | 0:07 | 47:19 | 0:00 | 0:01 | 37:11 | 33:39 | 2:00:38 | +# | - avg | 0:00 | 0:24 | 0:00 | 0:00 | 0:19 | 0:17 | 1:03 | +# | this job | 0:00 | 10:27 | 0:00 | 0:00 | 8:29 | 8:30 | 28:02 | +# | - avg | 0:00 | 0:13 | 0:00 | 0:00 | 0:11 | 0:11 | 0:36 | +# | last | 0:00 | 0:12 | 0:00 | 0:00 | 0:10 | 0:14 | 0:39 | +# +-----------+------+-------+------+------+-------+-------+----------+ +# Note: Only formats correctly on Python3 +# +# Comma separated list of desired columns +# Options: pre_unload, unload, post_unload, pre_load, load, post_load, total +console_stat_columns: unload, load, post_load, total + +# Comma separated list of rows. The order determines the order in which they're shown. +# Options: total, total_average, job, job_average, last +console_stat_rows: total, total_average, job, job_average, last + +# How you'd want to see the state of the gates and how they're performing +# string - poor, good, perfect, etc.. +# percentage - rate of success +# emoticon - fun sad to happy faces (python3 only) +console_gate_stat: emoticon + +# Always display the full statistics table +console_always_output_full: 1 # 1 = Show full table, 0 = Only show totals out of print + + +# Miscellaneous, but you should review ------------------------------------------------------------------------------- +# ███╗ ███╗██╗███████╗ ██████╗ +# ████╗ ████║██║██╔════╝██╔════╝ +# ██╔████╔██║██║███████╗██║ +# ██║╚██╔╝██║██║╚════██║██║ +# ██║ ╚═╝ ██║██║███████║╚██████╗ +# ╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ +# +# Important you verify these work for you setup/workflow. Temperature and timeouts +# +timeout_pause: 72000 # Idle time out (printer shuts down) in seconds used when in MMU pause state +disable_heater: 600 # Delay in seconds after which the hotend heater is disabled in the MMU_PAUSE state +default_extruder_temp: 200 # Default temperature for performing swaps and forming tips when not in print (overridden by gate map) +extruder_temp_variance: 2 # When waiting for extruder temperature this is the +/- permissible variance in degrees (>= 1) +# +# These are auto calibration/tuning settings. Once the gear rotation_distance and encoder are calibrated, enabling these options +# will lessen the initial calibration and will automatically tune bowden length and individual gate rotation_distance differences. +# Note: What can be tuned is based on "variable_rotation_distance" and "variable_bowden_lengths" settings in mmu_hardware.cfg +# E.g. with fixed bowden and multiple BMG gears and encoder like the ERCF, the bowden length is tuned on gate#0 and +# rotation_distance (MMU_CALIBRATE_GATE) is tuned for other gates. +# +autotune_bowden_length: 0 # Automated bowden length calibration/tuning. 1=automatic, 0=manual/off +autotune_rotation_distance: 0 # Automated gate calibration/tuning (requires encoder). 1=automatic, 0=manual/off +# +# Other workflow options +# +startup_home_if_unloaded: 0 # 1 = force mmu homing on startup if unloaded, 0 = do nothing +startup_reset_ttg_map: 0 # 1 = reset TTG map on startup, 0 = do nothing +show_error_dialog: 0 # 1 = show pop-up dialog in addition to console message, 0 = show error in console +preload_attempts: 5 # How many "grabbing" attempts are made to pick up the filament with preload feature +strict_filament_recovery: 0 # If enabled with MMU with toolhead sensor, this will cause filament position recovery to + # perform extra moves to look for filament trapped in the space after extruder but before sensor +filament_recovery_on_pause: 1 # 1 = Run a quick check to determine current filament position on pause/error, 0 = disable +retry_tool_change_on_error: 0 # Whether to automatically retry a failed tool change. If enabled Happy Hare will perform + # the equivalent of 'MMU_RECOVER' + 'Tx' commands which usually is all that is necessary + # to recover. Note that enabling this can mask problems with your MMU +bypass_autoload: 1 # If extruder sensor fitted this controls the automatic loading of extruder for bypass operation +has_filament_buffer: 1 # Whether the MMU has a filament buffer. Set to 0 if using Filamentalist or DC eSpooler, etc +# +# Advanced options. Don't mess unless you fully understand. Read documentation. +# +encoder_move_validation: 1 # ADVANCED: 1 = Normally Encoder validates move distances are within given tolerance + # 0 = Validation is disabled (eliminates slight pause between moves but less safe) +print_start_detection: 1 # ADVANCED: Enabled for Happy Hare to automatically detect start and end of print and call + # ADVANCED: MMU_PRINT_START and MMU_PRINT_END automatically. Harmless to leave enabled but can disable + # if you think it is causing problems and known START/END is covered in your macros +extruder: extruder # ADVANCED: Name of the toolhead extruder that MMU is using +gcode_load_sequence: 0 # VERY ADVANCED: Gcode loading sequence 1=enabled, 0=internal logic (default) +gcode_unload_sequence: 0 # VERY ADVANCED: Gcode unloading sequence, 1=enabled, 0=internal logic (default) + + +# ADVANCED: Klipper tuning ------------------------------------------------------------------------------------------- +# ██╗ ██╗██╗ ██╗██████╗ ██████╗ ███████╗██████╗ +# ██║ ██╔╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗ +# █████╔╝ ██║ ██║██████╔╝██████╔╝█████╗ ██████╔╝ +# ██╔═██╗ ██║ ██║██╔═══╝ ██╔═══╝ ██╔══╝ ██╔══██╗ +# ██║ ██╗███████╗██║██║ ██║ ███████╗██║ ██║ +# ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ +# +# Timer too close is a catch all error, however it has been found to occur on some systems during homing and probing +# operations especially so with CANbus connected MCUs. Happy Hare uses many homing moves for reliable extruder loading +# and unloading and enabling this option affords klipper more tolerance and avoids this dreaded error +# +update_trsync: 0 # 1 = Increase TRSYNC_TIMEOUT, 0 = Leave the klipper default +# +# Some CANbus boards are prone to this but it have been seen on regular USB boards where a comms timeout will kill +# the print. Since it seems to occur only on homing moves they can be safely retried to workaround. This has been +# working well in practice +canbus_comms_retries: 3 # Number of retries. Recommend the default of 3. +# +# Older neopixels have very finicky timing and can generate lots of "Unable to obtain 'neopixel_result' response" +# errors in klippy.log. An often cited workaround is to increase BIT_MAX_TIME in neopixel.py. This option does that +# automatically for you to save dirtying klipper +update_bit_max_time: 1 # 1 = Increase BIT_MAX_TIME, 0 = Leave the klipper default + + +# ADVANCED: MMU macro overrides --- ONLY SET IF YOU'RE COMFORTABLE WITH KLIPPER MACROS ------------------------------- +# ███╗ ███╗ █████╗ ██████╗██████╗ ██████╗ ███████╗ +# ████╗ ████║██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔════╝ +# ██╔████╔██║███████║██║ ██████╔╝██║ ██║███████╗ +# ██║╚██╔╝██║██╔══██║██║ ██╔══██╗██║ ██║╚════██║ +# ██║ ╚═╝ ██║██║ ██║╚██████╗██║ ██║╚██████╔╝███████║ +# ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ +# +# 'pause_macro' defines what macro to call on MMU error (must put printer in paused state) +# Other macros are detailed in 'mmu_sequence.cfg' +# Also see form_tip_macro in Tip Forming section +# +pause_macro: PAUSE # What macro to call to pause the print +action_changed_macro: _MMU_ACTION_CHANGED # Called when action (printer.mmu.action) changes +print_state_changed_macro: _MMU_PRINT_STATE_CHANGED # Called when print state (printer.mmu.print_state) changes +mmu_event_macro: _MMU_EVENT # Called on useful MMU events +pre_unload_macro: _MMU_PRE_UNLOAD # Called before starting the unload +post_form_tip_macro: _MMU_POST_FORM_TIP # Called immediately after tip forming +post_unload_macro: _MMU_POST_UNLOAD # Called after unload completes +pre_load_macro: _MMU_PRE_LOAD # Called before starting the load +post_load_macro: _MMU_POST_LOAD # Called after the load is complete +unload_sequence_macro: _MMU_UNLOAD_SEQUENCE # VERY ADVANCED: Optionally called based on 'gcode_unload_sequence' +load_sequence_macro: _MMU_LOAD_SEQUENCE # VERY ADVANCED: Optionally called based on 'gcode_load_sequence' +espooler_start_macro: '' # Called to start eSpooler if fitted (params: GATE, STEP_SPEED, MAX_DISTANCE, HOMING) +espooler_stop_macro: '' # Called to stop eSpooler if fitted (params: GATE, DISTANCE) + + +# ADVANCED: See documentation for use of these ----------------------------------------------------------------------- +# ██████╗ ███████╗███████╗███████╗████████╗ ██████╗ ███████╗███████╗███████╗ +# ██╔══██╗██╔════╝██╔════╝██╔════╝╚══██╔══╝ ██╔══██╗██╔════╝██╔════╝██╔════╝ +# ██████╔╝█████╗ ███████╗█████╗ ██║ ██║ ██║█████╗ █████╗ ███████╗ +# ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██║ ██║ ██║██╔══╝ ██╔══╝ ╚════██║ +# ██║ ██║███████╗███████║███████╗ ██║ ██████╔╝███████╗██║ ███████║ +# ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚══════╝ +# +# These are the values that the various "RESET" commands will reset too rather than the built-in defaults. The lenght +# of the lists must match the number of gates on your MMU +# +# e.g. MMU_GATE_MAP RESET=1 - will use all the 'gate_XXX' values +# MMU_TTG_MAP RESET=1 - will use the 'tool_to_gate_map' +# MMU_ENDLESS_SPOOL_GROUPS RESET=1 - will use the 'endless_spool_groups' +# +# Gate: #0 #1 #2 #3 #4 #5 #6 #7 #8 +#gate_status: 1, 0, 1, 2, 2, -1, -1, 0, 1 +#gate_filament_name: one, two, three, four, five, six, seven, eight, nine +#gate_material: PLA, ABS, ABS, ABS+, PLA, PLA, PETG, TPU, ABS +#gate_color: red, black, yellow, green, blue, indigo, ffffff, grey, black +#gate_temperature: 210, 240, 235, 245, 210, 200, 215, 240, 240 +#gate_spool_id: 3, 2, 1, 4, 5, 6, 7, -1, 9 +#gate_speed_override: 100, 100, 100, 100, 100, 100, 100, 50, 100 +#endless_spool_groups: 0, 1, 2, 1, 0, 0, 3, 4, 1 +# +# Tool: T0 T1 T2 T3 T4 T5 T6 T7 T8 +#tool_to_gate_map: 0, 1, 2, 3, 4, 5, 6, 7, 8 + + +# ADVANCED/CUSTOM MMU: See documentation for use of these ------------------------------------------------------------ +# ██████╗██╗ ██╗███████╗████████╗ ██████╗ ███╗ ███╗ ███╗ ███╗███╗ ███╗██╗ ██╗ +# ██╔════╝██║ ██║██╔════╝╚══██╔══╝██╔═══██╗████╗ ████║ ████╗ ████║████╗ ████║██║ ██║ +# ██║ ██║ ██║███████╗ ██║ ██║ ██║██╔████╔██║ ██╔████╔██║██╔████╔██║██║ ██║ +# ██║ ██║ ██║╚════██║ ██║ ██║ ██║██║╚██╔╝██║ ██║╚██╔╝██║██║╚██╔╝██║██║ ██║ +# ╚██████╗╚██████╔╝███████║ ██║ ╚██████╔╝██║ ╚═╝ ██║ ██║ ╚═╝ ██║██║ ╚═╝ ██║╚██████╔╝ +# ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ +# +# Normally all these settings are set based on your choice of 'mmu_vendor' and 'mmu_version' in mmu_hardware.cfg, but they +# can be overridden. If you have selected a vendor of "Other" and your MMU has a selector you must set these CAD based +# dimensions else you will get arbitrary defaults. You may also need to set additional attributes in '[mmu_machine]' +# section of mmu_hardware.cfg. +# +#cad_gate0_pos: 4.2 # Approximate distance from endstop to first gate. Used for rough calibration only +#cad_gate_width: 21.0 # Width of each gate +#cad_bypass_offset: 0 # Distance from limit of travel back to the bypass (e.g. ERCF v2.0) +#cad_last_gate_offset: 2.0 # Distance from limit of travel back to last gate +#cad_selector_tolerance: 10.0 # How much extra selector movement to allow for calibration +#cad_gate_directions = [1, 1, 0, 0] # Directions of gear depending on gate (3DChameleon) +#cad_release_gates = [2, 3, 0, 1] # Gate to move to when releasing filament (3DChameleon) + +# SUPPLEMENTAL USER CONFIG retained after upgrade -------------------------------------------------------------------- +# diff --git a/mmu-20250423_130617/base/mmu_sequence.cfg b/mmu-20250423_130617/base/mmu_sequence.cfg new file mode 120000 index 0000000..4e1cdc5 --- /dev/null +++ b/mmu-20250423_130617/base/mmu_sequence.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_sequence.cfg \ No newline at end of file diff --git a/mmu-20250423_130617/base/mmu_software.cfg b/mmu-20250423_130617/base/mmu_software.cfg new file mode 120000 index 0000000..957302e --- /dev/null +++ b/mmu-20250423_130617/base/mmu_software.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_software.cfg \ No newline at end of file diff --git a/mmu-20250423_130617/base/mmu_state.cfg b/mmu-20250423_130617/base/mmu_state.cfg new file mode 120000 index 0000000..be67d3e --- /dev/null +++ b/mmu-20250423_130617/base/mmu_state.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_state.cfg \ No newline at end of file diff --git a/mmu-20250423_130617/mmu_vars.cfg b/mmu-20250423_130617/mmu_vars.cfg new file mode 100644 index 0000000..dd5fd54 --- /dev/null +++ b/mmu-20250423_130617/mmu_vars.cfg @@ -0,0 +1,38 @@ +[Variables] +mmu__revision = 2552 +mmu_calibration_bowden_home = 'encoder' +mmu_calibration_bowden_lengths = [1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1] +mmu_calibration_clog_length = 17.4 +mmu_encoder_resolution = 0.959616 +mmu_gear_rotation_distances = [22.731687, 22.686238, 22.849841, 22.94982, 22.958909, 22.94982, 22.895286, 22.958909] +mmu_selector_bypass = 179.7 +mmu_selector_offsets = [2.1, 25.2, 48.5, 71.7, 94.9, 118.9, 142.1, 164.5] +mmu_servo_angles = {'down': 90, 'up': 10, 'move': 35} +mmu_state_enable_endless_spool = 1 +mmu_state_endless_spool_groups = [0, 1, 2, 3, 4, 5, 6, 7] +mmu_state_filament_pos = 10 +mmu_state_filament_remaining = 0.0 +mmu_state_filament_remaining_color = '' +mmu_state_gate_color = ['', '', '', '', '', '', '', ''] +mmu_state_gate_filament_name = ['', '', '', '', '', '', '', ''] +mmu_state_gate_material = ['', '', '', '', '', '', '', ''] +mmu_state_gate_selected = -2 +mmu_state_gate_speed_override = [100, 100, 100, 100, 100, 100, 100, 100] +mmu_state_gate_spool_id = [-1, -1, -1, -1, -1, -1, -1, -1] +mmu_state_gate_status = [1, 1, -1, -1, -1, 0, -1, -1] +mmu_state_gate_temperature = [200, 200, 200, 200, 200, 200, 200, 200] +mmu_state_last_tool = 1 +mmu_state_tool_selected = -2 +mmu_state_tool_to_gate_map = [0, 1, 2, 3, 4, 5, 6, 7] +mmu_statistics_counters = {'servo_down': {'count': 812, 'limit': 5000, 'warning': 'Inspect servo arm for wear/damage', 'pause': False}, 'mmu_restarts': {'count': 161, 'limit': -1, 'warning': ''}, 'cutter_blade': {'count': 48, 'limit': 3000, 'warning': 'Inspect/replace filament cutting blade', 'pause': False}} +mmu_statistics_gate_0 = {'pauses': 12, 'loads': 28, 'load_distance': 38354.336, 'load_delta': 6896.202, 'unloads': 43, 'unload_distance': 31567.3, 'unload_delta': 1877.741, 'load_failures': 7, 'unload_failures': 16, 'quality': 0.9546537865318246} +mmu_statistics_gate_1 = {'pauses': 2, 'loads': 22, 'load_distance': 28896.615, 'load_delta': 90.861, 'unloads': 25, 'unload_distance': 27502.0, 'unload_delta': 1483.93, 'load_failures': 1, 'unload_failures': 5, 'quality': 0.8375118313601163} +mmu_statistics_gate_2 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_3 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_4 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_5 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_6 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_7 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_swaps = {'pre_unload': 18.72, 'post_unload': 12.62, 'unload': 1789.69, 'pre_load': 13.84, 'post_load': 168.54, 'load': 1191.74, 'total_swaps': 40, 'swaps_since_pause': 3, 'swaps_since_pause_record': 8, 'total': 2629.04, 'total_pauses': 13, 'pause': 1679.71} +nvm_offset = -0.11599999999999978 + diff --git a/mmu-20250423_130617/optional/client_macros.cfg b/mmu-20250423_130617/optional/client_macros.cfg new file mode 120000 index 0000000..292db3e --- /dev/null +++ b/mmu-20250423_130617/optional/client_macros.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/optional/client_macros.cfg \ No newline at end of file diff --git a/mmu-20250423_130617/optional/mmu_menu.cfg b/mmu-20250423_130617/optional/mmu_menu.cfg new file mode 120000 index 0000000..f0c615f --- /dev/null +++ b/mmu-20250423_130617/optional/mmu_menu.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/optional/mmu_menu.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/addons/blobifier.cfg b/mmu-20250423_131125/addons/blobifier.cfg new file mode 100644 index 0000000..af10248 --- /dev/null +++ b/mmu-20250423_131125/addons/blobifier.cfg @@ -0,0 +1,924 @@ +# Include servo hardware definition separately to allow for automatic upgrade +[include blobifier_hw.cfg] + +########################################################################################## + +# Sample config to be used in conjunction with Blobifier Purge Tray, Bucket & Nozzle +# Scrubber mod. Created by Dendrowen (dendrowen on Discord). The Macro is based on a +# version, and Nozzle Scrubber is made by Hernsl (hernsl#8860 on Discord). The device is +# designed around a Voron V2.4 300mm, but should work for 250mm and 350mm too. This +# version only supports the assembly on the rear-left of the bed. If you decide to change +# that, please consider contributing to the project by creating a pull request with the +# needed changes. + +# IMPORTANT: The rear-left part of your bed becomes unusable by this mod because the +# toolhead needs to lower down to 0. Be sure not to use the left-rear 130x35mm. + +# The goals of this combination of devices is to dispose of purged filament during a +# multicolored print without the need of a purge block and without the flurries of +# filament poops consuming your entire 3D printer room. The Blobifier achieves that by +# purging onto a retractable tray which causes the filament to turn into a tiny blob +# rather then a large spiral. This keeps the waste relatively small. The bucket should be +# able to account for up to 200 filament swaps (for the 300mm V2). + +# The Blobifier uses some room at the back-left side of your printer, depending on your +# printer limits and positions. (usually max_pos.y - toolhead_y and brush_start + +# brush_width + toolhead_x). If you do place objects within this region, Blobifier will +# skip purging automatically. It does this by extending the EXCLUDE_OBJECT_* macro's, so +# make sure you have exclude objects enabled in your slicer. + +# If your using Blobifier in conjunction with the filament cutter on the stealthburner +# toolhead, you can place the pin at max_pos.y - 7 (e.g., max pos y is 307, place it at +# 300). The pin will then poke through the cavity in your toolhead. (Be careful with +# manually moving the toolhead. I have broken many filament cutter pins) + +# It is advised to use the start_gcode from Happy Hare. Then you will be able to fully +# and efficiently use this mod. Check the Happy Hare document at gcode_preprocessing.md +# in the Happy Hare github for more details. + +###################################### DISCLAIMER ######################################## + +# You, and you alone, are responsible for the correct execution of these macros and +# gcodes. Any damage that may occur to your machine remains your responsibility. +# Especially when executing this macro for the first few times, keep an eye on your +# printer and the +# emergency stop. + +########################################################################################## + +########################################################################################## +# Main macro. Usually you should only need to call this one or place it in the Happy Hare +# _MMU_POST_LOAD macro using the variable_user_post_load_extension: +# +# variable_user_post_load_extension : `BLOBIFIER` +# +# Notes on parameters: +# PURGE_LENGTH=[float] (optional) The length to purge. If omitted (default) it will check +# the purge_volumes matrix or variable_purge_length. This can be used +# to override and for testing. +# +[gcode_macro BLOBIFIER] +# These parameters define your filament purging. +# Note that the control of retraction is set in 'mmu_macro_vars.cfg' which can be increased +# if you experience excessive oozing. +variable_purge_spd: 400 # Speed, in mm/min, of the purge. +variable_purge_temp_min: 200 # Minimum nozzle purge temperature. +variable_toolhead_x: 70 # From the nozzle to the left of your toolhead +variable_toolhead_y: 50 # From the nozzle to the front of your toolhead + +# This macro will prevent a gcode movement downward while 'blobbing' if there might be a +# print in the way (e.g. You print something large and need the area where Blobifier does +# its... 'business'). However, at low heights (or at print start) this might not be +# desireable. You can force a 'safe descend' with this variable. Keep in mind that the +# height of the print is an estimation based on previous heights and certain assumptions +# so it might be wise to include a safety margin of 0.2mm +variable_force_safe_descend_height_until: 1.0 + +# Adjust this so that your nozzle scrubs within the brush. Be careful not to go too low! +# Start out with a high value (like, 6) and go +# down from there. +variable_brush_top: 6 + +# These parameters define your scrubbing, travel speeds, safe z clearance and how many +# times you want to wipe. Update as necessary. +variable_clearance_z: 2 # When traveling, but not cleaning, the + # clearance along the z-axis between nozzle + # and brush. +variable_wipe_qty: 2 # Number of complete (A complete wipe: left, + # right, left OR right, left, right) wipes. +variable_travel_spd_xy: 10000 # Travel (not cleaning) speed along x and + # y-axis in mm/min. +variable_travel_spd_z: 1000 # Travel (not cleaning) speed along z axis + # in mm/min. +variable_wipe_spd_xy: 10000 # Nozzle wipe speed in mm/min. + +# The acceleration to use when using the brush action. If set to 0, it uses the already +# set acceleration. However, in some cases this is not desirable for the last motion +# could be an 'outer contour' acceleration which is usually lower. +variable_brush_accel: 0 + +# Blobifier sends the toolhead to the maximum y position during purge operations and +# minimum x position during shake operations. This can cause issues when skew correction +# is set up. If you have skew correction enabled and get 'move out of range' errors +# regarding blobifier while skew is enabled, try increasing this value. Keep the +# adjustments small though! (0.1mm - 0.5mm) and increase it until it works. +variable_skew_correction: 0.1 + +# These parameters define the size of the brush. Update as necessary. A visual reference +# is provided below. +# +# ← brush_width → +# _________________ +# | | ↑ Y position is acquired from your +# brush_start (x) | | brush_depth stepper_y position_max. Adjust +# |_________________| ↓ your brush physically in Y so +# (y) that the nozzle scrubs within the +# brush_front brush. +# __________________________________________________________ +# PRINTER FRONT +# +# +# Start location of the brush. Defaults for 250, 300 and 350mm are provided below. +# Uncomment as necessary +#variable_brush_start: 34 # For 250mm build +variable_brush_start: 67 # For 300mm build +#variable_brush_start: 84 # for 350mm build + +# width of the brush +variable_brush_width: 35 + +# Location of where to purge. The tray is 15mm in length, so if you assemble it against +# the side of the bed (default), 10mm is a good location +variable_purge_x: 10 + +# Height of the tray. If it's below your bed, give this a negative number equal to the +# difference. If it's above your bed, give it a positive number. You can find this number +# by homing, optional QGL or equivalent, and moving you toolhead above the tray, and +# lowering it with the paper method. +variable_tray_top: 0.7 + +# Servo angles for tray positions +variable_tray_angle_out: 0 +variable_tray_angle_in: 180 + +# Increase this value if the servo doesn't have enough time to fully retract or extend +variable_dwell_time: 200 + +# ======================================================================================== +# ==================== BLOB TUNING ======================================================= +# ======================================================================================== + +# The following section defines how the purging sequence is executed. This is where you +# tune the purging to create pretty blobs. Refer to the visual reference for a better +# understanding. The visual is populated with example values. Below are some guides +# provided to help with tuning. +# +# \_____________/ +# |___|___| +# \_/ ______________ < End of third iteration. +# / \ HEIGHT: 3 x iteration_z_raise - (2 + 1) x iteration_z_change (3 x 5 - 2 x 1.2 = 11.4) +# | | EXTRUDED: 3 x max_iteration_length (3 x 50 = 150) +# / \ ______________ < End of second iteration. +# | \ HEIGHT: 2 x iteration_z_raise - 1 x iteration_z_change (2 x 5 - 1 x 1.2 = 8.8) +# / | EXTRUDED: 2 x max_iteration_length (2 x 50 = 100) +# | \ ______________ < End of first iteration. +# / \ HEIGHT: 1 x iteration_z_raise (1 x 5 = 5) +# | | EXTRUDED: 1 x max_iteration_length (1 x 50 = 50) +#___________ \ / ______________ < Start height of the nozzle. default value: 1.5mm +# |_______________\___________/_ ______________ < Bottom of the tray +# |_____________________________| +# | +# +########################### BLOB TUNING ############################## +# +-------------------------------------+----------------------------+ +# | Filament sticks to the nozzle at | Incr. purge start | +# | initial purge (first few mm) | | +# +-------------------------------------+----------------------------+ +# | Filament scoots out from under | Incr. temperature | +# | the nozzle at the first iteration | Decr. z_raise | +# | | Incr. purge_length_maximum | +# +-------------------------------------+----------------------------+ +# | Filament scoots out from under the | Decr. purge_spd | +# | the nozzle at later iterations | Decr. z_raise_exp | +# | | Decr. z_raise | +# | | Incr. purge_length_maximum | +# +-------------------------------------+----------------------------+ +# | Filament sticks to the nozzle at | Incr. z_raise_exp | +# | later iterations | (Not above 1) | +# +-------------------------------------+----------------------------+ +# + +# 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.2 + +# The amount to raise Z +variable_z_raise: 12 + +# As the nozzle gets higher and the blob wider, the Z raise needs to be reduced, this +# follows the following formula: +# (extruded_amount/max_purge_length)^z_raise_exp * z_raise +# 1 is linear, below 1 will cause z to raise less quickly over time, above 1 will make it +# raise quicker over time. 0.85 is a good starting point and you should not have it above 1 +variable_z_raise_exp: 0.85 + +# Lift the nozzle slightly after creating the blob te release pressure on the tray. +variable_eject_hop: 1.0 + +# Dwell time (ms) after purging and before cleaning to relieve pressure from the nozzle. +variable_pressure_release_time: 1000 + +# 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. Values range +# from 0 .. 1, or -1 if you don't want it changed. +#variable_part_cooling_fan: -1 # Leave it unchanged +#variable_part_cooling_fan: 0 # Disable the fan +variable_part_cooling_fan: 1 # Run it at full speed + +# Define the part fan name if you are using a fan other than [fan] +# Applies to [fan_generic] or other fan definitons +# Example would be if you are using auxiliary fan control in Orcaslicer (https://github.com/SoftFever/OrcaSlicer/wiki/Auxiliary-fan) +# If you are unsure if you need this, then probably just leave it commented out. + +#variable_fan_name: "fan_generic fan0" + + + +# ======================================================================================== +# ==================== PURGE LENGTH TUNING =============================================== +# ======================================================================================== + +# The absolute minimum to purge, even if you don't changed tools. This is to prime the +# nozzle before printing +variable_purge_length_minimum: 30 + +# The maximum amount of filament (in mm¹) to purge in a single blob. Blobifier will +# automatically purge multiple blobs if the purge amount exceeds this. +variable_purge_length_maximum: 150 + +# Default purge length to fall back on when neither the tool map purge_volumes or +# parameter PURGE_LENGTH is set. +variable_purge_length: 150 + +# The slicer values often are a bit too wasteful. Tune it here to get optimal values. +# 0.6 (60%) is a good starting point. +variable_purge_length_modifier: 0.6 + +# Fixed length of filament to add after the purge volume calculation. Happy Hare already +# shares info on the extra amount of filament to purge based on known residual filament, +# tip cutting fragment and initial retraction setting. However this setting can add a fixed +# amount on top on that if necessary although it is recommended to start with 0 and tune +# slicer purge matrix first. +# 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 + +# ======================================================================================== +# ==================== BUCKET ============================================================ +# ======================================================================================== + +# Maximum number of blobs that fit in the bucket. Pauses the print if it exceeds this +# number. +variable_max_blobs: 400 +# Enable the bucket shaker. You need to have the shaker.stl installed +variable_enable_shaker: 1 +# The number of back-and-forth motions of one shake +variable_bucket_shakes: 10 +# During shaking acceleration can often be higher because you don't need to keep print +# quality in mind. Higher acceleration helps better with dispersing the blobs. +variable_shake_accel: 10000 + +# The frequency at which to shake the bucket. A decimal value ranging from 0 to 1, where 0 +# is never, and 1 is every time. This way the shaking occurs more often as the bucket +# fills up. Sensible values range from 0.75 to 0.95 +variable_bucket_shake_frequency: 0.95 + +# Height of the shaker arm. If your hotend hits your tray during shaking, increase. +variable_shaker_arm_z: 2 + +gcode: + + # ====================================================================================== + # ==================== RECORD STATE (INCL. FANS, SPEEDS, ETC...) ======================= + # ====================================================================================== + + # General state + SAVE_GCODE_STATE NAME=BLOBIFIER_state + + + # ====================================================================================== + # ==================== CHECK HOMING STATUS ============================================= + # ====================================================================================== + + {% if "xyz" not in printer.toolhead.homed_axes %} + RESPOND MSG="BLOBIFIER: Not homed! Home xyz before blobbing" + {% elif printer.quad_gantry_level and printer.quad_gantry_level.applied == False %} + RESPOND MSG="BLOBIFIER: QGL not applied! run quad_gantry_level before blobbing" + {% else %} + + # Part cooling fan + {% if part_cooling_fan >= 0 %} + {% set fan = fan_name|string %} + # Save the part cooling fan speed to be enabled again later + {% set backup_fan_speed = (printer[fan].speed if printer[fan] is defined else printer.fan.speed) %} + # Set part cooling fan speed + M106 S{part_cooling_fan * 255} + {% endif %} + + # Set feedrate to 100% for correct speed purging + {% set backup_feedrate = printer.gcode_move.speed_factor %} + M220 S100 + + # ====================================================================================== + # ==================== DEFINE BASIC VARIABLES ========================================== + # ====================================================================================== + + {% set sequence_vars = printer['gcode_macro _MMU_SEQUENCE_VARS'] %} + {% set park_vars = printer['gcode_macro _MMU_PARK'] %} + {% set filament_diameter = printer.configfile.config.extruder.filament_diameter|float %} + {% set filament_cross_section = (filament_diameter/2) ** 2 * 3.1415 %} + {% set from_tool = printer.mmu.last_tool %} + {% set to_tool = printer.mmu.tool %} + {% set bl_count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% set pos = printer.gcode_move.gcode_position %} + {% set safe = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'] %} + {% set ignore_safe = safe.print_height < force_safe_descend_height_until %} + {% set restore_z = [printer['gcode_macro BLOBIFIER_PARK'].restore_z,pos.z]|max %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - skew_correction %} + + # Get purge volumes from the slicer (if set up right. see + # https://github.com/moggieuk/Happy-Hare/wiki/Gcode-Preprocessing) + {% set pv = printer.mmu.slicer_tool_map.purge_volumes %} + + # ====================================================================================== + # ==================== DETERMINE PURGE LENGTH ========================================== + # ====================================================================================== + + {% if params.PURGE_LENGTH %} # =============== PARAM PURGE LENGTH ====================== + {action_respond_info("BLOBIFIER: param PURGE_LENGTH provided")} + {% set purge_len = params.PURGE_LENGTH|float %} + {% elif from_tool == to_tool and to_tool >= 0 %} # ==== TOOL DIDN'T CHANGE ============= + {action_respond_info("BLOBIFIER: Tool didn't change (T%s > T%s), %s" % (from_tool, to_tool, "priming" if purge_length_minimum else "skipping"))} + {% set purge_len = 0 %} + + {% elif pv %} # ============== FETCH FROM HAPPY HARE (LIKELY FROM SLICER) ============== + {% if from_tool < 0 and to_tool >= 0%} + {action_respond_info("BLOBIFIER: from tool unknown. Finding largest value for T? > T%d" % to_tool)} + {% set purge_vol = pv|map(attribute=to_tool)|max %} + {% elif to_tool < 0 %} + {action_respond_info("BLOBIFIER: tool(s) unknown. Finding largest value")} + {% set purge_vol = pv|map('max')|max %} + {% else %} + {% set purge_vol = pv[from_tool][to_tool]|float * purge_length_modifier %} + {action_respond_info("BLOBIFIER: Swapped T%s > T%s" % (from_tool, to_tool))} + {% endif %} + {% set purge_len = purge_vol / filament_cross_section %} + + {% set purge_len = purge_len + printer.mmu.extruder_filament_remaining + park_vars.retracted_length + purge_length_addition %} + + {% else %} # ========================= USE CONFIG VARIABLE ============================= + {action_respond_info("BLOBIFIER: No toolmap or PURGE_LENGTH. Using default")} + {% set purge_len = purge_length|float + printer.mmu.extruder_filament_remaining + park_vars.retracted_length %} + {% endif %} + + # ==================================== APPLY PURGE MINIMUM ============================= + {% set purge_len = [purge_len,purge_length_minimum]|max|round(0, 'ceil')|int %} + {action_respond_info("BLOBIFIER: Purging %dmm of filament" % (purge_len))} + + # ====================================================================================== + # ==================== PURGING SEQUENCE ================================================ + # ====================================================================================== + + # Set to absolute positioning. + G90 + + # Check for purge length and purge if necessary. + {% if purge_len|float > 0 %} + + # ==================================================================================== + # ==================== POSITIONING =================================================== + # ==================================================================================== + + # Retract the tray so it is not in the way + BLOBIFIER_SERVO POS=in + + # Move to the assembly, first a bit more to the right (brush_start) to avoid a + # potential filametrix pin if it's not already on the same Y coordinate. + {% if printer.toolhead.position.y != position_y %} + G1 X{[brush_start - 20, 30]|max} Y{position_y} F{travel_spd_xy} + {% endif %} + + # ==================================================================================== + # ==================== BUCKET SHAKE ================================================== + # ==================================================================================== + + {% if enable_shaker and (safe.shake or ignore_safe) %} + {% if (bl_count.current_blobs + 1) >= bl_count.next_shake %} + BLOBIFIER_SHAKE_BUCKET SHAKES={bucket_shakes} + _BLOBIFIER_CALCULATE_NEXT_SHAKE + {% endif %} + {% endif %} + + # ==================================================================================== + # ==================== POSITIONING ON TRAY =========================================== + # ==================================================================================== + {% if safe.tray or ignore_safe %} + G1 Z{tray_top + purge_start} F{travel_spd_z} + {% endif %} + + # Move over to the tray after z change (For cases when the tool is lower than the tray) + G1 X{purge_x} F{travel_spd_xy} + + # Extend the tray + BLOBIFIER_SERVO POS=out + + # ==================================================================================== + # ==================== HEAT HOTEND =================================================== + # ==================================================================================== + + {% if printer.extruder.temperature < purge_temp_min %} + {% if printer.extruder.target < purge_temp_min %} + M109 S{purge_temp_min} + {% else %} + TEMPERATURE_WAIT SENSOR=extruder MINIMUM={purge_temp_min} + {% endif %} + {% endif %} + + # ==================================================================================== + # ==================== START ITERATING =============================================== + # ==================================================================================== + + # Calculate total number of iterations based on the purge length and the max_iteration + # length. + {% set blobs = (purge_len / purge_length_maximum)|round(0, 'ceil')|int %} + {% set purge_per_blob = purge_len|float / blobs %} + {% set retracts_per_blob = (purge_per_blob / 40)|round(0, 'ceil')|int %} + {% set purge_per_retract = (purge_per_blob / retracts_per_blob)|int %} + {% set pulses_per_retract = (purge_per_blob / retracts_per_blob / 5)|round(0, 'ceil')|int %} + {% set pulses_per_blob = (purge_per_blob / 5)|round(0, 'ceil')|int %} + {% set purge_per_pulse = purge_per_blob / pulses_per_blob %} + {% set pulse_time_constant = purge_per_pulse * 0.95 / purge_spd / (purge_per_pulse * 0.95 / purge_spd + purge_per_pulse * 0.05 / 50) %} + {% set pulse_duration = purge_per_pulse / purge_spd %} + + # Repeat the process until purge_len is reached + {% for blob in range(blobs) %} + RESPOND MSG={"'BLOBIFIER: Blob %d of %d (%.1fmm)'" % (blob + 1, blobs, purge_per_blob)} + + {% if safe.tray or ignore_safe %} + G1 Z{tray_top + purge_start} F{travel_spd_z} + {% endif %} + + # relative positioning + G91 + # relative extrusion + M83 + + # Purge filament in a pulsating motion to purge the filament quicker and better + {% for pulse in range(pulses_per_blob) %} + # Calculations to determine z-speed + {% set purged_this_blob = pulse * purge_per_pulse %} + {% set z_last_pos = purge_start + ((purged_this_blob)/purge_length_maximum)**z_raise_exp * z_raise %} + {% set z_pos = purge_start + ((purged_this_blob + purge_per_pulse)/purge_length_maximum)**z_raise_exp * z_raise %} + {% set z_up = z_pos - z_last_pos %} + {% set speed = z_up / pulse_duration %} + + # Purge quickly + G1 Z{z_up * pulse_time_constant} E{purge_per_pulse * 0.95} F{speed} + # Purge a tiny bit slowly + G1 Z{z_up * (1 - pulse_time_constant)} E{purge_per_pulse * 0.05} F{speed} + + # retract and unretract filament every now and then for thorough cleaning + {% if pulse % pulses_per_retract == 0 and pulse > 0 %} + G1 E-2 F1800 + G1 E2 F800 + {% endif %} + {% endfor %} + + # ================================================================================== + # ==================== DEPOSIT BLOB ================================================ + # ================================================================================== + {% if safe.tray or ignore_safe %} + # Raise z a bit to relieve pressure on the blob preventing it to go sideways + G1 Z{eject_hop} F{travel_spd_z} + # Retract the tray + BLOBIFIER_SERVO POS=in + # Move the toolhead down to purge_start height lowering the blob below the tray + G90 # absolute positioning + G1 Z{tray_top} F{travel_spd_z} + # Extend the tray to 'cut off' the blob and prepare for the next blob + BLOBIFIER_SERVO POS=out + BLOBIFIER_SERVO POS=in + BLOBIFIER_SERVO POS=out + # Keep track of the # of blobs + _BLOBIFIER_COUNT + {% endif %} + {% endfor %} + {% endif %} + {% if safe.tray or ignore_safe %} + G1 Z{tray_top + 1} F{travel_spd_z} + G4 P{pressure_release_time} + {% endif %} + {% if safe.brush or ignore_safe %} + BLOBIFIER_CLEAN + {% else %} + G1 X{brush_start} F{travel_spd_xy} + {% endif %} + + # ====================================================================================== + # ==================== RESTORE STATE =================================================== + # ====================================================================================== + + # Retract to match what Happy Hare is expecting + G1 E-{park_vars.retracted_length} F{sequence_vars.retract_speed * 60} + + G90 # absolute positioning + G1 Z{restore_z} F{travel_spd_z} + + {% if part_cooling_fan >= 0 %} + # Reset part cooling fan if it was changed + M106 S{(backup_fan_speed * 255)|int} + {% endif %} + + M220 S{(backup_feedrate * 100)|int} + {% endif %} + + # Retract the tray + BLOBIFIER_SERVO POS=in + + RESTORE_GCODE_STATE NAME=BLOBIFIER_state + + +########################################################################################## +# Wipes the nozzle on the brass brush +# +[gcode_macro BLOBIFIER_CLEAN] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + {% set original_accel = printer.toolhead.max_accel %} + {% set original_minimum_cruise_ratio = printer.toolhead.minimum_cruise_ratio %} + {% set pos = printer.gcode_move.gcode_position %} + + SAVE_GCODE_STATE NAME=BLOBIFIER_CLEAN_state + + G90 + + {% if bl.brush_accel > 0 %} + SET_VELOCITY_LIMIT ACCEL={bl.brush_accel} MINIMUM_CRUISE_RATIO=0.1 + {% endif %} + + {% if pos.z < bl.brush_top + bl.clearance_z %} + G1 Z{bl.brush_top + bl.clearance_z} F{bl.travel_spd_z} + {% endif %} + G1 X{bl.brush_start} F{bl.travel_spd_xy} + G1 Y{position_y} + G1 Z{bl.brush_top + bl.clearance_z} F{bl.travel_spd_z} + + # Move nozzle down into brush. + G1 Z{bl.brush_top} F{bl.travel_spd_z} + + SET_VELOCITY_LIMIT ACCEL={original_accel} MINIMUM_CRUISE_RATIO={original_minimum_cruise_ratio} + + # Perform wipe. Wipe direction based off bucket_pos for cool random scrubby routine. + {% for wipes in range(1, (bl.wipe_qty + 1)) %} + G1 X{bl.brush_start + bl.brush_width} F{bl.wipe_spd_xy} + G1 X{bl.brush_start} F{bl.wipe_spd_xy} + {% endfor %} + + # Move away from the brush, but not onto the tray or in front of the filametrix cutter pin + G1 X{[bl.brush_start - 20, 30]|max} F{bl.travel_spd_xy} + + RESTORE_GCODE_STATE NAME=BLOBIFIER_CLEAN_state + + + +########################################################################################## +# Park the nozzle on the tray to prevent oozing during filament swaps. Place this +# extension in the post_form_tip extension in mmu_macro_vars.cfg: +# variable_user_post_form_tip_extension: "BLOBIFIER_PARK" +# +[gcode_macro BLOBIFIER_PARK] +variable_restore_z: 0 +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos = printer.gcode_move.gcode_position %} + {% set safe = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'] %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + + SET_GCODE_VARIABLE MACRO=BLOBIFIER_PARK VARIABLE=restore_z VALUE={pos.z} + + SAVE_GCODE_STATE NAME=blobifier_park_state + + {% if "xyz" in printer.toolhead.homed_axes and printer.quad_gantry_level and printer.quad_gantry_level.applied %} + G90 + + # Retract the tray + BLOBIFIER_SERVO POS=in + + G1 X{[bl.brush_start - 20, 30]|max} Y{position_y} F{bl.travel_spd_xy} + {% if safe.tray or ignore_safe %} + G1 Z{bl.tray_top} F{bl.travel_spd_z} + {% endif %} + G1 X{bl.purge_x} F{bl.travel_spd_xy} + + # Extend the tray + BLOBIFIER_SERVO POS=out + + {% else %} + RESPOND MSG="Please home (and QGL) before parking" + {% endif %} + + RESTORE_GCODE_STATE NAME=blobifier_park_state + +########################################################################################## +# Retract or extend the tray +# POS=[in|out] Retractor extend the tray +# +[gcode_macro BLOBIFIER_SERVO] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos = params.POS %} + {% if pos == "in" %} + SET_SERVO SERVO=blobifier ANGLE={bl.tray_angle_in} + G4 P{bl.dwell_time} + {% elif pos == "out" %} + SET_SERVO SERVO=blobifier ANGLE={bl.tray_angle_out} + G4 P{bl.dwell_time} + {% else %} + {action_respond_info("BLOBIFIER: provide POS=[in|out]")} + {% endif %} + SET_SERVO SERVO=blobifier WIDTH=0 + +########################################################################################## +# Define exclude objects for those who haven't already +# +[exclude_object] + +########################################################################################## +# Overwrite the existing EXCLUDE_OBJECT_DEFINE to also check for safe descend. +# +[gcode_macro EXCLUDE_OBJECT_DEFINE] +rename_existing: _EXCLUDE_OBJECT_DEFINE +gcode: + # only reset on the first object at the beginning of a print + {% if printer.exclude_object.objects|length < 1 %} + _BLOBIFIER_RESET_SAFE_DESCEND + {% endif %} + _EXCLUDE_OBJECT_DEFINE {rawparams} + _BLOBIFIER_SAFE_DESCEND + UPDATE_DELAYED_GCODE ID=BLOBIFIER_SHOW_SAFE_DESCEND DURATION=1 + +[delayed_gcode BLOBIFIER_SHOW_SAFE_DESCEND] +gcode: + {% set safe = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'] %} + {action_respond_info( + "BLOBIFIER: Safe descend possible:\n - tray: %s\n - brush: %s\n - shake: %s" % + ( + "yes" if safe.tray else "no", + "yes" if safe.brush else "no", + "yes" if safe.shake else "no" + ) + )} + +########################################################################################## +# Use the EXCLUDE_OBJECT_START gcode macro to record the current height +# +[gcode_macro EXCLUDE_OBJECT_START] +rename_existing: _EXCLUDE_OBJECT_START +gcode: + _EXCLUDE_OBJECT_START {rawparams} + {% if printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'].first_layer %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=first_layer VALUE=False + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_height VALUE={printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'].print_layer_height} + {% else %} + {% set pos = printer.gcode_move.gcode_position %} + {% set last_height = printer['gcode_macro _BLOBIFIER_SAFE_DESCEND'].print_previous_height|float %} + {% if pos.z > last_height %} + {% set last_layer = (pos.z - last_height)|round(2) %} + {% set print_height = (pos.z + last_layer)|round(2) %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_previous_height VALUE={pos.z} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_height VALUE={print_height} + {% endif %} + {% endif %} + +########################################################################################## +# Reset the safe descend variables. +# +[gcode_macro _BLOBIFIER_RESET_SAFE_DESCEND] +gcode: + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=tray VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=brush VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=shake VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=first_layer VALUE=True + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_height VALUE=0 + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=print_previous_height VALUE=0 + +########################################################################################## +# Determine if it is safe to drop the toolhead (e.g. not hit a print) +# +[gcode_macro _BLOBIFIER_SAFE_DESCEND] +variable_tray: True # Assume it is safe +variable_brush: True +variable_shake: True +variable_first_layer: True +variable_print_height: 0 +variable_print_previous_height: 0 +variable_print_layer_height: 0.3 +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + {% set tray = [bl.purge_x + bl.toolhead_x, position_y - bl.toolhead_y] %} + {% set brush = [bl.brush_start + bl.brush_width + bl.toolhead_x, position_y - bl.toolhead_y] %} + {% set shake = [bl.purge_x + bl.toolhead_x, position_y - bl.toolhead_y - 4] %} + {% set objects = printer.exclude_object.objects | map(attribute='polygon') %} + + {% for polygon in objects %} + {% for point in polygon %} + {% if point[0] < tray[0] and point[1] > tray[1] %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=tray VALUE=False + {% endif %} + {% if point[0] < brush[0] and point[1] > brush[1] %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=brush VALUE=False + {% endif %} + {% if point[0] < shake[0] and point[1] > shake[1] %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_SAFE_DESCEND VARIABLE=shake VALUE=False + {% endif %} + {% endfor %} + {% endfor %} + +########################################################################################## +# Increment the blob count with 1 and check if the bucket is full. Pause +# the printer if it is. +# +[gcode_macro _BLOBIFIER_COUNT] +# Don't change these variables +variable_current_blobs: 0 +variable_last_shake: 0 +variable_next_shake: 0 +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% if current_blobs >= bl.max_blobs %} + {action_respond_info("BLOBIFIER: Empty purge bucket!")} + M117 Empty purge bucket! + MMU_PAUSE MSG="Empty purge bucket!" + {% else %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=current_blobs VALUE={current_blobs + 1} + _BLOBIFIER_SAVE_STATE + {action_respond_info( + "BLOBIFIER: Blobs in bucket: %s/%s. Next shake @ %s" + % (current_blobs + 1, bl.max_blobs, next_shake) + )} + {% endif %} + +########################################################################################## +# Reset the blob count to 0 +# +[gcode_macro _BLOBIFIER_COUNT_RESET] +gcode: + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=current_blobs VALUE=0 + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=last_shake VALUE=0 + _BLOBIFIER_SAVE_STATE + + _BLOBIFIER_CALCULATE_NEXT_SHAKE + +########################################################################################## +# Shake the blob bucket to disperse the blobs +# +[gcode_macro BLOBIFIER_SHAKE_BUCKET] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% set original_accel = printer.toolhead.max_accel %} + {% set original_minimum_cruise_ratio = printer.toolhead.minimum_cruise_ratio %} + {% set position_x = bl.skew_correction %} + + {% if "xyz" not in printer.toolhead.homed_axes %} + {action_raise_error("BLOBIFIER: Not homed. Home xyz first")} + {% endif %} + + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=last_shake VALUE={count.current_blobs} + _BLOBIFIER_SAVE_STATE + SAVE_GCODE_STATE NAME=shake_bucket + + M400 + M117 (^_^) + + G90 + {% set shakes = params.SHAKES|default(10)|int %} + {% set pos_max = printer.toolhead.axis_maximum %} + {% set position_y = pos_max.y - bl.skew_correction %} + + # move to save y if not already there + {% if printer.toolhead.position.y != position_y %} + G1 X{bl.brush_start} Y{position_y} F{bl.travel_spd_xy} + {% endif %} + + # Retract the tray + BLOBIFIER_SERVO POS=in + + # move up a bit to prevent oozing on base + G1 Z{bl.shaker_arm_z} F{bl.travel_spd_z} + # slide into the slot + G1 X{position_x} F{bl.travel_spd_xy} + + M400 + M117 (+(+_+)+) + + SET_VELOCITY_LIMIT ACCEL={bl.shake_accel} MINIMUM_CRUISE_RATIO=0.1 + + # Shake away! + {% for shake in range(1, shakes) %} + G1 Y{position_y - 4} + G1 Y{position_y} + {% endfor %} + + SET_VELOCITY_LIMIT ACCEL={original_accel} MINIMUM_CRUISE_RATIO={original_minimum_cruise_ratio} + # move out of slot + G1 X{bl.purge_x} + + M400 + M117 (X_x) + + RESTORE_GCODE_STATE NAME=shake_bucket + +########################################################################################## +# Calculate when the bucket should be shaken. +# +[gcode_macro _BLOBIFIER_CALCULATE_NEXT_SHAKE] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + + {% set remaining_blobs = bl.max_blobs - count.last_shake %} + {% set next_shake = (1 - bl.bucket_shake_frequency) * remaining_blobs + count.last_shake %} + _BLOBIFIER_SAVE_STATE + _BLOBIFIER_SET_NEXT_SHAKE VALUE={next_shake|int} + +########################################################################################## +# Set when the bucket should be shaken next +# VALUE=[int] At what amount of blobs should it be shaken +# +[gcode_macro _BLOBIFIER_SET_NEXT_SHAKE] +gcode: + {% if params.VALUE %} + {% set next_shake = params.VALUE %} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=next_shake VALUE={next_shake} + _BLOBIFIER_SAVE_STATE + {% else %} + {action_respond_info("BLOBIFIER: Provide parameter VALUE=")} + {% endif %} + +########################################################################################## +# Some sanity checks +# +[delayed_gcode BLOBIFIER_INIT] +initial_duration: 5.0 +gcode: + _BLOBIFIER_INIT + # Extend and retract the tray to test + BLOBIFIER_SERVO POS=out + BLOBIFIER_SERVO POS=in + +[gcode_macro _BLOBIFIER_INIT] +gcode: + {% set bl = printer['gcode_macro BLOBIFIER'] %} + + # Valid part cooling fan setting + {% if bl.part_cooling_fan != -1 and (bl.part_cooling_fan < 0 or bl.part_cooling_fan > 1) %} + {action_emergency_stop("BLOBIFIER: Value %f is invalid for variable part_cooling_fan. Either -1 or a value from 0 .. 1 is valid." % (bl.part_cooling_fan))} + {% endif %} + + # Valid bucket shake frequency + {% if bl.bucket_shake_frequency < 0 or bl.bucket_shake_frequency > 1 %} + {action_emergency_stop("BLOBIFIER: Value %f is invalid for variable bucket_shake_frequency. Change it to a value between 0 .. 1" % (bl.bucket_shake_frequency))} + {% endif %} + + # Check if position is on 'next' + {% if printer.mmu %} + {% if printer['gcode_macro _MMU_SEQUENCE_VARS'].restore_xy_pos != 'next' %} + {action_respond_info("BLOBIFIER: If not using a wipe tower, consider setting restore_xy_pos: 'next' in mmu_macro_vars.cfg")} + {% endif %} + {% endif %} + + # Check the z_raise variable for normal values + {% if bl.z_raise < 3 %} + {action_respond_info("BLOBIFIER: variable_z_raise: %f is very low. This is the value z raises in total on a single blob. Make sure the value is correct before continuing." % (bl.z_raise))} + {% endif %} + + # Z raise exponent + {% if bl.z_raise_exp > 1 or bl.z_raise_exp < 0.5 %} + {action_respond_info("BLOBIFIER: variable_z_raise_exp has value: %f. This value is out of spec (0.5 ... 1.0)." % (bl.z_raise_exp))} + {% endif %} + + # cap user defined accels at printer max_accel if greater + {% if bl.shake_accel > printer.configfile.config.printer.max_accel|int %} + {action_respond_info("BLOBIFIER: variable_shake_accel has value: %d which is higher than your printer limit of %d. Reduce this if your printer skips steps." % (bl.shake_accel,printer.configfile.config.printer.max_accel|int))} + {% endif %} + {% if bl.brush_accel > printer.configfile.config.printer.max_accel|int %} + {action_respond_info("BLOBIFIER: variable_brush_accel has value: %d which is higher than your printer limit of %d. Reduce this if your printer skips steps." % (bl.brush_accel,printer.configfile.config.printer.max_accel|int))} + {% endif %} + +[delayed_gcode BLOBIFIER_LOAD_STATE] +initial_duration: 2.0 # Give it some time to boot up +gcode: + {% set sv = printer.save_variables.variables.blobifier %} + + {% if sv %} + # Restore state + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=last_shake VALUE={sv.last_shake} + SET_GCODE_VARIABLE MACRO=_BLOBIFIER_COUNT VARIABLE=current_blobs VALUE={sv.current_blobs} + {% endif %} + _BLOBIFIER_CALCULATE_NEXT_SHAKE + +[gcode_macro _BLOBIFIER_SAVE_STATE] +gcode: + {% set count = printer['gcode_macro _BLOBIFIER_COUNT'] %} + {% set sv = {'current_blobs': count.current_blobs, 'last_shake': count.last_shake} %} + SAVE_VARIABLE VARIABLE=blobifier VALUE="{sv}" diff --git a/mmu-20250423_131125/addons/blobifier_hw.cfg b/mmu-20250423_131125/addons/blobifier_hw.cfg new file mode 100644 index 0000000..5f76ae8 --- /dev/null +++ b/mmu-20250423_131125/addons/blobifier_hw.cfg @@ -0,0 +1,28 @@ + +########################################################################################## +# The servo hardware configuration. Change the values to your needs. +# +[mmu_servo blobifier] +# Pin for the servo. +pin: PG14 +# Adjust this value until a 'BLOBIFIER_SERVO POS=out' extends the tray fully without a +# buzzing sound +minimum_pulse_width: 0.00053 +# Adjust this value until a 'BLOBIFIER_SERVO POS=in' retracts the tray fully without a +# buzzing sound +maximum_pulse_width: 0.0023 +# Leave this value at 180 +maximum_servo_angle: 180 + + +########################################################################################## +# The bucket hardware configuration. Change the pin to whatever pin you've connected the +# switch to. +# +[gcode_button bucket] +pin: ^PG15 # The pullup ( ^ ) is important here. +press_gcode: + M117 bucket installed +release_gcode: + M117 bucket removed + _BLOBIFIER_COUNT_RESET diff --git a/mmu-20250423_131125/addons/mmu_eject_buttons.cfg b/mmu-20250423_131125/addons/mmu_eject_buttons.cfg new file mode 100644 index 0000000..59080b6 --- /dev/null +++ b/mmu-20250423_131125/addons/mmu_eject_buttons.cfg @@ -0,0 +1,31 @@ +# Include servo hardware definition separately to allow for automatic upgrade +[include mmu_eject_buttons_hw.cfg] + +########################################################################### +# Optional hardware MMU eject buttons (e.g. QuattroBox) +# +# This is the supplementary macro to support dedicated per-gate eject +# buttons for easy unloading. It is complimentary to the built-in auto +# preload of filament +# +# To configure: +# 1. Add this to your printer.cfg: +# +# [include mmu/addons/mmu_eject_buttons.cfg] +# + +########################################################################### +# Macro to simply call MMU_EJECT for the specified gate +# +# This logic is separated from actual button h/w setup to facilitate upgrades +# and to allow addition of logic (perhaps validation or warning logic) +# +[gcode_macro _MMU_EJECT_BUTTON] +description: Wrapper around ejecting filament via dedicated hardware buttons +gcode: + {% set gate = params.GATE|default(-1)|int %} + {% set mmu = printer['mmu'] %} + {% set current_gate = mmu.gate %} + + # TODO add validation and warning logic + MMU_EJECT GATE={gate} diff --git a/mmu-20250423_131125/addons/mmu_eject_buttons_hw.cfg b/mmu-20250423_131125/addons/mmu_eject_buttons_hw.cfg new file mode 100644 index 0000000..693ee57 --- /dev/null +++ b/mmu-20250423_131125/addons/mmu_eject_buttons_hw.cfg @@ -0,0 +1,21 @@ + +########################################################################################## +# The eject button hardware configuration. Change the values to your needs and number +# of gates +# + +[gcode_button mmu_eject_button_0] +pin: mmu:EJECT_BUTTON_0 +press_gcode: _MMU_EJECT_BUTTON GATE=0 + +[gcode_button mmu_eject_button_1] +pin: mmu:EJECT_BUTTON_1 +press_gcode: _MMU_EJECT_BUTTON GATE=1 + +[gcode_button mmu_eject_button_2] +pin: mmu:EJECT_BUTTON_2 +press_gcode: _MMU_EJECT_BUTTON GATE=2 + +[gcode_button mmu_eject_button_3] +pin: mmu:EJECT_BUTTON_3 +press_gcode: _MMU_EJECT_BUTTON GATE=3 diff --git a/mmu-20250423_131125/addons/mmu_erec_cutter.cfg b/mmu-20250423_131125/addons/mmu_erec_cutter.cfg new file mode 100644 index 0000000..12e1d53 --- /dev/null +++ b/mmu-20250423_131125/addons/mmu_erec_cutter.cfg @@ -0,0 +1,91 @@ +# Include servo hardware definition separately to allow for automatic upgrade +[include mmu_erec_cutter_hw.cfg] + +########################################################################### +# Optional EREC Filament Cutter Support +# +# https://github.com/kevinakasam/ERCF_Filament_Cutter +# +# This is the supplementary macro to support filament cutting at the MMU +# on a ERCF design. +# +# To configure: +# 1. Add this to your printer.cfg: +# +# [include mmu/addons/mmu_erec_cutter.cfg] +# +# 2. In mmu_macro_vars.cfg, change this line: +# +# variable_user_post_unload_extension : "EREC_CUTTER_ACTION" +# +# 3. Tune the servo configuration and macro "variables" below +# + +# EREC CUTTER CONFIGURATION ----------------------------------------------- +# (addons/mmu_erec_cutter.cfg) +# +[gcode_macro _EREC_VARS] +description: Empty macro to store the variables +gcode: # Leave empty + +# These variables control the servo movement +variable_servo_closed_angle : 70 ; Servo angle for closed position with bowden aligned MMU +variable_servo_open_angle : 10 ; Servo angle to open up the cutter and move bowden away from MMU +variable_servo_duration : 1.5 ; Time (s) of PWM pulse train to activate servo +variable_servo_idle_time : 1.8 ; Time (s) to let the servo to reach it's position + +# Controls for feed and cut lengths +variable_feed_length : 48 ; Distance in mm from gate parking position to blade (ERCFv1.1: 58, v2/other: 48) +variable_cut_length : 10 ; Amount in mm of filament to cut +variable_cut_attempts : 1 ; Number of times the cutter tries to cut the filament + + +########################################################################### +# Macro to perform the cutting step. Designed to be included to the +# _MMU_POST_UNLOAD step +# +[gcode_macro EREC_CUTTER_ACTION] +description: Cut off the filament tip at the MMU after the unload sequence is complete +gcode: + {% set vars = printer["gcode_macro _EREC_VARS"] %} + + MMU_LOG MSG="Cutting filament tip..." + + _CUTTER_OPEN + _MMU_STEP_MOVE MOVE={vars.feed_length + vars.cut_length} + {% for i in range(vars.cut_attempts - 1) %} + _CUTTER_CLOSE + _CUTTER_OPEN + {% endfor %} + _MMU_STEP_MOVE MOVE=-1 + _CUTTER_CLOSE + _MMU_EVENT EVENT="filament_cut" # Count as one cut for consumption counter + + _MMU_STEP_SET_FILAMENT STATE=2 # FILAMENT_POS_START_BOWDEN + _MMU_STEP_UNLOAD_GATE # Repeat gate parking move + _MMU_M400 # Wait on both move queues + +[gcode_macro _CUTTER_ANGLE] +description: Helper macro to set cutter servo angle +gcode: + {% set angle = params.ANGLE|default(0)|int %} + SET_SERVO SERVO=cut_servo ANGLE={angle} + +[gcode_macro _CUTTER_CLOSE] +description: Helper macro to set cutting servo the closed position +gcode: + {% set vars = printer["gcode_macro _EREC_VARS"] %} + SET_SERVO SERVO=cut_servo ANGLE={vars.servo_closed_angle} DURATION={vars.servo_duration} + G4 P{vars.servo_idle_time * 1000} + RESPOND MSG="EREC Cutter closed" + M400 + +[gcode_macro _CUTTER_OPEN] +description: Helper macro to set cutting servo the open position +gcode: + {% set vars = printer["gcode_macro _EREC_VARS"] %} + SET_SERVO SERVO=cut_servo ANGLE={vars.servo_open_angle} DURATION={vars.servo_duration} + G4 P{vars.servo_idle_time * 1000} + RESPOND MSG="EREC Cutter open" + M400 + diff --git a/mmu-20250423_131125/addons/mmu_erec_cutter_hw.cfg b/mmu-20250423_131125/addons/mmu_erec_cutter_hw.cfg new file mode 100644 index 0000000..4fec0c1 --- /dev/null +++ b/mmu-20250423_131125/addons/mmu_erec_cutter_hw.cfg @@ -0,0 +1,10 @@ + +########################################################################################## +# The servo hardware configuration. Change the values to your needs. +# +[mmu_servo cut_servo] +pin: mmu:PA7 # Extra Pin on the ERCF easy Board +maximum_servo_angle: 180 # Set this to 60 for a 60° Servo +minimum_pulse_width: 0.0005 # Adapt these for your servo +maximum_pulse_width: 0.0025 # Adapt these for your servo + diff --git a/mmu-20250423_131125/base/mmu.cfg b/mmu-20250423_131125/base/mmu.cfg new file mode 100644 index 0000000..3ff44dc --- /dev/null +++ b/mmu-20250423_131125/base/mmu.cfg @@ -0,0 +1,154 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Happy Hare MMU hardware pin config +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# +# This contains aliases for pins for MCU type MMB11 +# +#[mcu oldmmu] +#canbus_uuid: 214adf7db8eb # Change to `canbus_uuid: 1234567890` for CANbus setups + +[mcu mmu] +canbus_uuid: 029f6dc0d75b + +# PIN ALIASES FOR MMU MCU BOARD ---------------------------------------------------------------------------------------- +# ██████╗ ██╗███╗ ██╗ █████╗ ██╗ ██╗ █████╗ ███████╗ +# ██╔══██╗██║████╗ ██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝ +# ██████╔╝██║██╔██╗ ██║ ███████║██║ ██║███████║███████╗ +# ██╔═══╝ ██║██║╚██╗██║ ██╔══██║██║ ██║██╔══██║╚════██║ +# ██║ ██║██║ ╚████║ ██║ ██║███████╗██║██║ ██║███████║ +# ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═╝╚══════╝ +# Section to create alias for pins used by MMU for easier integration into Klippain and RatOS. The names match those +# referenced in the mmu_hardware.cfg file. If you get into difficulty you can also comment out this aliases definition +# completely and configure the pin names directly into mmu_hardware.cfg. However, use of aliases is encouraged. + +# Note: that aliases are not created for TOOLHEAD_SENSOR, EXTRUDER_SENSOR or SYNC_FEEDBACK_SENSORS because those are +# most likely on the printer's main mcu. These should be set directly in mmu_hardware.cfg +# +# [board_pins oldmmu] +# mcu: mmu # Assumes using an external / extra mcu dedicated to MMU +# aliases: +# MMU_GEAR_UART=PA10, +# MMU_GEAR_STEP=PB15, +# MMU_GEAR_DIR=PB14, +# MMU_GEAR_ENABLE=PB8, +# MMU_GEAR_DIAG=PA3, + +# MMU_GEAR_UART_1=, +# MMU_GEAR_STEP_1=, +# MMU_GEAR_DIR_1=, +# MMU_GEAR_ENABLE_1=, +# MMU_GEAR_DIAG_1=, + +# MMU_GEAR_UART_2=, +# MMU_GEAR_STEP_2=, +# MMU_GEAR_DIR_2=, +# MMU_GEAR_ENABLE_2=, +# MMU_GEAR_DIAG_2=, + +# MMU_GEAR_UART_3=, +# MMU_GEAR_STEP_3=, +# MMU_GEAR_DIR_3=, +# MMU_GEAR_ENABLE_3=, +# MMU_GEAR_DIAG_3=, + +# MMU_SEL_UART=PC7, +# MMU_SEL_STEP=PD2, +# MMU_SEL_DIR=PB13, +# MMU_SEL_ENABLE=PD1, +# MMU_SEL_DIAG=PA4, +# MMU_SEL_ENDSTOP=PB2, +# MMU_SEL_SERVO=PA0, + +# MMU_ENCODER=PA1, +# MMU_GATE_SENSOR=, +# MMU_NEOPIXEL=PA2, + +# MMU_PRE_GATE_0=, +# MMU_PRE_GATE_1=PA3, +# MMU_PRE_GATE_2=, +# MMU_PRE_GATE_3=, +# MMU_PRE_GATE_4=, +# MMU_PRE_GATE_5=, +# MMU_PRE_GATE_6=, +# MMU_PRE_GATE_7=, +# MMU_PRE_GATE_8=, +# MMU_PRE_GATE_9=, +# MMU_PRE_GATE_10=, +# MMU_PRE_GATE_11=, + +# MMU_POST_GEAR_0=, +# MMU_POST_GEAR_1=, +# MMU_POST_GEAR_2=, +# MMU_POST_GEAR_3=, +# MMU_POST_GEAR_4=, +# MMU_POST_GEAR_5=, +# MMU_POST_GEAR_6=, +# MMU_POST_GEAR_7=, +# MMU_POST_GEAR_8=, +# MMU_POST_GEAR_9=, +# MMU_POST_GEAR_10=, +# MMU_POST_GEAR_11=, + +[board_pins mmu] +mcu: mmu # Assumes using an external / extra mcu dedicated to MMU +aliases: + MMU_GEAR_UART=gpio9, + MMU_GEAR_STEP=gpio7, + MMU_GEAR_DIR=gpio8, + MMU_GEAR_ENABLE=gpio6, + MMU_GEAR_DIAG=gpio23, + + MMU_SEL_UART=gpio0, + MMU_SEL_STEP=gpio2, + MMU_SEL_DIR=gpio1, + MMU_SEL_ENABLE=gpio3, + MMU_SEL_DIAG=gpio22, + + MMU_SEL_ENDSTOP=gpio20, + MMU_SEL_SERVO=gpio21, + + MMU_ENCODER=gpio15, + MMU_NEOPIXEL=gpio14, + MMU_GATE_SENSOR=, + + MMU_PRE_GATE_0=gpio10, + MMU_PRE_GATE_1=gpio11, + MMU_PRE_GATE_2=gpio12, + MMU_PRE_GATE_3=gpio24, + MMU_PRE_GATE_4=gpio13, + MMU_PRE_GATE_5=gpio26, + MMU_PRE_GATE_6=gpio27, + MMU_PRE_GATE_7=gpio28, + MMU_PRE_GATE_8=, + MMU_PRE_GATE_9=, + MMU_PRE_GATE_10=, + MMU_PRE_GATE_11=, + + MMU_POST_GEAR_0=, + MMU_POST_GEAR_1=, + MMU_POST_GEAR_2=, + MMU_POST_GEAR_3=, + MMU_POST_GEAR_4=, + MMU_POST_GEAR_5=, + MMU_POST_GEAR_6=, + MMU_POST_GEAR_7=, + MMU_POST_GEAR_8=, + MMU_POST_GEAR_9=, + MMU_POST_GEAR_10=, + MMU_POST_GEAR_11=, + +[temperature_sensor MMB] +sensor_type: temperature_mcu +sensor_mcu: mmu diff --git a/mmu-20250423_131125/base/mmu_cut_tip.cfg b/mmu-20250423_131125/base/mmu_cut_tip.cfg new file mode 120000 index 0000000..12b45af --- /dev/null +++ b/mmu-20250423_131125/base/mmu_cut_tip.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_cut_tip.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/base/mmu_form_tip.cfg b/mmu-20250423_131125/base/mmu_form_tip.cfg new file mode 120000 index 0000000..e2b93da --- /dev/null +++ b/mmu-20250423_131125/base/mmu_form_tip.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_form_tip.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/base/mmu_hardware.cfg b/mmu-20250423_131125/base/mmu_hardware.cfg new file mode 100644 index 0000000..fc44d73 --- /dev/null +++ b/mmu-20250423_131125/base/mmu_hardware.cfg @@ -0,0 +1,368 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Happy Hare MMU hardware config file with config for MMB11 MCU board +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# +# Notes about setup of common external MCUs can be found here: +# https://github.com/moggieuk/Happy-Hare/blob/main/doc/mcu_notes.md +# +# Note about "touch" endstops: Happy Hare provides extremely flexible homing options using both single steppers or +# synced steppers. The "touch" option leverages stallguard and thus requires the appropriate 'diag_pin' and stallguard +# parameters set on the TMC driver section. If you have the diag_pin exposed, it is harmless to define this because +# they will only be used when explicitly needed and configured. +# +# Touch option for each stepper provides these benefits / possibilities (experimental): +# - on extruder stepper allows for the automatic detection of the nozzle! +# - on selector stepper allows for the automatic detection of filament stuck in the gate and subsequent recovery +# - on gear stepper allows for the automatic detection of the extruder entrance +# +# These sound wonderful right? They are, but there are caveats: +# - Some external MCUs are terrible at detecting stallguard and often result in an "undervoltage error" +# It is generally possible to get selector touch (TMC2209) tuned especially if you set 'stealthchop_threshold' +# to a value greater than homing speeds and less than move speed. I.e. the stepper runs in stealthchop mode when +# homing. [klipper experts will know that it switches the chip mode automatically to stealthchop and then back for +# Stallguard2 support, however the automatic switching back to spreadcycle at the end homing move seems to provoke +# the error condition and setting 'stealthchop_threshold' appropriately avoids this condition. More than you wanted +# to know I'm sure! +# - I have not had much luck with touch (stallguard) on the gear stepper with EASY-BRD and ERB MCUs and you really +# want the extra torque of spreadcycle so adjusting 'stealthchop_threshold' is not really an option +# - Enabling on the extruder stepper is viable but you will likely have to change jumpers on your main mcu to expose +# the DIAG pin for whichever driver the extruder stepper is connected to. +# +# In summary, "touch" homing with your MMU is an advanced option that requires patience and careful tuning. Everything +# works with regular endstops and there are workaround options for certain homing points (like extruder entry) in +# the absence of any endstop. I'm really interested in creative setups. Ping me on Discord (moggieuk#6538) +# +# See 'mmu.cfg' for serial definition and pins aliases +# +# HOMING CAPABLE EXTRUDER (VERY ADVANCED) ----------------------------------------------------------------------------- +# With Happy Hare installed even the extruder can be homed. You will find the usual 'endstop' parameters can be added +# to your '[extruder]' section. Useless you have some clever load cell attached to your nozzle it only really makes +# sense to configure stallguard style "touch" homing. To do this add lines similar to this to your existing +# '[extruder]' definition in printer.cfg. +# +# [extruder] +# endstop_pin: tmc2209_extruder:virtual_endstop +# +# Also be sure to add the appropriate stallguard config to the TMC section, e.g. +# +# [tmc2209 extruder] +# diag_pin: E_DIAG # Set to MCU pin connected to TMC DIAG pin for extruder +# driver_SGTHRS: 100 # 255 is most sensitive value, 0 is least sensitive +# +# Happy Hare will take care of the rest and add a 'mmu_ext_touch' endstop automatically +# + + +# MMU MACHINE / TYPE --------------------------------------------------------------------------------------------------- +# ███╗ ███╗███╗ ███╗██╗ ██╗ ███╗ ███╗ █████╗ ██████╗██╗ ██╗██╗███╗ ██╗███████╗ +# ████╗ ████║████╗ ████║██║ ██║ ████╗ ████║██╔══██╗██╔════╝██║ ██║██║████╗ ██║██╔════╝ +# ██╔████╔██║██╔████╔██║██║ ██║ ██╔████╔██║███████║██║ ███████║██║██╔██╗ ██║█████╗ +# ██║╚██╔╝██║██║╚██╔╝██║██║ ██║ ██║╚██╔╝██║██╔══██║██║ ██╔══██║██║██║╚██╗██║██╔══╝ +# ██║ ╚═╝ ██║██║ ╚═╝ ██║╚██████╔╝ ██║ ╚═╝ ██║██║ ██║╚██████╗██║ ██║██║██║ ╚████║███████╗ +# ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚══════╝ +[mmu_machine] + +# Number of selectable gate on (each) MMU. Generally this is a single number, but with multi-mmu (type-B) setups +# it can be a comma separated list of the number of gates per unit. +# E.g. 'num_gates: 4,4,2' for a 2xBox Turtle and 1xNight Owl multiplexed setup +# +num_gates: 8 + +# MMU Vendor & Version is used to automatically configure some parameters and validate configuration +# If custom set to "Other" and uncomment the additional parameters below +# +# ERCF 1.1 add "s" suffix for Springy, "b" for Binky, "t" for Triple-Decky +# e.g. "1.1sb" for v1.1 with Springy mod and Binky encoder +# ERCF 2.0 community edition ERCFv2 +# Tradrack 1.0 add "e" if encoder is fitted (assumed to be Binky) +# AngryBeaver 1.0 +# BoxTurtle 1.0 +# NightOwl 1.0 +# 3MS 1.0 +# 3D Chameleon 1.0 +# Prusa 3.0 NOT YET SUPPORTED - COMING SOON +# Other Generic setup that may require further customization of 'cad' parameters. See doc in mmu_parameters.cfg +# +mmu_vendor: ERCF # MMU family +mmu_version: 2.0 # MMU hardware version number (add mod suffix documented above) + +# The following attributes are set internally from vendor/version above. Only uncomment to customize the vendor +# default or for custom ("Other") designs +# +#selector_type: LinearSelector # E.g. LinearSelector (type-A), VirtualSelector (type-B), MacroSelector, RotarySelector, ... +#variable_bowden_lengths: 0 # 1 = If MMU design has different bowden lengths per gate, 0 = bowden length is the same +#variable_rotation_distances: 1 # 1 = If MMU design has dissimilar drive/BMG gears, thus rotation distance, 0 = One drive gear (e.g. Tradrack) +#require_bowden_move: 1 # 1 = If MMU design has bowden move that is included in load/unload, 0 = zero length bowden (skip bowden move) +#filament_always_gripped: 0 # 1 = Filament is always trapped by MMU (most type-B designs), 0 = MMU can release filament +#has_bypass: 0 # 1 = Bypass gate available, 0 = No filament bypass possible + +# Uncomment to change the display name in UI's. Defaults to the vendor name +#display_name: My Precious + +homing_extruder: 1 # CAUTION: Normally this should be 1. 0 will disable the homing extruder capability + + +# FILAMENT DRIVE GEAR STEPPER(S) -------------------------------------------------------------------------------------- +# ██████╗ ███████╗ █████╗ ██████╗ +# ██╔════╝ ██╔════╝██╔══██╗██╔══██╗ +# ██║ ███╗█████╗ ███████║██████╔╝ +# ██║ ██║██╔══╝ ██╔══██║██╔══██╗ +# ╚██████╔╝███████╗██║ ██║██║ ██║ +# ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ +# Note that 'toolhead' & 'mmu_gear' endstops will automatically be added if a toolhead sensor or gate sensor is defined +# +# The default values are tested with the ERCF BOM NEMA14 motor. Please adapt these values to the motor you are using +# Example : for NEMA17 motors, you'll usually use higher current +# +# [tmc2209 stepper_mmu_gear] +# uart_pin: mmu:MMU_GEAR_UART +# run_current: 1.1 # ERCF v2.5 BOM NEMA17 motor +# hold_current: 0.1 # Recommend to be small if not using "touch" or move (TMC stallguard) +# interpolate: True +# sense_resistor: 0.110 # Usually 0.11, 0.15 for BTT TMC2226 +# stealthchop_threshold: 0 # Spreadcycle has more torque and better at speed +# +# Uncomment two lines below if you have TMC and want the ability to use filament "touch" homing with gear stepper +#diag_pin: ^mmu:MMU_GEAR_DIAG # Set to MCU pin connected to TMC DIAG pin for gear stepper +#driver_SGTHRS: 60 # 255 is most sensitive value, 0 is least sensitive + +[stepper_mmu_gear] +step_pin: mmu:MMU_GEAR_STEP +dir_pin: mmu:MMU_GEAR_DIR +enable_pin: !mmu:MMU_GEAR_ENABLE +rotation_distance: 22.7316868 # Bondtech 5mm Drive Gears. Overridden by 'mmu_gear_rotation_distance' in mmu_vars.cfg +#gear_ratio: 80:20 # ERCF v2.5 is direct drive +microsteps: 16 # Recommend 16. Increase only if you "step compress" issues when syncing +full_steps_per_rotation: 200 # 200 for 1.8 degree, 400 for 0.9 degree +# +# Uncomment the two lines below to enable filament "touch" homing option with gear motor +#extra_endstop_pins: tmc2209_stepper_mmu_gear:virtual_endstop +#extra_endstop_names: mmu_gear_touch + + + +# SELECTOR STEPPER ---------------------------------------------------------------------------------------------------- +# ███████╗███████╗██╗ ███████╗ ██████╗████████╗ ██████╗ ██████╗ +# ██╔════╝██╔════╝██║ ██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗ +# ███████╗█████╗ ██║ █████╗ ██║ ██║ ██║ ██║██████╔╝ +# ╚════██║██╔══╝ ██║ ██╔══╝ ██║ ██║ ██║ ██║██╔══██╗ +# ███████║███████╗███████╗███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║ +# ╚══════╝╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ +# Consult doc if you want to setup selector for "touch" homing instead or physical endstop +# +[tmc2209 stepper_mmu_selector] +uart_pin: mmu:MMU_SEL_UART +run_current: 0.8 # ERCF BOM NEMA17 motor +hold_current: 0.6 # Can be small if not using "touch" movement (TMC stallguard) +interpolate: True +sense_resistor: 0.110 +stealthchop_threshold: 100 # Stallguard "touch" movement (slower speeds) best done with stealthchop +# +# Uncomment two lines below if you have TMC and want to use selector "touch" movement +#diag_pin: ^mmu:MMU_SEL_DIAG # Set to MCU pin connected to TMC DIAG pin for selector stepper +#driver_SGTHRS: 75 # 255 is most sensitive value, 0 is least sensitive + +[stepper_mmu_selector] +step_pin: mmu:MMU_SEL_STEP +dir_pin: !mmu:MMU_SEL_DIR +enable_pin: !mmu:MMU_SEL_ENABLE +rotation_distance: 40 +microsteps: 16 # Don't need high fidelity +full_steps_per_rotation: 200 # 200 for 1.8 degree, 400 for 0.9 degree +endstop_pin: ^mmu:MMU_SEL_ENDSTOP # Selector microswitch +endstop_name: mmu_sel_home +# Uncomment this line only if default endstop above is using stallguard +#homing_retract_dist: 0 +# +# Uncomment two lines below to give option of selector "touch" movement +#extra_endstop_pins: tmc2209_stepper_mmu_selector:virtual_endstop +#extra_endstop_names: mmu_sel_touch + + +# SERVOS --------------------------------------------------------------------------------------------------------------- +# ███████╗███████╗██████╗ ██╗ ██╗ ██████╗ ███████╗ +# ██╔════╝██╔════╝██╔══██╗██║ ██║██╔═══██╗██╔════╝ +# ███████╗█████╗ ██████╔╝██║ ██║██║ ██║███████╗ +# ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║ ██║╚════██║ +# ███████║███████╗██║ ██║ ╚████╔╝ ╚██████╔╝███████║ +# ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ +# Basic servo PWM setup. If these values are changed then the angles defined for different positions will also change +# +# SELECTOR SERVO ------------------------------------------------------------------------------------------------------- +# +[mmu_servo selector_servo] +pin: mmu:MMU_SEL_SERVO +maximum_servo_angle: 180 +minimum_pulse_width: 0.00085 +maximum_pulse_width: 0.00215 +# +# OPTIONAL GANTRY SERVO FOR TOOLHEAD FILAMENT CUTTER ------------------------------------------------------------------ +# +# (uncomment this section if you have a gantry servo for toolhead cutter pin) +#[mmu_servo mmu_gantry_servo] +#pin: +#maximum_servo_angle:180 +#minimum_pulse_width: 0.00075 +#maximum_pulse_width: 0.00225 +#initial_angle: 180 + + +# FILAMENT SENSORS ----------------------------------------------------------------------------------------------------- +# ███████╗███████╗███╗ ██╗███████╗ ██████╗ ██████╗ ███████╗ +# ██╔════╝██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝ +# ███████╗█████╗ ██╔██╗ ██║███████╗██║ ██║██████╔╝███████╗ +# ╚════██║██╔══╝ ██║╚██╗██║╚════██║██║ ██║██╔══██╗╚════██║ +# ███████║███████╗██║ ╚████║███████║╚██████╔╝██║ ██║███████║ +# ╚══════╝╚══════╝╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ +# Define the pins for optional sensors in the filament path. All but the pre-gate sensors will be automatically setup as +# both endstops (for homing) and sensors for visibility purposes. +# +# 'pre_gate_switch_pin_X' .. 'mmu_pre_gate_X' sensor detects filament at entry to MMU. X=gate number (0..N) +# 'gate_switch_pin' .. 'mmu_gate' shared sensor detects filament past the gate of the MMU +# or +# 'post_gear_switch_pin_X' .. 'mmu_gear_X' post gear sensor for each filament +# 'extruder_switch_pin' .. 'extruder' sensor detects filament just before the extruder entry +# 'toolhead_switch_pin' .. 'toolhead' sensor detects filament after extruder entry +# +# Sync motor feedback will typically have a tension switch (most important for syncing) or both tension and compression. +# Note that compression switch is useful for use as a endstop to detect hitting the extruder entrance +# 'sync_feedback_tension_pin' .. pin for switch activated when filament is under tension +# 'sync_feedback_compression_pin' .. pin for switch activated when filament is under compression +# +# Configuration is flexible: Simply define pins for any sensor you want to enable, if pin is not set (or the alias is empty) +# it will be ignored. You can also just comment out what you are not using. +# +[mmu_sensors] +pre_gate_switch_pin_0: ^mmu:MMU_PRE_GATE_0 +pre_gate_switch_pin_1: ^mmu:MMU_PRE_GATE_1 +pre_gate_switch_pin_2: ^mmu:MMU_PRE_GATE_2 +pre_gate_switch_pin_3: ^mmu:MMU_PRE_GATE_3 +pre_gate_switch_pin_4: ^mmu:MMU_PRE_GATE_4 +pre_gate_switch_pin_5: ^mmu:MMU_PRE_GATE_5 +pre_gate_switch_pin_6: ^mmu:MMU_PRE_GATE_6 +pre_gate_switch_pin_7: ^mmu:MMU_PRE_GATE_7 +pre_gate_switch_pin_8: ^mmu:MMU_PRE_GATE_8 +pre_gate_switch_pin_9: ^mmu:MMU_PRE_GATE_9 +pre_gate_switch_pin_10: ^mmu:MMU_PRE_GATE_10 +pre_gate_switch_pin_11: ^mmu:MMU_PRE_GATE_11 + +post_gear_switch_pin_0: ^mmu:MMU_POST_GEAR_0 +post_gear_switch_pin_1: ^mmu:MMU_POST_GEAR_1 +post_gear_switch_pin_2: ^mmu:MMU_POST_GEAR_2 +post_gear_switch_pin_3: ^mmu:MMU_POST_GEAR_3 +post_gear_switch_pin_4: ^mmu:MMU_POST_GEAR_4 +post_gear_switch_pin_5: ^mmu:MMU_POST_GEAR_5 +post_gear_switch_pin_6: ^mmu:MMU_POST_GEAR_6 +post_gear_switch_pin_7: ^mmu:MMU_POST_GEAR_7 +post_gear_switch_pin_8: ^mmu:MMU_POST_GEAR_8 +post_gear_switch_pin_9: ^mmu:MMU_POST_GEAR_9 +post_gear_switch_pin_10: ^mmu:MMU_POST_GEAR_10 +post_gear_switch_pin_11: ^mmu:MMU_POST_GEAR_11 + +# These sensors can be replicated in a multi-mmu, type-B setup (see num_gates comment). +# If so, then use a comma separated list of per-unit pins instead of single pin +gate_switch_pin: ^mmu:MMU_GATE_SENSOR +sync_feedback_tension_pin: +sync_feedback_compression_pin: + +# These sensors are on the toolhead and often controlled by the main printer mcu +extruder_switch_pin: ^ebb36: PB6 +toolhead_switch_pin: ^ebb36: PB5 + + +# ENCODER ------------------------------------------------------------------------------------------------------------- +# ███████╗███╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗ +# ██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗ +# █████╗ ██╔██╗ ██║██║ ██║ ██║██║ ██║█████╗ ██████╔╝ +# ██╔══╝ ██║╚██╗██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗ +# ███████╗██║ ╚████║╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║ +# ╚══════╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ +# Encoder measures distance, monitors for runout and clogging and constantly calculates % flow rate +# Note that the encoder_resolution set here is purely a default to get started. It will be correcly set after calibration +# with the value stored in mmu_vars.cfg +# +# The encoder resolution will be calibrated but it needs a default approximation +# If BMG gear based: +# resolution = bmg_circumfrance / (2 * teeth) +# 24 / (2 * 17) = 0.7059 for TRCT5000 based sensor +# 24 / (2 * 12) = 1.0 for Binky with 12 tooth disc +# +[mmu_encoder mmu_encoder] +encoder_pin: ^mmu:MMU_ENCODER +encoder_resolution: 1.0 # This is just a starter value. Overriden by calibrated 'mmu_encoder_resolution' in mmm_vars.cfg +desired_headroom: 5.0 # The clog/runout headroom that MMU attempts to maintain (closest point to triggering runout) +average_samples: 4 # The "damping" effect of last measurement (higher value means slower automatic clog_length reduction) +flowrate_samples: 20 # How many "movements" of the extruder to measure average flowrate over + + +# MMU OPTIONAL NEOPIXEL LED SUPPORT ------------------------------------------------------------------------------------ +# ██╗ ███████╗██████╗ ███████╗ +# ██║ ██╔════╝██╔══██╗██╔════╝ +# ██║ █████╗ ██║ ██║███████╗ +# ██║ ██╔══╝ ██║ ██║╚════██║ +# ███████╗███████╗██████╔╝███████║ +# ╚══════╝╚══════╝╚═════╝ ╚══════╝ +# Define the led connection, type and length +# +# (comment out this section if you don't have leds or have them defined elsewhere) +[neopixel mmu_leds] +pin: mmu:MMU_NEOPIXEL +chain_count: 9 # Need number gates x1 or x2 + status leds +color_order: GRBW # Set based on your particular neopixel specification (can be comma separated list) + +# MMU LED EFFECT SEGMENTS ---------------------------------------------------------------------------------------------- +# Define neopixel LEDs for your MMU. The chain_count must be large enough for your desired ranges: +# exit .. this set of LEDs, one for every gate, usually would be mounted at the exit point of the gate +# entry .. this set of LEDs, one for every gate, could be mounted at the entry point of filament into the MMU/buffer +# status .. these LED. represents the status of the MMU (and selected filament). More than one status LED is possible +# logo .. these LEDs don't change during operation and are designed for driving a logo. More than one logo LED is possible +# +# Note that all sets are optional. You can opt to just have the 'exit' set for example. The advantage to having +# both entry and exit LEDs is, for example, so that 'entry' can display gate status while 'exit' displays the color +# +# The animation effects requires the installation of Julian Schill's awesome LED effect module otherwise the LEDs +# will be static: +# https://github.com/julianschill/klipper-led_effect +# +# LED's are indexed in the chain from 1..N. Thus to set up LED's on 'exit' and a single 'status' LED on a 4 gate MMU: +# +# exit_leds: neopixel:mmu_leds (1,2,3,4) +# status_leds: neopixel:mmu_leds (5) +# +# In this example no 'entry' set is configured. Note that constructs like "mmu_leds (1-3,4)" are also valid +# +# The range is completely flexible and can be comprised of different led strips, individual LEDs, or combinations of +# both on different pins. In addition, the ordering is flexible based on your wiring, thus (1-4) and (4-1) both represent +# the same LED range but mapped to increasing or decreasing gates respectively. E.g if you have two Box Turtle MMUs, one +# with a chain of LEDs wired in reverse order and another with individual LEDs, to define 8 exit LEDs: +# +# exit_leds: neopixel:bt_1 (4-1) +# neopixel:bt_2a +# neopixel:bt_2b +# neopixel:bt_2c +# neopixel:bt_2d +# +# Note the use of separate lines for each part of the definition, +# +# ADVANCED: Happy Hare provides a convenience wrapper [mmu_led_effect] that not only creates an effect on each of the +# [mmu_leds] specified segments as a whole but also each individual LED for atomic control. See mmu_leds.cfg for examples +# +# (comment out this whole section if you don't have/want leds; uncomment/edit LEDs fitted on your MMU) +[mmu_leds] +exit_leds: neopixel:mmu_leds (8-1) +#entry_leds: neopixel:mmu_leds (9-16) +#status_leds: neopixel:mmu_leds (17) +#logo_leds: neopixel:mmu_leds (18) +frame_rate: 24 diff --git a/mmu-20250423_131125/base/mmu_leds.cfg b/mmu-20250423_131125/base/mmu_leds.cfg new file mode 120000 index 0000000..1a16abe --- /dev/null +++ b/mmu-20250423_131125/base/mmu_leds.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_leds.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/base/mmu_macro_vars.cfg b/mmu-20250423_131125/base/mmu_macro_vars.cfg new file mode 100644 index 0000000..5f047c0 --- /dev/null +++ b/mmu-20250423_131125/base/mmu_macro_vars.cfg @@ -0,0 +1,535 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Happy Hare supporting MACRO configuration +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# +# Supporting set of macros supplied with Happy Hare can be customized by editing the macro "variables" declared here. +# +# This configuration will automatically retained and upgraded between releases (a backup of previous config files will +# always be made for your reference). If you want to customize macros beyond what is possible through these variables +# it is highly recommended you copy the macro to a new name and change the callback macro name in 'mmu_parameters.cfg' +# That way the default macros can still be upgraded but your customization will be left intact +# + + +# PERSISTED STATE --------------------------------------------------------- +# Happy Hare stores configuration and state in the klipper variables file. +# Since klipper can only be a single 'save_variables' file, if you already +# have one you will need to merge the two and point this appropriately. +# +[save_variables] +filename: ~/printer_data/config/mmu/mmu_vars.cfg + + +# NECESSARY KLIPPER OVERRIDES --------------------------------------------- +# ██╗ ██╗██╗ ██╗██████╗ ██████╗ ███████╗██████╗ +# ██║ ██╔╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗ +# █████╔╝ ██║ ██║██████╔╝██████╔╝█████╗ ██████╔╝ +# ██╔═██╗ ██║ ██║██╔═══╝ ██╔═══╝ ██╔══╝ ██╔══██╗ +# ██║ ██╗███████╗██║██║ ██║ ███████╗██║ ██║ +# ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ +# +# These supplemental settings essentially disable klipper's built in +# extrusion limits and is necessary when using an MMU +[extruder] +max_extrude_only_distance: 200 +max_extrude_cross_section: 50 + +# For dialog prompts and progress in Mainsail. Requires Mainsail version >= v2.9.0 +[respond] + +# Other Happy Hare prerequisites. Harmless if already defined elsewhere in user config +[display_status] +[pause_resume] +[virtual_sdcard] +path: ~/printer_data/gcodes +#on_error_gcode: CANCEL_PRINT + + +# PRINT START/END --------------------------------------------------------- +# ██████╗ ██████╗ ██╗███╗ ██╗████████╗ ███████╗████████╗ █████╗ ██████╗ ████████╗ +# ██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔══██╗╚══██╔══╝ +# ██████╔╝██████╔╝██║██╔██╗ ██║ ██║ ███████╗ ██║ ███████║██████╔╝ ██║ +# ██╔═══╝ ██╔══██╗██║██║╚██╗██║ ██║ ╚════██║ ██║ ██╔══██║██╔══██╗ ██║ +# ██║ ██║ ██║██║██║ ╚████║ ██║ ███████║ ██║ ██║ ██║██║ ██║ ██║ +# ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ +# (base/mmu_software.cfg) +# +[gcode_macro _MMU_SOFTWARE_VARS] +description: Happy Hare optional configuration for print start/end checks +gcode: # Leave empty + +# These variables control the behavior of the MMU_START_SETUP and MMU_START_LOAD_INITIAL_TOOL macros +variable_user_pre_initialize_extension : '' ; Executed at start of MMU_START_SETUP. Commonly G28 to home +variable_home_mmu : False ; True/False, Whether to home mmu before print starts +variable_check_gates : True ; True/False, Whether to check filament is loaded in all gates used +variable_load_initial_tool : True ; True/False, Whether to automatically load initial tool +# +# Automapping strategy to apply slicer tool map to find matching MMU gate (will adjust tool-to-gate map). Options are: +# 'none' - don't automap (i.e. don't update tool-to-gate map) +# 'filament_name' - exactly match on case insensitive filament name +# 'material' - exactly match on material +# 'color' - exactly match on color (with same material) +# 'closest_color' - match to closest available filament color (with same material) +# 'spool_id' - exactly match on spool_id [FUTURE] +variable_automap_strategy : "none" ; none|filament_name|material|color|closest_color|spool_id + +# These variables control the behavior of the MMU_END macro +variable_user_print_end_extension : '' ; Executed at start of MMU_END. Good place to move off print +variable_unload_tool : True ; True/False, Whether to unload the tool at the end of the print +variable_reset_ttg : False ; True/False, Whether reset TTG map at end of print +variable_dump_stats : True ; True/False, Whether to display print stats at end of print + + +# STATE MACHINE CHANGES --------------------------------------------------- +# ███████╗████████╗ █████╗ ████████╗███████╗ ██████╗██╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗ +# ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝ ██╔════╝██║ ██║██╔══██╗████╗ ██║██╔════╝ ██╔════╝ +# ███████╗ ██║ ███████║ ██║ █████╗ ██║ ███████║███████║██╔██╗ ██║██║ ███╗█████╗ +# ╚════██║ ██║ ██╔══██║ ██║ ██╔══╝ ██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║██╔══╝ +# ███████║ ██║ ██║ ██║ ██║ ███████╗ ╚██████╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗ +# ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ +# (base/mmu_state.cfg) +# +[gcode_macro _MMU_STATE_VARS] +description: Happy Hare configuration for state change hooks +gcode: # Leave empty + +# You can extend functionality to all Happy Hare state change or event +# macros by adding a command (or call to your gcode macro). +# E.g for additional LED logic or consumption counters +variable_user_action_changed_extension : '' ; Executed after default logic with duplicate params +variable_user_print_state_changed_extension : '' ; Executed after default logic with duplicate params +variable_user_mmu_event_extension : '' ; Executed after default logic with duplicate params + +# Maintenance warning limits (consumption counters) +variable_servo_down_limit : 5000 ; Set to -1 for no limit / disable warning +variable_cutter_blade_limit : 3000 ; Set to -1 for no limit / disable warning + + +# LED CONTROL ------------------------------------------------------------- +# ██╗ ███████╗██████╗ ███████╗ +# ██║ ██╔════╝██╔══██╗██╔════╝ +# ██║ █████╗ ██║ ██║███████╗ +# ██║ ██╔══╝ ██║ ██║╚════██║ +# ███████╗███████╗██████╔╝███████║ +# ╚══════╝╚══════╝╚═════╝ ╚══════╝ +# Only configure if you have LEDs installed. The led_effects option is +# automatically ignored if led-effects klipper module is not installed +# (base/mmu_led.cfg) +# +[gcode_macro _MMU_LED_VARS] +description: Happy Hare led macro configuration variables +gcode: # Leave empty + +# Default effects for LED segments when not providing action status +# 'off' - LED's off +# 'on' - LED's white +# 'gate_status' - indicate gate availability / status (printer.mmu.gate_status) +# 'filament_color' - display filament color defined in gate map (printer.mmu.gate_color_rgb) +# 'slicer_color' - display slicer defined set color for each gate (printer.mmu.slicer_color_rgb) +# 'r,g,b' - display static r,g,b color e.g. "0,0,0.3" for dim blue +# '_effect_' - display the named led effect +# +variable_led_enable : True ; True = LEDs are enabled at startup (MMU_LED can control), False = Disabled +variable_led_animation : True ; True = Use led-animation-effects, False = Static LEDs +variable_default_exit_effect : "gate_status" ; off|gate_status|filament_color|slicer_color|r,g,b|_effect_ +variable_default_entry_effect : "filament_color" ; off|gate_status|filament_color|slicer_color|r,g,b|_effect_ +variable_default_status_effect : "filament_color" ; on|off|gate_status|filament_color|slicer_color|r,g,b|_effect_ +variable_default_logo_effect : "0,0,.3" ; off |r,g,b|_effect_ +variable_white_light : (1, 1, 1) ; RGB color for static white light +variable_black_light : (.01, 0, .02) ; RGB color used to represent "black" (filament) +variable_empty_light : (0, 0, 0) ; RGB color used to represent empty gate + + +# SEQUENCE MACRO - PARKING MOVEMENT AND TOOLCHANGE CONTROL ---------------- +# ███╗ ███╗ ██████╗ ██╗ ██╗███████╗███╗ ███╗███████╗███╗ ██╗████████╗ +# ████╗ ████║██╔═══██╗██║ ██║██╔════╝████╗ ████║██╔════╝████╗ ██║╚══██╔══╝ +# ██╔████╔██║██║ ██║██║ ██║█████╗ ██╔████╔██║█████╗ ██╔██╗ ██║ ██║ +# ██║╚██╔╝██║██║ ██║╚██╗ ██╔╝██╔══╝ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ +# ██║ ╚═╝ ██║╚██████╔╝ ╚████╔╝ ███████╗██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ +# ╚═╝ ╚═╝ ╚═════╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ +# Configure carefully if you 'enable_park: True' +# (base/mmu_sequence.cfg) +# +[gcode_macro _MMU_SEQUENCE_VARS] +description: Happy Hare sequence macro configuration variables +gcode: # Leave empty + +# Parking and movement controls: +# Happy Hare defines 7 operations that may require parking. You can specify +# whether to park for each of those operations both during a print and +# standalone (not printing) with Happy Hare or when HH is disabled: +# +# enable_park_printing +# This is a list of the operations that should result in toolhead parking +# while in a print. There are really two main starting points from which +# you can customize. If using the slicer to form tips (and toolchange is +# over the wipetower) you don't want to park on "toolchange" but you would +# want to on "runout" which is a forced toolchange unknown by the slicer. +# Typically you would also want to park at least on pause, cancel and +# complete if not done elsewhere +# +# enabled_park_standalone +# List of the operations that should result in toolhead parking when not +# printing, for example, just manipulating the MMU manually or via +# Klipperscreen. Really it is up to you to choose based on personal +# workflow preferences but this defaults to just 'pause,cancel' +# (i.e. disabled for toolchange) +# +# enabled_park_disabled +# List of the operations that should result in toolhead parking when MMU is +# disabled (MMU ENABLE=0) and using Happy Hare client macros. Note that only +# pause and cancel can occur in this mode and would typically be enabled +# +# The operations are as follows: +# toolchange - normal toolchange initiated with Tx or MMU_CHANGE_TOOL command +# runout - when a forced toolchange occurs as a result of runout +# load - individual MMU_LOAD operation +# unload - individual MMU_UNLOAD/MMU_EJECT operation +# complete - when print is complete (Happy Hare enabled) +# pause - a regular klipper PAUSE +# cancel - a regular klipper CANCEL_PRINT +# +# It is possible to call the parking macro manually in this form should you wish +# to include in your macros. +# +# _MMU_PARK FORCE_PARK=1 X=10 Y=10 Z_HOP=5 +# +# restore_xy_pos +# Controls where the toolhead (x,y) is returned to after an operation that +# invokes a parking move: +# last - return to original position before park (frequently the default) +# next - return to next print position if possible else last logic will be applied. +# In print this reduces dwell time at the last position reducing blobbing +# and unnecessary movement. Only applied to "toolchange" operation +# none - the toolhead is left wherever it ends up after change. In a print the +# next gcode command will restore toolhead x,y position +# +# Notes: +# - The starting z-height will always be restored, thus the different between 'next' +# and 'none' is the z-height at which the (x,y) move occurs and the location of +# of any un-retract +# - The default parking logic is a straight line move to the 'park_*' position. +# To implement fancy movement and control you can specify your own +# 'user_park_move_macro' to use instead of default straight line move +# - x,y parking coordinates can be negative if your printer can handle it +# +# Retraction can be used to optimize stringing and blobs that can occur when +# changing tools and are active only during a print. +# IMPORTANT: For toolchanging the config order would be: +# 1. In mmu_parameters.cfg configure extruder dimensions like +# 'toolhead_extruder_to_nozzle',etc. These are based on geometry. +# 2. In mmu_parameters.cfg tweak 'toolhead_ooze_reduction' only if necessary +# so that filament _just_ appears at the nozzle on load +# 3. Only then, adjust retraction to control stringing and blobs when +# changing tool in a print +variable_enable_park_printing : 'toolchange,runout,load,unload,complete,pause,cancel' ; Empty '' to disable parking +variable_enable_park_standalone : 'toolchange,load,unload,pause,cancel' ; Empty '' to disable parking +variable_enable_park_disabled : 'pause,cancel' ; Empty '' to disable parking + +variable_min_toolchange_z : 1.0 ; The absolute minimum safety floor (z-height) for ALL parking moves + +# These specify the parking location, z_hop and retraction for all enabled operation +# types. Each must be 5 values: +# x_coord, y_coord, z_hop(delta), z_hop_ramp, retraction length +# Use -999,-999 for no x,y move (you can just have z_hop). Use 0 for no z_hop +# The z_hop ramp is the horizontal distance in mm to travel during the lift. The +# direction is automatic and only applied if lifting the first time from print. +# This move is useful to help break the filament "string" +variable_park_toolchange : -999, -999, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract for "toolchange" operations (toolchange,load,unload) +variable_park_runout : -999, -999, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract +variable_park_pause : 50, 50, 5, 0, 2 ; x,y,z-hop,z_hop_ramp,retract (park position when mmu error occurs) +variable_park_cancel : -999, -999, 10, 0, 5 ; x,y,z-hop,z_hop_ramp,retract +variable_park_complete : 50, 50, 10, 0, 5 ; x,y,z-hop,z_hop_ramp,retract + +# For toolchange operations, this allows to you to specify additional parking moves +# at various stages of the toolchange. Each must have 3 values: +# x_coord, y_coord, z_hop(delta) +# Use -999,-999,0 for no movement at that stage (no-op). +# All movement will be at the established movement plane (z-height) +variable_pre_unload_position : -999, -999, 0 ; x,y,z-hop position before unloading starts +variable_post_form_tip_position : -999, -999, 0 ; x,y,z-hop position after form/cut tip on unload +variable_pre_load_position : -999, -999, 0 ; x,y,z-hop position before loading starts + +variable_restore_xy_pos : "last" ; last|next|none - What x,y position the toolhead should travel to after a "toolchange" + +variable_park_travel_speed : 200 ; Speed for any travel movement XY(Z) in mm/s +variable_park_lift_speed : 15 ; Z-only travel speed in mm/s +variable_retract_speed : 30 ; Speed of the retract move in mm/s +variable_unretract_speed : 30 ; Speed of the unretract move in mm/s + +# ADVANCED: Normally x,y moves default to 'G1 X Y' to park position. This allows +# you to create exotic movements. Macro will be provided the following parameters: +# YOUR_MOVE_MACRO X= Y= F= +# when restoring the from parked postion the same macro is called but passed a RESTORE=1 parameter, along with co-ordinates to restore to +# YOUR_MOVE_MACRO RESTORE=1 X= Y= F= +variable_user_park_move_macro : '' ; Executed instead of default 'G1 X Y move' to park position + +variable_auto_home : True ; True = automatically home if necessary, False = disable +variable_timelapse : False ; True = take frame snapshot after load, False = disable + +# Instead of completely defining your your own macros you can can extend functionality +# of default sequence macros by adding a command (or call to your gcode macro) +variable_user_mmu_error_extension : '' ; Executed after default logic when mmu error condition occurs +variable_user_pre_unload_extension : '' ; Executed after default logic +variable_user_post_form_tip_extension : '' ; Executed after default logic +variable_user_post_unload_extension : '' ; Executed after default logic +variable_user_pre_load_extension : '' ; Executed after default logic +variable_user_post_load_extension : 'CLEAN_NOZZLE' ; Executed after default logic but before restoring toolhead position + + +# CUT_TIP ----------------------------------------------------------------- +# ██████╗██╗ ██╗████████╗ ████████╗██╗██████╗ +# ██╔════╝██║ ██║╚══██╔══╝ ╚══██╔══╝██║██╔══██╗ +# ██║ ██║ ██║ ██║ ██║ ██║██████╔╝ +# ██║ ██║ ██║ ██║ ██║ ██║██╔═══╝ +# ╚██████╗╚██████╔╝ ██║ ██║ ██║██║ +# ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ +# Don't need to configure if using tip forming +# (base/mmu_cut_tip.cfg) +# +[gcode_macro _MMU_CUT_TIP_VARS] +description: Happy Hare toolhead tip cutting macro configuration variables +gcode: # Leave empty + +# Whether the toolhead tip cutting macro will return toolhead to initial position +# after the cut is complete. If using parking logic it is better to disable this +variable_restore_position : False ; True = return to initial position, False = don't return + +# Distance from the internal nozzle tip to the cutting blade. This dimension +# is based on your toolhead and should not be used for tuning +# Note: If you have a toolhead sensor this variable can be automatically determined! +# Read https://github.com/moggieuk/Happy-Hare/wiki/Blobing-and-Stringing +variable_blade_pos : 37.5 ; TUNE ME: Distance in mm from internal nozzle tip + +# Distance to retract prior to making the cut, measured from the internal nozzle +# tip. This reduces wasted filament (left behind in extruder) but might cause a +# clog if set too large. This must be less than 'blade_pos' +# Note: the residual filament left in nozzle ('toolhead_ooze_reduction') is +# subtracted from this value so make sure toolhead is calibrated +variable_retract_length : 32.5 ; TUNE ME: 5mm less than 'blade_pos' is a good starting point + +# Whether to perform a simple tip forming move after the initial retraction +# Enabling this adds gives some additional cooling time of molten filament and +# may help avoid potential clogging on some hotends +variable_simple_tip_forming : False ; True = Perform simple tip forming, False = skip + +# Change to X and Y stepper current during the cut operation. Technically any stepper +# current can be modified by adding the stepper name to the list. Be careful not to +# overload your steppers but generally up to 150% is safe +variable_cut_axis_steppers : 'stepper_x, stepper_y' ; Comma separated list of stepper names to increase current for cutting +variable_cut_stepper_current : 100 ; % of stepper current to use for cutting motion (100 to disable) + +# This should be the position of the toolhead where the cutter arm just +# lightly touches the depressor pin +variable_cutting_axis : "x" ; "x" or "y". Determines cut direction (axis) during cut motion, used for park distance +variable_pin_loc_xy : 16.5, 354.5 ; x,y coordinates of depressor pin + +# This distance is added to "pin_loc_x" or "pin_loc_y" depending on the 'cutting_axis' +# to determine the starting position and to create a small safety distance that aids +# in generating momentum +variable_pin_park_dist : 5.0 ; Distance in mm + +# Position of the toolhead when the cutter is fully compressed. Should leave a small headroom from the +# extremes of your printer edges (e.g. it should be a bit larger than 0, or whatever Xmin is) to avoid +# banging the toolhead or gantry. Typically x position will match x in pin_loc_xy if cutting in y direction +# or y position will match y in pin_loc_xy if cutting in x direction, but diagonal cuts are possible +variable_pin_loc_compressed_xy : 3, 354.5 ; x,y coordinates of fully depressed location + +# Retract length and speed after the cut so that the cutter blade doesn't +# get stuck on return to 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. This does +# not have to push back all the way, just sufficient to ensure filament fragment +# stays in hot end and the "nail head" of the cut is pushed back past the +# PTFE/metal junction so it cannot cause clogging problems on future loads. +# Cannot be larger than 'retract_length' - `toolhead_ooze_reduction` +variable_pushback_length : 15.0 ; TUNE ME: PTFE tube length + 3mm is good starting point +variable_pushback_dwell_time : 0 ; Time in ms to dwell after the pushback + +# 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_travel_speed : 150 ; Speed mm/s +variable_cut_fast_move_speed : 32 ; Speed mm/s +variable_cut_slow_move_speed : 8 ; Speed mm/s +variable_evacuate_speed : 150 ; Speed mm/s +variable_cut_dwell_time : 50 ; Time in ms to dwell at the cut point +variable_cut_fast_move_fraction : 1.0 ; Fraction of the move that uses fast move +variable_extruder_move_speed : 25 ; Speed mm/s for all extruder movement + +# 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) + +# If gantry servo option is installed, enable the servo and set up and down +# angle positions +variable_gantry_servo_enabled : False ; True = enabled, False = disabled +variable_gantry_servo_down_angle: 55 ; Angle for when pin is deployed +variable_gantry_servo_up_angle : 180 ; Angle for when pin is retracted + + +# FORM_TIP ---------------------------------------------------------------- +# ███████╗ ██████╗ ██████╗ ███╗ ███╗ ████████╗██╗██████╗ +# ██╔════╝██╔═══██╗██╔══██╗████╗ ████║ ╚══██╔══╝██║██╔══██╗ +# █████╗ ██║ ██║██████╔╝██╔████╔██║ ██║ ██║██████╔╝ +# ██╔══╝ ██║ ██║██╔══██╗██║╚██╔╝██║ ██║ ██║██╔═══╝ +# ██║ ╚██████╔╝██║ ██║██║ ╚═╝ ██║ ██║ ██║██║ +# ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ +# Don't need to configure if using tip cutting +# (base/mmu_form_tip.cfg) +# +[gcode_macro _MMU_FORM_TIP_VARS] +description: Happy Hare tip forming macro configuration variables +gcode: # Leave empty + +# Step 1 - Ramming +# Ramming is the initial squeeze of filament prior to cooling moves and is +# described in terms of total volume and progression of squeeze intensity +# printing/standalone. This can be separately controlled when printing or +# standalone +variable_ramming_volume : 0 ; Volume in mm^3, 0 = disabled (optionally let slicer do it) +variable_ramming_volume_standalone : 0 ; Volume in mm^3, 0 = disabled + +# Optionally set for temperature change (reduction). The wait will occur +# before nozzle separation if 'use_fast_skinnydip: False' else after cooling +# moves. Temperature will be restored after tip creation is complete +variable_toolchange_temp : 0 ; 0 = don't change temp, else temp to set +variable_toolchange_fan_assist : False ; Whether to use part cooling fan for quicker temp change +variable_toolchange_fan_name : '' ; Define the part fan name if not default [fan] e.g "fan_generic fan0" +variable_toolchange_fan_speed : 50 ; Fan speed % if using fan_assist enabled + +# Step 2 - Nozzle Separation +# The filament is then quickly separated from the meltzone by a fast movement +# before then slowing to travel the remaining distance to cooling tube. The +# initial fast movement should be as fast as extruder can comfortably perform. +# A good starting point# for slower move is unloading_speed_start/cooling_moves. +# Too fast a slower movement can lead to excessively long tips or hairs +variable_unloading_speed_start : 80 ; Speed in mm/s for initial fast movement +variable_unloading_speed : 18 ; Speed in mm/s for slow move to cooling zone + +# Step 3 - Cooling Moves +# The cooling move allows the filament to harden while constantly moving back +# and forth in the cooling tube portion of the extruder to prevent a bulbous +# tip forming. The cooling tube position is measured from the internal nozzle +# to just past the top of the heater block (often it is beneficial to add a +# couple of mm to ensure the tip is in the cooling section. The cooling tube +# length is then the distance from here to top of heatsink (this is the length +# length of the cooling moves). The final cooling move is a fast movement to +# break the string formed. +variable_cooling_tube_position : 35 ; Start of cooling tube. DragonST:35, DragonHF:30, Mosquito:30, Revo:35, RapidoHF:27 +variable_cooling_tube_length : 10 ; Movement length. DragonST:15, DragonHF:10, Mosquito:20, Revo:10, RapidoHF:10 +variable_initial_cooling_speed : 10 ; Initial slow movement (mm/s) to solidify tip and cool string if formed +variable_final_cooling_speed : 50 ; Fast movement (mm/s) Too fast: tip deformation on eject, Too Slow: long string/no separation +variable_cooling_moves : 4 ; Number of back and forth cooling moves to make (2-4 is a good start) + +# Step 4 - Skinnydip +# Skinnydip is an advanced final move that may have benefit with some +# material like PLA to burn off persistent very fine hairs. To work the +# depth of insertion is critical (start with it disabled and tune last) +# For reference the internal nozzle would be at a distance of +# cooling_tube_position + cooling_tube_length, the top of the heater +# block would be cooling_tube_length away. +variable_use_skinnydip : False ; True = enable skinnydip, False = skinnydip move disabled +variable_skinnydip_distance : 30 ; Distance to reinsert filament into hotend starting from end of cooling tube +variable_dip_insertion_speed : 30 ; Medium/Slow insertion speed mm/s - Just long enough to melt the fine hairs, too slow will pull up molten filament +variable_dip_extraction_speed : 70 ; Speed mm/s - Around 2x Insertion speed to prevents forming new hairs +variable_melt_zone_pause : 0 ; Pause if melt zone in ms. Default 0 +variable_cooling_zone_pause : 0 ; Pause if cooling zone after dip in ms. Default 0 +variable_use_fast_skinnydip : False ; False = Skip the toolhead temp change wait during skinnydip move + +# Step 5 - Parking +# Park filament ready to eject +variable_parking_distance : 0 ; Position mm to park the filament at end of tip forming, 0 = leave where filament ends up after tip forming +variable_extruder_eject_speed : 25 ; Speed mm/s used for parking_distance (and final_eject when testing) + + +# PURGE ------------------------------------------------------------------- +# ██████╗ ██╗ ██╗██████╗ ██████╗ ███████╗ +# ██╔══██╗██║ ██║██╔══██╗██╔════╝ ██╔════╝ +# ██████╔╝██║ ██║██████╔╝██║ ███╗█████╗ +# ██╔═══╝ ██║ ██║██╔══██╗██║ ██║██╔══╝ +# ██║ ╚██████╔╝██║ ██║╚██████╔╝███████╗ +# ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ +# +# Optional reference (bucket) purge. Blobifier if far better but this can be +# used as a basis for custom purge +# (base/mmu_purge.cfg) +# +[gcode_macro _MMU_PURGE_VARS] +description: Happy Hare reference purging macro configuration variables +gcode: # Leave empty + +# Set speed as fast as you can without the extruder skipping steps. Note that +# you can increase the extruder current for purging in mmu_parameters.cfg +variable_extruder_purge_speed : 2 ; Speed in mm/s for purging + + +# CLIENT MACROS ----------------------------------------------------------- +# ██████╗ █████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███████╗███████╗██╗ ██╗███╗ ███╗███████╗ +# ██╔══██╗██╔══██╗██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██║ ██║████╗ ████║██╔════╝ +# ██████╔╝███████║██║ ██║███████╗█████╗ ██████╔╝█████╗ ███████╗██║ ██║██╔████╔██║█████╗ +# ██╔═══╝ ██╔══██║██║ ██║╚════██║██╔══╝ ██╔══██╗██╔══╝ ╚════██║██║ ██║██║╚██╔╝██║██╔══╝ +# ██║ ██║ ██║╚██████╔╝███████║███████╗ ██║ ██║███████╗███████║╚██████╔╝██║ ╚═╝ ██║███████╗ +# ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ +# If using the recommended PAUSE/RESUME/CANCEL_PRINT macros shipped with +# Happy Hare these variables allow for customization and basic extension +# Note that most parameters are pulled from the "movement" (sequence) +# macro above and thus these are supplemental a +# (optional/client_macros.cfg) +# +[gcode_macro _MMU_CLIENT_VARS] +description: Happy Hare client macro configuration variables +gcode: # Leave empty + +variable_reset_ttg_on_cancel : False ; True/False, Whether reset TTG map if print is canceled +variable_unload_tool_on_cancel : False ; True/False, Whether to unload the tool on cancel + +# You can extend functionality by adding a command (or call to your gcode macro) +variable_user_pause_extension : '' ; Executed after the klipper base pause +variable_user_resume_extension : '' ; Executed before the klipper base resume +variable_user_cancel_extension : '' ; Executed before the klipper base cancel_print + + +########################################################################### +# Tool change macros +# This is automatically created on installation but you can increase or +# reduce this list to match your number of tools in operation +# Note: it is annoying to have to do this but interfaces like Mainsail rely +# on real macro definitions for tools to be visible in the UI +# +[gcode_macro T0] +gcode: MMU_CHANGE_TOOL TOOL=0 +[gcode_macro T1] +gcode: MMU_CHANGE_TOOL TOOL=1 +[gcode_macro T2] +gcode: MMU_CHANGE_TOOL TOOL=2 +[gcode_macro T3] +gcode: MMU_CHANGE_TOOL TOOL=3 +[gcode_macro T4] +gcode: MMU_CHANGE_TOOL TOOL=4 +[gcode_macro T5] +gcode: MMU_CHANGE_TOOL TOOL=5 +[gcode_macro T6] +gcode: MMU_CHANGE_TOOL TOOL=6 +[gcode_macro T7] +gcode: MMU_CHANGE_TOOL TOOL=7 + diff --git a/mmu-20250423_131125/base/mmu_parameters.cfg b/mmu-20250423_131125/base/mmu_parameters.cfg new file mode 100644 index 0000000..5c82fef --- /dev/null +++ b/mmu-20250423_131125/base/mmu_parameters.cfg @@ -0,0 +1,685 @@ +######################################################################################################################## +# Happy Hare MMU Software +# +# EDIT THIS FILE BASED ON YOUR SETUP +# +# Copyright (C) 2022-2025 moggieuk#6538 (discord) +# moggieuk@hotmail.com +# This file may be distributed under the terms of the GNU GPLv3 license. +# +# Goal: Main configuration parameters for the klipper module +# +# (\_/) +# ( *,*) +# (")_(") Happy Hare Ready +# +# Notes: +# Macro configuration is specified separately in 'mmu_macro_vars.cfg'. +# Full details in https://github.com/moggieuk/Happy-Hare/tree/main/doc/configuration.md +# +[mmu] +happy_hare_version: 3.2 # Don't mess, used for upgrade detection + +# MMU Hardware Limits -------------------------------------------------------------------------------------------------- +# ██╗ ██╗███╗ ███╗██╗████████╗███████╗ +# ██║ ██║████╗ ████║██║╚══██╔══╝██╔════╝ +# ██║ ██║██╔████╔██║██║ ██║ ███████╗ +# ██║ ██║██║╚██╔╝██║██║ ██║ ╚════██║ +# ███████╗██║██║ ╚═╝ ██║██║ ██║ ███████║ +# ╚══════╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ +# +# Define the physical limits of your MMU. These settings will be respected regardless of individual speed settings. +# +gear_max_velocity: 300 # Never to be exceeded gear velocity regardless of specific parameters +gear_max_accel: 1500 # Never to be exceeded gear acceleration regardless of specific parameters +selector_max_velocity: 250 # Never to be exceeded selector velocity regardless of specific parameters +selector_max_accel: 1200 # Never to be exceeded selector acceleration regardless of specific parameters + + +# Servo configuration ------------------------------------------------------------------------------------------------- +# ███████╗███████╗██████╗ ██╗ ██╗ ██████╗ +# ██╔════╝██╔════╝██╔══██╗██║ ██║██╔═══██╗ +# ███████╗█████╗ ██████╔╝██║ ██║██║ ██║ +# ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║ ██║ +# ███████║███████╗██║ ██║ ╚████╔╝ ╚██████╔╝ +# ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═════╝ +# +# Angle of the servo in three named positions +# up = tool is selected and filament is allowed to freely move through gate +# down = to grip filament +# move = ready the servo for selector move (optional - defaults to up) +# V2.4.0 on: These positions are only for initial config they are replaced with calibrated servo positions in `mmu_vars.cfg` +# +# Note that leaving the servo active when down can stress the electronics and is not recommended with EASY-BRD or ERB board +# unless the 5v power supply has been improved and it is not necessary with standard ERCF builds +# Make sure your hardware is suitable for the job! +# +servo_up_angle: 140 # ERCF: MG90S: 30 ; SAVOX SH0255MG: 140 ; Tradrack: 145 +servo_down_angle: 30 # ERCF: MG90S: 140 ; SAVOX SH0255MG: 30 ; Tradrack: 1 +servo_move_angle: 109 # Optional angle used when selector is moved (defaults to up position) +servo_duration: 0.4 # Duration of PWM burst sent to servo (default non-active mode, automatically turns off) +servo_dwell: 0.5 # Minimum time given to servo to complete movement prior to next move +servo_always_active: 0 # CAUTION - WILL DAMAGE COMMON SERVOS, PLEASE USE AT YOUR OWN RISK: 1=Force servo to always stay active, 0=Release after movement +servo_active_down: 0 # CAUTION - WILL DAMAGE COMMON SERVOS, PLEASE USE AT YOUR OWN RISK: 1=Force servo to stay active when down only, 0=Release after movement +servo_buzz_gear_on_down: 1 # Whether to "buzz" the gear stepper on down to aid engagement + + +# Logging -------------------------------------------------------------------------------------------------------------- +# ██╗ ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ +# ██║ ██╔═══██╗██╔════╝ ██╔════╝ ██║████╗ ██║██╔════╝ +# ██║ ██║ ██║██║ ███╗██║ ███╗██║██╔██╗ ██║██║ ███╗ +# ██║ ██║ ██║██║ ██║██║ ██║██║██║╚██╗██║██║ ██║ +# ███████╗╚██████╔╝╚██████╔╝╚██████╔╝██║██║ ╚████║╚██████╔╝ +# ╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# log_level & logfile_level can be set to one of (0 = essential, 1 = info, 2 = debug, 3 = trace, 4 = stepper moves) +# Generally you can keep console logging to a minimal whilst still sending debug output to the mmu.log file +# Increasing the console log level is only really useful during initial setup to save having to constantly open the log file +# Note: that it is not recommended to keep logging at level greater that 2 (debug) if not debugging an issue because +# of the additional overhead +# +log_level: 1 +log_file_level: 2 # Can also be set to -1 to disable log file completely +log_statistics: 1 # 1 to log statistics on every toolchange (default), 0 to disable (but still recorded) +log_visual: 1 # 1 log visual representation of filament, 0 = disable +log_startup_status: 1 # Whether to log tool to gate status on startup, 1 = summary (default), 0 = disable +log_m117_messages: 1 # Whether send toolchange message via M117 to screen + + +# Movement speeds ------------------------------------------------------------------------------------------------------ +# ███████╗██████╗ ███████╗███████╗██████╗ ███████╗ +# ██╔════╝██╔══██╗██╔════╝██╔════╝██╔══██╗██╔════╝ +# ███████╗██████╔╝█████╗ █████╗ ██║ ██║███████╗ +# ╚════██║██╔═══╝ ██╔══╝ ██╔══╝ ██║ ██║╚════██║ +# ███████║██║ ███████╗███████╗██████╔╝███████║ +# ╚══════╝╚═╝ ╚══════╝╚══════╝╚═════╝ ╚══════╝ +# +# Long moves are faster than the small ones and used for the bulk of the bowden movement. You can set two fast load speeds +# depending on whether pulling from the spool or filament buffer (if fitted and not the first time load). This can be helpful +# in allowing faster loading from buffer and slower when pulling from the spool because of the additional friction (prevents +# loosing steps). Unloading speed can be tuning if you have a rewinder system that imposes additional limits. +# NOTE: Encoder cannot keep up much above 450mm/s so make sure 'bowden_apply_correction' is off at very high speeds! +# +gear_from_spool_speed: 80 # mm/s Speed when loading from the spool (for the first time if has_filament_buffer: 1) +gear_from_spool_accel: 100 # Acceleration when loading from spool +gear_from_buffer_speed: 150 # mm/s Speed when loading filament from buffer. Conservative is 100mm/s, Max around 400mm/s +gear_from_buffer_accel: 400 # Normal acceleration when loading filament +gear_unload_speed: 80 # mm/s Use (lower) speed when unloading filament (defaults to "from spool" speed) +gear_unload_accel: 100 # Acceleration when unloading filament (defaults to "from spool" accel) +# +gear_short_move_speed: 80 # mm/s Speed when making short moves (like incremental retracts with encoder) +gear_short_move_accel: 600 # Usually the same as gear_from_buffer_accel (for short movements) +gear_short_move_threshold: 70 # Move distance that controls application of 'short_move' speed/accel +gear_homing_speed: 50 # mm/s Speed of gear stepper only homing moves (e.g. homing to gate or extruder) + +# Speeds of extruder movement. The 'sync' speeds will be used when gear and extruder steppers are moving in sync +# +extruder_load_speed: 16 # mm/s speed of load move inside extruder from homing position to meltzone +extruder_unload_speed: 16 # mm/s speed of unload moves inside of extruder (very initial move from meltzone is 50% of this) +extruder_sync_load_speed: 18 # mm/s speed of synchronized extruder load moves +extruder_sync_unload_speed: 18 # mm/s speed of synchronized extruder unload moves +extruder_homing_speed: 18 # mm/s speed of extruder only homing moves (e.g. to toolhead sensor) + +# Selector movement speeds. (Acceleration is defined by physical MMU limits set above and passed to selector stepper driver) +# +selector_move_speed: 200 # mm/s speed of selector movement (not touch) +selector_homing_speed: 60 # mm/s speed of initial selector homing move (not touch) +selector_touch_speed: 80 # mm/s speed of all touch selector moves (if stallguard configured) + +# Selector touch (stallguard) operation. If stallguard is configured, then this can be used to switch on touch movement which +# can detect blocked filament path and try to recover automatically but it is more difficult to set up +# +selector_touch_enable: 0 # If selector touch operation configured this can be used to disable it 1=enabled, 0=disabled + +# When Happy Hare calls out to a macro for user customization and for parking moves these settings are applied and the previous +# values automatically restored afterwards. This allows for deterministic movement speed regardless of the starting state. +# +macro_toolhead_max_accel: 0 # Default printer toolhead acceleration applied when macros are run. 0 = use printer max +macro_toolhead_min_cruise_ratio: 0.5 # Default printer cruise ratio applied when macros are run + + +# Gate loading/unloading ----------------------------------------------------------------------------------------------- +# ██████╗ █████╗ ████████╗███████╗ ██╗ ██████╗ █████╗ ██████╗ +# ██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝ ██║ ██╔═══██╗██╔══██╗██╔══██╗ +# ██║ ███╗███████║ ██║ █████╗ ██║ ██║ ██║███████║██║ ██║ +# ██║ ██║██╔══██║ ██║ ██╔══╝ ██║ ██║ ██║██╔══██║██║ ██║ +# ╚██████╔╝██║ ██║ ██║ ███████╗ ███████╗╚██████╔╝██║ ██║██████╔╝ +# ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ +# +# These settings control the loading and unloading filament at the gate which is the parking position inside the MMU. +# Typically this would be switch sensor but you can also use an encoder. Even with encoder the endstop can be a switch +# and the encoder used for move verifcation (see advanced 'gate_endstop_to_encoder' option). Note that the `encoder` +# method, due to the nature of its operation will overshoot a little. This is not a problem in practice because the +# overshoot will simply be compensated for in the subsequent move. A +ve parking distance moves towards the MMU, -ve +# moves back through the endstop towards the toolhead. If the MMU has multiple bowden tubes then it is possible to home +# at the extruder sensor and avoid long bowden moves! +# +# Possible gate_homing_endstop names: +# encoder - Detect filament position using movement of the encoder +# mmu_gate - Use gate endstop +# mmu_gear - Use individual per-gate endstop (type-B MMU's) +# extruder - Use extruder entry sensor (Only for some type-B designs, see [mmu_machine] require_bowden_move setting) +# +gate_homing_endstop: encoder # Name of gate endstop, "encoder" forces use of encoder for parking +gate_homing_max: 70 # Maximum move distance to home to the gate (or actual move distance for encoder parking) +gate_preload_homing_max: 70 # Maximum homing distance to the mmu_gear endstop (if MMU is fitted with one) +gate_unload_buffer: 50 # Amount to reduce the fast unload so that filament doesn't overshoot when parking +gate_load_retries: 2 # Number of times MMU will attempt to grab the filament on initial load (type-A designs) +gate_parking_distance: 13 # Parking position in the gate (distance back from homing point, -ve value means move forward) +gate_endstop_to_encoder: 10 # Distance between gate endstop and encoder (IF both fitted. +ve if encoder after endstop) +gate_autoload: 1 # If pre-gate sensor fitted this controls the automatic loading of the gate +gate_final_eject_distance: 0 # Distance to eject filament on MMU_EJECT (Ignored by MMU_UNLOAD) + + +# Bowden tube loading/unloading ---------------------------------------------------------------------------------------- +# ██████╗ ██████╗ ██╗ ██╗██████╗ ███████╗███╗ ██╗ ██╗ ██████╗ █████╗ ██████╗ +# ██╔══██╗██╔═══██╗██║ ██║██╔══██╗██╔════╝████╗ ██║ ██║ ██╔═══██╗██╔══██╗██╔══██╗ +# ██████╔╝██║ ██║██║ █╗ ██║██║ ██║█████╗ ██╔██╗ ██║ ██║ ██║ ██║███████║██║ ██║ +# ██╔══██╗██║ ██║██║███╗██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██║██╔══██║██║ ██║ +# ██████╔╝╚██████╔╝╚███╔███╔╝██████╔╝███████╗██║ ╚████║ ███████╗╚██████╔╝██║ ██║██████╔╝ +# ╚═════╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ +# +# In addition to different bowden loading speeds for buffer and non-buffered filament it is possible to detect missed +# steps caused by "jerking" on a heavy spool. If bowden correction is enabled the driver with "believe" the encoder +# reading and make correction moves to bring the filament to within the 'bowden_allowable_load_delta' of the end of +# bowden position (this does require a reliable encoder and is not recommended for very high speed loading >350mm/s) +# +bowden_apply_correction: 1 # 1 to enable, 0 disabled. Requires Encoder +bowden_allowable_load_delta: 20.0 # How close in mm the correction moves will attempt to get to target. Requires Encoder + +# This test verifies the filament is free of extruder before the fast bowden movement to reduce possibility of grinding filament +bowden_pre_unload_test: 1 # 1 to check for bowden movement before full pull (slower), 0 don't check (faster). Requires Encoder + +# ADVANCED: If pre-unload test is enabled, this controls the detection of successful bowden pre-unload test and represents +# the fraction of allowable mismatch between actual movement and that seen by encoder. Setting to 50% tolerance usually +# works well. Increasing will make test more tolerant. Value of 100% essentially disables error detection +bowden_pre_unload_error_tolerance: 50 + + +# Extruder homing ----------------------------------------------------------------------------------------------------- +# ███████╗██╗ ██╗████████╗ ██╗ ██╗ ██████╗ ███╗ ███╗██╗███╗ ██╗ ██████╗ +# ██╔════╝╚██╗██╔╝╚══██╔══╝ ██║ ██║██╔═══██╗████╗ ████║██║████╗ ██║██╔════╝ +# █████╗ ╚███╔╝ ██║ ███████║██║ ██║██╔████╔██║██║██╔██╗ ██║██║ ███╗ +# ██╔══╝ ██╔██╗ ██║ ██╔══██║██║ ██║██║╚██╔╝██║██║██║╚██╗██║██║ ██║ +# ███████╗██╔╝ ██╗ ██║██╗ ██║ ██║╚██████╔╝██║ ╚═╝ ██║██║██║ ╚████║╚██████╔╝ +# ╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# Happy Hare needs a reference "homing point" close to the extruder from which to accurately complete the loading of +# the toolhead. This homing operation takes place after the fast bowden load and it is anticipated that that load +# operation will leave the filament just shy of the homing point. If using a toolhead sensor this initial extruder +# homing is unnecessary (but can be forced) because the homing will occur inside the extruder for the optimum in accuracy. +# You still should set this homing method because it is also used for the determination and calibration of bowden length. +# +# In addition to an entry sensor "extruder" it is possible for Happy Hare to "feel" for the extruder gear entry +# by colliding with it. This can be done with encoder based collision detection, the compression of the sync-feedback +# (aka buffer) sensor or using "touch" (stallguard) on the gear stepper. Note that encoder collision detection is not +# completely deterministic and you will have to find the sweetspot for your setup by adjusting the TMC current reduction. +# Note that reduced current during collision detection can also prevent unecessary filament griding. +# +# Possible extruder_homing_endtop names: +# collision - Detect the collision with the extruder gear by monitoring encoder movement (Requires encoder) +# Fast bowden load will move to the extruder gears +# mmu_gear_touch - Use touch detection when the gear stepper hits the extruder (Requires stallguard) +# Fast bowden load will move to extruder_homing_buffer distance before extruder gear, then home +# extruder - If you have a "filament entry" endstop configured (Requires 'extruder' endstop) +# Fast bowden load will move to extruder_homing_buffer distance before sensor, then home +# filament_compression - If you have a "sync-feedback" sensor with compression switch configured +# Fast bowden load will move to extruder_homing_buffer distance before extruder gear, then home +# none - Don't attempt to home. Only possibiliy if lacking all sensor options +# Fast bowden load will move to the extruder gears. Option is fine if using toolhead sensor +# Note: The homing_endstop will be ignored ("none") if a toolhead sensor is available unless "extruder_force_homing: 1" +# +extruder_homing_max: 80 # Maximum distance to advance in order to attempt to home the extruder +extruder_homing_endstop: extruder # Filament homing method/endstop name (fallback if toolhead sensor not available) +extruder_homing_buffer: 25 # Amount to reduce the fast bowden load so filament doesn't overshoot the extruder homing point +extruder_collision_homing_current: 30 # % gear_stepper current (10%-100%) to use when homing to extruder homing (100 to disable) + +# If you have a toolhead sensor it will always be used as a homing point making the homing outside of the extruder +# potentially unnecessary. However you can still force this initial homing step by setting this option in which case +# the filament will home to the extruder and then home to the toolhead sensor in two steps +# +extruder_force_homing: 0 + + +# Toolhead loading and unloading -------------------------------------------------------------------------------------- +# ████████╗ ██████╗ ██████╗ ██╗ ██╗ ██╗███████╗ █████╗ ██████╗ ██╗ ██████╗ █████╗ ██████╗ +# ╚══██╔══╝██╔═══██╗██╔═══██╗██║ ██║ ██║██╔════╝██╔══██╗██╔══██╗ ██║ ██╔═══██╗██╔══██╗██╔══██╗ +# ██║ ██║ ██║██║ ██║██║ ███████║█████╗ ███████║██║ ██║ ██║ ██║ ██║███████║██║ ██║ +# ██║ ██║ ██║██║ ██║██║ ██╔══██║██╔══╝ ██╔══██║██║ ██║ ██║ ██║ ██║██╔══██║██║ ██║ +# ██║ ╚██████╔╝╚██████╔╝███████╗██║ ██║███████╗██║ ██║██████╔╝ ███████╗╚██████╔╝██║ ██║██████╔╝ +# ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ +# +# It is possible to define highly customized loading and unloading sequences, however, unless you have a specialized +# setup it is probably easier to opt for the built-in toolhead loading and unloading sequence which already offers a +# high degree of customization. If you need even more control then edit the _MMU_LOAD_SEQUENCE and _MMU_UNLOAD_SEQUENCE +# macros in mmu_sequence.cfg - but be careful! +# +# An MMU must have a known point at the end of the bowden from which it can precisely load the extruder. Generally this +# will either be the extruder entrance (which is controlled with settings above) or by homing to toolhead sensor. If +# you have toolhead sensor it is past the extruder gear and the driver needs to know the max distance (from end of +# bowden move) to attempt homing +# +toolhead_homing_max: 40 # Maximum distance to advance in order to attempt to home to defined homing endstop + +# IMPORTANT: These next three settings are based on the physical dimensions of your toolhead +# Once a homing position is determined, Happy Hare needs to know the final move distance to the nozzle. There is only +# one correct value for your setup - use 'toolhead_ooze_reduction' (which corresponds to the residual filament left in +# your nozzle) to control excessive oozing on load. See doc for table of proposed values for common configurations. +# +# NOTE: If you have a toolhead sensor you can automate the calculation of these parameters! Read about the +# `MMU_CALIBRATE_TOOLHEAD` command (https://github.com/moggieuk/Happy-Hare/wiki/Blobbing-and-Stringing#---calibrating-toolhead) +# +toolhead_extruder_to_nozzle: 72 # Distance from extruder gears (entrance) to nozzle +toolhead_sensor_to_nozzle: 62 # Distance from toolhead sensor to nozzle (ignored if not fitted) +toolhead_entry_to_extruder: 8 # Distance from extruder "entry" sensor to extruder gears (ignored if not fitted) + +# This setting represents how much residual filament is left behind in the nozzle when filament is removed, it is thus +# used to reduce the extruder loading length and prevent excessive blobbing but also in the calculation of purge volume. +# Note that this value can also be measured with the `MMU_CALIBRATE_TOOLHEAD` procedure +# +toolhead_residual_filament: 0 # Reduction in extruder loading length because of residual filament left behind + +# TUNING: Finally, this is the last resort tuning value to fix blobbing. It is expected that this value is NEAR ZERO as +# it represents a further reduction in extruder load length to fix blobbing. If using a wipetower and you experience blobs +# on it, increase this value (reduce the quantity of filament loaded). If you experience gaps, decrease this value. If gaps +# and already at 0 then perhaps the 'toolhead_extruder_to_nozzle' or 'toolhead_residual_filament' settings are incorrect. +# Similarly a value >+5mm also suggests the four settings above are not correct. Also see 'retract' setting in +# 'mmu_macro_vars.cfg' for final in-print ooze tuning. +# +toolhead_ooze_reduction: 0 # Reduction in extruder loading length to prevent ooze (represents filament remaining) + +# Distance added to the extruder unload movement to ensure filament is free of extruder. This adds some degree of tolerance +# to slightly incorrect configuration or extruder slippage. However don't use as an excuse for incorrect toolhead settings +# +toolhead_unload_safety_margin: 10 # Extra movement safety margin (default: 10mm) + +# If not synchronizing gear and extruder and you experience a "false" clog detection immediately after the tool change +# it might be because of a long bowden and/or large internal diameter that causes slack in the filament. This optional +# move will tighten the filament after a load by % of current clog detection length. Gear stepper will run at 50% current +# +toolhead_post_load_tighten: 60 # % of clog detection length, 0 to disable. Ignored if 'sync_to_extruder: 1' + +# ADVANCED: Controls the detection of successful extruder load/unload movement and represents the fraction of allowable +# mismatch between actual movement and that seen by encoder. Setting to 100% tolerance effectively turns off checking. +# Some designs of extruder have a short move distance that may not be picked up by encoder and cause false errors. This +# allows masking of those errors. However the error often indicates that your extruder load speed is too high or the +# friction is too high on the filament and in that case masking the error is not a good idea. Try reducing friction +# and lowering speed first! +# +toolhead_move_error_tolerance: 60 + + +# Tip forming --------------------------------------------------------------------------------------------------------- +# ████████╗██╗██████╗ ███████╗ ██████╗ ██████╗ ███╗ ███╗██╗███╗ ██╗ ██████╗ +# ╚══██╔══╝██║██╔══██╗ ██╔════╝██╔═══██╗██╔══██╗████╗ ████║██║████╗ ██║██╔════╝ +# ██║ ██║██████╔╝ █████╗ ██║ ██║██████╔╝██╔████╔██║██║██╔██╗ ██║██║ ███╗ +# ██║ ██║██╔═══╝ ██╔══╝ ██║ ██║██╔══██╗██║╚██╔╝██║██║██║╚██╗██║██║ ██║ +# ██║ ██║██║ ██║ ╚██████╔╝██║ ██║██║ ╚═╝ ██║██║██║ ╚████║╚██████╔╝ +# ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# Tip forming responsibility can be split between slicer (in-print) and standalone macro (not in-print) or forced to always +# be done by Happy Hare's standalone macro. Since you always need the option to form tips without the slicer so it is +# generally easier to completely turn off the slicer, force "standalone" tip forming and tune only in Happy Hare. +# +# When Happy Hare is asked to form a tip it will run the referenced macro. Two are reference examples are provided but +# you can implement your own: +# _MMU_FORM_TIP .. default tip forming similar to popular slicers like Superslicer and Prusaslicer +# _MMU_CUT_TIP .. for Filametrix (originally ERCFv2) or similar style toolhead filament cutting system +# +# NOTE: For MMU located cutting like the optional EREC cutter you should set still this to _MMU_FORM_TIP to build a decent +# tip prior to extraction and cutting after the unload. +# +# Often it is useful to increase the extruder current for the rapid movement to ensure high torque and no skipped steps +# +# If opting for slicer tip forming you MUST configure where the slicer leaves the filament in the extruder since +# there is no way to determine this. This can be ignored if all tip forming is performed by Happy Hare +# +force_form_tip_standalone: 1 # 0 = Slicer in print else standalone, 1 = Always standalone tip forming (TURN SLICER OFF!) +form_tip_macro: _MMU_CUT_TIP # Name of macro to call to perform the tip forming (or cutting) operation +extruder_form_tip_current: 100 # % of extruder current (100%-150%) to use when forming tip (100 to disable) +slicer_tip_park_pos: 0 # This specifies the position of filament in extruder after slicer completes tip forming + + +# Purging ------------------------------------------------------------------------------------------------------------- +# ██████╗ ██╗ ██╗██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ +# ██╔══██╗██║ ██║██╔══██╗██╔════╝ ██║████╗ ██║██╔════╝ +# ██████╔╝██║ ██║██████╔╝██║ ███╗██║██╔██╗ ██║██║ ███╗ +# ██╔═══╝ ██║ ██║██╔══██╗██║ ██║██║██║╚██╗██║██║ ██║ +# ██║ ╚██████╔╝██║ ██║╚██████╔╝██║██║ ╚████║╚██████╔╝ +# ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# After a toolchange it is necessary to purge the old filament. Similar to tip forming this can be done by the slicer and/or +# by Happy Hare using an extension like Blobifer. If a purge_macro is defined it will be called when not printing or whenever +# the slicer isn't going to purge (like initial tool load). You can force it to always be called in a print by setting +# force_purge_standalone, but remember to turn off the slicer wipetower +# +# The default is for no (empty) macro so purging will not be done out of a print and thus wipetower. Two options are shipped with +# Happy Hare but you can also build your own custom one: +# _MMU_PURGE .. default purging that just dumps the desired amount of filament (setup correct parking before enabling this!) +# BLOBIFER .. for excellent Blobifer addon (https://github.com/Dendrowen/Blobifier) +# +# Often it is useful to increase the extruder current for the often rapid puring movement to ensure high torque and no skipped steps +# +force_purge_standalone: 0 # 0 = Slicer wipetower in print else standalone, 1 = Always standalone purging (TURN WIPETOWER OFF!) +purge_macro: _MMU_PURGE # Name of macro to call to perform the standalone purging operation. E.g. BLOBIFIER, _MMU_PURGE +extruder_purge_current: 100 # % of extruder current (100%-150%) to use when purging (100 to disable) + + +# Synchronized gear/extruder movement ---------------------------------------------------------------------------------- +# ███╗ ███╗ ██████╗ ████████╗ ██████╗ ██████╗ ███████╗██╗ ██╗███╗ ██╗ ██████╗ +# ████╗ ████║██╔═══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╔════╝╚██╗ ██╔╝████╗ ██║██╔════╝ +# ██╔████╔██║██║ ██║ ██║ ██║ ██║██████╔╝ ███████╗ ╚████╔╝ ██╔██╗ ██║██║ +# ██║╚██╔╝██║██║ ██║ ██║ ██║ ██║██╔══██╗ ╚════██║ ╚██╔╝ ██║╚██╗██║██║ +# ██║ ╚═╝ ██║╚██████╔╝ ██║ ╚██████╔╝██║ ██║ ███████║ ██║ ██║ ╚████║╚██████╗ +# ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ +# +# This controls whether the extruder and gear steppers are synchronized during printing operations +# If you normally run with maxed out gear stepper current consider reducing it with 'sync_gear_current' +# If equipped with TMC drivers the current of the gear and extruder motors can be controlled to optimize performance. +# This can be useful to control gear stepper temperature when printing with synchronized motor +# +sync_to_extruder: 1 # Gear motor is synchronized to extruder during print +sync_gear_current: 70 # % of gear_stepper current (10%-100%) to use when syncing with extruder during print +sync_form_tip: 0 # Synchronize during standalone tip formation (initial part of unload) +sync_purge: 0 # Synchronize during standalone purging (last part of load) + +# Optionally it is possible to leverage feedback for a "compression/expansion" sensor in the bowden path from MMU to +# extruder to ensure that the two motors are kept in sync as viewed by the filament (the signal feedback state can be +# binary supplied by one or two switches: -1 (expanded) and 1 (compressed) of proportional value between -1.0 and 1.0 +# Requires [mmu_sensors] setting +# +sync_feedback_enable: 0 # 0 = Turn off (even with fitted sensor), 1 = Turn on +sync_multiplier_high: 1.05 # Maximum factor to apply to gear stepper 'rotation_distance' +sync_multiplier_low: 0.95 # Minimum factor to apply + + +# ESpooler control ----------------------------------------------------------------------------------------------------- +# ███████╗███████╗██████╗ ██████╗ ██████╗ ██╗ ███████╗██████╗ +# ██╔════╝██╔════╝██╔══██╗██╔═══██╗██╔═══██╗██║ ██╔════╝██╔══██╗ +# █████╗ ███████╗██████╔╝██║ ██║██║ ██║██║ █████╗ ██████╔╝ +# ██╔══╝ ╚════██║██╔═══╝ ██║ ██║██║ ██║██║ ██╔══╝ ██╔══██╗ +# ███████╗███████║██║ ╚██████╔╝╚██████╔╝███████╗███████╗██║ ██║ +# ╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝ +# +# If your MMU has a dc motor (often N20) controlled respooler/assist then how it operates can be controlled with these +# settings. Typically the espooler will be controlled with PWM signal. This will be at the maximum at speeds equal or +# above 'espooler.max_stepper_speed'. The PWM signal will scale downwards towards 0 for slower speeds. The falloff being +# controlled by the 'espooler_speed_exponent' setting according to this formula and allows for non-linear characteristics +# the DC motor (0.5 is a good starting value). +# +# espooler_pwm = (stepper_speed / espooler_max_stepper_speed) ^ {espooler_speed_exponent} +# +# Regardless of h/w configuration you can enable/disable actions with the 'espooler_operations' list. E.g. remove 'play' to +# turn off operation while printing. Options are: +# +# rewind - when filament is being unloaded under MMU control (aka respool) +# assist - when filament is being loaded under MMU control (% of "rewind" speed but with minimum of "print" power) +# print - while printing. Generally set 'espooler_printing_power' to a low percentage just to allow motor to be turned +# freely or set to 0 to enable/allow "burst" assist movements +# +# If using a digitally controlled espooler motor (not PWM) then you should turn off the "print" mode and set +# 'espooler_min_stepper_speed' to prevent "over movement" +# +espooler_min_distance: 200 # Individual stepper movements less than this distance will not active espooler +espooler_max_stepper_speed: 200 # Gear stepper speed at which espooler will be at maximum power +espooler_min_stepper_speed: 0 # Gear stepper speed at which espooler will become inactive (useful for non PWM control) +espooler_speed_exponent: 0.5 # Controls non-linear espooler power relative to stepper speed (see notes) +espooler_assist_reduced_speed: 50 # Control the % of the rewind speed that is applied to assisting load (want rewind to be faster) +espooler_printing_power: 0 # If >0, fixes the % of PWM power while printing. 0=allows burst movement +espooler_operations: rewind, assist, print # List of operational modes (allows disabling even if h/w is configured) +# +# The following burst configuration is used only if 'print' operation is enabled and 'espooler_printing_power: 0' +# +espooler_assist_extruder_move_length: 100 # Distance (mm) extruder needs to move between each assist burst +espooler_assist_burst_power: 100 # The % power of the burst move +espooler_assist_burst_duration: 0.4 # The duration of the burst move is seconds +espooler_assist_burst_trigger: 0 # If trigger assist switch is fitted 0=disable, 1=enable +espooler_assist_burst_trigger_max: 3 # If trigger assist switch is fitted this limits the max number of back-to-back advances + + +# Filament Management Options ---------------------------------------------------------------------------------------- +# ███████╗██╗██╗ ███╗ ███╗ ██████╗ ███╗ ███╗████████╗ +# ██╔════╝██║██║ ████╗ ████║██╔════╝ ████╗ ████║╚══██╔══╝ +# █████╗ ██║██║ ██╔████╔██║██║ ███╗██╔████╔██║ ██║ +# ██╔══╝ ██║██║ ██║╚██╔╝██║██║ ██║██║╚██╔╝██║ ██║ +# ██║ ██║███████╗██╗ ██║ ╚═╝ ██║╚██████╔╝██║ ╚═╝ ██║ ██║ +# ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ +# +# - Clog detection is available when encoder is fitted and it can detect when filament is not moving and pause the print +# - EndlessSpool feature allows detection of runout on one spool and the automatic mapping of tool to an alternative +# gate (spool). Set to '1', this feature requires clog detection or gate sensor or pre-gate sensors. EndlessSpool +# functionality can optionally be extended to attempt to load an empty gate with 'endless_spool_on_load'. On some MMU +# designs (with linear selector) it can also be configured to eject filament remains to a designated gate rather than +# defaulting to current gate. A custom gate will disable pre-gate runout detection for EndlessSpool because filament +# end must completely pass through the gate for selector to move +# +enable_clog_detection: 2 # 0 = disable, 1 = static length clog detection, 2 = automatic length clog detection +enable_endless_spool: 1 # 0 = disable, 1 = enable endless spool +endless_spool_on_load: 0 # 0 = don't apply endless spool on load, 1 = run endless spool if gate is empty +endless_spool_eject_gate: -1 # Which gate to eject the filament remains. -1 = current gate +#endless_spool_groups: # Default EndlessSpool groups (see later in file) +# +# Spoolman support requires you to correctly enable spoolman with moonraker first. If enabled, the gate SpoolId will +# be used to load filament details and color from the spoolman database and Happy Hare will activate/deactivate +# spools as they are used. The enabled variation allows for either the local map or the spoolman map to be the +# source of truth as well as just fetching filament attributes. See this table for explanation: +# +# | Activate/ | Fetch filament attributes | Filament gate | Filament gate | +# spoolman_support | Deactivate | attributes from spoolman | assignment shown | assignment pulled | +# | spool? | based on spool_id? | in spoolman db? | from spoolman db? | +# -----------------+------------+---------------------------+------------------+-------------------+ +# off | no | no | no | no | +# readonly | yes | yes | no | no | +# push | yes | yes | yes | no | +# pull | yes | yes | yes | yes | +# +spoolman_support: off # off = disabled, readonly = enabled, push = local gate map, pull = remote gate map +pending_spool_id_timeout: 20 # Seconds after which this pending spool_id (set with rfid) is voided +# +# Mainsail/Fluid UI can visualize the color of filaments next to the extruder/tool chooser. The color is dynamic and +# can be customized to your choice: +# +# slicer - Color from slicer tool map (what the slicer expects) +# allgates - Color from all the tools in the gate map after running through the TTG map +# gatemap - As per gatemap but hide empty tools +# off - Turns off support +# +# Note: Happy Hare will also add the 'spool_id' variable to the Tx macro if spoolman is enabled +# +t_macro_color: slicer # 'slicer' = default | 'allgates' = mmu | 'gatemap' = mmu without empty gates | 'off' + + +# Print Statistics --------------------------------------------------------------------------------------------------- +# ███████╗████████╗ █████╗ ████████╗███████╗ +# ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝ +# ███████╗ ██║ ███████║ ██║ ███████╗ +# ╚════██║ ██║ ██╔══██║ ██║ ╚════██║ +# ███████║ ██║ ██║ ██║ ██║ ███████║ +# ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ +# +# These parameters determine how print statistic data is shown in the console. This table can show a lot of data, +# probably more than you'd want to see. Below you can enable/disable options to your needs. +# +# +-----------+---------------------+----------------------+----------+ +# | 114(46) | unloading | loading | complete | +# | swaps | pre | - | post | pre | - | post | swap | +# +-----------+------+-------+------+------+-------+-------+----------+ +# | all time | 0:07 | 47:19 | 0:00 | 0:01 | 37:11 | 33:39 | 2:00:38 | +# | - avg | 0:00 | 0:24 | 0:00 | 0:00 | 0:19 | 0:17 | 1:03 | +# | this job | 0:00 | 10:27 | 0:00 | 0:00 | 8:29 | 8:30 | 28:02 | +# | - avg | 0:00 | 0:13 | 0:00 | 0:00 | 0:11 | 0:11 | 0:36 | +# | last | 0:00 | 0:12 | 0:00 | 0:00 | 0:10 | 0:14 | 0:39 | +# +-----------+------+-------+------+------+-------+-------+----------+ +# Note: Only formats correctly on Python3 +# +# Comma separated list of desired columns +# Options: pre_unload, form_tip, unload, post_unload, pre_load, load, purge, post_load, total +console_stat_columns: unload, load, post_load, total + +# Comma separated list of rows. The order determines the order in which they're shown. +# Options: total, total_average, job, job_average, last +console_stat_rows: total, total_average, job, job_average, last + +# How you'd want to see the state of the gates and how they're performing +# string - poor, good, perfect, etc.. +# percentage - rate of success +# emoticon - fun sad to happy faces (python3 only) +console_gate_stat: emoticon + +# Always display the full statistics table +console_always_output_full: 1 # 1 = Show full table, 0 = Only show totals out of print + + +# Miscellaneous, but you should review ------------------------------------------------------------------------------- +# ███╗ ███╗██╗███████╗ ██████╗ +# ████╗ ████║██║██╔════╝██╔════╝ +# ██╔████╔██║██║███████╗██║ +# ██║╚██╔╝██║██║╚════██║██║ +# ██║ ╚═╝ ██║██║███████║╚██████╗ +# ╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ +# +# Important you verify these work for you setup/workflow. Temperature and timeouts +# +timeout_pause: 72000 # Idle time out (printer shuts down) in seconds used when in MMU pause state +disable_heater: 600 # Delay in seconds after which the hotend heater is disabled in the MMU_PAUSE state +default_extruder_temp: 200 # Default temperature for performing swaps and forming tips when not in print (overridden by gate map) +extruder_temp_variance: 2 # When waiting for extruder temperature this is the +/- permissible variance in degrees (>= 1) +# +# These are auto calibration/tuning settings. Once the gear rotation_distance and encoder are calibrated, enabling these options +# will lessen the initial calibration and will automatically tune bowden length and individual gate rotation_distance differences. +# Note: What can be tuned is based on "variable_rotation_distance" and "variable_bowden_lengths" settings in mmu_hardware.cfg +# E.g. with fixed bowden and multiple BMG gears and encoder like the ERCF, the bowden length is tuned on gate#0 and +# rotation_distance (MMU_CALIBRATE_GATE) is tuned for other gates. +# +autotune_bowden_length: 0 # Automated bowden length calibration/tuning. 1=automatic, 0=manual/off +autotune_rotation_distance: 0 # Automated gate calibration/tuning (requires encoder). 1=automatic, 0=manual/off +# +# Other workflow options +# +startup_home_if_unloaded: 0 # 1 = force mmu homing on startup if unloaded, 0 = do nothing +startup_reset_ttg_map: 0 # 1 = reset TTG map on startup, 0 = do nothing +show_error_dialog: 0 # 1 = show pop-up dialog in addition to console message, 0 = show error in console +preload_attempts: 5 # How many "grabbing" attempts are made to pick up the filament with preload feature +strict_filament_recovery: 0 # If enabled with MMU with toolhead sensor, this will cause filament position recovery to + # perform extra moves to look for filament trapped in the space after extruder but before sensor +filament_recovery_on_pause: 1 # 1 = Run a quick check to determine current filament position on pause/error, 0 = disable +retry_tool_change_on_error: 0 # Whether to automatically retry a failed tool change. If enabled Happy Hare will perform + # the equivalent of 'MMU_RECOVER' + 'Tx' commands which usually is all that is necessary + # to recover. Note that enabling this can mask problems with your MMU +bypass_autoload: 1 # If extruder sensor fitted this controls the automatic loading of extruder for bypass operation +has_filament_buffer: 1 # Whether the MMU has a filament buffer. Set to 0 if using Filamentalist or DC eSpooler, etc +# +# Advanced options. Don't mess unless you fully understand. Read documentation. +# +encoder_move_validation: 1 # ADVANCED: 1 = Normally Encoder validates move distances are within given tolerance + # 0 = Validation is disabled (eliminates slight pause between moves but less safe) +print_start_detection: 1 # ADVANCED: Enabled for Happy Hare to automatically detect start and end of print and call + # ADVANCED: MMU_PRINT_START and MMU_PRINT_END automatically. Harmless to leave enabled but can disable + # if you think it is causing problems and known START/END is covered in your macros +extruder: extruder # ADVANCED: Name of the toolhead extruder that MMU is using +gcode_load_sequence: 0 # VERY ADVANCED: Gcode loading sequence 1=enabled, 0=internal logic (default) +gcode_unload_sequence: 0 # VERY ADVANCED: Gcode unloading sequence, 1=enabled, 0=internal logic (default) + + +# ADVANCED: Klipper tuning ------------------------------------------------------------------------------------------- +# ██╗ ██╗██╗ ██╗██████╗ ██████╗ ███████╗██████╗ +# ██║ ██╔╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗ +# █████╔╝ ██║ ██║██████╔╝██████╔╝█████╗ ██████╔╝ +# ██╔═██╗ ██║ ██║██╔═══╝ ██╔═══╝ ██╔══╝ ██╔══██╗ +# ██║ ██╗███████╗██║██║ ██║ ███████╗██║ ██║ +# ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ +# +# Timer too close is a catch all error, however it has been found to occur on some systems during homing and probing +# operations especially so with CANbus connected MCUs. Happy Hare uses many homing moves for reliable extruder loading +# and unloading and enabling this option affords klipper more tolerance and avoids this dreaded error +# +update_trsync: 0 # 1 = Increase TRSYNC_TIMEOUT, 0 = Leave the klipper default +# +# Some CANbus boards are prone to this but it have been seen on regular USB boards where a comms timeout will kill +# the print. Since it seems to occur only on homing moves they can be safely retried to workaround. This has been +# working well in practice +canbus_comms_retries: 3 # Number of retries. Recommend the default of 3. +# +# Older neopixels have very finicky timing and can generate lots of "Unable to obtain 'neopixel_result' response" +# errors in klippy.log. An often cited workaround is to increase BIT_MAX_TIME in neopixel.py. This option does that +# automatically for you to save dirtying klipper +update_bit_max_time: 1 # 1 = Increase BIT_MAX_TIME, 0 = Leave the klipper default + + +# ADVANCED: MMU macro overrides --- ONLY SET IF YOU'RE COMFORTABLE WITH KLIPPER MACROS ------------------------------- +# ███╗ ███╗ █████╗ ██████╗██████╗ ██████╗ ███████╗ +# ████╗ ████║██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔════╝ +# ██╔████╔██║███████║██║ ██████╔╝██║ ██║███████╗ +# ██║╚██╔╝██║██╔══██║██║ ██╔══██╗██║ ██║╚════██║ +# ██║ ╚═╝ ██║██║ ██║╚██████╗██║ ██║╚██████╔╝███████║ +# ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ +# +# 'pause_macro' defines what macro to call on MMU error (must put printer in paused state) +# Other macros are detailed in 'mmu_sequence.cfg' +# Also see form_tip_macro in Tip Forming section and purge_macro in Purging section +# +pause_macro: PAUSE # What macro to call to pause the print +action_changed_macro: _MMU_ACTION_CHANGED # Called when action (printer.mmu.action) changes +print_state_changed_macro: _MMU_PRINT_STATE_CHANGED # Called when print state (printer.mmu.print_state) changes +mmu_event_macro: _MMU_EVENT # Called on useful MMU events +pre_unload_macro: _MMU_PRE_UNLOAD # Called before starting the unload +post_form_tip_macro: _MMU_POST_FORM_TIP # Called immediately after tip forming +post_unload_macro: _MMU_POST_UNLOAD # Called after unload completes +pre_load_macro: _MMU_PRE_LOAD # Called before starting the load +post_load_macro: _MMU_POST_LOAD # Called after the load is complete +unload_sequence_macro: _MMU_UNLOAD_SEQUENCE # VERY ADVANCED: Optionally called based on 'gcode_unload_sequence' +load_sequence_macro: _MMU_LOAD_SEQUENCE # VERY ADVANCED: Optionally called based on 'gcode_load_sequence' + + +# ADVANCED: See documentation for use of these ----------------------------------------------------------------------- +# ██████╗ ███████╗███████╗███████╗████████╗ ██████╗ ███████╗███████╗███████╗ +# ██╔══██╗██╔════╝██╔════╝██╔════╝╚══██╔══╝ ██╔══██╗██╔════╝██╔════╝██╔════╝ +# ██████╔╝█████╗ ███████╗█████╗ ██║ ██║ ██║█████╗ █████╗ ███████╗ +# ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██║ ██║ ██║██╔══╝ ██╔══╝ ╚════██║ +# ██║ ██║███████╗███████║███████╗ ██║ ██████╔╝███████╗██║ ███████║ +# ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚══════╝ +# +# These are the values that the various "RESET" commands will reset too rather than the built-in defaults. The lenght +# of the lists must match the number of gates on your MMU +# +# e.g. MMU_GATE_MAP RESET=1 - will use all the 'gate_XXX' values +# MMU_TTG_MAP RESET=1 - will use the 'tool_to_gate_map' +# MMU_ENDLESS_SPOOL_GROUPS RESET=1 - will use the 'endless_spool_groups' +# +# Gate: #0 #1 #2 #3 #4 #5 #6 #7 #8 +#gate_status: 1, 0, 1, 2, 2, -1, -1, 0, 1 +#gate_filament_name: one, two, three, four, five, six, seven, eight, nine +#gate_material: PLA, ABS, ABS, ABS+, PLA, PLA, PETG, TPU, ABS +#gate_color: red, black, yellow, green, blue, indigo, ffffff, grey, black +#gate_temperature: 210, 240, 235, 245, 210, 200, 215, 240, 240 +#gate_spool_id: 3, 2, 1, 4, 5, 6, 7, -1, 9 +#gate_speed_override: 100, 100, 100, 100, 100, 100, 100, 50, 100 +#endless_spool_groups: 0, 1, 2, 1, 0, 0, 3, 4, 1 +# +# Tool: T0 T1 T2 T3 T4 T5 T6 T7 T8 +#tool_to_gate_map: 0, 1, 2, 3, 4, 5, 6, 7, 8 + + +# ADVANCED/CUSTOM MMU: See documentation for use of these ------------------------------------------------------------ +# ██████╗██╗ ██╗███████╗████████╗ ██████╗ ███╗ ███╗ ███╗ ███╗███╗ ███╗██╗ ██╗ +# ██╔════╝██║ ██║██╔════╝╚══██╔══╝██╔═══██╗████╗ ████║ ████╗ ████║████╗ ████║██║ ██║ +# ██║ ██║ ██║███████╗ ██║ ██║ ██║██╔████╔██║ ██╔████╔██║██╔████╔██║██║ ██║ +# ██║ ██║ ██║╚════██║ ██║ ██║ ██║██║╚██╔╝██║ ██║╚██╔╝██║██║╚██╔╝██║██║ ██║ +# ╚██████╗╚██████╔╝███████║ ██║ ╚██████╔╝██║ ╚═╝ ██║ ██║ ╚═╝ ██║██║ ╚═╝ ██║╚██████╔╝ +# ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ +# +# Normally all these settings are set based on your choice of 'mmu_vendor' and 'mmu_version' in mmu_hardware.cfg, but they +# can be overridden. If you have selected a vendor of "Other" and your MMU has a selector you must set these CAD based +# dimensions else you will get arbitrary defaults. You may also need to set additional attributes in '[mmu_machine]' +# section of mmu_hardware.cfg. +# +#cad_gate0_pos: 4.2 # Approximate distance from endstop to first gate. Used for rough calibration only +#cad_gate_width: 21.0 # Width of each gate +#cad_bypass_offset: 0 # Distance from limit of travel back to the bypass (e.g. ERCF v2.0) +#cad_last_gate_offset: 2.0 # Distance from limit of travel back to last gate +#cad_selector_tolerance: 10.0 # How much extra selector movement to allow for calibration +#cad_gate_directions = [1, 1, 0, 0] # Directions of gear depending on gate (3DChameleon) +#cad_release_gates = [2, 3, 0, 1] # Gate to move to when releasing filament (3DChameleon) + +# SUPPLEMENTAL USER CONFIG retained after upgrade -------------------------------------------------------------------- +# diff --git a/mmu-20250423_131125/base/mmu_purge.cfg b/mmu-20250423_131125/base/mmu_purge.cfg new file mode 120000 index 0000000..e9554a2 --- /dev/null +++ b/mmu-20250423_131125/base/mmu_purge.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_purge.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/base/mmu_sequence.cfg b/mmu-20250423_131125/base/mmu_sequence.cfg new file mode 120000 index 0000000..4e1cdc5 --- /dev/null +++ b/mmu-20250423_131125/base/mmu_sequence.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_sequence.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/base/mmu_software.cfg b/mmu-20250423_131125/base/mmu_software.cfg new file mode 120000 index 0000000..957302e --- /dev/null +++ b/mmu-20250423_131125/base/mmu_software.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_software.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/base/mmu_state.cfg b/mmu-20250423_131125/base/mmu_state.cfg new file mode 120000 index 0000000..be67d3e --- /dev/null +++ b/mmu-20250423_131125/base/mmu_state.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_state.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/mmu_vars.cfg b/mmu-20250423_131125/mmu_vars.cfg new file mode 100644 index 0000000..5998064 --- /dev/null +++ b/mmu-20250423_131125/mmu_vars.cfg @@ -0,0 +1,38 @@ +[Variables] +mmu__revision = 2555 +mmu_calibration_bowden_home = 'encoder' +mmu_calibration_bowden_lengths = [1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1] +mmu_calibration_clog_length = 17.4 +mmu_encoder_resolution = 0.959616 +mmu_gear_rotation_distances = [22.731687, 22.686238, 22.849841, 22.94982, 22.958909, 22.94982, 22.895286, 22.958909] +mmu_selector_bypass = 179.7 +mmu_selector_offsets = [2.1, 25.2, 48.5, 71.7, 94.9, 118.9, 142.1, 164.5] +mmu_servo_angles = {'down': 90, 'up': 10, 'move': 35} +mmu_state_enable_endless_spool = 1 +mmu_state_endless_spool_groups = [0, 1, 2, 3, 4, 5, 6, 7] +mmu_state_filament_pos = 10 +mmu_state_filament_remaining = 0.0 +mmu_state_filament_remaining_color = '' +mmu_state_gate_color = ['', '', '', '', '', '', '', ''] +mmu_state_gate_filament_name = ['', '', '', '', '', '', '', ''] +mmu_state_gate_material = ['', '', '', '', '', '', '', ''] +mmu_state_gate_selected = -2 +mmu_state_gate_speed_override = [100, 100, 100, 100, 100, 100, 100, 100] +mmu_state_gate_spool_id = [-1, -1, -1, -1, -1, -1, -1, -1] +mmu_state_gate_status = [1, 1, -1, -1, -1, 0, -1, -1] +mmu_state_gate_temperature = [200, 200, 200, 200, 200, 200, 200, 200] +mmu_state_last_tool = 1 +mmu_state_tool_selected = -2 +mmu_state_tool_to_gate_map = [0, 1, 2, 3, 4, 5, 6, 7] +mmu_statistics_counters = {'servo_down': {'count': 812, 'limit': 5000, 'warning': 'Inspect servo arm for wear/damage', 'pause': False}, 'mmu_restarts': {'count': 161, 'limit': -1, 'warning': ''}, 'cutter_blade': {'count': 48, 'limit': 3000, 'warning': 'Inspect/replace filament cutting blade', 'pause': False}} +mmu_statistics_gate_0 = {'pauses': 12, 'loads': 28, 'load_distance': 38354.336, 'load_delta': 6896.202, 'unloads': 43, 'unload_distance': 31567.3, 'unload_delta': 1877.741, 'load_failures': 7, 'unload_failures': 16, 'quality': 0.9546537865318246} +mmu_statistics_gate_1 = {'pauses': 2, 'loads': 22, 'load_distance': 28896.615, 'load_delta': 90.861, 'unloads': 25, 'unload_distance': 27502.0, 'unload_delta': 1483.93, 'load_failures': 1, 'unload_failures': 5, 'quality': 0.8375118313601163} +mmu_statistics_gate_2 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_3 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_4 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_5 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_6 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_gate_7 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} +mmu_statistics_swaps = {'pre_unload': 18.72, 'post_unload': 12.62, 'unload': 1789.69, 'pre_load': 13.84, 'post_load': 168.54, 'load': 1191.74, 'total_swaps': 40, 'swaps_since_pause': 3, 'swaps_since_pause_record': 8, 'total': 2629.04, 'total_pauses': 13, 'pause': 1679.71} +nvm_offset = -0.11599999999999978 + diff --git a/mmu-20250423_131125/optional/client_macros.cfg b/mmu-20250423_131125/optional/client_macros.cfg new file mode 120000 index 0000000..292db3e --- /dev/null +++ b/mmu-20250423_131125/optional/client_macros.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/optional/client_macros.cfg \ No newline at end of file diff --git a/mmu-20250423_131125/optional/mmu_menu.cfg b/mmu-20250423_131125/optional/mmu_menu.cfg new file mode 120000 index 0000000..f0c615f --- /dev/null +++ b/mmu-20250423_131125/optional/mmu_menu.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/optional/mmu_menu.cfg \ No newline at end of file diff --git a/mmu/addons/blobifier.cfg b/mmu/addons/blobifier.cfg index e86d62d..af10248 100644 --- a/mmu/addons/blobifier.cfg +++ b/mmu/addons/blobifier.cfg @@ -72,23 +72,23 @@ variable_toolhead_y: 50 # From the nozzle to the front of your t # desireable. You can force a 'safe descend' with this variable. Keep in mind that the # height of the print is an estimation based on previous heights and certain assumptions # so it might be wise to include a safety margin of 0.2mm -variable_force_safe_descend_height_until: 1.0 +variable_force_safe_descend_height_until: 1.0 # Adjust this so that your nozzle scrubs within the brush. Be careful not to go too low! # Start out with a high value (like, 6) and go # down from there. -variable_brush_top: 6 +variable_brush_top: 6 # These parameters define your scrubbing, travel speeds, safe z clearance and how many # times you want to wipe. Update as necessary. -variable_clearance_z: 2 # When traveling, but not cleaning, the +variable_clearance_z: 2 # When traveling, but not cleaning, the # clearance along the z-axis between nozzle # and brush. -variable_wipe_qty: 2 # Number of complete (A complete wipe: left, +variable_wipe_qty: 2 # Number of complete (A complete wipe: left, # right, left OR right, left, right) wipes. -variable_travel_spd_xy: 10000 # Travel (not cleaning) speed along x and +variable_travel_spd_xy: 10000 # Travel (not cleaning) speed along x and # y-axis in mm/min. -variable_travel_spd_z: 1000 # Travel (not cleaning) speed along z axis +variable_travel_spd_z: 1000 # Travel (not cleaning) speed along z axis # in mm/min. variable_wipe_spd_xy: 10000 # Nozzle wipe speed in mm/min. @@ -121,7 +121,7 @@ variable_skew_correction: 0.1 # Start location of the brush. Defaults for 250, 300 and 350mm are provided below. # Uncomment as necessary #variable_brush_start: 34 # For 250mm build -variable_brush_start: 67 # For 300mm build +variable_brush_start: 67 # For 300mm build #variable_brush_start: 84 # for 350mm build # width of the brush @@ -213,7 +213,7 @@ variable_pressure_release_time: 1000 # from 0 .. 1, or -1 if you don't want it changed. #variable_part_cooling_fan: -1 # Leave it unchanged #variable_part_cooling_fan: 0 # Disable the fan -variable_part_cooling_fan: 1 # Run it at full speed +variable_part_cooling_fan: 1 # Run it at full speed # Define the part fan name if you are using a fan other than [fan] # Applies to [fan_generic] or other fan definitons @@ -475,12 +475,8 @@ gcode: G1 E-2 F1800 G1 E2 F800 {% endif %} - {% endfor %} - # Retract to match what Happy Hare is expecting - G1 E-{park_vars.retracted_length} F{sequence_vars.retract_speed * 60} - # ================================================================================== # ==================== DEPOSIT BLOB ================================================ # ================================================================================== @@ -514,6 +510,10 @@ gcode: # ====================================================================================== # ==================== RESTORE STATE =================================================== # ====================================================================================== + + # Retract to match what Happy Hare is expecting + G1 E-{park_vars.retracted_length} F{sequence_vars.retract_speed * 60} + G90 # absolute positioning G1 Z{restore_z} F{travel_spd_z} diff --git a/mmu/base/mmu_macro_vars.cfg b/mmu/base/mmu_macro_vars.cfg index 4dc14b7..5f047c0 100644 --- a/mmu/base/mmu_macro_vars.cfg +++ b/mmu/base/mmu_macro_vars.cfg @@ -171,7 +171,7 @@ gcode: # Leave empty # whether to park for each of those operations both during a print and # standalone (not printing) with Happy Hare or when HH is disabled: # -# enable_park_printing +# enable_park_printing # This is a list of the operations that should result in toolhead parking # while in a print. There are really two main starting points from which # you can customize. If using the slicer to form tips (and toolchange is @@ -180,14 +180,14 @@ gcode: # Leave empty # Typically you would also want to park at least on pause, cancel and # complete if not done elsewhere # -# enabled_park_standalone +# enabled_park_standalone # List of the operations that should result in toolhead parking when not # printing, for example, just manipulating the MMU manually or via # Klipperscreen. Really it is up to you to choose based on personal # workflow preferences but this defaults to just 'pause,cancel' # (i.e. disabled for toolchange) # -# enabled_park_disabled +# enabled_park_disabled # List of the operations that should result in toolhead parking when MMU is # disabled (MMU ENABLE=0) and using Happy Hare client macros. Note that only # pause and cancel can occur in this mode and would typically be enabled @@ -223,6 +223,7 @@ gcode: # Leave empty # - The default parking logic is a straight line move to the 'park_*' position. # To implement fancy movement and control you can specify your own # 'user_park_move_macro' to use instead of default straight line move +# - x,y parking coordinates can be negative if your printer can handle it # # Retraction can be used to optimize stringing and blobs that can occur when # changing tools and are active only during a print. @@ -242,24 +243,24 @@ variable_min_toolchange_z : 1.0 ; The absolute minimum safety floor (z-he # These specify the parking location, z_hop and retraction for all enabled operation # types. Each must be 5 values: # x_coord, y_coord, z_hop(delta), z_hop_ramp, retraction length -# Use -1,-1 for no x,y move (you can just have z_hop). Use 0 for no z_hop +# Use -999,-999 for no x,y move (you can just have z_hop). Use 0 for no z_hop # The z_hop ramp is the horizontal distance in mm to travel during the lift. The # direction is automatic and only applied if lifting the first time from print. # This move is useful to help break the filament "string" -variable_park_toolchange : -1, -1, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract for "toolchange" operations (toolchange,load,unload) -variable_park_runout : -1, -1, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract -variable_park_pause : 50, 50, 5, 0, 2 ; x,y,z-hop,z_hop_ramp,retract (park position when mmu error occurs) -variable_park_cancel : -1, -1, 10, 0, 5 ; x,y,z-hop,z_hop_ramp,retract +variable_park_toolchange : -999, -999, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract for "toolchange" operations (toolchange,load,unload) +variable_park_runout : -999, -999, 1, 5, 2 ; x,y,z-hop,z_hop_ramp,retract +variable_park_pause : 50, 50, 5, 0, 2 ; x,y,z-hop,z_hop_ramp,retract (park position when mmu error occurs) +variable_park_cancel : -999, -999, 10, 0, 5 ; x,y,z-hop,z_hop_ramp,retract variable_park_complete : 50, 50, 10, 0, 5 ; x,y,z-hop,z_hop_ramp,retract # For toolchange operations, this allows to you to specify additional parking moves # at various stages of the toolchange. Each must have 3 values: # x_coord, y_coord, z_hop(delta) -# Use -1,-1,0 for no movement at that stage (no-op). +# Use -999,-999,0 for no movement at that stage (no-op). # All movement will be at the established movement plane (z-height) -variable_pre_unload_position : -1, -1, 0 ; x,y,z-hop position before unloading starts -variable_post_form_tip_position : -1, -1, 0 ; x,y,z-hop position after form/cut tip on unload -variable_pre_load_position : -1, -1, 0 ; x,y,z-hop position before loading starts +variable_pre_unload_position : -999, -999, 0 ; x,y,z-hop position before unloading starts +variable_post_form_tip_position : -999, -999, 0 ; x,y,z-hop position after form/cut tip on unload +variable_pre_load_position : -999, -999, 0 ; x,y,z-hop position before loading starts variable_restore_xy_pos : "last" ; last|next|none - What x,y position the toolhead should travel to after a "toolchange" @@ -275,7 +276,7 @@ variable_unretract_speed : 30 ; Speed of the unretract move in mm/s # YOUR_MOVE_MACRO RESTORE=1 X= Y= F= variable_user_park_move_macro : '' ; Executed instead of default 'G1 X Y move' to park position -variable_auto_home : True ; True = automatically home if necessary, False = disable +variable_auto_home : True ; True = automatically home if necessary, False = disable variable_timelapse : False ; True = take frame snapshot after load, False = disable # Instead of completely defining your your own macros you can can extend functionality @@ -324,9 +325,15 @@ variable_retract_length : 32.5 ; TUNE ME: 5mm less than 'blade_pos' is # may help avoid potential clogging on some hotends variable_simple_tip_forming : False ; True = Perform simple tip forming, False = skip +# Change to X and Y stepper current during the cut operation. Technically any stepper +# current can be modified by adding the stepper name to the list. Be careful not to +# overload your steppers but generally up to 150% is safe +variable_cut_axis_steppers : 'stepper_x, stepper_y' ; Comma separated list of stepper names to increase current for cutting +variable_cut_stepper_current : 100 ; % of stepper current to use for cutting motion (100 to disable) + # This should be the position of the toolhead where the cutter arm just # lightly touches the depressor pin -variable_cutting_axis : "x" ; "x" or "y". Determines cut direction (axis) during cut motion, used for park distance +variable_cutting_axis : "x" ; "x" or "y". Determines cut direction (axis) during cut motion, used for park distance variable_pin_loc_xy : 16.5, 354.5 ; x,y coordinates of depressor pin # This distance is added to "pin_loc_x" or "pin_loc_y" depending on the 'cutting_axis' @@ -338,7 +345,7 @@ variable_pin_park_dist : 5.0 ; Distance in mm # extremes of your printer edges (e.g. it should be a bit larger than 0, or whatever Xmin is) to avoid # banging the toolhead or gantry. Typically x position will match x in pin_loc_xy if cutting in y direction # or y position will match y in pin_loc_xy if cutting in x direction, but diagonal cuts are possible -variable_pin_loc_compressed_xy : 3, 354.5 ; x,y coordinates of fully depressed location (This is 0 actually but skew correction!) +variable_pin_loc_compressed_xy : 3, 354.5 ; x,y coordinates of fully depressed location # Retract length and speed after the cut so that the cutter blade doesn't # get stuck on return to origin position @@ -407,6 +414,7 @@ variable_ramming_volume_standalone : 0 ; Volume in mm^3, 0 = disabled # moves. Temperature will be restored after tip creation is complete variable_toolchange_temp : 0 ; 0 = don't change temp, else temp to set variable_toolchange_fan_assist : False ; Whether to use part cooling fan for quicker temp change +variable_toolchange_fan_name : '' ; Define the part fan name if not default [fan] e.g "fan_generic fan0" variable_toolchange_fan_speed : 50 ; Fan speed % if using fan_assist enabled # Step 2 - Nozzle Separation @@ -454,6 +462,27 @@ variable_parking_distance : 0 ; Position mm to park the filament at end o variable_extruder_eject_speed : 25 ; Speed mm/s used for parking_distance (and final_eject when testing) +# PURGE ------------------------------------------------------------------- +# ██████╗ ██╗ ██╗██████╗ ██████╗ ███████╗ +# ██╔══██╗██║ ██║██╔══██╗██╔════╝ ██╔════╝ +# ██████╔╝██║ ██║██████╔╝██║ ███╗█████╗ +# ██╔═══╝ ██║ ██║██╔══██╗██║ ██║██╔══╝ +# ██║ ╚██████╔╝██║ ██║╚██████╔╝███████╗ +# ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ +# +# Optional reference (bucket) purge. Blobifier if far better but this can be +# used as a basis for custom purge +# (base/mmu_purge.cfg) +# +[gcode_macro _MMU_PURGE_VARS] +description: Happy Hare reference purging macro configuration variables +gcode: # Leave empty + +# Set speed as fast as you can without the extruder skipping steps. Note that +# you can increase the extruder current for purging in mmu_parameters.cfg +variable_extruder_purge_speed : 2 ; Speed in mm/s for purging + + # CLIENT MACROS ----------------------------------------------------------- # ██████╗ █████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███████╗███████╗██╗ ██╗███╗ ███╗███████╗ # ██╔══██╗██╔══██╗██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██║ ██║████╗ ████║██╔════╝ diff --git a/mmu/base/mmu_parameters.cfg b/mmu/base/mmu_parameters.cfg index acbdf55..5c82fef 100644 --- a/mmu/base/mmu_parameters.cfg +++ b/mmu/base/mmu_parameters.cfg @@ -18,7 +18,7 @@ # Full details in https://github.com/moggieuk/Happy-Hare/tree/main/doc/configuration.md # [mmu] -happy_hare_version: 3.1 # Don't mess, used for upgrade detection +happy_hare_version: 3.2 # Don't mess, used for upgrade detection # MMU Hardware Limits -------------------------------------------------------------------------------------------------- # ██╗ ██╗███╗ ███╗██╗████████╗███████╗ @@ -83,6 +83,7 @@ log_file_level: 2 # Can also be set to -1 to disable log file completely log_statistics: 1 # 1 to log statistics on every toolchange (default), 0 to disable (but still recorded) log_visual: 1 # 1 log visual representation of filament, 0 = disable log_startup_status: 1 # Whether to log tool to gate status on startup, 1 = summary (default), 0 = disable +log_m117_messages: 1 # Whether send toolchange message via M117 to screen # Movement speeds ------------------------------------------------------------------------------------------------------ @@ -323,17 +324,45 @@ toolhead_move_error_tolerance: 60 # When Happy Hare is asked to form a tip it will run the referenced macro. Two are reference examples are provided but # you can implement your own: # _MMU_FORM_TIP .. default tip forming similar to popular slicers like Superslicer and Prusaslicer -# _MMU_CUT_TIP .. for Filametrix (ERCFv2) or similar style toolhead filament cutting system +# _MMU_CUT_TIP .. for Filametrix (originally ERCFv2) or similar style toolhead filament cutting system +# +# NOTE: For MMU located cutting like the optional EREC cutter you should set still this to _MMU_FORM_TIP to build a decent +# tip prior to extraction and cutting after the unload. # # Often it is useful to increase the extruder current for the rapid movement to ensure high torque and no skipped steps # # If opting for slicer tip forming you MUST configure where the slicer leaves the filament in the extruder since # there is no way to determine this. This can be ignored if all tip forming is performed by Happy Hare # -force_form_tip_standalone: 1 # 0 = Slicer in print else standalone, 1 = Always standalone tip forming (TURN SLICER OFF!) -form_tip_macro: _MMU_CUT_TIP # Name of macro to call to perform the tip forming (or cutting) operation -extruder_form_tip_current: 100 # % of extruder current (100%-150%) to use when forming tip (100 to disable) -slicer_tip_park_pos: 0 # This specifies the position of filament in extruder after slicer completes tip forming +force_form_tip_standalone: 1 # 0 = Slicer in print else standalone, 1 = Always standalone tip forming (TURN SLICER OFF!) +form_tip_macro: _MMU_CUT_TIP # Name of macro to call to perform the tip forming (or cutting) operation +extruder_form_tip_current: 100 # % of extruder current (100%-150%) to use when forming tip (100 to disable) +slicer_tip_park_pos: 0 # This specifies the position of filament in extruder after slicer completes tip forming + + +# Purging ------------------------------------------------------------------------------------------------------------- +# ██████╗ ██╗ ██╗██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ +# ██╔══██╗██║ ██║██╔══██╗██╔════╝ ██║████╗ ██║██╔════╝ +# ██████╔╝██║ ██║██████╔╝██║ ███╗██║██╔██╗ ██║██║ ███╗ +# ██╔═══╝ ██║ ██║██╔══██╗██║ ██║██║██║╚██╗██║██║ ██║ +# ██║ ╚██████╔╝██║ ██║╚██████╔╝██║██║ ╚████║╚██████╔╝ +# ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ +# +# After a toolchange it is necessary to purge the old filament. Similar to tip forming this can be done by the slicer and/or +# by Happy Hare using an extension like Blobifer. If a purge_macro is defined it will be called when not printing or whenever +# the slicer isn't going to purge (like initial tool load). You can force it to always be called in a print by setting +# force_purge_standalone, but remember to turn off the slicer wipetower +# +# The default is for no (empty) macro so purging will not be done out of a print and thus wipetower. Two options are shipped with +# Happy Hare but you can also build your own custom one: +# _MMU_PURGE .. default purging that just dumps the desired amount of filament (setup correct parking before enabling this!) +# BLOBIFER .. for excellent Blobifer addon (https://github.com/Dendrowen/Blobifier) +# +# Often it is useful to increase the extruder current for the often rapid puring movement to ensure high torque and no skipped steps +# +force_purge_standalone: 0 # 0 = Slicer wipetower in print else standalone, 1 = Always standalone purging (TURN WIPETOWER OFF!) +purge_macro: _MMU_PURGE # Name of macro to call to perform the standalone purging operation. E.g. BLOBIFIER, _MMU_PURGE +extruder_purge_current: 100 # % of extruder current (100%-150%) to use when purging (100 to disable) # Synchronized gear/extruder movement ---------------------------------------------------------------------------------- @@ -352,6 +381,7 @@ slicer_tip_park_pos: 0 # This specifies the position of filament in extruder sync_to_extruder: 1 # Gear motor is synchronized to extruder during print sync_gear_current: 70 # % of gear_stepper current (10%-100%) to use when syncing with extruder during print sync_form_tip: 0 # Synchronize during standalone tip formation (initial part of unload) +sync_purge: 0 # Synchronize during standalone purging (last part of load) # Optionally it is possible to leverage feedback for a "compression/expansion" sensor in the bowden path from MMU to # extruder to ensure that the two motors are kept in sync as viewed by the filament (the signal feedback state can be @@ -363,6 +393,50 @@ sync_multiplier_high: 1.05 # Maximum factor to apply to gear stepper 'rotation_ sync_multiplier_low: 0.95 # Minimum factor to apply +# ESpooler control ----------------------------------------------------------------------------------------------------- +# ███████╗███████╗██████╗ ██████╗ ██████╗ ██╗ ███████╗██████╗ +# ██╔════╝██╔════╝██╔══██╗██╔═══██╗██╔═══██╗██║ ██╔════╝██╔══██╗ +# █████╗ ███████╗██████╔╝██║ ██║██║ ██║██║ █████╗ ██████╔╝ +# ██╔══╝ ╚════██║██╔═══╝ ██║ ██║██║ ██║██║ ██╔══╝ ██╔══██╗ +# ███████╗███████║██║ ╚██████╔╝╚██████╔╝███████╗███████╗██║ ██║ +# ╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝ +# +# If your MMU has a dc motor (often N20) controlled respooler/assist then how it operates can be controlled with these +# settings. Typically the espooler will be controlled with PWM signal. This will be at the maximum at speeds equal or +# above 'espooler.max_stepper_speed'. The PWM signal will scale downwards towards 0 for slower speeds. The falloff being +# controlled by the 'espooler_speed_exponent' setting according to this formula and allows for non-linear characteristics +# the DC motor (0.5 is a good starting value). +# +# espooler_pwm = (stepper_speed / espooler_max_stepper_speed) ^ {espooler_speed_exponent} +# +# Regardless of h/w configuration you can enable/disable actions with the 'espooler_operations' list. E.g. remove 'play' to +# turn off operation while printing. Options are: +# +# rewind - when filament is being unloaded under MMU control (aka respool) +# assist - when filament is being loaded under MMU control (% of "rewind" speed but with minimum of "print" power) +# print - while printing. Generally set 'espooler_printing_power' to a low percentage just to allow motor to be turned +# freely or set to 0 to enable/allow "burst" assist movements +# +# If using a digitally controlled espooler motor (not PWM) then you should turn off the "print" mode and set +# 'espooler_min_stepper_speed' to prevent "over movement" +# +espooler_min_distance: 200 # Individual stepper movements less than this distance will not active espooler +espooler_max_stepper_speed: 200 # Gear stepper speed at which espooler will be at maximum power +espooler_min_stepper_speed: 0 # Gear stepper speed at which espooler will become inactive (useful for non PWM control) +espooler_speed_exponent: 0.5 # Controls non-linear espooler power relative to stepper speed (see notes) +espooler_assist_reduced_speed: 50 # Control the % of the rewind speed that is applied to assisting load (want rewind to be faster) +espooler_printing_power: 0 # If >0, fixes the % of PWM power while printing. 0=allows burst movement +espooler_operations: rewind, assist, print # List of operational modes (allows disabling even if h/w is configured) +# +# The following burst configuration is used only if 'print' operation is enabled and 'espooler_printing_power: 0' +# +espooler_assist_extruder_move_length: 100 # Distance (mm) extruder needs to move between each assist burst +espooler_assist_burst_power: 100 # The % power of the burst move +espooler_assist_burst_duration: 0.4 # The duration of the burst move is seconds +espooler_assist_burst_trigger: 0 # If trigger assist switch is fitted 0=disable, 1=enable +espooler_assist_burst_trigger_max: 3 # If trigger assist switch is fitted this limits the max number of back-to-back advances + + # Filament Management Options ---------------------------------------------------------------------------------------- # ███████╗██╗██╗ ███╗ ███╗ ██████╗ ███╗ ███╗████████╗ # ██╔════╝██║██║ ████╗ ████║██╔════╝ ████╗ ████║╚══██╔══╝ @@ -439,7 +513,7 @@ t_macro_color: slicer # 'slicer' = default | 'allgates' = mmu | 'gatemap' = mm # Note: Only formats correctly on Python3 # # Comma separated list of desired columns -# Options: pre_unload, unload, post_unload, pre_load, load, post_load, total +# Options: pre_unload, form_tip, unload, post_unload, pre_load, load, purge, post_load, total console_stat_columns: unload, load, post_load, total # Comma separated list of rows. The order determines the order in which they're shown. @@ -542,7 +616,7 @@ update_bit_max_time: 1 # 1 = Increase BIT_MAX_TIME, 0 = Leave the klipper defau # # 'pause_macro' defines what macro to call on MMU error (must put printer in paused state) # Other macros are detailed in 'mmu_sequence.cfg' -# Also see form_tip_macro in Tip Forming section +# Also see form_tip_macro in Tip Forming section and purge_macro in Purging section # pause_macro: PAUSE # What macro to call to pause the print action_changed_macro: _MMU_ACTION_CHANGED # Called when action (printer.mmu.action) changes @@ -555,8 +629,6 @@ pre_load_macro: _MMU_PRE_LOAD # Called before starting the load post_load_macro: _MMU_POST_LOAD # Called after the load is complete unload_sequence_macro: _MMU_UNLOAD_SEQUENCE # VERY ADVANCED: Optionally called based on 'gcode_unload_sequence' load_sequence_macro: _MMU_LOAD_SEQUENCE # VERY ADVANCED: Optionally called based on 'gcode_load_sequence' -espooler_start_macro: '' # Called to start eSpooler if fitted (params: GATE, STEP_SPEED, MAX_DISTANCE, HOMING) -espooler_stop_macro: '' # Called to stop eSpooler if fitted (params: GATE, DISTANCE) # ADVANCED: See documentation for use of these ----------------------------------------------------------------------- diff --git a/mmu/base/mmu_purge.cfg b/mmu/base/mmu_purge.cfg new file mode 120000 index 0000000..e9554a2 --- /dev/null +++ b/mmu/base/mmu_purge.cfg @@ -0,0 +1 @@ +/home/pi/Happy-Hare/config/base/mmu_purge.cfg \ No newline at end of file diff --git a/mmu/mmu_vars.cfg b/mmu/mmu_vars.cfg index 3fe29f0..e92ab09 100644 --- a/mmu/mmu_vars.cfg +++ b/mmu/mmu_vars.cfg @@ -1,5 +1,5 @@ [Variables] -mmu__revision = 2547 +mmu__revision = 2590 mmu_calibration_bowden_home = 'encoder' mmu_calibration_bowden_lengths = [1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1] mmu_calibration_clog_length = 17.4 @@ -24,7 +24,7 @@ mmu_state_gate_temperature = [200, 200, 200, 200, 200, 200, 200, 200] mmu_state_last_tool = 1 mmu_state_tool_selected = -2 mmu_state_tool_to_gate_map = [0, 1, 2, 3, 4, 5, 6, 7] -mmu_statistics_counters = {'servo_down': {'count': 812, 'limit': 5000, 'warning': 'Inspect servo arm for wear/damage', 'pause': False}, 'mmu_restarts': {'count': 160, 'limit': -1, 'warning': ''}, 'cutter_blade': {'count': 48, 'limit': 3000, 'warning': 'Inspect/replace filament cutting blade', 'pause': False}} +mmu_statistics_counters = {'servo_down': {'count': 812, 'limit': 5000, 'warning': 'Inspect servo arm for wear/damage', 'pause': False}, 'mmu_restarts': {'count': 165, 'limit': -1, 'warning': ''}, 'cutter_blade': {'count': 48, 'limit': 3000, 'warning': 'Inspect/replace filament cutting blade', 'pause': False}} mmu_statistics_gate_0 = {'pauses': 12, 'loads': 28, 'load_distance': 38354.336, 'load_delta': 6896.202, 'unloads': 43, 'unload_distance': 31567.3, 'unload_delta': 1877.741, 'load_failures': 7, 'unload_failures': 16, 'quality': 0.9546537865318246} mmu_statistics_gate_1 = {'pauses': 2, 'loads': 22, 'load_distance': 28896.615, 'load_delta': 90.861, 'unloads': 25, 'unload_distance': 27502.0, 'unload_delta': 1483.93, 'load_failures': 1, 'unload_failures': 5, 'quality': 0.8375118313601163} mmu_statistics_gate_2 = {'pauses': 0, 'loads': 0, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 0, 'unload_failures': 0, 'quality': -1.0} diff --git a/printer.cfg b/printer.cfg index 5d1f94f..a3e9dd7 100644 --- a/printer.cfg +++ b/printer.cfg @@ -36,7 +36,6 @@ canbus_uuid: 970febd72165 [include stealthburner_leds.cfg] [include bedfans.cfg] [include martyn_macros.cfg] -[include shaketune.cfg] [printer] kinematics: corexy @@ -324,7 +323,7 @@ points: 300,25 speed: 100 -horizontal_move_z: 10 +horizontal_move_z: 2 retries: 5 retry_tolerance: 0.04 max_adjust: 10 @@ -426,7 +425,7 @@ sensor_type: temperature_mcu [bed_mesh] speed: 800 -horizontal_move_z: 3 +horizontal_move_z: 2 mesh_min: 30, 30 mesh_max: 310, 310 zero_reference_position: 175, 175 @@ -448,29 +447,25 @@ shaper_type: 3hump_ei [mcu eddy] canbus_uuid: 01dd4779f312 -[probe_eddy_current btt_eddy] -sensor_type: ldc1612 -z_offset: 2.01 +[probe_eddy_ng btt_eddy] +sensor_type: btt_eddy i2c_mcu: eddy i2c_bus: i2c0f x_offset: 0 y_offset: 21.42 +reg_drive_current: 15 +tap_drive_current: 16 +tap_adjust_z: 0.15 -[temperature_probe btt_eddy] +[temperature_sensor btt_eddy_mcu] +sensor_type: temperature_mcu +sensor_mcu: eddy +min_temp: 10 +max_temp: 100 + +[temperature_sensor btt_eddy] sensor_type: Generic 3950 sensor_pin: eddy:gpio26 -horizontal_move_z: 2 - -[gcode_macro PROBE_EDDY_CURRENT_CALIBRATE_AUTO] -gcode: - BED_MESH_CLEAR - G28 X Y - G90 # Abs positioning - G1 X{ printer.toolhead.axis_maximum.x/2 } Y{ printer.toolhead.axis_maximum.y/2 } F6000 - {% if 'z' not in printer.toolhead.homed_axes %} - SET_KINEMATIC_POSITION Z={ printer.toolhead.axis_maximum.z-1 } # Allows the user to work it down until it touches. - {% endif %} - PROBE_EDDY_CURRENT_CALIBRATE {rawparams} [force_move] enable_force_move: True @@ -481,15 +476,15 @@ enable_force_move: True #*# [bed_mesh default] #*# version = 1 #*# points = -#*# 0.056360, 0.067675, 0.043291, 0.049857, 0.049857, 0.040359, 0.056423, 0.032923, 0.009465 -#*# 0.049821, 0.048075, 0.046974, 0.054641, 0.040398, 0.030274, 0.051682, 0.025871, 0.019834 -#*# 0.027509, 0.056302, 0.037514, 0.015357, 0.049939, 0.033519, 0.033874, 0.005136, -0.009108 -#*# 0.040608, 0.017364, 0.018759, 0.017411, 0.032271, 0.006685, 0.017411, -0.008411, -0.025214 -#*# 0.020039, 0.007966, 0.009584, 0.026020, -0.000823, 0.017287, -0.005193, -0.026172, -0.059551 -#*# 0.023237, 0.007831, 0.036805, 0.009506, 0.009502, -0.028274, 0.000816, -0.012714, -0.043808 -#*# 0.011155, 0.040385, 0.022873, 0.036750, 0.003410, 0.010397, 0.000831, -0.032395, -0.022543 -#*# 0.009978, 0.032564, 0.028053, 0.009943, -0.012340, 0.001206, 0.014305, -0.033977, -0.052455 -#*# -0.000439, -0.002121, 0.002249, 0.014322, -0.014391, -0.003142, -0.027852, -0.045480, -0.072374 +#*# -0.039360, -0.033419, -0.020854, -0.015895, -0.025468, -0.039360, -0.001768, -0.022150, -0.025468 +#*# -0.019553, -0.012942, -0.008350, -0.017542, -0.011298, -0.017542, 0.008655, -0.001136, -0.024164 +#*# -0.031392, -0.039360, -0.003779, 0.004094, 0.005377, -0.006713, -0.011651, -0.012942, -0.022520 +#*# -0.009640, -0.009640, -0.012959, -0.017542, -0.017542, -0.017901, 0.019737, 0.005377, -0.012954 +#*# -0.014234, -0.022150, -0.014949, -0.016248, -0.000476, 0.002100, -0.007055, -0.022150, -0.023447 +#*# -0.016248, -0.009640, 0.002100, 0.019037, -0.005054, 0.011924, 0.030075, -0.011660, -0.017542 +#*# 0.011924, 0.022293, 0.022620, 0.008655, 0.022293, 0.013209, 0.036560, -0.005054, -0.011291 +#*# 0.000809, 0.007368, 0.028798, 0.011924, -0.000476, -0.002473, 0.016478, -0.001768, -0.011302 +#*# 0.011924, 0.013209, 0.004094, 0.005078, -0.026767, 0.014494, 0.010908, -0.022799, -0.031392 #*# x_count = 9 #*# y_count = 9 #*# mesh_x_pps = 9 @@ -506,54 +501,8 @@ enable_force_move: True #*# xz_skew = 0.0004313347372552723 #*# yz_skew = -0.0005939714989857676 #*# -#*# [probe_eddy_current btt_eddy] -#*# reg_drive_current = 15 -#*# calibrate = -#*# 0.050000:3257588.070,0.090000:3256964.916,0.130000:3256304.573, -#*# 0.170000:3255627.762,0.210000:3254987.031,0.250000:3254339.955, -#*# 0.290000:3253702.183,0.330000:3253055.241,0.370000:3252462.920, -#*# 0.410000:3251870.953,0.450000:3251222.715,0.490000:3250619.815, -#*# 0.530000:3250006.877,0.570000:3249441.817,0.610000:3248836.353, -#*# 0.650000:3248246.169,0.690000:3247681.761,0.730000:3247143.636, -#*# 0.770000:3246541.450,0.810000:3246011.719,0.850000:3245477.255, -#*# 0.890000:3244924.790,0.930000:3244401.932,0.970000:3243850.098, -#*# 1.010000:3243383.419,1.050000:3242812.820,1.090000:3242313.228, -#*# 1.130000:3241788.575,1.170000:3241304.196,1.210000:3240811.189, -#*# 1.250000:3240330.713,1.290000:3239850.828,1.330000:3239431.896, -#*# 1.370000:3238915.608,1.410000:3238479.186,1.450000:3238017.048, -#*# 1.490000:3237583.714,1.530000:3237154.934,1.570000:3236718.382, -#*# 1.610000:3236280.224,1.650000:3235872.001,1.690000:3235459.235, -#*# 1.730000:3235049.059,1.770000:3234643.809,1.810000:3234254.456, -#*# 1.850000:3233866.757,1.890000:3233490.216,1.930000:3233109.405, -#*# 1.970000:3232746.999,2.010000:3232379.923,2.050000:3232006.220, -#*# 2.090000:3231658.941,2.130000:3231313.139,2.170000:3230957.177, -#*# 2.210000:3230633.999,2.250000:3230307.913,2.290000:3229966.771, -#*# 2.330000:3229649.263,2.370000:3229335.018,2.410000:3229011.378, -#*# 2.450000:3228712.819,2.490000:3228417.910,2.530000:3228108.281, -#*# 2.570000:3227815.038,2.610000:3227532.720,2.650000:3227249.805, -#*# 2.690000:3226976.764,2.730000:3226686.376,2.770000:3226417.626, -#*# 2.810000:3226166.807,2.850000:3225899.633,2.890000:3225606.227, -#*# 2.930000:3225383.271,2.970000:3225140.767,3.010000:3224884.488, -#*# 3.050000:3224632.580,3.090000:3224375.721,3.130000:3224165.999, -#*# 3.170000:3223942.487,3.210000:3223723.353,3.250000:3223477.094, -#*# 3.290000:3223247.144,3.330000:3223043.429,3.370000:3222823.368, -#*# 3.410000:3222588.610,3.450000:3222381.195,3.490000:3222221.090, -#*# 3.530000:3221989.948,3.570000:3221809.201,3.610000:3221622.117, -#*# 3.650000:3221392.225,3.690000:3221206.721,3.730000:3221051.522, -#*# 3.770000:3220834.386,3.810000:3220690.522,3.850000:3220499.700, -#*# 3.890000:3220307.943,3.930000:3220149.243,3.970000:3219964.886, -#*# 4.010000:3219791.608,4.050000:3219632.208 -#*# -#*# [temperature_probe btt_eddy] -#*# calibration_temp = 39.478475 -#*# drift_calibration = -#*# 3283778.235798, -965.466451, 7.227764 -#*# 3268264.899482, -672.371276, 4.751202 -#*# 3255073.726147, -430.741384, 2.745695 -#*# 3244394.549464, -246.759626, 1.241065 -#*# 3234441.269724, -51.153784, -0.446005 -#*# 3227424.139563, 62.633837, -1.378854 -#*# 3222282.704100, 131.724886, -1.919297 -#*# 3217484.155747, 210.709950, -2.581193 -#*# 3214114.202863, 253.314424, -2.921597 -#*# drift_calibration_min_temp = 39.40781081763649 +#*# [probe_eddy_ng btt_eddy] +#*# calibrated_drive_currents = 15, 16 +#*# calibration_version = 5 +#*# calibration_15 = gASVygMAAAAAAAB9lCiMAXaUSwWMBGZ0b2iUjBtudW1weS5wb2x5bm9taWFsLnBvbHlub21pYWyUjApQb2x5bm9taWFslJOUKYGUfZQojARjb2VmlIwVbnVtcHkuY29yZS5tdWx0aWFycmF5lIwMX3JlY29uc3RydWN0lJOUjAVudW1weZSMB25kYXJyYXmUk5RLAIWUQwFilIeUUpQoSwFLCoWUaAyMBWR0eXBllJOUjAJmOJSJiIeUUpQoSwOMATyUTk5OSv////9K/////0sAdJRiiUNQvHqKZCu7/T+febkVt3v9P7ocU8yZsuI/ssbRaiOC0T81dwr6qm/QPwF9wmPvWtQ/Y4gPa6M9wL9f+cUCv47av9fEcJ0H+L0/BM3sZIFi0D+UdJRijAZkb21haW6UaAtoDksAhZRoEIeUUpQoSwFLAoWUaBiJQxCoh307lqiUPg9H7OOt3pQ+lHSUYowGd2luZG93lGgLaA5LAIWUaBCHlFKUKEsBSwKFlGgYiUMQAAAAAAAA8L8AAAAAAADwP5R0lGKMB19zeW1ib2yUjAF4lIwGc3ltYm9slGgsdWKMCWZ0b2hfaGlnaJRoBSmBlH2UKGgIaAtoDksAhZRoEIeUUpQoSwFLCoWUaBiJQ1APbwKF0vIaQGi3jsUCowlA1wa5xxsPAEAEqZDnrm4KQHrjtLCNEuK/l/TJYQhaIsC9ZIaAnN4BQNffLAxX6y1AbOURhYiy4b8afwUwUgYcwJR0lGJoHWgLaA5LAIWUaBCHlFKUKEsBSwKFlGgYiUMQqAE8SkjclD6f20GCzu2UPpR0lGJoJGgLaA5LAIWUaBCHlFKUKEsBSwKFlGgYiUMQAAAAAAAA8L8AAAAAAADwP5R0lGJoK2gsaC1oLHVijARodG9mlGgFKYGUfZQoaAhoC2gOSwCFlGgQh5RSlChLAUsKhZRoGIlDUBmW/+hMzpQ+j4JkdDZ9GD7/3Q/6vk0FvrTROV5bHvE9yeG9ys8pob0iYepLED34vfeRmluH9Mc9ZaKoXpnRAD66n9rLZxDEvTEzWnIkQ/C9lHSUYmgdaAtoDksAhZRoEIeUUpQoSwFLAoWUaBiJQxBgP/pPyZXaP7ZhhSmG8xNAlHSUYmgkaAtoDksAhZRoEIeUUpQoSwFLAoWUaBiJQxAAAAAAAADwvwAAAAAAAPA/lHSUYmgraCxoLWgsdWKMB2hfcmFuZ2WUXZQoRz/alclP+j9gR0AuAAAAAAAAZYwHZl9yYW5nZZRdlChHQUh2t8sfsABHQUjIsA5BEABljAJkY5RLD3Uu +#*# calibration_16 = gASVygMAAAAAAAB9lCiMAXaUSwWMBGZ0b2iUjBtudW1weS5wb2x5bm9taWFsLnBvbHlub21pYWyUjApQb2x5bm9taWFslJOUKYGUfZQojARjb2VmlIwVbnVtcHkuY29yZS5tdWx0aWFycmF5lIwMX3JlY29uc3RydWN0lJOUjAVudW1weZSMB25kYXJyYXmUk5RLAIWUQwFilIeUUpQoSwFLCoWUaAyMBWR0eXBllJOUjAJmOJSJiIeUUpQoSwOMATyUTk5OSv////9K/////0sAdJRiiUNQvQ+iKHtX9j9FC0GbIff9P7KRZUNM0uc/d9X8F2iZ3z+B4aGnjd/OP+VqOESewdC/3CZkG9Nrtz931Ctg/C7nP0fOSBWvg6I/Zcy38hqV1L+UdJRijAZkb21haW6UaAtoDksAhZRoEIeUUpQoSwFLAoWUaBiJQxAs7DbYKaSUPuGbBN9L+JQ+lHSUYowGd2luZG93lGgLaA5LAIWUaBCHlFKUKEsBSwKFlGgYiUMQAAAAAAAA8L8AAAAAAADwP5R0lGKMB19zeW1ib2yUjAF4lIwGc3ltYm9slGgsdWKMCWZ0b2hfaGlnaJRoBSmBlH2UKGgIaAtoDksAhZRoEIeUUpQoSwFLCoWUaBiJQ1DuZlsaPuEaQEr4VjM8hApA31q9v4Y++j+TcGjpW+DlP7YzB+vwOvI/mVLwCn09AEABFzo32rfdv6pdhsPDm/+/zu7dAFJj6z/9p5ZPElL1P5R0lGJoHWgLaA5LAIWUaBCHlFKUKEsBSwKFlGgYiUMQmFyS/EH1lD5r8jWPtwiVPpR0lGJoJGgLaA5LAIWUaBCHlFKUKEsBSwKFlGgYiUMQAAAAAAAA8L8AAAAAAADwP5R0lGJoK2gsaC1oLHVijARodG9mlGgFKYGUfZQoaAhoC2gOSwCFlGgQh5RSlChLAUsKhZRoGIlDULllnYPu4ZQ+9HmUPoaMIT4GVEBP9nUSvlIUxJp9Xfo90ZX69fBB1L0rfjP8ViTTPePuwVky8869mjYMnvB50L2CXH80/MXOPUwPhoZEVJw9lHSUYmgdaAtoDksAhZRoEIeUUpQoSwFLAoWUaBiJQxAAPbIJDBFDP7bIo+Mn+RNAlHSUYmgkaAtoDksAhZRoEIeUUpQoSwFLAoWUaBiJQxAAAAAAAADwvwAAAAAAAPA/lHSUYmgraCxoLWgsdWKMB2hfcmFuZ2WUXZQoRz9DEQwJsj0AR0At/+lj18HmZYwHZl9yYW5nZZRdlChHQUhXa3Q4AABHQUjN/7ZOYABljAJkY5RLEHUu