Search models, users, collections, and posts

Voron Trident Bambu-style nozzle wiper, modified with servo-driven baffle

Remixed by
GIF

Print Profile(1)

All
A1
X1
H2D
X1E
P1S
A1 mini
H2S
H2C
X2D
X1 Carbon
P2S
H2D Pro
P1P
A2L

0.2mm layer, 2 walls, 15% infill
0.2mm layer, 2 walls, 15% infill
Designer
1.5 h
1 plate

Open in Bambu Studio
Boost
2
0
0
0
1
0
Released 

Description

Content has been automatically translated.
Show original

A version of Big Horse's nozzle wiper has been modified to use a servo to drive the baffle up and down, which eliminates the need to print TPU parts. It is also no longer limited by printhead type (actually, the main point is no longer having to use the toolhead to hit the push rod; I've broken five push rods). For the complete nozzle wiper model, get it from Big Horse's Bilibili channel: https://www.bilibili.com/video/BV1nPWZzuE9g. You no longer need to print the push rod; you only need to print the waste bucket and the baffle.

 

Also, I'm providing a gcode for Rabbit Multi-color adapted from this nozzle wiper model. Note that you need to modify the parameters. It mainly has the following functions:

  1. Servo adaptation
  2. Supports Rabbit Multi-color to pass in extrusion length
  3. Pulse extrusion

Rabbit Multi-color modifies mmu/base/mmu_parameters.cfg

force_purge_standalone: 1         # 0 = Slicer wipetower in print else standalone, 1 = Always standalone purging (TURN WIPETOWER OFF!)
purge_macro: WIPE_NOZZLE            # Name of macro to call to perform the standalone purging operation. E.g. BLOBIFIER, _MMU_PURGE
extruder_purge_current: 120        # % of extruder current (100%-150%) to use when purging (100 to disable)

 

wipe_nozzle.cfg

[servo nozzle]
pin: PA14
minimum_pulse_width: 0.0005
maximum_pulse_width: 0.0024
maximum_servo_angle: 180
initial_angle: 0

[gcode_macro WIPE_CONFIG]
# This macro is only for storing parameters, not for executing any G-code
# Please configure the following parameters
variable_ptfe_x: 239                # X-coordinate for purging waste
variable_ptfe_y: 310                # Y-coordinate for purging waste
variable_wipe_x: 250                # Nozzle wipe X-coordinate
variable_wipe_y: 310                # Nozzle wipe Y-coordinate

variable_servo_angle_default: 0     # Servo default angle
variable_servo_angle_wipe: 90       # Servo angle for raising baffle

# Extrusion length calculation parameters ported from Blobifier. The default is fine; if you think the extrusion is too much or too little, adjust variable_purge_length_modifier
variable_purge_length_minimum: 30   # Minimum purge length (mm), ensures purge_len is not less than this value
variable_purge_length: 150          # Default purge length (mm), used when there is no slicer mapping
variable_purge_length_modifier: 1   # Switching volume correction factor, scales the purge volume provided by the slicer
variable_purge_length_addition: 0   # Additional compensation length (mm), added to the calculated purge length
variable_purge_spd: 400             # Pulse fast segment feed rate (F, mm/min)
variable_purge_temp_min: 200        # Minimum nozzle temperature (°C) before purging
variable_purge_pulse_mm: 5          # Target length per pulse (mm), determines the number of pulses
gcode:
   # Deliberately left blank


[gcode_macro WIPE_NOZZLE]
description: Wipe nozzle for filament change

