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

    Cura Script to Automatically Probe Only Printed Area

    Scheduled Pinned Locked Moved
    General Discussion
    15
    60
    7.7k
    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.
    • Baenwortundefined
      Baenwort @tcj
      last edited by

      @tcj So I'm still learning Cura after switching from using MatterControl since I got my Rostock v3. I tried adding the duet3d_automesh.py from zapta's github to the scripts area of the postprocessing folder of Cura's plugin folder.

      I do have Python 3 installed (3.8.3 to be exact) but this seems to make no difference to it showing up in Cura. 😕

      zaptaundefined 1 Reply Last reply Reply Quote 0
      • zaptaundefined
        zapta @Baenwort
        last edited by

        @Baenwort, can you provide a little bit more info. E.g. what computer you are using (windows? mac? linux?) and how you set up the script in cura.

        Baenwortundefined 1 Reply Last reply Reply Quote 0
        • Baenwortundefined
          Baenwort @zapta
          last edited by

          @zapta

          Window's but I also tried it with a Ubuntu 20.04 Cura install. Both are Cura 4.6 and the OP and most post processing scripts direct placing the .py file in the plugin post processing directory.

          I can get you the exact tree when I get.back to my home tonight.

          1 Reply Last reply Reply Quote 0
          • sandozundefined
            sandoz
            last edited by

            I have installed this into Cura 4.62 and using on my Railcore II. When it goes to run it always defines my X end point as being 1800.

            M557 X103.850:1800.000 Y115.304:164.705 S10.000 ; Leveling mesh defined by LevelingMeshOptimizer

            Railcore of course doesn't like this and then just skips the mesh:

            Error: M557: bad grid definition: Too many grid points; suggest increase spacing to 44.2mm
            Error: G29: No valid grid defined for bed probing

            Is there something I am doing wrong?

            zaptaundefined 1 Reply Last reply Reply Quote 0
            • zaptaundefined
              zapta @sandoz
              last edited by

              @sandoz said in Cura Script to Automatically Probe Only Printed Area:

              Is there something I am doing wrong?

              My guess is that there is a X1800 somewhere in the gcode that is picked by the script. Can you post the gcode file?

              sandozundefined 1 Reply Last reply Reply Quote 1
              • sandozundefined
                sandoz @zapta
                last edited by sandoz

                @zapta Alright.. using your comments as a place to start I found that having my Jerk control turned on in Cura led to some M566 x1800 commands that it was picking up. I turned off Curas control and just set it in the machine settings and now it slices properly.

                zaptaundefined 1 Reply Last reply Reply Quote 1
                • zaptaundefined
                  zapta @sandoz
                  last edited by

                  @sandoz, the code is dump, looking for X<number> in the text regardless of the command, may even look in comments, I am not sure. If needed, it can be restricted it to a set of commands such as G0, G1, etc.

                  1 Reply Last reply Reply Quote 0
                  • MartinNYHCundefined
                    MartinNYHC
                    last edited by

                    I wanted to set the probe spacing according to the size of the model. If it's <= 100 spacing should be 20, if it's >100 spacing should be 50.

                    Need to find the proper size/spacing values, but if anyone is interested, here's the diff:

                    128,135d127
                    <     sizeX = int(bounds['X']['max'] - bounds['X']['min'])
                    <     sizeY = int(bounds['Y']['max'] - bounds['Y']['min'])
                    <
                    <     if sizeX >= 100 or sizeY >= 100:
                    <         bounds['S'] = 50
                    <     else:
                    <         bounds['S'] = 20
                    <
                    137c129
                    <     gridNew = 'M557 X%d:%d Y%d:%d S%d' % (
                    ---
                    >     gridNew = 'M557 X%d:%d Y%d:%d' % (
                    140d131
                    <         bounds['S'],
                    147c138
                    <             linesNew.append(re.sub(r'^M557 X\d+:\d+ Y\d+:\d+ S\d+', gridNew, line, flags=re.MULTILINE))
                    ---
                    >             linesNew.append(re.sub(r'^M557 X\d+:\d+ Y\d+:\d+', gridNew, line, flags=re.MULTILINE))
                    
                    
                    1 Reply Last reply Reply Quote 0
                    • nick9one1undefined
                      nick9one1
                      last edited by nick9one1

                      I'm trying to get this working in superslicer but get an error. Can anyone help?

                      Capture.PNG

                      in post-processing script

                      C:\Users\mumby\.windows-build-tools\python27\python.exe "C:\Program Files\SuperSlicer\meshgrid.py"
                      

                      my start gcode (added M557)

                      M557 X20:292 Y15:300 P5                      	; define mesh grid
                      M104 S[first_layer_temperature]                   ; set extruder temp
                      M140 S[first_layer_bed_temperature]           ; set bed temp
                      G21			                   ; metric values
                      M190 S[first_layer_bed_temperature]           ; wait for bed temp
                      G28			                   ; home all
                      G32			                   ; Run mesh grid compenstion
                      G92 E0 F100			; reset extruder
                      G1 Z10 F3000 			; move z up little to prevent scratching of surface
                      M109 S[first_layer_temperature]                    ; wait for extruder temp
                      M98 P"0:/macros/Filament/Clean Nozzle"	; Clean nozzle macro
                      M98 P/macros/Filament/Purge		; Run nozzle purge macro
                      G1 E-3 F2000		                  ; Retract 3mm filament
                      G92 E0 		                                     ; reset extruder
                      
                      

                      this script itself (coped from an earlier post here)

                      #!/usr/bin/env python3
                      """Simplify3D post-processing script for RepRap firmware printers which dynamically defines the mesh grid dimensions (M557) based on the print dimensions. 
                      {1}
                      Usage:
                      {1}
                          Within Simplify3D > Process Settings > Scripts > Post Processing > add the following command:
                              python3 <script_location>/meshgrid.py "[output_filepath]"
                          
                          Starting script must contain M557 Command (ie M557 X30:300 Y30:300 P20).
                      {1}
                      Args:
                      {1}
                          Path: Complete path to the gcode file created by Simplify 3d.
                      {1}
                      Requirements:
                      {1}
                          Tested using Python 3.8.1.
                      {1}
                      Credit:
                      {1}
                          Adapted from code originally posted by CCS86 on https://forum.duet3d.com/topic/15302/cura-script-to-automatically-probe-only-printed-area?_=1587348242875.
                      {1}
                      """
                      import sys
                      import re
                      import math
                       
                      def main(filename):
                          
                          try:
                              _s3dFile = open(filename, encoding='utf-8')
                       
                          except TypeError:
                              try:
                                  _s3dFile = open(filename)
                                  
                              except:
                                  print("Open file exception. Exiting meshgrid.py.")
                                  sys.exit()
                          
                          except FileNotFoundError:
                              print('File not found. Exiting meshgrid.py.')
                              sys.exit()
                          
                          lines = _s3dFile.readlines()
                          _s3dFile.close()
                       
                          linesNew = calcBed(lines)
                       
                          _s3dFileNew = open(filename, "r+")
                          _s3dFileNew.seek(0)                       
                          _s3dFileNew.truncate()
                          for element in linesNew:
                              _s3dFileNew.write(element)
                          _s3dFileNew.close()
                       
                          return
                       
                       
                      def calcBed(lines):
                       
                          bounds = findBounds(lines)
                          bed = findBed(lines)
                       
                          for axis in bounds:
                              if bounds[axis]['max'] - bounds[axis]['min'] < bed[axis]:
                                  print(f'Success: {axis} mesh is smaller than bed')
                                  
                              else:
                                  print('Error: Mesh is larger than bed. Exiting meshgrid.py.')
                                  sys.exit()
                       
                              for limit in bounds[axis]:
                                  if limit == 'min':
                                      if (bed[axis] / 2) - bounds[axis][limit] > 0: 
                                          print (f'Success: {axis} {limit} coordinate is on the bed.')
                                      else:
                                          print (f'Error: {axis} {limit} coordinate is off the bed. Exiting meshgrid.py.')
                                          sys.exit()
                       
                                  if limit == 'max':
                                      if (bed[axis]) - bounds[axis][limit] > 0: 
                                          print (f'Success: {axis} {limit} coordinate is on the bed.')
                                      else:
                                          print (f'Error: {axis} {limit} coordinate is off the bed. Exiting meshgrid.py.')
                                          sys.exit()
                       
                          return fillGrid(bounds, lines)
                       
                          
                      def findBed(lines):
                          bed = {
                              'X': 0,
                              'Y': 0,
                              }
                       
                          for line in lines:
                              if line.startswith(';   strokeXoverride,'):
                                  bed['X'] = int(re.search(r'\d.+\S', line).group())
                              elif line.startswith(';   strokeYoverride,'):
                                  bed['Y'] = int(re.search(r'\d.+', line).group())
                                  break
                                  
                          return bed
                       
                       
                      def findBounds(lines):
                          bounds = {
                              'X': {'min': 9999, 'max': 0},
                              'Y': {'min': 9999, 'max': 0},
                              }
                          parsing = False
                          for line in lines:
                              if line.startswith('; layer 1,'):
                                  parsing = True
                                  continue
                              elif line.startswith('; layer 2,'):
                                  break
                       
                              if parsing:
                                  # Get coordinates on this line
                                  for match in re.findall(r'([YX])([\d.]+)\s', line):
                                      # Get axis letter
                                      axis = match[0]
                       
                                      # Skip axes we don't care about
                                      if axis not in bounds:
                                          continue
                       
                                      # Parse parameter value
                                      value = float(match[1])
                       
                                      # Update bounds
                                      bounds[axis]['min'] = math.floor(min(bounds[axis]['min'], value))
                                      bounds[axis]['max'] = math.ceil(max(bounds[axis]['max'], value))
                       
                          return bounds
                       
                       
                      def fillGrid(bounds, lines):
                          # Fill in the level command template
                          gridNew = 'M557 X%d:%d Y%d:%d' % (
                              bounds['X']['min'], bounds['X']['max'],
                              bounds['Y']['min'], bounds['Y']['max'],
                          )
                       
                          # Replace M557 command in GCODE
                          linesNew = []
                          for line in lines:
                              if line.startswith('M557'):
                                  linesNew.append(re.sub(r'^M557 X\d+:\d+ Y\d+:\d+', gridNew, line, flags=re.MULTILINE))
                              else:
                                  linesNew.append(line)
                          return linesNew
                       
                       
                      if __name__ == '__main__':
                          if sys.argv[1]:
                              main(filename = sys.argv[1])
                          else:
                              print('Error: Proper s3d post processing command is python3 <script_location>/meshgrid.py "[output_filepath]". Exiting meshgrid.py.')
                              sys.exit()
                      
                      PCRundefined 1 Reply Last reply Reply Quote 0
                      • Phaedruxundefined Phaedrux referenced this topic
                      • PCRundefined
                        PCR @nick9one1
                        last edited by

                        @nick9one1 See this 😉

                        https://forum.duet3d.com/topic/25882/only-probe-bed-where-it-is-printed-solution-with-prusaslicer/3

                        nick9one1undefined 1 Reply Last reply Reply Quote 1
                        • gloomyandyundefined gloomyandy referenced this topic
                        • gloomyandyundefined gloomyandy referenced this topic
                        • nick9one1undefined
                          nick9one1 @PCR
                          last edited by

                          @pcr

                          Thanks! I actually got this working, and its been great since I posted. But will take a look at your solution 🙂

                          1 Reply Last reply Reply Quote 0
                          • engikeneerundefined engikeneer referenced this topic
                          • KP0005undefined KP0005 referenced this topic
                          • First post
                            Last post
                          Unless otherwise noted, all forum content is licensed under CC-BY-SA