Compare commits
	
		
			No commits in common. "main" and "eddy-ng" have entirely different histories.
		
	
	
		
	
		
					 25 changed files with 46 additions and 3032 deletions
				
			
		|  | @ -81,7 +81,7 @@ kick_start_time: 0.5 | ||||||
| heater: extruder | heater: extruder | ||||||
| heater_temp: 50.0 | heater_temp: 50.0 | ||||||
| ##  If you are experiencing back flow, you can reduce fan_speed | ##  If you are experiencing back flow, you can reduce fan_speed | ||||||
| fan_speed: 0.6 | #fan_speed: 1.0 | ||||||
| 
 | 
 | ||||||
| [neopixel sb_leds] | [neopixel sb_leds] | ||||||
| pin: ebb36:PD3 | pin: ebb36:PD3 | ||||||
|  |  | ||||||
|  | @ -10,58 +10,41 @@ gcode: | ||||||
|       {% set CHAMBER_TEMP_MATERIAL = 25 %} |       {% set CHAMBER_TEMP_MATERIAL = 25 %} | ||||||
|     {% endif %} |     {% endif %} | ||||||
|     {% set CHAMBER_TEMP = params.CHAMBER|default(CHAMBER_TEMP_MATERIAL)|float %} |     {% set CHAMBER_TEMP = params.CHAMBER|default(CHAMBER_TEMP_MATERIAL)|float %} | ||||||
|     {% set CLEAN_TEMP = params.CLEAN|default(150)|float %} |     {% set CLEAN_TEMP = params.CLEAN|default(170)|float %} | ||||||
|     G90 ; ensure absolute positioning |     G90 ; ensure absolute positioning | ||||||
|     M117 Homing |     M117 Homing | ||||||
|     STATUS_HOMING |     STATUS_HOMING | ||||||
|     G92 E0 ; Reset Extruder |     G92 E0 ; Reset Extruder | ||||||
|     BED_MESH_CLEAR |     BED_MESH_CLEAR | ||||||
|     RESPOND PREFIX=DEBUG: MSG="G28" |  | ||||||
|     G28 ; Home all axes |     G28 ; Home all axes | ||||||
|     ;QUAD_GANTRY_LEVEL |     ;QUAD_GANTRY_LEVEL | ||||||
|     STATUS_HEATING |     STATUS_HEATING | ||||||
|     ;TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={STANDBY_TEMP} ; Start heating up the nozzle most of the way |     ;TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={STANDBY_TEMP} ; Start heating up the nozzle most of the way | ||||||
|     {% if "ABS" == MATERIAL_TYPE %} |     {% if "ABS" == MATERIAL_TYPE %} | ||||||
|     RESPOND PREFIX=DEBUG: MSG="ABS, Preheating bed for heat-soak" |  | ||||||
|     M117 Bed to 100{"\xf8"}C... |     M117 Bed to 100{"\xf8"}C... | ||||||
|     M190 S100 |     M190 S100 | ||||||
|     {% endif %} |     {% endif %} | ||||||
|     M117 Chamber to {CHAMBER_TEMP}C... |     M117 Chamber to {CHAMBER_TEMP}{"\xf8"}C... | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Wait for chamber to {CHAMBER_TEMP}C" |  | ||||||
|     TEMPERATURE_WAIT SENSOR="temperature_sensor chamber_temp" MINIMUM={CHAMBER_TEMP} ; Wait for chamber temp |     TEMPERATURE_WAIT SENSOR="temperature_sensor chamber_temp" MINIMUM={CHAMBER_TEMP} ; Wait for chamber temp | ||||||
|     M117 Bed to {BED_TEMP}C... |     M117 Bed to {BED_TEMP}C... | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Set Bed to {BED_TEMP}C" |  | ||||||
|     M140 S{BED_TEMP} ; Set the bed temp to the original request (might be lower than preheat) |     M140 S{BED_TEMP} ; Set the bed temp to the original request (might be lower than preheat) | ||||||
|     M117 Gantry Level |     M117 Gantry Level | ||||||
|     RESPOND PREFIX=DEBUG: MSG="QGL" |  | ||||||
|     QUAD_GANTRY_LEVEL |     QUAD_GANTRY_LEVEL | ||||||
|  |     M117 Cleaning nozzle | ||||||
|  |     M109 S{CLEAN_TEMP} | ||||||
|  |     CLEAN_NOZZLE | ||||||
|  |     M117 Eddy Tap | ||||||
|  |     G1 X175 Y175 Z2 | ||||||
|  |     PROBE_EDDY_NG_TAP | ||||||
|     M117 Bed mesh eddy scan |     M117 Bed mesh eddy scan | ||||||
|     STATUS_MESHING |     STATUS_MESHING | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Homing Z" |  | ||||||
|     G28 Z |  | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Mesh scan" |  | ||||||
|     BED_MESH_CALIBRATE ;Well, this is fine and dandy... |     BED_MESH_CALIBRATE ;Well, this is fine and dandy... | ||||||
|     M117 Cleaning nozzle |  | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Preheating nozzle to clean (non-ooze) temp S{CLEAN_TEMP}C" |  | ||||||
|     M109 S{CLEAN_TEMP} |  | ||||||
|     RESPOND PREFIX=DEBUG: MSG="CLEAN_NOZZLE macro" |  | ||||||
|     CLEAN_NOZZLE |  | ||||||
|     M117 Carto Touch |  | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Homing Z" |  | ||||||
|     G28 Z |  | ||||||
|     RESPOND PREFIX=DEBUG: MSG="CARTOGRAPHER_TOUCH macro" |  | ||||||
|     CARTOGRAPHER_TOUCH |  | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Lifting Z a little more" |  | ||||||
|     G1 Z10 ; carto leaves it at Z=5 which is theoretically okay, but cleaning then might skip steps and cause problems. |  | ||||||
|     M117 Final heat {EXTRUDER_TEMP}/{BED_TEMP} |     M117 Final heat {EXTRUDER_TEMP}/{BED_TEMP} | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Final heat {EXTRUDER_TEMP}/{BED_TEMP}" |  | ||||||
|     STATUS_HEATING |     STATUS_HEATING | ||||||
|     M190 S{BED_TEMP} ; Start heating the bed, wait until target temperature reached |     M190 S{BED_TEMP} ; Start heating the bed, wait until target temperature reached | ||||||
|     M109 S{EXTRUDER_TEMP} ; Finish heating the nozzle |     M109 S{EXTRUDER_TEMP} ; Finish heating the nozzle | ||||||
|     M117 Clean and prime |     M117 Clean and prime | ||||||
|     RESPOND PREFIX=DEBUG: MSG="CLEAN_NOZZLE macro (wipe ooze before prime line)" |  | ||||||
|     CLEAN_NOZZLE |     CLEAN_NOZZLE | ||||||
|     RESPOND PREFIX=DEBUG: MSG="PRIME LINE" |  | ||||||
|     G1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed |     G1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed | ||||||
|     G1 X0.1 Y20 Z0.3 F5000.0 ; Move to start position |     G1 X0.1 Y20 Z0.3 F5000.0 ; Move to start position | ||||||
|     G1 X0.1 Y200.0 Z0.3 F1500.0 E15 ; Draw the first line |     G1 X0.1 Y200.0 Z0.3 F1500.0 E15 ; Draw the first line | ||||||
|  | @ -70,13 +53,9 @@ gcode: | ||||||
|     G92 E0 ; Reset Extruder |     G92 E0 ; Reset Extruder | ||||||
|     G1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed |     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 X5 Y20 Z0.3 F5000.0 ; Move over to prevent blob squish | ||||||
|     RESPOND PREFIX=DEBUG: MSG="CLEAN_NOZZLE macro (wipe any retraction debris picked up during prime line)" |  | ||||||
|     CLEAN_NOZZLE |  | ||||||
|     RESPOND PREFIX=DEBUG: MSG="SKEW_PROFILE LOAD=calilantern_skew_profile" |  | ||||||
|     SKEW_PROFILE LOAD=calilantern_skew_profile |     SKEW_PROFILE LOAD=calilantern_skew_profile | ||||||
|     M117 Print started |     M117 Print started | ||||||
|     STATUS_PRINTING |     STATUS_PRINTING | ||||||
|     RESPOND PREFIX=DEBUG: MSG="Handing to slicer GCODE" |  | ||||||
| 
 | 
 | ||||||
