ScrubbyXL is an automatic nozzle-wipe add-on for the Prusa XL that keeps the nozzle tip clean where it matters most: before Mesh Bed Leveling (MBL) to help achieve a cleaner first layer, and during long prints to reduce filament buildup on the nozzle tip that can lead to failed prints.
Blog Post: https://investegate.de/scrubbyxl-automatic-nozzle-wipe-mbl-during-printing/
It’s designed as a reliability-focused mod for real-world printing—especially long jobs—where small blobs or residue on the nozzle can accumulate over time and eventually cause surface defects, collisions, or a print going off the rails. Use it as a preventative “maintenance move” built into your workflow, rather than waiting until a problem appears.
You can integrate the wipe routine directly into your slicer via G-code: a small Start G-code tweak wipes the nozzle before MBL so the nozzle probes the bed cleanly, and optional in-print wipes can be triggered every N layers (user-defined) to keep the tip free of buildup during long jobs.
This is a remix. The original is from @Ro3Deee. Thank you for the great basic design <3
Choose your version:
Mounting hole size: M3 / M4 / M5.
Silicone brush size: A1 or A1 mini.
Mounting style: magnetic or fixed (screwed).
Magnetic mount:
Magnets can be inserted during printing (pause-at-layer) or glued in after printing. (choose the version you want)
Fixed mount (no magnets):
A no-magnet version is included for a fully screwed, rigid installation.
Recommended setup:
>> I recommend the magnetic version with inserted magnets and the A1 mini brushes <<
Magnetic mounting is the better choice, because on the right side (Tool 5) the toolhead is loaded/unloaded directly above the wiper area—so it’s useful to remove the brush quickly when needed.
For best results, mounting wipers on both sides is recommended. That said, you can also run only one brush on a single side—just adjust the G-code accordingly.
Material List:
Print Settings:
Material: PETG, ABS, PC
Layer high: 0.2mm
3 perimeters
20-50% Infill
Quality mode
Use support only for the silicone brush inlets
Consider using a brim
Tip: When overprinting the magnet in the mounting plate, apply some tape to the operable side to ensure better overprinting. (3M 2090 blue tape is best)
Be careful when handling the magnets during preparation; if they attract each other and collide, they will break. This unfortunately happened to me as well. Therefore, it's advisable to have a few spare magnets. Of course, the problem no longer exists once they are installed.
When inserting the magnets, a pause must be set in the slicer at the correct height:
Pause for the mounting plate: 4.2 mm height
Pause for the brush holders: 52.6 mm height
IMPORTANT: It's best to mark the correct polarity with a permanent marker to avoid mistakes :)
Mounting Instruction:
Remove the supports/brim and place the brushes in the holder. If your brushes don't have an adhesive strip on the underside, you can use some glue. However, the brushes will also hold well without glue.
Lower the heated bed by about 6 mm. A print plate must be in place. The brushes should be about 1 to 2 mm away from the print bed. Then you can adjust the height. Deactivate the printer's motors and slide the tool towards the brush. The brushes should make good contact with the nozzle—not too much and not too little. Take your time and do it properly :)


