Share a macro: purge to a rectangle
-
I'm using this macro within the start macro, with all states are ready and some global variables, it purges the nozzle and writes a rectangle -- I have not tried, but I think you can use a narrow rectangle to purge a line.
I have tried and found G1 {var.w_sym}100 does not work with var.w_sym = 'X' or 'Y', which looks natural to me.
; Purge to a rectangle, or print a rectangle. ; ; This assumes everything is ready and uses ; ; global.DEFAULT_SPEED: the default travel speed ; global.NOZZLE_DIAMETER: the nozzle diameter, like 0.4 ; ; This uses first layer height d * 0.75, width d * 1.25, while d is the nozzle ; diameter, with an extrusion factor 0.85. ; ; param.A-D: min/max x and min/max y of the rectangle ; param.S: the speed of print, default to 1440 (24 mm/s) var x1 = param.A var x2 = param.B var y1 = param.C var y2 = param.D var purge_speed = 1440 if exists(param.S) set var.purge_speed = param.S var tip_h = global.NOZZLE_DIAMETER * 0.75 var tip_w = global.NOZZLE_DIAMETER * 1.25 var purge_ratio = var.tip_w * var.tip_h / pow(1.75 / 2, 2) / 3.1415926 * 0.85 ; write line in the w (longer) direction var w_sym = var.x2 - var.x1 >= var.y2 - var.y1 ? "X" : "Y" var w1 = var.w_sym == "X" ? var.x1 : var.y1 var w2 = var.w_sym == "X" ? var.x2 : var.y2 var h1 = var.w_sym != "X" ? var.x1 : var.y1 var h2 = var.w_sym != "X" ? var.x2 : var.y2 if move.axes[2].machinePosition < 1 G1 Z2 if var.w_sym == "X" G1 X{var.w1} Y{var.h1} F{global.DEFAULT_SPEED} else G1 Y{var.w1} X{var.h1} F{global.DEFAULT_SPEED} G1 Z{var.tip_h} M204 P300; the max print acceleration var h_num = max(floor((var.h2 - var.h1) / var.tip_w + 0.5), 1) var hd = (var.h2 - var.h1) / var.h_num var h_e = var.purge_ratio * (var.w2 - var.w1) / var.tip_w * var.hd while true if iterations >= var.h_num break if var.w_sym == "X" G1 Y{var.h1 + var.hd * (iterations + 0.5)} G1 X{mod(iterations, 2) == 0 ? var.w2 : var.w1} E{var.h_e} F{var.purge_speed} else G1 X{var.h1 + var.hd * (iterations + 0.5)} G1 Y{mod(iterations, 2) == 0 ? var.w2 : var.w1} E{var.h_e} F{var.purge_speed} G10 ; retract G1 Z1 ; a print usually starts with retract + move + unretract, so we do not unretract here.
-
Using an expression to replace a parameter letter, or to replace the command number after the initial G or M, is not supported. (so for example G1 {global.extruder_axis}^2 is not supported)
you need to write the macro with X and Ys explicitly, that will make it a little longer I know.
-
Thanks for sharing this macro. Some things to think about when adding extrusions to start.g.
- Has a tool been selected? If you have multiple tools, or are not setting it in config.g, there could be a problem
- Is the tool heated to the proper temperature for the particular filament?
I had started to write a macro like this for my multi-tool printer and eventually gave up because of challenges in coordinating different location for different tools, getting each tool heated up properly, and selecting the proper temperature for each filament. In the end, I opted to put these kinds of steps into the custom gcode of the slicer. That let me use the extruder temperatures defined in the slicer to set active and standby temperatures for each tool and ensure they are up to temp.
-
@mikeabuilder I don't have multiple tools, so it's simple. I never thought we can use slicer for this. In my start script, it tries different area (4 side rects) with different clearances, and calls this macro at the first suitable place. I think you may need to find a larger area so that multiple head can purge at the same time?
var min_x = ... ... var xc = (var.min_x + var.max_x) / 2 var yc = (var.min_y + var.max_y) / 2 var clearance = 40 ; start from 40 / 2 var rect_x1 = 0 var rect_x2 = 0 var rect_y1 = 0 var rect_y2 = 0 while var.clearance > 1 if mod(iterations, 4) == 0 set var.clearance = var.clearance / 2 if var.clearance < 1 break set var.rect_x1 = mod(iterations, 4) == 0 ? var.max_x + var.clearance : move.axes[0].min set var.rect_x2 = mod(iterations, 4) == 1 ? var.min_x - var.clearance : move.axes[1].max set var.rect_y1 = mod(iterations, 4) == 2 ? var.max_y + var.clearance : move.axes[2].min set var.rect_y2 = mod(iterations, 4) == 3 ? var.min_y - var.clearance : move.axes[2].max if var.rect_x1 + global.NOZZLE_DIAMETER > var.rect_x2 continue if var.rect_y1 + global.NOZZLE_DIAMETER > var.rect_y2 continue if (var.rect_x2 - var.rect_x1) * (var.rect_y2 - var.rect_y1) < var.purge_area continue ; Project (xc, yc) into the rect set var.xc = min(max(var.xc, var.rect_x1), var.rect_x2) set var.yc = min(max(var.yc, var.rect_y1), var.rect_y2) ; Shrink the rect to purge_area, close to (xc, yc) and close to a square var xl = max(sqrt(var.purge_area), var.purge_area / (var.rect_y2 - var.rect_y1)) var yl = var.purge_area / var.xl set var.rect_x1 = max(min(var.xc - var.xl / 2, var.rect_x2 - var.xl), var.rect_x1) set var.rect_x2 = var.rect_x1 + var.xl set var.rect_y1 = max(min(var.yc - var.yl / 2, var.rect_y2 - var.yl), var.rect_y1) set var.rect_y2 = var.rect_y1 + var.yl echo "Purge in the rect " ^ {var.rect_x1, var.rect_x2, var.rect_y1, var.rect_y2} M98 P"0:/macros/purge_rect.g" A{var.rect_x1} B{var.rect_x2} C{var.rect_y1} D{var.rect_y2} break if var.clearance < 1 echo "no place to purge"