| #   Use PRINT_END for the slicer ending script - please customise for your slicer of choice | #   Use PRINT_END for the slicer ending script - please customise for your slicer of choice | ||||||
| [gcode_macro PRINT_END] | [gcode_macro PRINT_END] | ||||||
|  | @ -89,6 +68,7 @@ gcode: | ||||||
|     {% set z_safe = [th.position.z + 2, th.axis_maximum.z]|min %} |     {% set z_safe = [th.position.z + 2, th.axis_maximum.z]|min %} | ||||||
|     SET_SKEW CLEAR=1 |     SET_SKEW CLEAR=1 | ||||||
|     BED_MESH_CLEAR |     BED_MESH_CLEAR | ||||||
|  |     PROBE_EDDY_NG_SET_TAP_OFFSET VALUE=0 | ||||||
| 
 | 
 | ||||||
|     SAVE_GCODE_STATE NAME=STATE_PRINT_END |     SAVE_GCODE_STATE NAME=STATE_PRINT_END | ||||||
|      |      | ||||||
|  | @ -115,32 +95,15 @@ gcode: | ||||||
|     G92 E0 ; Reset Extruder |     G92 E0 ; Reset Extruder | ||||||
|     BED_MESH_CLEAR |     BED_MESH_CLEAR | ||||||
|     G28 ; Home all axes |     G28 ; Home all axes | ||||||
|  |     M117 Eddy Tap | ||||||
|  |     G1 X175 Y175 Z2 | ||||||
|  |     PROBE_EDDY_NG_TAP | ||||||
|     M117 Bed mesh eddy scan |     M117 Bed mesh eddy scan | ||||||
|     STATUS_MESHING |     STATUS_MESHING | ||||||
|     M117 Carto touch |  | ||||||
|     G28 Z |  | ||||||
|     CARTOGRAPHER_TOUCH |  | ||||||
|     BED_MESH_CALIBRATE |     BED_MESH_CALIBRATE | ||||||
|     SKEW_PROFILE LOAD=calilantern_skew_profile |     SKEW_PROFILE LOAD=calilantern_skew_profile | ||||||
|     M117 Ready.  Printing coordinates in place. |     M117 Ready.  Printing coordinates in place. | ||||||
| 
 | 
 | ||||||
| [gcode_macro OOPS_QUAD_LEVEL] |  | ||||||
| description: gantry is so unlevel that 2mm is probably not good enough. |  | ||||||
| gcode: |  | ||||||
|     QUAD_GANTRY_LEVEL horizontal_move_z=10 |  | ||||||
| 
 |  | ||||||
| [gcode_macro MARTYN_CUT_TIP] |  | ||||||
| description: Clears mesh and skew, cuts tip, then restores them.  The mesh may be unnecessary but we can, so why not :-) |  | ||||||
| gcode: |  | ||||||
|     SAVE_GCODE_STATE NAME=STATE_PRINT_END |  | ||||||
|     BED_MESH_PROFILE SAVE=CUT_TIP_STATE |  | ||||||
|     BED_MESH_CLEAR |  | ||||||
|     SET_SKEW CLEAR=1 |  | ||||||
|     _MMU_CUT_TIP |  | ||||||
|     BED_MESH_PROFILE LOAD=CUT_TIP_STATE |  | ||||||
|     SKEW_PROFILE LOAD=calilantern_skew_profile |  | ||||||
|     RESTORE_GCODE_STATE NAME=STATE_PRINT_END |  | ||||||
| 
 |  | ||||||
