Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login

    Share a macro: purge to a rectangle

    Scheduled Pinned Locked Moved
    Gcode meta commands
    3
    4
    174
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • zuoyanundefined
      zuoyan
      last edited by zuoyan

      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.
      
      T3P3Tonyundefined 1 Reply Last reply Reply Quote 0
      • T3P3Tonyundefined
        T3P3Tony administrators @zuoyan
        last edited by

        @zuoyan

        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)

        https://docs.duet3d.com/en/User_manual/Reference/Gcode_meta_commands#use-of-expressions-within-gcode-commands

        you need to write the macro with X and Ys explicitly, that will make it a little longer I know.

        www.duet3d.com

        1 Reply Last reply Reply Quote 0
        • mikeabuilderundefined
          mikeabuilder
          last edited by

          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.

          zuoyanundefined 1 Reply Last reply Reply Quote 1
          • zuoyanundefined
            zuoyan @mikeabuilder
            last edited by zuoyan

            @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"
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post
            Unless otherwise noted, all forum content is licensed under CC-BY-SA