V1 Logo Klipper Adaptive Purge

I have somewhat recently started using Klipper. One of the first things I researched and set up was Adaptive Mesh and Adaptive Purge.

For KAMP(the original adaptive mesh and purge), there exists a purge shaped like the Voron logo.

It didn’t feel right purging a Voron logo on a V1 printer, so I figured why not a V1 logo?

The macro below has been tested by me quite a bit as it is configured with a 0.6 nozzle on both of my printers.

There are some variables at the top that can be changed to tune the purge to your liking.

Requirements for Adaptive Purge

  1. You will need [exclude_object] defined in printer.cfg.
  2. You will need to make sure your slicer is labeling objects


If these are not properly configured, the purge will still work, however the origin of the purge will always be set to (0,0), rather than purging near the print itself.

[gcode_macro _ADAPTIVE_PURGE_V1]
description: A purge macro that adapts to be near your actual printed objects

variable_adaptive_enable: True      # Change to False if you'd like the purge to be in the same spot every print
variable_z_height: 0.3              # Height above the bed to purge
variable_tip_distance: 10           # Distance between filament tip and nozzle before purge (this will require some tuning)
variable_purge_amount: 25          # Amount of filament to purge
variable_flow_rate: 10              # Desired flow rate in mm3/s
variable_x_default: 5              # X location to purge, overwritten if adaptive is True
variable_y_default: 5              # Y location to purge, overwritten if adaptive is True
variable_size: 16                   # Size of the logo
variable_distance_to_object_x: 5   # Distance in x to the print area
variable_distance_to_object_y: 5   # Distance in y to the print area

    {% if adaptive_enable == True %}
        {% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %}
        {% set x_origin = (all_points | map(attribute=0) | min | default(x_default + distance_to_object_x + size)) - distance_to_object_x - size %}
        {% set y_origin = (all_points | map(attribute=1) | min | default(y_default + distance_to_object_y + size)) - distance_to_object_y - size %}
        {% set x_origin = ([x_origin, 0] | max) %}
        {% set y_origin = ([y_origin, 0] | max) %}
         {% if x_origin < x_default %}
            set x_origin = x_default | float
         {% endif %}
         {% if y_origin < y_default %}
            set y_origin = y_default | float
         {% endif %}

    {% else %}
        {% set x_origin = x_default | float %}
        {% set y_origin = y_default | float %}
    {% endif %}
    # Flow rate (mm3/s) = nozzle size(mm) x layer height(mm) x print speed(mm/s)
    # Filament Radius = 1.75mm / 2 = 0.875
    # cross sectional area = pi * (0.875)^2 = 2.405 mm2
    {% set purge_move_speed = 2.31 * size * flow_rate / (purge_amount * 2.405) %}
    {% set prepurge_speed = flow_rate / 2.405 %}
    {% set travel_speed = printer.toolhead.max_velocity %}
    { action_respond_info( "x: " + x_origin|string + " y: " + y_origin|string + " purge_move_speed: " + purge_move_speed|string + " prepurge_speed: " + prepurge_speed|string ) }

    G92 E0
    G90                                                                                 # Absolute positioning
    G0 X{x_origin} Y{y_origin+size/2} F3000                                             # Move to purge origin
    G0 Z{z_height} F1500                                                                # Move to purge Z height
    G0 F3000                                                                            # Set travel speed
    M83                                                                                 # Relative extrusion mode
    G1 X{x_origin+size*0.1883125} Y{y_origin+size*0.05125}
    G1 E{tip_distance} F{prepurge_speed*60}                                             # Move tip of filament to nozzle

    # Draw V1 logo outline
    G1 F600
    G1 X{x_origin+size*0.1976875} Y{y_origin+size*0.0538125} E{purge_amount*0.00362396204033215}
    G1 X{x_origin+size*0.2070625} Y{y_origin+size*0.056375} E{purge_amount*0.00348517200474496}
    G1 X{x_origin+size*0.273} Y{y_origin+size*0.0889375} E{purge_amount*0.0253226571767497}
    G1 X{x_origin+size*0.3568125} Y{y_origin+size*0.125125} E{purge_amount*0.0313760379596679}
    G1 X{x_origin+size*0.442375} Y{y_origin+size*0.1563125} E{purge_amount*0.0312455516014235}
    G1 X{x_origin+size*0.5295625} Y{y_origin+size*0.1825} E{purge_amount*0.0311731909845789}
    G1 X{x_origin+size*0.5311875} Y{y_origin+size*0.1829375} E{purge_amount*0.000575326215895611}
    G1 X{x_origin+size*0.6196875} Y{y_origin+size*0.2038125} E{purge_amount*0.0311376037959668}
    G1 X{x_origin+size*0.7093125} Y{y_origin+size*0.219625} E{purge_amount*0.0312253855278766}
    G1 X{x_origin+size*0.799875} Y{y_origin+size*0.2301875} E{purge_amount*0.0313368920521945}
    G1 X{x_origin+size*0.8735625} Y{y_origin+size*0.2349375} E{purge_amount*0.0254270462633452}
    G1 X{x_origin+size*0.8824375} Y{y_origin+size*0.237} E{purge_amount*0.00326809015421115}
    G1 X{x_origin+size*0.8913125} Y{y_origin+size*0.2390625} E{purge_amount*0.00339739027283511}
    G1 X{x_origin+size*0.8959375} Y{y_origin+size*0.2481875} E{purge_amount*0.00381494661921708}
    G1 X{x_origin+size*0.9005} Y{y_origin+size*0.257375} E{purge_amount*0.00366548042704626}
    G1 X{x_origin+size*0.951125} Y{y_origin+size*0.4463125} E{purge_amount*0.0668623962040332}
    G1 X{x_origin+size*0.9521875} Y{y_origin+size*0.4540625} E{purge_amount*0.00276156583629893}
    G1 X{x_origin+size*0.9531875} Y{y_origin+size*0.46175} E{purge_amount*0.00282443653618031}
    G1 X{x_origin+size*0.9528125} Y{y_origin+size*0.4654375} E{purge_amount*0.00138078291814947}
    G1 X{x_origin+size*0.9458125} Y{y_origin+size*0.4720625} E{purge_amount*0.00359193357058126}
    G1 X{x_origin+size*0.9388125} Y{y_origin+size*0.4786875} E{purge_amount*0.00342467378410439}
    G1 X{x_origin+size*0.9145625} Y{y_origin+size*0.4951875} E{purge_amount*0.00993950177935943}
    G1 X{x_origin+size*0.8395} Y{y_origin+size*0.547875} E{purge_amount*0.0316453143534994}
    G1 X{x_origin+size*0.7680625} Y{y_origin+size*0.6045} E{purge_amount*0.0314733096085409}
    G1 X{x_origin+size*0.700125} Y{y_origin+size*0.665125} E{purge_amount*0.0314483985765125}
    G1 X{x_origin+size*0.6358125} Y{y_origin+size*0.7295} E{purge_amount*0.0314317912218268}
    G1 X{x_origin+size*0.5755625} Y{y_origin+size*0.7971875} E{purge_amount*0.0312977461447212}
    G1 X{x_origin+size*0.5465} Y{y_origin+size*0.8325625} E{purge_amount*0.0155836298932384}
    G1 X{x_origin+size*0.492125} Y{y_origin+size*0.9056875} E{purge_amount*0.0313190984578885}
    G1 X{x_origin+size*0.451125} Y{y_origin+size*0.967125} E{purge_amount*0.0254341637010676}
    G1 X{x_origin+size*0.444625} Y{y_origin+size*0.9739375} E{purge_amount*0.00337959667852906}
    G1 X{x_origin+size*0.4380625} Y{y_origin+size*0.98075} E{purge_amount*0.00353262158956109}
    G1 X{x_origin+size*0.428125} Y{y_origin+size*0.98} E{purge_amount*0.00372123368920522}
    G1 X{x_origin+size*0.41825} Y{y_origin+size*0.97925} E{purge_amount*0.00354211150652432}
    G1 X{x_origin+size*0.22925} Y{y_origin+size*0.928625} E{purge_amount*0.0668837485172005}
    G1 X{x_origin+size*0.2204375} Y{y_origin+size*0.924125} E{purge_amount*0.00351601423487545}
    G1 X{x_origin+size*0.2115625} Y{y_origin+size*0.919625} E{purge_amount*0.00366903914590747}
    G1 X{x_origin+size*0.2091875} Y{y_origin+size*0.910625} E{purge_amount*0.00343179122182681}
    G1 X{x_origin+size*0.2068125} Y{y_origin+size*0.9016875} E{purge_amount*0.00329774614472123}
    G1 X{x_origin+size*0.2020625} Y{y_origin+size*0.82825} E{purge_amount*0.0253404507710558}
    G1 X{x_origin+size*0.1915} Y{y_origin+size*0.737625} E{purge_amount*0.0313582443653618}
    G1 X{x_origin+size*0.17575} Y{y_origin+size*0.6479375} E{purge_amount*0.0312431791221827}
    G1 X{x_origin+size*0.154875} Y{y_origin+size*0.5593125} E{purge_amount*0.0311791221826809}
    G1 X{x_origin+size*0.1544375} Y{y_origin+size*0.5576875} E{purge_amount*0.000575326215895611}
    G1 X{x_origin+size*0.12825} Y{y_origin+size*0.470625} E{purge_amount*0.0311328588374852}
    G1 X{x_origin+size*0.0970625} Y{y_origin+size*0.385125} E{purge_amount*0.0312253855278766}
    G1 X{x_origin+size*0.061} Y{y_origin+size*0.3014375} E{purge_amount*0.0313190984578885}
    G1 X{x_origin+size*0.02825} Y{y_origin+size*0.2351875} E{purge_amount*0.0254483985765125}
    G1 X{x_origin+size*0.025625} Y{y_origin+size*0.226125} E{purge_amount*0.00338671411625148}
    G1 X{x_origin+size*0.023} Y{y_origin+size*0.2170625} E{purge_amount*0.00352313167259787}
    G1 X{x_origin+size*0.028625} Y{y_origin+size*0.208875} E{purge_amount*0.00370937129300119}
    G1 X{x_origin+size*0.03425} Y{y_origin+size*0.200625} E{purge_amount*0.003570581257414}
    G1 X{x_origin+size*0.1725625} Y{y_origin+size*0.0623125} E{purge_amount*0.0668623962040332}
    G1 X{x_origin+size*0.1804375} Y{y_origin+size*0.0568125} E{purge_amount*0.00343297746144721}
    G1 X{x_origin+size*0.18375} Y{y_origin+size*0.0545} E{purge_amount*0.00150652431791222}

    G92 E0                                                                              # Reset extruder distance
    M82                                                                                 # Absolute extrusion mode
    G0 Z{z_height*2}                                                                    # Z hop
    {% if printer["gcode_macro status_printing"] != null %}
    {% endif %}


Great Job @Michael_Melancon Its been working well on my V4!


That’s cool. I have a line on the front of my print bed. I don’t know where I got the idea.

I love it… and thank you for the details on how to do it that are written well enough for even me to follow!


Is there a reason for using both the purge AND the brim?

I’ve always just used the brim around my prints to purge the nozzle before starting the print.

not really. It’s mostly a holdover from my standard profile I’ve been using for the last few years with no type of auto bed leveling.

So I would purge to make sure the filament was ready to go, and then the skirt loops were to let me make sure it was going to stick to the bed all the way around and give me time to turn my screws and adjust, I just haven’t fully adjusted to the new world yet.

2 months ago was the first time I was not manually checking my bed level on every print :grin:

1 Like

Heh. I feel this.

I don’t use a brim on most prints. I don’t like to clean them off.

The skirt could be used as a purge. But if the prusa profiles have a 3 layer height skirt. If you do that, you could have it come off and ruin your print. Those are the nit picky reasons to have a purge, skirt, and brim separately.

I use a very small skirt. It’s a single layer, 3 laps around the part, 5 mm offset.