| [gcode_macro CANCEL_PRINT] | [gcode_macro CANCEL_PRINT] | ||||||
| description: Cancel the actual running print | description: Cancel the actual running print | ||||||
| rename_existing: CANCEL_PRINT_BASE | rename_existing: CANCEL_PRINT_BASE | ||||||
|  | @ -196,22 +159,19 @@ gcode: | ||||||
|   SET_PIN PIN=caselight VALUE={S} |   SET_PIN PIN=caselight VALUE={S} | ||||||
| 
 | 
 | ||||||
| [gcode_macro CLEAN_NOZZLE] | [gcode_macro CLEAN_NOZZLE] | ||||||
| variable_start_x: 124 | variable_start_x: 101 | ||||||
| variable_start_y: 354 | variable_start_y: 354 | ||||||
| variable_start_z: -0.6 | variable_start_z: 5 | ||||||
| variable_wipe_dist: -40 | variable_wipe_dist: -40 | ||||||
| variable_wipe_qty: 5 | variable_wipe_qty: 5 | ||||||
| variable_wipe_spd: 200 | variable_wipe_spd: 200 | ||||||
| variable_raise_distance: 10 | variable_raise_distance: 5 | ||||||
| 
 | 
 | ||||||
| gcode: | gcode: | ||||||
|  {% if "xyz" not in printer.toolhead.homed_axes %} |  {% if "xyz" not in printer.toolhead.homed_axes %} | ||||||
|    G28 |    G28 | ||||||
|  {% endif %} |  {% endif %} | ||||||
|   |   | ||||||
|  G91 ; relative |  | ||||||
|  G1 Z10 ; just in case! |  | ||||||
| 
 |  | ||||||
|  G90                                            ; absolute positioning |  G90                                            ; absolute positioning | ||||||
|  ## Move nozzle to start position |  ## Move nozzle to start position | ||||||
|  G1 X{start_x} Y{start_y} F6000 |  G1 X{start_x} Y{start_y} F6000 | ||||||
|  |  | ||||||
|  | @ -1,924 +0,0 @@ | ||||||
| # 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}" |  | ||||||
|  | @ -1,28 +0,0 @@ | ||||||
| 
 |  | ||||||
| ########################################################################################## |  | ||||||
| # 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 |  | ||||||
|  | @ -1,31 +0,0 @@ | ||||||
| # 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} |  | ||||||
|  | @ -1,21 +0,0 @@ | ||||||
| 
 |  | ||||||
| ########################################################################################## |  | ||||||
| # 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 |  | ||||||
|  | @ -1,91 +0,0 @@ | ||||||
| # 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 |  | ||||||
| 
 |  | ||||||
|  | @ -1,10 +0,0 @@ | ||||||
| 
 |  | ||||||
| ########################################################################################## |  | ||||||
| # 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 |  | ||||||
| 
 |  | ||||||
|  | @ -1,154 +0,0 @@ | ||||||
| ######################################################################################################################## |  | ||||||
| # 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 |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/base/mmu_cut_tip.cfg |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/base/mmu_form_tip.cfg |  | ||||||
|  | @ -1,368 +0,0 @@ | ||||||
| ######################################################################################################################## |  | ||||||
| # 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 |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/base/mmu_leds.cfg |  | ||||||
|  | @ -1,536 +0,0 @@ | ||||||
| ######################################################################################################################## |  | ||||||
| # 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=<x_coord> Y=<y_coord> F=<speed> |  | ||||||
| # 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=<x_coord> Y=<y_coord> F=<speed> |  | ||||||
| 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 |  | ||||||
| # NOTE: this is with skew correction ON |  | ||||||
| variable_cutting_axis           : "x"		; "x" or "y". Determines cut direction (axis) during cut motion, used for park distance |  | ||||||
| variable_pin_loc_xy             : 19.54, 353	; 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.54, 353	; 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 |  | ||||||
| 
 |  | ||||||
