############################################################################# # NOZZLE CLEAN CODE ############################################################################# # ------------------------------------------------------------------------ # !!! DO NOT EDIT THIS FILE !!! - Changes below are unsupported # ------------------------------------------------------------------------ [gcode_macro CLEAN_NOZZLE] description: Nozzle cleaning using a brush gcode: # ------------------------------------------------------------------------ # LOAD SETTINGS # ------------------------------------------------------------------------ # Load variables from KNCM_settings.cfg {% set KNCM_SETTINGS = printer['gcode_macro _KNCM_SETTINGS'] %} # cleaningHeight {% set cleaningHeight = KNCM_SETTINGS.cleaning_height %} # wipingAxis {% set wipingAxis = KNCM_SETTINGS.wiping_axis %} # printerBedYMax {% set printerBedYMax = KNCM_SETTINGS.printer_bed_y_max %} # cleaningLoops {% set cleaningLoops = KNCM_SETTINGS.cleaning_loops %} # purgeSHake {% set purgeShake = KNCM_SETTINGS.purge_shake %} # waitNozzleTempRestore {% set waitNozzleTempRestore = KNCM_SETTINGS.wait_nozzle_temp_restore %} # debug {% set debug = KNCM_SETTINGS.debug %} # acceleration {% set acceleration = KNCM_SETTINGS.acceleration %} # speed {% set travelSpeed = KNCM_SETTINGS.travel_speed %} {% set slowSpeed = KNCM_SETTINGS.slow_speed %} {% set fastSpeed = KNCM_SETTINGS.fast_speed %} # cleaningTemperatures {% set cleaningTemperatures = KNCM_SETTINGS.cleaning_temperatures %} # wiperWidth {% set wiperWidth = KNCM_SETTINGS.wiper_width %} # wiperLength {% set wiperLength = KNCM_SETTINGS.wiper_length %} # wiperWallOffset {% set wiperWallOffset = KNCM_SETTINGS.wiper_walloffset %} # bedCornerToWiperOffset {% set bedCornerToWiperOffset = KNCM_SETTINGS.bed_corner_to_wiper_offset %} # waves {% set waves = KNCM_SETTINGS.waves %} # ------------------------------------------------------------------------ # DEBUG MESSAGE - LOADED VARIABLES # ------------------------------------------------------------------------ {% if debug == 1 %} RESPOND MSG="INFO: loaded Variables" RESPOND MSG=" - cleaningHeight : { cleaningHeight }" RESPOND MSG=" - wipingAxis : { wipingAxis }" RESPOND MSG=" - printerBedYMax : { printerBedYMax }" RESPOND MSG=" - cleaningLoops : { cleaningLoops }" RESPOND MSG=" - purgeShake : { purgeShake }" RESPOND MSG=" - waitNozzleTempRestore : { waitNozzleTempRestore }" RESPOND MSG=" - debug : { debug }" RESPOND MSG=" - wiperWidth : { wiperWidth }" RESPOND MSG=" - wiperLength : { wiperLength }" RESPOND MSG=" - wiperWallOffset : { wiperWallOffset }" RESPOND MSG=" - bedCornerToWiperOffset : { bedCornerToWiperOffset }" RESPOND MSG=" - waves : { waves }" RESPOND MSG=" - acceleration : { acceleration }" RESPOND MSG=" - travelSpeed : { travelSpeed }" RESPOND MSG=" - slowSpeed : { slowSpeed }" RESPOND MSG=" - fastSpeed : { fastSpeed }" RESPOND MSG=" - cleaningTemperatures : { cleaningTemperatures }" {% endif %} # ------------------------------------------------------------------------ # INITIALIZE, CHECK AND PROCESS VARIABLES # ------------------------------------------------------------------------ {% set filamentType = params.FILAMENT_TYPE|default("PLA")|string|upper %} # Set filamentType to the provided variable (fallback to PLA) {% set error = 0 %} # Initialize error variable {% if wipingAxis not in ["x", "X", "y", "Y"] %} # Check for a valid wipingAxis RESPOND MSG="ERROR: Wiping axis configuration error. Please check your wipingAxis setting!" {% set error = 1 %} {% endif %} {% if wipingAxis in ["x", "X"] %} # Check clearances for cleaning with head movements {% if ((printer.toolhead.axis_maximum.y - printerBedYMax) < 3.2) %} RESPOND MSG="ERROR: Insufficient vertical clearance between printerBedYMax ({printerBedYMax}) and nozzle max Y ({printer.toolhead.axis_maximum.y}). Minimum required: 3.2mm." {% set error = 1 %} {% endif %} {% if ((printerBedYMax < 1) or ((printerBedYMax > 1000))) %} RESPOND MSG="ERROR: Printer bed Y-axis size ({printerBedYMax}) out of expected range. Please verify configuration." {% set error = 1 %} {% endif %} {% elif ((printer.configfile.config.stepper_x.position_endstop|float + 3.2) > 0) %} # Check clearances for cleaning with bed movements RESPOND MSG="ERROR: X homing sensor position ({printer.configfile.config.stepper_x.position_endstop}) is too close to the bed. Required: ≤ -3.2mm." {% set error = 1 %} {% endif %} {% if cleaningLoops < 1 %} # Check if cleaningLoops is set to a minimum of 1 loop RESPOND MSG="WARNING: cleaningLoops set to false value:{cleaningLoops} - changed to default 1 " {% set cleaningLoops = 1 %} {% endif %} {% if wipingAxis in ["y", "Y"] %} # Cleaning using bed movement {% set wiperYmax = printerBedYMax %} {% if wiperWidth + wiperWallOffset + printer.configfile.config.stepper_x.position_endstop|float > 0 %} # limited clearance {% set wiperXmin = printer.configfile.config.stepper_x.position_endstop|float %} {% set wiperWidth = 0 - wiperWallOffset - printer.configfile.config.stepper_x.position_endstop|float %} {% else %} {% set wiperXmin = 0 - wiperWallOffset - wiperWidth %} {% endif %} {% else %} # Cleaning using head movement {% set wiperXmin = bedCornerToWiperOffset %} {% if printer.toolhead.axis_maximum.y - printerBedYMax - wiperWallOffset - wiperWidth < 0 %} {% set wiperYmax = printer.toolhead.axis_maximum.y %} {% set wiperWidth = printer.toolhead.axis_maximum.y - printerBedYMax - wiperWallOffset %} {% else %} {% set wiperYmax = printerBedYMax + wiperWallOffset + wiperWidth %} {% endif %} {% endif %} {% if acceleration != 0 %} {% if acceleration > printer.configfile.config['printer']['max_accel']|float %} {% set accelerationValidated = printer.configfile.config['printer']['max_accel']|float %} {% else %} {% set accelerationValidated = acceleration %} {% endif %} {% endif %} {% if travelSpeed > printer.configfile.config['printer']['max_velocity'] | float %} {% set travelSpeed = printer.configfile.config['printer']['max_velocity'] | float %} {% endif %} {% set travelFeedrate = travelSpeed * 60 %} # Convert travelSpeed to travelFeedrate {% if slowSpeed > printer.configfile.config['printer']['max_velocity'] | float %} {% set slowSpeed = printer.configfile.config['printer']['max_velocity'] | float / 2 %} {% endif %} {% set slowFeedrate = slowSpeed * 60 %} # Convert slowSpeed to slowFeedrate {% if fastSpeed > printer.configfile.config['printer']['max_velocity'] | float %} {% set fastSpeed = printer.configfile.config['printer']['max_velocity'] | float %} {% endif %} {% set fastFeedrate = fastSpeed * 60 %} # Convert fastSpeed to fastFeedrate {% if debug == 1 %} RESPOND MSG="INFO: processed Variables" RESPOND MSG=" - wiperYmax : { wiperYmax }" RESPOND MSG=" - wiperXmin : { wiperXmin }" RESPOND MSG=" - wiperWidth : { wiperWidth }" RESPOND MSG=" - acceleration : { accelerationValidated }" RESPOND MSG=" - travelFeedrate : F{ travelFeedrate }" RESPOND MSG=" - slowFeedrate : F{ slowFeedrate }" RESPOND MSG=" - fastFeedrate : F{ fastFeedrate }" {% endif %} # ------------------------------------------------------------------------ # ERROR CHECK # ------------------------------------------------------------------------ {% if error == 0 %} # Continue only if error is zero # ------------------------------------------------------------------------ # SET CLEANING ACCELERATION # ------------------------------------------------------------------------ {% if acceleration != 0 %} SET_VELOCITY_LIMIT ACCEL={accelerationValidated} {% endif %} # ------------------------------------------------------------------------ # HOMING PROCESS # ------------------------------------------------------------------------ {% if "x" not in printer.toolhead.homed_axes and "y" not in printer.toolhead.homed_axes and "z" not in printer.toolhead.homed_axes %} G28 {% elif "x" not in printer.toolhead.homed_axes %} G28 X {% elif "y" not in printer.toolhead.homed_axes %} G28 Y {% elif "z" not in printer.toolhead.homed_axes %} G28 Z {% endif %} # ------------------------------------------------------------------------ # SAVE Z AXIS POSITION # ------------------------------------------------------------------------ {% set zHeight = printer.toolhead.position.z %} {% if zHeight == 0 %} {% set zHeight = 10 %} {% set travelHeight = zHeight %} {% else %} {% set travelHeight = zHeight + 10 %} {% if travelHeight > printer.toolhead.axis_maximum.z|float %} {% set travelHeight = printer.toolhead.axis_maximum.z|float -10 %} {% endif %} {% endif %} {% if debug == 1 %} RESPOND MSG="INFO: travelHeight set to {travelHeight}" {% endif %} # ------------------------------------------------------------------------ # CHECK FOR BLENDED FILAMENTS # ------------------------------------------------------------------------ {% if "-" in filamentType %} {% set baseFilament = filamentType.split("-")[0] %} {% set stringSplitted = 1 %} {% else %} {% set baseFilament = filamentType %} {% set stringSplitted = 0 %} {% endif %} # ------------------------------------------------------------------------ # EVALUATE CLEANING TEMPERATURE # ------------------------------------------------------------------------ {% if baseFilament in cleaningTemperatures %} {% set cleaningTemperature = cleaningTemperatures[baseFilament] %} {% if debug == 1 %} {% if stringSplitted == 0 %} RESPOND MSG="INFO: Detected filament type {filamentType}. Cleaning temperature set to {cleaningTemperature}c." {% else %} RESPOND MSG="INFO: Detected filament type {filamentType} (base: {baseFilament}). Cleaning temperature set to {cleaningTemperature}c." {% endif %} {% endif %} {% else %} {% set cleaningTemperature = 140 %} RESPOND MSG="WARNING: Unknown filament type {filamentType}. Default cleaning temperature of {cleaningTemperature}c will be used." {% endif %} # ------------------------------------------------------------------------ # SAVE NOZZLE TARGET TEMPERATURE # ------------------------------------------------------------------------ {% set nozzleTargetTemperature = printer['extruder'].target %} # ------------------------------------------------------------------------ # HEAT EXTRUDER # ------------------------------------------------------------------------ {% if cleaningTemperature != nozzleTargetTemperature %} SET_HEATER_TEMPERATURE HEATER=extruder TARGET={cleaningTemperature} {% if debug == 1 %} RESPOND MSG="INFO: Heating extruder to {cleaningTemperature}c for cleaning..." {% endif %} TEMPERATURE_WAIT SENSOR=extruder MINIMUM={cleaningTemperature-4} MAXIMUM={cleaningTemperature+10} {% endif %} # ------------------------------------------------------------------------ # CLEANING SEQUENCE # ------------------------------------------------------------------------ {% if debug == 1 %} RESPOND MSG="INFO: Initiating nozzle cleaning sequence..." {% endif %} # ------------------------------------------------------------------------ # Purge Shake # ------------------------------------------------------------------------ {% if purgeShake == 1 %} # Travel to PurgeShake position G90 G1 Z{travelHeight} F3000 {% if wipingAxis in ["y", "Y"] %} {% if debug == 1 %} RESPOND MSG="INFO: Shaking movement starting at X=0, Y={printerBedYMax-1} (1mm safety margin)." {% endif %} G1 X0 Y{printerBedYMax-1} F{travelFeedrate} {% else %} {% if debug == 1 %} RESPOND MSG="INFO: Shaking movement starting at X={bedCornerToWiperOffset+wiperLength+1}, Y={printerBedYMax-1} (1mm safety margin)." {% endif %} G1 X{bedCornerToWiperOffset+wiperLength+1} Y{printerBedYMax-1} F{travelFeedrate} {% endif %} # Quick left/right movements to clear filament strings G91 G1 X20 F{fastFeedrate} G1 X-20 G1 X20 G1 X-20 G1 X20 G1 X-20 {% endif %} # ------------------------------------------------------------------------ # Nozzle cleaning # ------------------------------------------------------------------------ {% if wipingAxis in ["y", "Y"] %} # --- BED MOVEMENT CLEANING SEQUENCE --- {% if debug == 1 %} RESPOND MSG="INFO: Repeating cleaning motions for {cleaningLoops} times" {% if wiperXmin == printer.configfile.config.stepper_x.position_endstop|float %} RESPOND MSG="INFO: Starting first cleaning passes near X endstop at X={wiperXmin+0.2}, Y={wiperYmax} (limited X clearance)." {% else %} RESPOND MSG="INFO: Starting first cleaning passes at X={wiperXmin+(wiperWidth/4)}, Y={wiperYmax}." {% endif %} {% endif %} {% for loops in range(0, cleaningLoops) %} G90 {% if wiperXmin == printer.configfile.config.stepper_x.position_endstop|float %} G1 X{wiperXmin+0.2} Y{wiperYmax} F{travelFeedrate} {% else %} G1 X{wiperXmin+(wiperWidth/4)} Y{wiperYmax} F{travelFeedrate} {% endif %} # Lower nozzle and start cleaning motion G1 Z{cleaningHeight} F1200 # Perform pseudosinusoidal cleaning motion G91 {%set ymov=(wiperLength/(waves*4)) %} G1 F{slowFeedrate} {% for i in range(0,waves) %} G1 X{wiperWidth/2} Y-{ymov} G1 Y-{ymov} G1 X-{wiperWidth/2} Y-{ymov} G1 Y-{ymov} {% endfor %} G1 X{wiperWidth/2} {% for i in range(0,waves) %} G1 X-{wiperWidth/2} Y{ymov} G1 Y{ymov} G1 X{wiperWidth/2} Y{ymov} G1 Y{ymov} {% endfor %} G1 F{fastFeedrate} G1 X-{wiperWidth/2} {% for i in range(0,waves) %} G1 Y-{ymov} G1 X{wiperWidth/2} Y-{ymov} G1 Y-{ymov} G1 X-{wiperWidth/2} Y-{ymov} {% endfor %} G1 X{wiperWidth/2} {% for i in range(0,waves) %} G1 Y{ymov} G1 X-{wiperWidth/2} Y{ymov} G1 Y{ymov} G1 X{wiperWidth/2} Y{ymov} {% endfor %} G1 F{slowFeedrate} G1 X-{wiperWidth/2} {% for i in range(0,waves) %} G1 X{wiperWidth/2} Y-{2*ymov} G1 X-{wiperWidth/2} Y-{2*ymov} {% endfor %} G1 X{wiperWidth/2} {% for i in range(0,waves) %} G1 X-{wiperWidth/2} Y{2*ymov} G1 X{wiperWidth/2} Y{2*ymov} {% endfor %} {% endfor %} {% else %} # --- HEAD MOVEMENT CLEANING SEQUENCE --- {% if debug == 1 %} RESPOND MSG="INFO: Repeating cleaning motions for {cleaningLoops} times" {% if wiperYmax == printer.toolhead.axis_maximum.y %} RESPOND MSG="INFO: Starting first cleaning passes near bed edge at X={wiperXmin+wiperLength}, Y={wiperYmax-0.1} (limited Y clearance)." {% else %} RESPOND MSG="INFO: Starting first cleaning passes at X={wiperXmin+wiperLength}, Y={wiperYmax-(wiperWidth/4)}." {% endif %} {% endif %} {% for loops in range(0, cleaningLoops) %} G90 {% if wiperYmax == printer.toolhead.axis_maximum.y %} G1 X{wiperXmin+wiperLength} Y{wiperYmax-0.1} F{travelFeedrate} {% else %} G1 X{wiperXmin+wiperLength} Y{wiperYmax-(wiperWidth/4)} F{travelFeedrate} {% endif %} # Lower nozzle and start cleaning motion G1 Z{cleaningHeight} F1200 # Perform pseudosinusoidal cleaning motion G91 {%set xmov=(wiperLength/(waves*4)) %} G1 F{slowFeedrate} {% for i in range(0,waves) %} G1 X-{xmov} Y-{wiperWidth} G1 X-{xmov} G1 X-{xmov} Y+{wiperWidth} G1 X-{xmov} {% endfor %} G1 Y-{wiperWidth} {% for i in range(0,waves) %} G1 X{xmov} Y+{wiperWidth} G1 X{xmov} G1 X{xmov} Y-{wiperWidth} G1 X{xmov} {% endfor %} G1 F{fastFeedrate} G1 Y+{wiperWidth} {% for i in range(0,waves) %} G1 X-{xmov} G1 X-{xmov} Y-{wiperWidth} G1 X-{xmov} G1 X-{xmov} Y+{wiperWidth} {% endfor %} G1 Y-{wiperWidth} {% for i in range(0,waves) %} G1 X{xmov} G1 X{xmov} Y+{wiperWidth} G1 X{xmov} G1 X{xmov} Y-{wiperWidth} {% endfor %} G1 F{slowFeedrate} G1 Y+{wiperWidth} {% for i in range(0,waves) %} G1 X-{xmov*2} Y-{wiperWidth} G1 X-{xmov*2} Y+{wiperWidth} {% endfor %} G1 Y-{wiperWidth} {% for i in range(0,waves) %} G1 X{xmov*2} Y+{wiperWidth} G1 X{xmov*2} Y-{wiperWidth} {% endfor %} {% endfor %} {% endif %} # ------------------------------------------------------------------------ # Restore saved nozze target temperature & move to middle of bed # ------------------------------------------------------------------------ {% if waitNozzleTempRestore == 0 %} SET_HEATER_TEMPERATURE HEATER=extruder TARGET={nozzleTargetTemperature} G1 Z{travelHeight} F3000 {% else %} G1 Z{travelHeight} F3000 {% if nozzleTargetTemperature <= 60 %} # Nozzle is considered cold, use fans at 100% for faster cooldown SET_HEATER_TEMPERATURE HEATER=extruder TARGET={nozzleTargetTemperature} M106 S255 {% if debug == 1 %} RESPOND MSG="INFO: Nozzle was cold. Waiting for temperature to rise into 50-60c range..." {% endif %} TEMPERATURE_WAIT SENSOR=extruder MINIMUM={50} MAXIMUM={60} M106 S0 {% if debug == 1 %} RESPOND MSG="INFO: Nozzle temperature reached target range (50-60c)." {% endif %} {% elif nozzleTargetTemperature > 60 and nozzleTargetTemperature < cleaningTemperature %} # Nozzle is preheated, use fans at 50% for faster cooldown SET_HEATER_TEMPERATURE HEATER=extruder TARGET={nozzleTargetTemperature} M106 S128 {% if debug == 1 %} RESPOND MSG="INFO: Restoring nozzle temperature to {nozzleTargetTemperature}c. Please wait for stabilization..." {% endif %} TEMPERATURE_WAIT SENSOR=extruder MINIMUM={nozzleTargetTemperature} MAXIMUM={nozzleTargetTemperature+10} M106 S0 {% if debug == 1 %} RESPOND MSG="INFO: Nozzle temperature stabilized at ~{nozzleTargetTemperature}c." {% endif %} {% elif nozzleTargetTemperature >= cleaningTemperature %} # Nozzle is hot, use no fans for faster heating SET_HEATER_TEMPERATURE HEATER=extruder TARGET={nozzleTargetTemperature} {% if debug == 1 %} RESPOND MSG="INFO: Restoring nozzle temperature to {nozzleTargetTemperature}c. Please wait for stabilization..." {% endif %} TEMPERATURE_WAIT SENSOR=extruder MINIMUM={nozzleTargetTemperature} MAXIMUM={nozzleTargetTemperature+10} {% if debug == 1 %} RESPOND MSG="INFO: Nozzle temperature stabilized at ~{nozzleTargetTemperature}c." {% endif %} {% endif %} G90 G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y/2} F{travelFeedrate} {% endif %} # ------------------------------------------------------------------------ # Reset Acceleration # ------------------------------------------------------------------------ SET_VELOCITY_LIMIT ACCEL={printer.configfile.config['printer']['max_accel']|float} # ------------------------------------------------------------------------ # Print finish message # ------------------------------------------------------------------------ {% if debug == 1 %} RESPOND MSG="INFO: Nozzle cleaning sequence complete." {% endif %} {% endif %}