G-Codes:
Changelog:
Integrated the nozzle-clean / wipe routine so the nozzle is mechanically cleaned as part of startup.
Adjusted the tool wait for temp position to the front to to make it easier to clean the nozzle manually.
Added an audible beep indicator (beeps before the nozzle wipe and before the purge line) for better feedback during startup.
Commented out G29 P9, because it drives the temperature too high right before MBL.
Shifted the purge line for the first and last tool by 3 mm to avoid any contact with the brush mod.
Reworked Surfalex2000’s brass brush-mod G-code to improve the cleaning result (more reliable wipe behavior).
Optimized and fixed Prusa XL full start gcode for the brush mod:
M17 ; enable steppers
M862.3 P "XL" ; printer model check
M862.5 P2 ; g-code level check
M862.6 P"Input shaper" ; FW feature check
M115 U6.4.0+11974
G90 ; use absolute coordinates
M83 ; extruder relative mode
; set print area
M555 X{first_layer_print_min[0]} Y{first_layer_print_min[1]} W{(first_layer_print_max[0]) - (first_layer_print_min[0])} H{(first_layer_print_max[1]) - (first_layer_print_min[1])}
; inform about nozzle diameter
{if (is_extruder_used[0])}M862.1 T0 P{nozzle_diameter[0]} A{(filament_abrasive[0] ? 1 : 0)} F{(nozzle_high_flow[0] ? 1 : 0)}{endif}
{if (is_extruder_used[1])}M862.1 T1 P{nozzle_diameter[1]} A{(filament_abrasive[1] ? 1 : 0)} F{(nozzle_high_flow[1] ? 1 : 0)}{endif}
{if (is_extruder_used[2])}M862.1 T2 P{nozzle_diameter[2]} A{(filament_abrasive[2] ? 1 : 0)} F{(nozzle_high_flow[2] ? 1 : 0)}{endif}
{if (is_extruder_used[3])}M862.1 T3 P{nozzle_diameter[3]} A{(filament_abrasive[3] ? 1 : 0)} F{(nozzle_high_flow[3] ? 1 : 0)}{endif}
{if (is_extruder_used[4])}M862.1 T4 P{nozzle_diameter[4]} A{(filament_abrasive[4] ? 1 : 0)} F{(nozzle_high_flow[4] ? 1 : 0)}{endif}
; turn off unused heaters
{if ! is_extruder_used[0]}M104 T0 S0{endif}
{if ! is_extruder_used[1]}M104 T1 S0{endif}
{if num_extruders > 2 and ! is_extruder_used[2]}M104 T2 S0{endif}
{if num_extruders > 3 and ! is_extruder_used[3]}M104 T3 S0{endif}
{if num_extruders > 4 and ! is_extruder_used[4]}M104 T4 S0{endif}
M217 Z{max(zhop, 2.0)} ; set toolchange z hop to 2mm, or zhop variable from slicer if higher
; set bed and extruder temp for MBL
M140 S[first_layer_bed_temperature] ; set bed temp
M104 T{initial_tool} S{((filament_notes[initial_tool]=~/.*MBL160.*/) ? 160 : (filament_notes[initial_tool]=~/.*HT_MBL10.*/) ? (first_layer_temperature[initial_tool] - 10) : (filament_type[initial_tool] == "PC" or filament_type[initial_tool] == "PA") ? (first_layer_temperature[initial_tool] - 25) : (filament_type[initial_tool] == "FLEX") ? 210 : (filament_type[initial_tool]=~/.*PET.*/) ? 175 : 170)} ; set temp
; Home XY
G28 XY
; try picking tools used in print
G1 F{travel_speed * 60}
{if (is_extruder_used[0]) and (initial_tool != 0)}T0 S1 L0 D0{endif}
{if (is_extruder_used[1]) and (initial_tool != 1)}T1 S1 L0 D0{endif}
{if (is_extruder_used[2]) and (initial_tool != 2)}T2 S1 L0 D0{endif}
{if (is_extruder_used[3]) and (initial_tool != 3)}T3 S1 L0 D0{endif}
{if (is_extruder_used[4]) and (initial_tool != 4)}T4 S1 L0 D0{endif}
; select tool that will be used to home & MBL
T{initial_tool} S1 L0 D0
; HERE THE TOOL HAS TO WAIT PURELY BECAUSE OF SILICONE BRUSH
G1 Z30
G1 X145 Y-8 F{travel_speed * 60}
M109 T{initial_tool} S{((filament_notes[initial_tool]=~/.*MBL160.*/) ? 160 : (filament_notes[initial_tool]=~/.*HT_MBL10.*/) ? (first_layer_temperature[initial_tool] - 10) : (filament_type[initial_tool] == "PC" or filament_type[initial_tool] == "PA") ? (first_layer_temperature[initial_tool] - 25) : (filament_type[initial_tool] == "FLEX") ? 210 : (filament_type[initial_tool]=~/.*PET.*/) ? 175 : 170)} ; wait for temp
; home Z with MBL tool
M84 E ; turn off E motor
G28 Z
G0 Z5 ; add Z clearance
; HERE THE TOOL HAS TO WAIT PURELY BECAUSE OF SILICONE BRUSH
G1 Z30
G1 X145 Y-8 F{travel_speed * 60}
M104 T{initial_tool} S{if is_nil(idle_temperature[initial_tool])}70{else}{idle_temperature[initial_tool]}{endif} ; set idle temp
M190 S[first_layer_bed_temperature] ; wait for bed temp
G29 G ; absorb heat
M109 T{initial_tool} S{((filament_notes[initial_tool]=~/.*MBL160.*/) ? 160 : (filament_notes[initial_tool]=~/.*HT_MBL10.*/) ? (first_layer_temperature[initial_tool] - 10) : (filament_type[initial_tool] == "PC" or filament_type[initial_tool] == "PA") ? (first_layer_temperature[initial_tool] - 25) : (filament_type[initial_tool] == "FLEX") ? 210 : (filament_type[initial_tool]=~/.*PET.*/) ? 175 : 170)} ; wait for temp
M300 S800 P200. ; PIEP indicator
; move to the nozzle cleanup area
; nozzle cleanup FOR LEFT AND RIGHT SILICONE WIPER
M302 S155 ; lower cold extrusion limit to 155C
G1 E{-(filament_type[0] == "FLEX" ? 4 : 2)} F2400 ; retraction for nozzle cleanup
M84 E ; turn off E motor
; --- Start Nozzle Wipe
G1 Z5 ; Move bed out of the way
{if initial_tool == 0 or initial_tool == 1 }
; --- Start Nozzle Wipe LEFT ---
G1 X-2 Y-8 F24000 ; Move to start of wipe area
G1 X28 Y-8 F24000 ; Wipe pass 1
G1 X-2 Y-7.5 F24000 ; Reposition
G1 X28 Y-7.5 F24000 ; Wipe pass 2
G1 X-2 Y-7 F24000 ; Reposition
G1 X28 Y-7 F24000 ; Wipe pass 3
G1 X-2 Y-6.5 F24000 ; Reposition
G1 X28 Y-6.5 F24000 ; Wipe pass 4
G1 X-2 Y-6 F24000 ; Reposition
G1 X28 Y-6 F24000 ; Wipe pass 5
G1 X-2 Y-6.5 F24000 ; Reposition
G1 X28 Y-6.5 F24000 ; Wipe pass 6
G1 X-2 Y-7 F24000 ; Reposition
G1 X28 Y-7 F24000 ; Wipe pass 7
G1 X-2 Y-7.5 F24000 ; Reposition
G1 X28 Y-7.5 F24000 ; Wipe pass 8
G1 X-2 Y-8 F24000 ; Reposition
G1 X28 Y-8 F24000 ; Wipe pass 9
; --- End Nozzle Wipe LEFT ---
{else}
; --- Start Nozzle Wipe RIGHT ---
G1 X332 Y-8 F24000 ; Move to start of wipe area
G1 X361 Y-8 F24000 ; Wipe pass 1
G1 X332 Y-7.5 F24000 ; Reposition
G1 X361 Y-7.5 F24000 ; Wipe pass 2
G1 X332 Y-7 F24000 ; Reposition
G1 X361 Y-7 F24000 ; Wipe pass 3
G1 X332 Y-6.5 F24000 ; Reposition
G1 X361 Y-6.5 F24000 ; Wipe pass 4
G1 X332 Y-6 F24000 ; Reposition
G1 X361 Y-6 F24000 ; Wipe pass 5
G1 X332 Y-6.5 F24000 ; Reposition
G1 X361 Y-6.5 F24000 ; Wipe pass 6
G1 X332 Y-7 F24000 ; Reposition
G1 X361 Y-7 F24000 ; Wipe pass 7
G1 X332 Y-7.5 F24000 ; Reposition
G1 X361 Y-7.5 F24000 ; Wipe pass 8
G1 X332 Y-8 F24000 ; Reposition
G1 X361 Y-8 F24000 ; Wipe pass 9
; --- End Nozzle Wipe RIGHT ---
{endif}
G1 X{(min(((((first_layer_print_min[0] + first_layer_print_max[0]) / 2) < ((print_bed_min[0] + print_bed_max[0]) / 2)) ? (((first_layer_print_min[1] - 7) < -2) ? 70 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)) : (((first_layer_print_min[1] - 7) < -2) ? 260 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32))), first_layer_print_min[0])) + 32} Y{(min((first_layer_print_min[1] - 7), first_layer_print_min[1]))} Z{5} F{(travel_speed * 60)}
; nozzle cleanup
;Commented out below because it sets the temperature too high in front of the MBL.
;G29 P9 X{((((first_layer_print_min[0] + first_layer_print_max[0]) / 2) < ((print_bed_min[0] + print_bed_max[0]) / 2)) ? (((first_layer_print_min[1] - 7) < -2) ? 70 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)) : (((first_layer_print_min[1] - 7) < -2) ? 260 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)))} Y{(first_layer_print_min[1] - 7)} W{32} H{7}
M107 ; turn off the fan
; MBL
M84 E ; turn off E motor
G29 P1 ; invalidate mbl & probe print area
G29 P1 X30 Y0 W{(((is_extruder_used[4]) or ((is_extruder_used[3]) or (is_extruder_used[2]))) ? "300" : ((is_extruder_used[1]) ? "130" : "50"))} H20 C ; probe near purge place
G29 P3.2 ; interpolate mbl probes
G29 P3.13 ; extrapolate mbl outside probe area
G29 A ; activate mbl
G1 Z10 F720 ; move away in Z
G1 F{travel_speed * 60}
P0 S1 L1 D0; park the tool
; set extruder temp
{if first_layer_temperature[0] > 0 and (is_extruder_used[0])}M104 T0 S{first_layer_temperature[0]}{endif}
{if first_layer_temperature[1] > 0 and (is_extruder_used[1])}M104 T1 S{first_layer_temperature[1]}{endif}
{if first_layer_temperature[2] > 0 and (is_extruder_used[2])}M104 T2 S{first_layer_temperature[2]}{endif}
{if first_layer_temperature[3] > 0 and (is_extruder_used[3])}M104 T3 S{first_layer_temperature[3]}{endif}
{if first_layer_temperature[4] > 0 and (is_extruder_used[4])}M104 T4 S{first_layer_temperature[4]}{endif}
{if (is_extruder_used[0]) and initial_tool != 0}
M591 S0 ; disable stuck detection
; Ready to print melody, before purging
M300 S1200 P150
G4 P200
M300 S1500 P150
G4 P200
M300 S1800 P300
G4 P500
;
; purge first tool
; Edited. X position changed from 30 to 33 due to silicone brush.
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T0 S{first_layer_temperature[0]}
T0 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X33 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[0])}10{else}30{endif} X40 Z0.2 F{if is_nil(filament_multitool_ramming[0])}500{else}170{endif} ; purge while moving towards the sheet
G0 X70 E9 F800 ; continue purging and wipe the nozzle
G0 X73 Z0.05 F8000 ; wipe, move close to the bed
G0 X76 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[0]} F2400 ; retract
{e_retracted[0] = retract_length_toolchange[0]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[0]) ? (first_layer_temperature[0] + standby_temperature_delta) : (idle_temperature[0]))} T0
{endif}
{if (is_extruder_used[1]) and initial_tool != 1}
;
; purge second tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T1 S{first_layer_temperature[1]}
T1 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X150 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[1])}10{else}30{endif} X140 Z0.2 F{if is_nil(filament_multitool_ramming[1])}500{else}170{endif} ; purge while moving towards the sheet
G0 X110 E9 F800 ; continue purging and wipe the nozzle
G0 X107 Z0.05 F8000 ; wipe, move close to the bed
G0 X104 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[1]} F2400 ; retract
{e_retracted[1] = retract_length_toolchange[1]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[1]) ? (first_layer_temperature[1] + standby_temperature_delta) : (idle_temperature[1]))} T1
{endif}
{if (is_extruder_used[2]) and initial_tool != 2}
;
; purge third tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T2 S{first_layer_temperature[2]}
T2 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X210 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[2])}10{else}30{endif} X220 Z0.2 F{if is_nil(filament_multitool_ramming[2])}500{else}170{endif} ; purge while moving towards the sheet
G0 X250 E9 F800 ; continue purging and wipe the nozzle
G0 X253 Z0.05 F8000 ; wipe, move close to the bed
G0 X256 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[2]} F2400 ; retract
{e_retracted[2] = retract_length_toolchange[2]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[2]) ? (first_layer_temperature[2] + standby_temperature_delta) : (idle_temperature[2]))} T2
{endif}
{if (is_extruder_used[3]) and initial_tool != 3}
;
; purge fourth tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T3 S{first_layer_temperature[3]}
T3 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X327 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[3])}10{else}30{endif} X320 Z0.2 F{if is_nil(filament_multitool_ramming[3])}500{else}170{endif} ; purge while moving towards the sheet
G0 X290 E9 F800 ; continue purging and wipe the nozzle
G0 X287 Z0.05 F8000 ; wipe, move close to the bed
G0 X284 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[3]} F2400 ; retract
{e_retracted[3] = retract_length_toolchange[3]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[3]) ? (first_layer_temperature[3] + standby_temperature_delta) : (idle_temperature[3]))} T3
{endif}
{if (is_extruder_used[4]) and initial_tool != 4}
;
; purge fifth tool
; Edited. X position for TOOL 4 changed from 330 to 327 due to silicone brush.
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T4 S{first_layer_temperature[4]}
T4 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X327 Y-4.5 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[4])}10{else}30{endif} X320 Z0.2 F{if is_nil(filament_multitool_ramming[4])}500{else}170{endif} ; purge while moving towards the sheet
G0 X290 E9 F800 ; continue purging and wipe the nozzle
G0 X287 Z0.05 F8000 ; wipe, move close to the bed
G0 X284 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[4]} F2400 ; retract
{e_retracted[4] = retract_length_toolchange[4]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[4]) ? (first_layer_temperature[4] + standby_temperature_delta) : (idle_temperature[4]))} T4
{endif}
;
; purge initial tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T{initial_tool} S{first_layer_temperature[initial_tool]}
T{initial_tool} S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
; Edited. X position for TOOL 0 changed from 30 to 33 due to silicone brush.
; Edited. X position for TOOL 4 changed from 330 to 327 due to silicone brush.
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327)))} Y{(initial_tool < 4 ? -7 : -4.5)} Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[initial_tool])}10{else}30{endif} X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 10)} Z0.2 F{if is_nil(filament_multitool_ramming[initial_tool])}500{else}170{endif} ; purge while moving towards the sheet
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 40)} E9 F800 ; continue purging and wipe the nozzle
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 40) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 3)} Z{0.05} F{8000} ; wipe, move close to the bed
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 40) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 3 * 2)} Z0.2 F{8000} ; wipe, move quickly away from the bed
G1 E-{retract_length[initial_tool]} F2400 ; retract
{e_retracted[initial_tool] = retract_length[initial_tool]}
M591 R ; restore stuck detection
G92 E0 ; reset extruder position
Before Layer Change G-code (During printing, the nozzle is automatically cleaned every X layer)
;BEFORE_LAYER_CHANGE
G92 E0.0
;[layer_z]
; During printing, the nozzle is automatically cleaned every X layer. (X = 400 layers)
; --- Every 400 layers: automatic wipe ---
{if layer_num > 0 && layer_num % 400 == 0}
; Save current position (Buddy FW)
G1 F{travel_speed * 100}
G60 S0 ; store current XYZ position
M300 S300 P200. ; PIEP indicator
; Lift Z a bit for safety
G1 Z{layer_z + 5} F1000
; --- Start Nozzle Wipe ---
{if initial_tool == 0 or initial_tool == 1 }
; --- Start Nozzle Wipe LEFT ---
G1 X-2 Y-8 F24000
G1 X28 Y-8 F24000
G1 X-2 Y-7.5 F24000
G1 X28 Y-7.5 F24000
G1 X-2 Y-7 F24000
G1 X28 Y-7 F24000
G1 X-2 Y-6.5 F24000
G1 X28 Y-6.5 F24000
G1 X-2 Y-6 F24000
G1 X28 Y-6 F24000
G1 X-2 Y-6.5 F24000
G1 X28 Y-6.5 F24000
G1 X-2 Y-7 F24000
G1 X28 Y-7 F24000
G1 X-2 Y-7.5 F24000
G1 X28 Y-7.5 F24000
G1 X-2 Y-8 F24000
G1 X28 Y-8 F24000
; --- End Nozzle Wipe LEFT ---
{else}
; --- Start Nozzle Wipe RIGHT ---
G1 X332 Y-8 F24000
G1 X361 Y-8 F24000
G1 X332 Y-7.5 F24000
G1 X361 Y-7.5 F24000
G1 X332 Y-7 F24000
G1 X361 Y-7 F24000
G1 X332 Y-6.5 F24000
G1 X361 Y-6.5 F24000
G1 X332 Y-6 F24000
G1 X361 Y-6 F24000
G1 X332 Y-6.5 F24000
G1 X361 Y-6.5 F24000
G1 X332 Y-7 F24000
G1 X361 Y-7 F24000
G1 X332 Y-7.5 F24000
G1 X361 Y-7.5 F24000
G1 X332 Y-8 F24000
G1 X361 Y-8 F24000
; --- End Nozzle Wipe RIGHT ---
{endif}
; --- End Nozzle Wipe ---
; Restore position
G61 S0 ; restore stored XYZ position
{endif}
BONUS: End G-Code (Plays a short finishing melody)
G4 ; wait
{if layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+5, max_print_height)}{endif} ; Move bed down
P0 S1 ; park tool
{if layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+97, max_print_height)} F300{endif} ; Move bed further down
; turn off extruder heaters
{if is_extruder_used[0]}M104 T0 S0{endif}
{if is_extruder_used[1]}M104 T1 S0{endif}
{if is_extruder_used[2]}M104 T2 S0{endif}
{if is_extruder_used[3]}M104 T3 S0{endif}
{if is_extruder_used[4]}M104 T4 S0{endif}
M140 S0 ; turn off heatbed
M107 ; turn off fan
M221 S100 ; reset flow percentage
M84 ; disable motors
;Finishing melody
M300 S1200 P150
G4 P200
M300 S1500 P150
G4 P200
M300 S1800 P300
G4 P500
M77 ; stop print timer
; max_layer_z = [max_layer_z]Optional: If you also want to use the MBL brass brush mod from @Surfalex2000:
M17 ; enable steppers
M862.3 P "XL" ; printer model check
M862.5 P2 ; g-code level check
M862.6 P"Input shaper" ; FW feature check
M115 U6.4.0+11974
G90 ; use absolute coordinates
M83 ; extruder relative mode
; set print area
M555 X{first_layer_print_min[0]} Y{first_layer_print_min[1]} W{(first_layer_print_max[0]) - (first_layer_print_min[0])} H{(first_layer_print_max[1]) - (first_layer_print_min[1])}
; inform about nozzle diameter
{if (is_extruder_used[0])}M862.1 T0 P{nozzle_diameter[0]} A{(filament_abrasive[0] ? 1 : 0)} F{(nozzle_high_flow[0] ? 1 : 0)}{endif}
{if (is_extruder_used[1])}M862.1 T1 P{nozzle_diameter[1]} A{(filament_abrasive[1] ? 1 : 0)} F{(nozzle_high_flow[1] ? 1 : 0)}{endif}
{if (is_extruder_used[2])}M862.1 T2 P{nozzle_diameter[2]} A{(filament_abrasive[2] ? 1 : 0)} F{(nozzle_high_flow[2] ? 1 : 0)}{endif}
{if (is_extruder_used[3])}M862.1 T3 P{nozzle_diameter[3]} A{(filament_abrasive[3] ? 1 : 0)} F{(nozzle_high_flow[3] ? 1 : 0)}{endif}
{if (is_extruder_used[4])}M862.1 T4 P{nozzle_diameter[4]} A{(filament_abrasive[4] ? 1 : 0)} F{(nozzle_high_flow[4] ? 1 : 0)}{endif}
; turn off unused heaters
{if ! is_extruder_used[0]}M104 T0 S0{endif}
{if ! is_extruder_used[1]}M104 T1 S0{endif}
{if num_extruders > 2 and ! is_extruder_used[2]}M104 T2 S0{endif}
{if num_extruders > 3 and ! is_extruder_used[3]}M104 T3 S0{endif}
{if num_extruders > 4 and ! is_extruder_used[4]}M104 T4 S0{endif}
M217 Z{max(zhop, 2.0)} ; set toolchange z hop to 2mm, or zhop variable from slicer if higher
; set bed and extruder temp for MBL
M140 S[first_layer_bed_temperature] ; set bed temp
M104 T{initial_tool} S{((filament_notes[initial_tool]=~/.*MBL160.*/) ? 160 : (filament_notes[initial_tool]=~/.*HT_MBL10.*/) ? (first_layer_temperature[initial_tool] - 10) : (filament_type[initial_tool] == "PC" or filament_type[initial_tool] == "PA") ? (first_layer_temperature[initial_tool] - 25) : (filament_type[initial_tool] == "FLEX") ? 210 : (filament_type[initial_tool]=~/.*PET.*/) ? 175 : 170)} ; set temp
; Home XY
G28 XY
; try picking tools used in print
G1 F{travel_speed * 60}
{if (is_extruder_used[0]) and (initial_tool != 0)}T0 S1 L0 D0{endif}
{if (is_extruder_used[1]) and (initial_tool != 1)}T1 S1 L0 D0{endif}
{if (is_extruder_used[2]) and (initial_tool != 2)}T2 S1 L0 D0{endif}
{if (is_extruder_used[3]) and (initial_tool != 3)}T3 S1 L0 D0{endif}
{if (is_extruder_used[4]) and (initial_tool != 4)}T4 S1 L0 D0{endif}
; select tool that will be used to home & MBL
T{initial_tool} S1 L0 D0
; HERE THE TOOL HAS TO WAIT PURELY BECAUSE OF SILICONE BRUSH
G1 Z30
G1 X145 Y-8 F{travel_speed * 60}
M109 T{initial_tool} S{((filament_notes[initial_tool]=~/.*MBL160.*/) ? 160 : (filament_notes[initial_tool]=~/.*HT_MBL10.*/) ? (first_layer_temperature[initial_tool] - 10) : (filament_type[initial_tool] == "PC" or filament_type[initial_tool] == "PA") ? (first_layer_temperature[initial_tool] - 25) : (filament_type[initial_tool] == "FLEX") ? 210 : (filament_type[initial_tool]=~/.*PET.*/) ? 175 : 170)} ; wait for temp
; home Z with MBL tool
M84 E ; turn off E motor
G28 Z
G0 Z5 ; add Z clearance
; HERE THE TOOL HAS TO WAIT PURELY BECAUSE OF SILICONE BRUSH
G1 Z30
G1 X145 Y-8 F{travel_speed * 60}
M104 T{initial_tool} S{if is_nil(idle_temperature[initial_tool])}70{else}{idle_temperature[initial_tool]}{endif} ; set idle temp
M190 S[first_layer_bed_temperature] ; wait for bed temp
G29 G ; absorb heat
M109 T{initial_tool} S{((filament_notes[initial_tool]=~/.*MBL160.*/) ? 160 : (filament_notes[initial_tool]=~/.*HT_MBL10.*/) ? (first_layer_temperature[initial_tool] - 10) : (filament_type[initial_tool] == "PC" or filament_type[initial_tool] == "PA") ? (first_layer_temperature[initial_tool] - 25) : (filament_type[initial_tool] == "FLEX") ? 210 : (filament_type[initial_tool]=~/.*PET.*/) ? 175 : 170)} ; wait for temp
M300 S800 P200. ; PIEP indicator
; move to the nozzle cleanup area
; Surfalex2000 Nozzle Brush Mount on Printables
; https://www.printables.com/model/644817-prusa-xl-series-front-nozzle-srcubber-for-use-with
G1 E-10 F2400 ; more retraction to compensate oozing before nozzle cleanup
; Start surfalex2000 nozzle brush cycle
; --- Start nozzle brush cycle (speed ramp) ---
G1 X160 Y-5 Z5 F8000
G1 X160 Y-5 Z1 F8000
; --- Zyklus 1 (langsam) ---
G1 X200 Y-5 F8000
G1 X200 Y-4
G1 X160 Y-4
G1 X160 Y-6
G1 X200 Y-6
G1 X200 Y-5
G1 X160 Y-5
; --- Zyklus 2 (mittel) ---
G1 X200 Y-5 F14000
G1 X200 Y-4
G1 X160 Y-4
G1 X160 Y-6
G1 X200 Y-6
G1 X200 Y-5
G1 X160 Y-5
; --- Zyklus 3 (schnell) ---
G1 X200 Y-5 F16000
G1 X200 Y-4
G1 X160 Y-4
G1 X160 Y-6
G1 X200 Y-6
G1 X200 Y-5
G1 X160 Y-5
; --- Zyklus 4 (schnell) ---
G1 X200 Y-5 F20000
G1 X200 Y-4
G1 X160 Y-4
G1 X160 Y-6
G1 X200 Y-6
G1 X200 Y-5
G1 X160 Y-5
G1 X160 Y-5 Z5 F20000 ; nozzle brush cycle
; End surfalex2000 nozzle brush cycle
; nozzle cleanup FOR LEFT AND RIGHT SILICONE WIPER
M302 S155 ; lower cold extrusion limit to 155C
G1 E{-(filament_type[0] == "FLEX" ? 4 : 2)} F2400 ; retraction for nozzle cleanup
M84 E ; turn off E motor
; --- Start Nozzle Wipe
G1 Z5 ; Move bed out of the way
{if initial_tool == 0 or initial_tool == 1 }
; --- Start Nozzle Wipe LEFT ---
G1 X-2 Y-8 F24000 ; Move to start of wipe area
G1 X28 Y-8 F24000 ; Wipe pass 1
G1 X-2 Y-7.5 F24000 ; Reposition
G1 X28 Y-7.5 F24000 ; Wipe pass 2
G1 X-2 Y-7 F24000 ; Reposition
G1 X28 Y-7 F24000 ; Wipe pass 3
G1 X-2 Y-6.5 F24000 ; Reposition
G1 X28 Y-6.5 F24000 ; Wipe pass 4
G1 X-2 Y-6 F24000 ; Reposition
G1 X28 Y-6 F24000 ; Wipe pass 5
G1 X-2 Y-6.5 F24000 ; Reposition
G1 X28 Y-6.5 F24000 ; Wipe pass 6
G1 X-2 Y-7 F24000 ; Reposition
G1 X28 Y-7 F24000 ; Wipe pass 7
G1 X-2 Y-7.5 F24000 ; Reposition
G1 X28 Y-7.5 F24000 ; Wipe pass 8
G1 X-2 Y-8 F24000 ; Reposition
G1 X28 Y-8 F24000 ; Wipe pass 9
; --- End Nozzle Wipe LEFT ---
{else}
; --- Start Nozzle Wipe RIGHT ---
G1 X332 Y-8 F24000 ; Move to start of wipe area
G1 X361 Y-8 F24000 ; Wipe pass 1
G1 X332 Y-7.5 F24000 ; Reposition
G1 X361 Y-7.5 F24000 ; Wipe pass 2
G1 X332 Y-7 F24000 ; Reposition
G1 X361 Y-7 F24000 ; Wipe pass 3
G1 X332 Y-6.5 F24000 ; Reposition
G1 X361 Y-6.5 F24000 ; Wipe pass 4
G1 X332 Y-6 F24000 ; Reposition
G1 X361 Y-6 F24000 ; Wipe pass 5
G1 X332 Y-6.5 F24000 ; Reposition
G1 X361 Y-6.5 F24000 ; Wipe pass 6
G1 X332 Y-7 F24000 ; Reposition
G1 X361 Y-7 F24000 ; Wipe pass 7
G1 X332 Y-7.5 F24000 ; Reposition
G1 X361 Y-7.5 F24000 ; Wipe pass 8
G1 X332 Y-8 F24000 ; Reposition
G1 X361 Y-8 F24000 ; Wipe pass 9
; --- End Nozzle Wipe RIGHT ---
{endif}
G1 X{(min(((((first_layer_print_min[0] + first_layer_print_max[0]) / 2) < ((print_bed_min[0] + print_bed_max[0]) / 2)) ? (((first_layer_print_min[1] - 7) < -2) ? 70 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)) : (((first_layer_print_min[1] - 7) < -2) ? 260 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32))), first_layer_print_min[0])) + 32} Y{(min((first_layer_print_min[1] - 7), first_layer_print_min[1]))} Z{5} F{(travel_speed * 60)}
; nozzle cleanup
;Commented out below because it sets the temperature too high in front of the MBL.
;G29 P9 X{((((first_layer_print_min[0] + first_layer_print_max[0]) / 2) < ((print_bed_min[0] + print_bed_max[0]) / 2)) ? (((first_layer_print_min[1] - 7) < -2) ? 70 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)) : (((first_layer_print_min[1] - 7) < -2) ? 260 : (min(print_bed_max[0], first_layer_print_min[0] + 32) - 32)))} Y{(first_layer_print_min[1] - 7)} W{32} H{7}
M107 ; turn off the fan
; MBL
M84 E ; turn off E motor
G29 P1 ; invalidate mbl & probe print area
G29 P1 X30 Y0 W{(((is_extruder_used[4]) or ((is_extruder_used[3]) or (is_extruder_used[2]))) ? "300" : ((is_extruder_used[1]) ? "130" : "50"))} H20 C ; probe near purge place
G29 P3.2 ; interpolate mbl probes
G29 P3.13 ; extrapolate mbl outside probe area
G29 A ; activate mbl
G1 Z10 F720 ; move away in Z
G1 F{travel_speed * 60}
P0 S1 L1 D0; park the tool
; set extruder temp
{if first_layer_temperature[0] > 0 and (is_extruder_used[0])}M104 T0 S{first_layer_temperature[0]}{endif}
{if first_layer_temperature[1] > 0 and (is_extruder_used[1])}M104 T1 S{first_layer_temperature[1]}{endif}
{if first_layer_temperature[2] > 0 and (is_extruder_used[2])}M104 T2 S{first_layer_temperature[2]}{endif}
{if first_layer_temperature[3] > 0 and (is_extruder_used[3])}M104 T3 S{first_layer_temperature[3]}{endif}
{if first_layer_temperature[4] > 0 and (is_extruder_used[4])}M104 T4 S{first_layer_temperature[4]}{endif}
{if (is_extruder_used[0]) and initial_tool != 0}
M591 S0 ; disable stuck detection
; Ready to print melody, before purging
M300 S1200 P150
G4 P200
M300 S1500 P150
G4 P200
M300 S1800 P300
G4 P500
;
; purge first tool
; Edited. X position changed from 30 to 33 due to silicone brush.
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T0 S{first_layer_temperature[0]}
T0 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X33 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[0])}10{else}30{endif} X40 Z0.2 F{if is_nil(filament_multitool_ramming[0])}500{else}170{endif} ; purge while moving towards the sheet
G0 X70 E9 F800 ; continue purging and wipe the nozzle
G0 X73 Z0.05 F8000 ; wipe, move close to the bed
G0 X76 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[0]} F2400 ; retract
{e_retracted[0] = retract_length_toolchange[0]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[0]) ? (first_layer_temperature[0] + standby_temperature_delta) : (idle_temperature[0]))} T0
{endif}
{if (is_extruder_used[1]) and initial_tool != 1}
;
; purge second tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T1 S{first_layer_temperature[1]}
T1 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X150 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[1])}10{else}30{endif} X140 Z0.2 F{if is_nil(filament_multitool_ramming[1])}500{else}170{endif} ; purge while moving towards the sheet
G0 X110 E9 F800 ; continue purging and wipe the nozzle
G0 X107 Z0.05 F8000 ; wipe, move close to the bed
G0 X104 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[1]} F2400 ; retract
{e_retracted[1] = retract_length_toolchange[1]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[1]) ? (first_layer_temperature[1] + standby_temperature_delta) : (idle_temperature[1]))} T1
{endif}
{if (is_extruder_used[2]) and initial_tool != 2}
;
; purge third tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T2 S{first_layer_temperature[2]}
T2 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X210 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[2])}10{else}30{endif} X220 Z0.2 F{if is_nil(filament_multitool_ramming[2])}500{else}170{endif} ; purge while moving towards the sheet
G0 X250 E9 F800 ; continue purging and wipe the nozzle
G0 X253 Z0.05 F8000 ; wipe, move close to the bed
G0 X256 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[2]} F2400 ; retract
{e_retracted[2] = retract_length_toolchange[2]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[2]) ? (first_layer_temperature[2] + standby_temperature_delta) : (idle_temperature[2]))} T2
{endif}
{if (is_extruder_used[3]) and initial_tool != 3}
;
; purge fourth tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T3 S{first_layer_temperature[3]}
T3 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X327 Y-7 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[3])}10{else}30{endif} X320 Z0.2 F{if is_nil(filament_multitool_ramming[3])}500{else}170{endif} ; purge while moving towards the sheet
G0 X290 E9 F800 ; continue purging and wipe the nozzle
G0 X287 Z0.05 F8000 ; wipe, move close to the bed
G0 X284 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[3]} F2400 ; retract
{e_retracted[3] = retract_length_toolchange[3]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[3]) ? (first_layer_temperature[3] + standby_temperature_delta) : (idle_temperature[3]))} T3
{endif}
{if (is_extruder_used[4]) and initial_tool != 4}
;
; purge fifth tool
; Edited. X position for TOOL 4 changed from 330 to 327 due to silicone brush.
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T4 S{first_layer_temperature[4]}
T4 S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
G0 X327 Y-4.5 Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[4])}10{else}30{endif} X320 Z0.2 F{if is_nil(filament_multitool_ramming[4])}500{else}170{endif} ; purge while moving towards the sheet
G0 X290 E9 F800 ; continue purging and wipe the nozzle
G0 X287 Z0.05 F8000 ; wipe, move close to the bed
G0 X284 Z0.2 F8000 ; wipe, move quickly away from the bed
G1 E{-retract_length_toolchange[4]} F2400 ; retract
{e_retracted[4] = retract_length_toolchange[4]}
G92 E0 ; reset extruder position
M104 S{(is_nil(idle_temperature[4]) ? (first_layer_temperature[4] + standby_temperature_delta) : (idle_temperature[4]))} T4
{endif}
;
; purge initial tool
;
G1 F{travel_speed * 60}
P0 S1 L2 D0; park the tool
M109 T{initial_tool} S{first_layer_temperature[initial_tool]}
T{initial_tool} S1 L0 D0; pick the tool
G92 E0 ; reset extruder position
; Edited. X position for TOOL 0 changed from 30 to 33 due to silicone brush.
; Edited. X position for TOOL 4 changed from 330 to 327 due to silicone brush.
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327)))} Y{(initial_tool < 4 ? -7 : -4.5)} Z10 F{(travel_speed * 60)} ; move close to the sheet's edge
G0 E{if is_nil(filament_multitool_ramming[initial_tool])}10{else}30{endif} X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 10)} Z0.2 F{if is_nil(filament_multitool_ramming[initial_tool])}500{else}170{endif} ; purge while moving towards the sheet
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 40)} E9 F800 ; continue purging and wipe the nozzle
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 40) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 3)} Z{0.05} F{8000} ; wipe, move close to the bed
G0 X{(initial_tool == 0 ? 33 : (initial_tool == 1 ? 150 : (initial_tool == 2 ? 210 : 327))) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 40) + ((initial_tool == 0 or initial_tool == 2 ? 1 : -1) * 3 * 2)} Z0.2 F{8000} ; wipe, move quickly away from the bed
G1 E-{retract_length[initial_tool]} F2400 ; retract
{e_retracted[initial_tool] = retract_length[initial_tool]}
M591 R ; restore stuck detection
G92 E0 ; reset extruder position

The author remixed this model.
Choose between models with magnets that can be glued or inserted, or models without magnets that are permanently attached. Select from small or large silicone brushes and choose the appropriate hole size for mounting. Whatever you want :)