|  | @ -1,685 +0,0 @@ | ||||||
| ######################################################################################################################## |  | ||||||
| # 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 -------------------------------------------------------------------- |  | ||||||
| # |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/base/mmu_purge.cfg |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/base/mmu_sequence.cfg |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/base/mmu_software.cfg |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/base/mmu_state.cfg |  | ||||||
|  | @ -1,38 +0,0 @@ | ||||||
| [Variables] |  | ||||||
| mmu__revision = 3771 |  | ||||||
| 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 = 8.9 |  | ||||||
| mmu_encoder_resolution = 0.968523 |  | ||||||
| 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 = [6.1, 26.9, 50.9, 74.1, 97.3, 121.3, 144.5, 167.7] |  | ||||||
| mmu_servo_angles = {'down': 90, 'up': 10, 'move': 35} |  | ||||||
| mmu_state_enable_endless_spool = 1 |  | ||||||
| mmu_state_endless_spool_groups = [0, 1, 0, 2, 3, 4, 5, 6] |  | ||||||
| mmu_state_filament_pos = 0 |  | ||||||
| mmu_state_filament_remaining = 0 |  | ||||||
| mmu_state_filament_remaining_color = '' |  | ||||||
| mmu_state_gate_color = ['', '', '', '', '', '', '', ''] |  | ||||||
| mmu_state_gate_filament_name = ['', '', '', '', '', '', '', ''] |  | ||||||
| mmu_state_gate_material = ['', '', '', '', '', '', '', ''] |  | ||||||
| mmu_state_gate_selected = 1 |  | ||||||
| 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, 2, -1, -1, -1, -1, -1] |  | ||||||
| mmu_state_gate_temperature = [200, 200, 200, 200, 200, 200, 200, 200] |  | ||||||
| mmu_state_last_tool = 0 |  | ||||||
| mmu_state_tool_selected = 0 |  | ||||||
| mmu_state_tool_to_gate_map = [1, 1, 1, 1, 1, 1, 1, 1] |  | ||||||
| mmu_statistics_counters = {'servo_down': {'count': 1133, 'limit': 5000, 'warning': 'Inspect servo arm for wear/damage', 'pause': False}, 'mmu_restarts': {'count': 256, 'limit': -1, 'warning': ''}, 'cutter_blade': {'count': 67, 'limit': 3000, 'warning': 'Inspect/replace filament cutting blade', 'pause': False}} |  | ||||||
| mmu_statistics_gate_0 = {'pauses': 0, 'loads': 2, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 2, 'unload_failures': 0, 'quality': -1.0} |  | ||||||
| mmu_statistics_gate_1 = {'pauses': 7, 'loads': 16, 'load_distance': 20400.457, 'load_delta': 7020.311, 'unloads': 16, 'unload_distance': 9610.7, 'unload_delta': 534.671, 'load_failures': 8, 'unload_failures': 5, 'quality': 0.4424617663045427} |  | ||||||
| mmu_statistics_gate_2 = {'pauses': 1, 'loads': 14, 'load_distance': 19284.879, 'load_delta': 4486.816, 'unloads': 15, 'unload_distance': 13736.0, 'unload_delta': 411.062, 'load_failures': 6, 'unload_failures': 2, 'quality': 0.5699077987480133} |  | ||||||
| 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_load': 9.64, 'load': 1067.77, 'total': 1120.72, 'pre_unload': 9.38, 'post_unload': 7.24, 'unload': 710.67, 'purge': 44.02, 'post_load': 92.64, 'total_swaps': 12, 'swaps_since_pause': 2, 'swaps_since_pause_record': 3, 'form_tip': 144.15, 'total_pauses': 8, 'pause': 1367.03} |  | ||||||
| nvm_offset = -0.11599999999999978 |  | ||||||
| 
 |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/optional/client_macros.cfg |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| /home/pi/Happy-Hare/config/optional/mmu_menu.cfg |  | ||||||
|  | @ -335,7 +335,7 @@ variable_cut_stepper_current    : 100				; % of stepper current to use for cutti | ||||||
| # lightly touches the depressor pin | # lightly touches the depressor pin | ||||||
| # NOTE: this is with skew correction ON | # NOTE: this is with skew correction ON | ||||||
| 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             : 14, 351	; x,y coordinates of depressor pin | variable_pin_loc_xy             : 19.54, 353	; x,y coordinates of depressor pin | ||||||
| 
 | 
 | ||||||
| # This distance is added to "pin_loc_x" or "pin_loc_y" depending on the 'cutting_axis' | # 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 | # to determine the starting position and to create a small safety distance that aids | ||||||
|  | @ -346,7 +346,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 | # 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 | # 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 | # 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  : 6, 351	; x,y coordinates of fully depressed location | variable_pin_loc_compressed_xy  : 3.54, 353	; x,y coordinates of fully depressed location | ||||||
| 
 | 
 | ||||||