gcode:
   # ======================================================================================
   # ==================== RECORD STATE (INCL. FANS, SPEEDS, ETC...) =======================
   # ======================================================================================
   
   SAVE_GCODE_STATE NAME=WIPE_NOZZLE_state
   
   {% set cfg = printer["gcode_macro WIPE_CONFIG"] %}
   {% set sequence_vars = printer['gcode_macro _MMU_SEQUENCE_VARS'] %}
   {% set park_vars = printer['gcode_macro _MMU_PARK'] %}
   
   # Save feed rate to restore later
   {% set backup_feedrate = printer.gcode_move.speed_factor %}
   # Set feed rate to 100% to ensure correct extrusion speed
   M220 S100
   
   # Save part cooling fan speed to restore later
   {% set backup_fan_speed = printer.fan.speed %}
   
   # ======================================================================================
   # ==================== EXTRUSION LENGTH CALCULATION LOGIC ================================
   # ======================================================================================
   
   # Extrusion length calculation logic ported from Blobifier
   {% 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 %}
   
   # Get purge volume (if correct slicer is set)
   {% set pv = printer.mmu.slicer_tool_map.purge_volumes %}
   
   # Determine extrusion length
   {% if from_tool == to_tool and to_tool >= 0 %}
       {action_respond_info("WIPE_NOZZLE: Tool not changed (T%s > T%s), %s" % (from_tool, to_tool, "priming" if cfg.purge_length_minimum else "skipping"))}
       {% set purge_len = 0 %}
   {% elif pv %}
       {% if from_tool < 0 and to_tool >= 0%}
           {action_respond_info("WIPE_NOZZLE: Source tool unknown. Seeking max for T? > T%d" % to_tool)}
           {% set purge_vol = pv|map(attribute=to_tool)|max %}
       {% elif to_tool < 0 %}
           {action_respond_info("WIPE_NOZZLE: Tool unknown. Seeking max")}
           {% set purge_vol = pv|map('max')|max %}
       {% else %}
           {% set purge_vol = pv[from_tool][to_tool]|float * cfg.purge_length_modifier %}
           {action_respond_info("WIPE_NOZZLE: Switching 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 + cfg.purge_length_addition %}
   {% else %}
       {action_respond_info("WIPE_NOZZLE: No tool mapping. Using default value")}
       {% set purge_len = cfg.purge_length|float + printer.mmu.extruder_filament_remaining + park_vars.retracted_length %}
   {% endif %}
   
   # Apply minimum extrusion length
   {% set purge_len = [purge_len, cfg.purge_length_minimum]|max|round(0, 'ceil')|int %}
   {action_respond_info("WIPE_NOZZLE: Extruding %dmm of filament" % (purge_len))}
   
   # Skip if no extrusion is needed
   {% if purge_len <= 0 %}
       {action_respond_info("WIPE_NOZZLE: No extrusion needed, skipping")}
       RESTORE_GCODE_STATE NAME=WIPE_NOZZLE_state
       M99
   {% endif %}
   
   # Calculate extrusion per pulse
   {% set pulses_count = (purge_len / cfg.purge_pulse_mm)|round(0, 'ceil')|int %}
   {% set purge_per_pulse = purge_len / pulses_count %}

   G90                         # All axes use absolute positioning
   M83                         # Extruder uses relative positioning

   ##------0. Servo raises baffle
   SET_SERVO SERVO=nozzle ANGLE={cfg.servo_angle_wipe | int}  # Switch angle according to the passed parameter
   G4 P500
   SET_SERVO SERVO=nozzle WIDTH=0
   
   ##------1. Move to purge waste coordinates
   G1 X{cfg.ptfe_x} Y{cfg.ptfe_y-50} F6000
   M400
   G1 X{cfg.ptfe_x} Y{cfg.ptfe_y} F6000
   
   ##------2. Heat nozzle to ensure sufficient temperature
   {% if printer.extruder.temperature < cfg.purge_temp_min %}
       {% if printer.extruder.target < cfg.purge_temp_min %}
           M109 S{cfg.purge_temp_min}
       {% else %}
           TEMPERATURE_WAIT SENSOR=extruder MINIMUM={cfg.purge_temp_min}
       {% endif %}
   {% endif %}
   
   ##------3. Extrude filament using pulse method (ported from Blobifier)
   G92 E0              # Reset extruder
   
   {action_respond_info("WIPE_NOZZLE: Extruding with pulses, total %d pulses" % pulses_count)}
   
   # Extrude with pulses
   {% for pulse in range(pulses_count) %}
       # Fast extrusion
       G1 E{purge_per_pulse * 0.95} F{cfg.purge_spd}
       # Slow extrusion
       G1 E{purge_per_pulse * 0.05} F50
       
       # Retract every 5 pulses for thorough cleaning
       {% if pulse % 5 == 0 and pulse > 0 %}
           G1 E-2 F1800
           G1 E2 F800
       {% endif %}
   {% endfor %}

   ##------4. Lower servo
   SET_SERVO SERVO=nozzle ANGLE={cfg.servo_angle_default | int}  # Switch angle according to the passed parameter
   G4 P500
   SET_SERVO SERVO=nozzle WIDTH=0
   
   M106 S255           # Fan full on
   G4 P4000            # Dwell P<milliseconds>
   G1 Y{cfg.wipe_y} F3000
   M400
   
   ##------5. Shake nozzle
   {% for wipes in range(1, 7) %}
       G1 X{cfg.ptfe_x+10} F15000
       G1 X{cfg.ptfe_x-10} F15000
   {% endfor %}

   ##------6. Wipe nozzle
   {% for wipes in range(1, 7) %}
       G1 X{cfg.wipe_x + 10} F5000
       G1 X{cfg.wipe_x - 10} F15000
   {% endfor %}

   # G92 E0
   M400
   
   # ======================================================================================
   # ==================== RESTORE STATE ===================================================
   # ======================================================================================
   
   # Retract to match Happy Hare's expectations
   {action_respond_info("WIPE_NOZZLE: Final retract length: %d mm" % (park_vars.retracted_length))}
   G1 E-{park_vars.retracted_length*0.9} F{sequence_vars.retract_speed * 60}
   
   # Restore part cooling fan speed
   M106 S{(backup_fan_speed * 255)|int}
   
   # Restore feed rate
   M220 S{(backup_feedrate * 100)|int}
   
   # Restore G-code state
   RESTORE_GCODE_STATE NAME=WIPE_NOZZLE_state
 

Comment & Rating (0)

(0/1000)