| # Retract length and speed after the cut so that the cutter blade doesn't | # Retract length and speed after the cut so that the cutter blade doesn't | ||||||
| # get stuck on return to origin position | # get stuck on return to origin position | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| [Variables] | [Variables] | ||||||
| mmu__revision = 4243 | mmu__revision = 3731 | ||||||
| mmu_calibration_bowden_home = 'encoder' | 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_bowden_lengths = [1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1, 1425.1] | ||||||
| mmu_calibration_clog_length = 8.9 | mmu_calibration_clog_length = 8.9 | ||||||
|  | @ -9,9 +9,9 @@ mmu_selector_bypass = 179.7 | ||||||
| mmu_selector_offsets = [6.1, 26.9, 50.9, 74.1, 97.3, 121.3, 144.5, 167.7] | mmu_selector_offsets = [6.1, 26.9, 50.9, 74.1, 97.3, 121.3, 144.5, 167.7] | ||||||
| mmu_servo_angles = {'down': 90, 'up': 10, 'move': 35} | mmu_servo_angles = {'down': 90, 'up': 10, 'move': 35} | ||||||
| mmu_state_enable_endless_spool = 1 | mmu_state_enable_endless_spool = 1 | ||||||
| mmu_state_endless_spool_groups = [0, 1, 2, 3, 4, 5, 6, 7] | mmu_state_endless_spool_groups = [0, 1, 0, 2, 3, 4, 5, 6] | ||||||
| mmu_state_filament_pos = 10 | mmu_state_filament_pos = 0 | ||||||
| mmu_state_filament_remaining = 10.0 | mmu_state_filament_remaining = 0 | ||||||
| mmu_state_filament_remaining_color = '' | mmu_state_filament_remaining_color = '' | ||||||
| mmu_state_gate_color = ['', '', '', '', '', '', '', ''] | mmu_state_gate_color = ['', '', '', '', '', '', '', ''] | ||||||
| mmu_state_gate_filament_name = ['', '', '', '', '', '', '', ''] | mmu_state_gate_filament_name = ['', '', '', '', '', '', '', ''] | ||||||
|  | @ -19,20 +19,20 @@ mmu_state_gate_material = ['', '', '', '', '', '', '', ''] | ||||||
| mmu_state_gate_selected = 1 | mmu_state_gate_selected = 1 | ||||||
| mmu_state_gate_speed_override = [100, 100, 100, 100, 100, 100, 100, 100] | 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_spool_id = [-1, -1, -1, -1, -1, -1, -1, -1] | ||||||
| mmu_state_gate_status = [-1, 1, 0, -1, -1, -1, -1, -1] | mmu_state_gate_status = [-1, 1, 2, -1, -1, -1, -1, -1] | ||||||
| mmu_state_gate_temperature = [200, 200, 200, 200, 200, 200, 200, 200] | mmu_state_gate_temperature = [200, 200, 200, 200, 200, 200, 200, 200] | ||||||
| mmu_state_last_tool = 0 | mmu_state_last_tool = 0 | ||||||
| mmu_state_tool_selected = 1 | mmu_state_tool_selected = 0 | ||||||
| mmu_state_tool_to_gate_map = [1, 1, 1, 1, 1, 1, 1, 1] | mmu_state_tool_to_gate_map = [1, 1, 1, 1, 1, 1, 1, 1] | ||||||
| mmu_statistics_counters = {'servo_down': {'count': 1209, 'limit': 5000, 'warning': 'Inspect servo arm for wear/damage', 'pause': False}, 'mmu_restarts': {'count': 311, 'limit': -1, 'warning': ''}, 'cutter_blade': {'count': 72, 'limit': 3000, 'warning': 'Inspect/replace filament cutting blade', 'pause': False}} | mmu_statistics_counters = {'servo_down': {'count': 1133, 'limit': 5000, 'warning': 'Inspect servo arm for wear/damage', 'pause': False}, 'mmu_restarts': {'count': 248, 'limit': -1, 'warning': ''}, 'cutter_blade': {'count': 67, 'limit': 3000, 'warning': 'Inspect/replace filament cutting blade', 'pause': False}} | ||||||
| mmu_statistics_gate_0 = {'pauses': 0, 'loads': 2, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 2, 'unload_failures': 0, 'quality': -1.0} | mmu_statistics_gate_0 = {'pauses': 0, 'loads': 2, 'load_distance': 0.0, 'load_delta': 0.0, 'unloads': 0, 'unload_distance': 0.0, 'unload_delta': 0.0, 'load_failures': 2, 'unload_failures': 0, 'quality': -1.0} | ||||||
| mmu_statistics_gate_1 = {'pauses': 7, 'loads': 17, 'load_distance': 21959.049, 'load_delta': 7303.358, 'unloads': 16, 'unload_distance': 9610.7, 'unload_delta': 534.671, 'load_failures': 8, 'unload_failures': 5, 'quality': 0.39797587469336376} | mmu_statistics_gate_1 = {'pauses': 7, 'loads': 16, 'load_distance': 20400.457, 'load_delta': 7020.311, 'unloads': 16, 'unload_distance': 9610.7, 'unload_delta': 534.671, 'load_failures': 8, 'unload_failures': 5, 'quality': 0.4424617663045427} | ||||||
| mmu_statistics_gate_2 = {'pauses': 1, 'loads': 18, 'load_distance': 23812.234, 'load_delta': 7179.788, 'unloads': 23, 'unload_distance': 17861.3, 'unload_delta': 2802.706, 'load_failures': 9, 'unload_failures': 5, 'quality': 0.6142025669990863} | mmu_statistics_gate_2 = {'pauses': 1, 'loads': 14, 'load_distance': 19284.879, 'load_delta': 4486.816, 'unloads': 15, 'unload_distance': 13736.0, 'unload_delta': 411.062, 'load_failures': 6, 'unload_failures': 2, 'quality': 0.5699077987480133} | ||||||
| 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_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_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_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_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_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_load': 10.54, 'load': 1165.82, 'total': 1160.5, 'pre_unload': 11.5, 'post_unload': 8.76, 'unload': 825.66, 'purge': 46.32, 'post_load': 106.49, 'total_swaps': 12, 'swaps_since_pause': 2, 'swaps_since_pause_record': 3, 'form_tip': 158.85, 'total_pauses': 8, 'pause': 1367.03} | mmu_statistics_swaps = {'pre_load': 9.64, 'load': 1067.77, 'total': 1120.72, 'pre_unload': 9.38, 'post_unload': 7.24, 'unload': 710.67, 'purge': 44.02, 'post_load': 92.64, 'total_swaps': 12, 'swaps_since_pause': 2, 'swaps_since_pause_record': 3, 'form_tip': 144.15, 'total_pauses': 8, 'pause': 1367.03} | ||||||
| nvm_offset = -0.11599999999999978 | nvm_offset = -0.11599999999999978 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										87
									
								
								printer.cfg
									
										
									
									
									
								
							
							
						
						
									
										87
									
								
								printer.cfg
									
										
									
									
									
								
							|  | @ -1,7 +1,6 @@ | ||||||
| # MMU to be disconnected, so let's have klipper able to run without it. | [include mmu/base/*.cfg] | ||||||
| #[include mmu/base/*.cfg] | [include mmu/optional/client_macros.cfg] | ||||||
| #[include mmu/optional/client_macros.cfg] | [include mmu/optional/mmu_menu.cfg] | ||||||
| #[include mmu/optional/mmu_menu.cfg] |  | ||||||
| [include timelapse.cfg] | [include timelapse.cfg] | ||||||
| # This file contains common pin mappings for the BigTreeTech Octopus V1. | # This file contains common pin mappings for the BigTreeTech Octopus V1. | ||||||
| # To use this config, the firmware should be compiled for the STM32F446 with a "32KiB bootloader" | # To use this config, the firmware should be compiled for the STM32F446 with a "32KiB bootloader" | ||||||
|  | @ -442,73 +441,23 @@ enable_force_move: True | ||||||
| #*# | #*# | ||||||
| #*# [scanner] | #*# [scanner] | ||||||
| #*# mode = touch | #*# mode = touch | ||||||
| #*# scanner_touch_threshold = 1250 | #*# scanner_touch_threshold = 3000 | ||||||
| #*# scanner_touch_speed = 2 | #*# scanner_touch_speed = 3 | ||||||
| #*# scanner_touch_z_offset = 0.100 |  | ||||||
| #*# | #*# | ||||||
| #*# [scanner model default] | #*# [scanner model default] | ||||||
| #*# model_coef = 1.3305122102001719, | #*# model_coef = 1.4660235274886952, | ||||||
| #*# 	1.778716040310351, | #*# 	  1.8088603709207522, | ||||||
| #*# 	0.7680440090844358, | #*# 	  0.7349055898946472, | ||||||
| #*# 	0.23859921897576467, | #*# 	  0.2687409591730736, | ||||||
| #*# 	0.43324242351119213, | #*# 	  0.47813534708329936, | ||||||
| #*# 	0.7990293243051444, | #*# 	  0.669955108628895, | ||||||
| #*# 	-0.29774573915060454, | #*# 	  -0.3235976797345473, | ||||||
| #*# 	-0.826319532368512, | #*# 	  -0.6702739199959514, | ||||||
| #*# 	0.3149315990912823, | #*# 	  0.2940760023005045, | ||||||
| #*# 	0.46089389855396873 | #*# 	  0.3745733001336773 | ||||||
| #*# model_domain = 3.190439773591761e-07,3.333428586585128e-07 | #*# model_domain = 3.2050348407481734e-07,3.335190657416707e-07 | ||||||
| #*# model_range = 0.100000,5.000000 | #*# model_range = 0.200000,5.100000 | ||||||
| #*# model_temp = 27.128733 | #*# model_temp = 30.248095 | ||||||
| #*# model_offset = 0.00000 | #*# model_offset = 0.00000 | ||||||
| #*# model_mode = touch | #*# model_mode = touch | ||||||
| #*# model_fw_version = CARTOGRAPHER 5.0.0 | #*# model_fw_version = CARTOGRAPHER 5.0.0 | ||||||
| #*# |  | ||||||
| #*# [bed_mesh default] |  | ||||||
| #*# version = 1 |  | ||||||
| #*# points = |  | ||||||
| #*# 	0.004141, 0.004549, -0.000733, -0.001003, -0.005359, -0.005042, -0.009642, -0.013812, -0.010166, -0.007716, -0.004855, -0.000425, 0.002495, -0.001015, -0.004729, -0.005912, -0.006870, -0.002302, 0.004081, 0.009434, 0.018398, 0.025699, 0.022665, 0.017863, 0.018018, 0.013572, 0.009637, 0.005972, -0.000404, 0.011483 |  | ||||||
| #*# 	0.006567, 0.003236, 0.006012, 0.004138, -0.002341, -0.005950, -0.010710, -0.011375, -0.007339, -0.007375, -0.007296, -0.005194, 0.004181, 0.003895, -0.011801, -0.011846, -0.009110, -0.004997, 0.009130, 0.008604, 0.017817, 0.027138, 0.032314, 0.022720, 0.015723, 0.012146, 0.013784, 0.015243, 0.006402, 0.013213 |  | ||||||
| #*# 	0.015125, 0.012134, 0.010536, 0.006715, 0.005960, 0.001845, -0.000486, -0.005612, -0.005394, -0.002616, -0.000621, -0.000459, 0.001777, -0.000055, -0.006750, -0.009486, -0.008739, -0.006074, 0.002905, 0.013089, 0.022485, 0.027253, 0.029100, 0.026988, 0.023004, 0.015705, 0.013318, 0.009580, 0.008696, 0.013590 |  | ||||||
| #*# 	0.020752, 0.018108, 0.016423, 0.015550, 0.012114, 0.007824, 0.004757, 0.003697, -0.000854, 0.003628, 0.004182, 0.004141, 0.001848, 0.004134, -0.000465, -0.009647, -0.007692, -0.000302, -0.000788, 0.011563, 0.027374, 0.031254, 0.026888, 0.032574, 0.026990, 0.017737, 0.023616, 0.015541, 0.013764, 0.022188 |  | ||||||
| #*# 	0.028236, 0.022995, 0.017853, 0.020215, 0.015295, 0.008719, 0.007567, 0.005262, 0.005299, 0.006798, 0.010862, 0.006510, 0.004132, 0.008693, 0.001344, -0.005151, -0.003890, -0.002739, 0.003711, 0.013027, 0.022634, 0.029440, 0.030338, 0.028053, 0.028985, 0.025826, 0.026912, 0.018018, 0.013308, 0.027996 |  | ||||||
| #*# 	0.026930, 0.022417, 0.021918, 0.017893, 0.013448, 0.009868, 0.008131, 0.005941, 0.006464, 0.009398, 0.009043, 0.007900, 0.007752, 0.006433, 0.003930, 0.001782, -0.002447, -0.001598, 0.003841, 0.012138, 0.023313, 0.029493, 0.031403, 0.031326, 0.031194, 0.027562, 0.022597, 0.021976, 0.018974, 0.026856 |  | ||||||
| #*# 	0.029299, 0.024563, 0.018284, 0.020053, 0.015134, 0.011038, 0.007319, 0.006661, 0.006559, 0.009320, 0.009079, 0.008744, 0.010833, 0.006747, 0.006316, 0.005284, -0.000912, -0.001439, 0.004928, 0.013298, 0.022567, 0.028930, 0.031029, 0.029758, 0.029212, 0.025781, 0.027079, 0.020701, 0.017009, 0.025382 |  | ||||||
| #*# 	0.031455, 0.025955, 0.022857, 0.019364, 0.013151, 0.010999, 0.009623, 0.008720, 0.004140, 0.010588, 0.011060, 0.013321, 0.007625, 0.009022, 0.007956, 0.005831, 0.005892, -0.001514, 0.005559, 0.018575, 0.020410, 0.031243, 0.030774, 0.031800, 0.038259, 0.031613, 0.022392, 0.024867, 0.026914, 0.020700 |  | ||||||
| #*# 	0.029243, 0.028111, 0.022949, 0.016939, 0.012835, 0.012467, 0.013531, 0.008741, 0.006449, 0.008657, 0.013844, 0.013789, 0.010883, 0.004140, 0.004490, 0.004612, 0.000478, 0.000490, 0.004319, 0.013193, 0.026911, 0.032451, 0.031452, 0.031437, 0.031625, 0.033729, 0.029190, 0.024654, 0.022058, 0.027502 |  | ||||||
| #*# 	0.031447, 0.026607, 0.020228, 0.017005, 0.013440, 0.011023, 0.006877, 0.003219, 0.003708, 0.006436, 0.008403, 0.009931, 0.006449, 0.005267, -0.001583, -0.002725, -0.003085, -0.000431, 0.001272, 0.008410, 0.022612, 0.031793, 0.028617, 0.022367, 0.030688, 0.029047, 0.031412, 0.020171, 0.017549, 0.022100 |  | ||||||
| #*# 	0.029691, 0.027286, 0.020073, 0.015962, 0.008717, 0.009395, 0.006407, 0.004179, -0.002743, -0.000788, 0.002132, 0.004823, -0.001062, -0.002748, -0.005456, -0.007313, -0.009897, -0.010492, -0.004780, 0.007642, 0.017719, 0.022314, 0.022409, 0.021429, 0.022620, 0.019002, 0.017279, 0.013300, 0.012185, 0.022299 |  | ||||||
| #*# 	0.027214, 0.022930, 0.017864, 0.017329, 0.012725, 0.004741, 0.001983, -0.001464, -0.003246, -0.000889, -0.000556, 0.000500, 0.000687, -0.005355, -0.006733, -0.010802, -0.012216, -0.011587, -0.004968, 0.006015, 0.018337, 0.013297, 0.019614, 0.023682, 0.018036, 0.018233, 0.015469, 0.012113, 0.018492, 0.011011 |  | ||||||
| #*# 	0.022373, 0.021051, 0.017864, 0.012471, 0.008716, 0.006432, 0.000036, -0.004988, -0.003958, -0.002406, -0.001275, -0.004444, -0.004800, -0.004561, -0.009028, -0.009527, -0.010000, -0.009645, -0.005256, 0.003028, 0.012414, 0.015850, 0.017859, 0.016012, 0.015562, 0.015568, 0.013336, 0.010532, 0.009063, 0.017900 |  | ||||||
| #*# 	0.021848, 0.016660, 0.012861, 0.010557, 0.008612, 0.004148, 0.000399, -0.002715, -0.005298, -0.002714, -0.000445, -0.005080, -0.006038, -0.005060, -0.010185, -0.009668, -0.008834, -0.011597, -0.005905, 0.005284, 0.013702, 0.012615, 0.015732, 0.018138, 0.012186, 0.013513, 0.017834, 0.003829, 0.008415, 0.018073 |  | ||||||
| #*# 	0.022602, 0.015587, 0.011012, 0.009007, 0.008211, 0.004084, 0.000849, -0.000350, -0.002716, -0.000963, -0.000138, -0.003621, -0.005213, -0.005522, -0.004784, -0.008491, -0.009218, -0.008966, -0.005133, 0.003042, 0.009507, 0.013274, 0.013549, 0.013766, 0.015559, 0.016716, 0.014435, 0.011015, 0.005084, 0.012858 |  | ||||||
| #*# 	0.018351, 0.015604, 0.013295, 0.012176, 0.009749, 0.007578, 0.004305, 0.000909, 0.000120, 0.004836, 0.004383, 0.003024, -0.001115, -0.001403, 0.002707, -0.002191, -0.007175, -0.005037, 0.000397, 0.005434, 0.008452, 0.018318, 0.020658, 0.020138, 0.027486, 0.022306, 0.021724, 0.016258, 0.015580, 0.016702 |  | ||||||
| #*# 	0.023398, 0.017273, 0.014179, 0.013007, 0.013371, 0.008961, 0.004136, 0.004139, 0.005443, 0.008857, 0.008535, 0.008120, 0.006306, 0.004301, 0.003903, 0.002512, -0.000419, -0.000609, 0.001683, 0.008729, 0.016646, 0.022171, 0.023460, 0.023092, 0.025825, 0.026271, 0.024361, 0.021418, 0.016835, 0.020293 |  | ||||||
| #*# 	0.026593, 0.020045, 0.017367, 0.016348, 0.012509, 0.009024, 0.008383, 0.008283, 0.009129, 0.008983, 0.009782, 0.010993, 0.011181, 0.008018, 0.004126, 0.005337, 0.001855, 0.001594, 0.005285, 0.010838, 0.024356, 0.025792, 0.022367, 0.026468, 0.029222, 0.025777, 0.026842, 0.019004, 0.022390, 0.022832 |  | ||||||
| #*# 	0.027033, 0.023453, 0.018625, 0.013299, 0.011158, 0.010994, 0.009701, 0.008328, 0.009861, 0.013287, 0.014116, 0.015428, 0.013151, 0.008698, 0.009486, 0.005439, 0.003055, 0.000719, 0.006462, 0.014431, 0.022154, 0.026713, 0.024950, 0.027837, 0.028052, 0.026637, 0.022413, 0.017956, 0.018670, 0.022427 |  | ||||||
| #*# 	0.029327, 0.023293, 0.018019, 0.017815, 0.017422, 0.013250, 0.013196, 0.011157, 0.014375, 0.018989, 0.023197, 0.022981, 0.020380, 0.017525, 0.013787, 0.013257, 0.006581, 0.003970, 0.010598, 0.018047, 0.024218, 0.026964, 0.032690, 0.029481, 0.031984, 0.026977, 0.021775, 0.021959, 0.019035, 0.023460 |  | ||||||
| #*# 	0.031663, 0.023508, 0.018081, 0.017529, 0.018112, 0.016985, 0.015537, 0.016760, 0.020266, 0.026618, 0.027582, 0.027746, 0.026278, 0.022228, 0.017836, 0.013151, 0.008567, 0.008139, 0.012313, 0.017817, 0.026769, 0.032518, 0.033354, 0.031144, 0.026941, 0.025824, 0.022986, 0.019139, 0.017185, 0.022654 |  | ||||||
| #*# 	0.031488, 0.023623, 0.018118, 0.017962, 0.019838, 0.017859, 0.018480, 0.022450, 0.025788, 0.031825, 0.032049, 0.031579, 0.027154, 0.022528, 0.016809, 0.014924, 0.005424, 0.009818, 0.011649, 0.016757, 0.027541, 0.030788, 0.036016, 0.029191, 0.027177, 0.025775, 0.025126, 0.027016, 0.020414, 0.025183 |  | ||||||
| #*# 	0.035607, 0.021562, 0.017692, 0.015561, 0.016730, 0.017687, 0.018118, 0.021418, 0.026686, 0.031315, 0.031841, 0.027341, 0.022363, 0.015712, 0.009796, 0.005130, 0.000396, -0.000444, 0.008495, 0.016123, 0.024390, 0.029230, 0.028765, 0.025849, 0.024619, 0.022423, 0.022082, 0.022231, 0.022061, 0.027891 |  | ||||||
| #*# 	0.043964, 0.024179, 0.014501, 0.012289, 0.013264, 0.013898, 0.017824, 0.018148, 0.022408, 0.026969, 0.026924, 0.022414, 0.014977, 0.009010, 0.003012, -0.000418, -0.003892, -0.003276, 0.004107, 0.014431, 0.022990, 0.022580, 0.024808, 0.023387, 0.021065, 0.027130, 0.027243, 0.021855, 0.023213, 0.031467 |  | ||||||
| #*# 	0.060099, 0.031499, 0.017280, 0.012255, 0.010777, 0.013306, 0.014271, 0.016368, 0.019241, 0.022392, 0.022365, 0.017815, 0.009551, 0.004140, -0.000447, -0.003210, -0.005008, -0.001131, 0.004985, 0.014441, 0.022418, 0.025921, 0.026948, 0.024730, 0.026395, 0.027129, 0.026958, 0.026657, 0.023521, 0.028451 |  | ||||||
| #*# 	0.073079, 0.036760, 0.015789, 0.008771, 0.008746, 0.008720, 0.009015, 0.011211, 0.013293, 0.017568, 0.016008, 0.013141, 0.005220, 0.000342, -0.004867, -0.005212, -0.005043, -0.004462, 0.002001, 0.013269, 0.018429, 0.026000, 0.026930, 0.025832, 0.025783, 0.027135, 0.022403, 0.021909, 0.023205, 0.027519 |  | ||||||
| #*# 	0.075660, 0.035724, 0.010739, 0.004137, 0.002715, 0.000362, 0.000355, 0.000240, 0.004142, 0.008220, 0.008697, 0.006020, 0.001274, -0.005018, -0.009594, -0.011496, -0.012400, -0.009846, -0.004837, 0.004023, 0.011238, 0.017775, 0.019838, 0.020333, 0.022210, 0.021112, 0.018758, 0.014701, 0.013612, 0.020221 |  | ||||||
| #*# 	0.063849, 0.024969, 0.006275, -0.004398, -0.005000, -0.005031, -0.008510, -0.007577, -0.003304, -0.000429, 0.001920, 0.000001, -0.005000, -0.009645, -0.012949, -0.014127, -0.017519, -0.016153, -0.011865, -0.005017, 0.004085, 0.011240, 0.014449, 0.016999, 0.017442, 0.014983, 0.013287, 0.008935, 0.008580, 0.013426 |  | ||||||
| #*# 	0.047570, 0.013019, 0.001633, -0.006082, -0.009606, -0.010260, -0.011903, -0.011992, -0.009599, -0.005027, -0.002671, -0.004084, -0.008438, -0.013071, -0.016090, -0.018868, -0.020674, -0.020079, -0.016068, -0.009599, -0.000540, 0.008251, 0.012981, 0.013275, 0.014277, 0.013323, 0.011943, 0.008287, 0.006290, 0.011704 |  | ||||||
| #*# 	0.037640, 0.011676, -0.002971, -0.005330, -0.008764, -0.009654, -0.010416, -0.011782, -0.009665, -0.005926, -0.003595, -0.004464, -0.008332, -0.013487, -0.016957, -0.018932, -0.021343, -0.020032, -0.015588, -0.007664, 0.000727, 0.008716, 0.011447, 0.011014, 0.012942, 0.012301, 0.008995, 0.008277, 0.006446, 0.011272 |  | ||||||
| #*# x_count = 30 |  | ||||||
| #*# y_count = 30 |  | ||||||
| #*# mesh_x_pps = 2 |  | ||||||
| #*# mesh_y_pps = 2 |  | ||||||
| #*# algo = bicubic |  | ||||||
| #*# tension = 0.2 |  | ||||||
| #*# min_x = 30.0 |  | ||||||
| #*# max_x = 310.0 |  | ||||||
| #*# min_y = 30.0 |  | ||||||
| #*# max_y = 310.0 |  | ||||||
| #*# |  | ||||||
| #*# [skew_correction Calilantern] |  | ||||||
| #*# xy_skew = 0.0004221439779203628 |  | ||||||
| #*# xz_skew = 0.0 |  | ||||||
| #*# yz_skew = 0.0 |  | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue