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.6k
    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.
    • zaptaundefined
      zapta @Red Sand Robot
      last edited by zapta

      @Red-Sand-Robot, the change that you made in the program, changing the default meshable area to -100:100 is correct. Just remember to apply it again if you will download a newer version of this script.

      I run your gcode file and got this which looks ok to me

      MESHABLE area: -100.0:100.0,-100.0:100.0
      Opening gcode file: flex.gcode
      Read 33099 lines
      Parsing state = ParsingState.WAITING_FOR_LAYER1
      ; Automesh: begin layer 0
      Parsing state = ParsingState.IN_LAYER1
      ; Automesh: begin layer 1
      Parsing state = ParsingState.LAYER1_DONE
      First layer print areas: -13:13,-48:48
      printArea: -13:13,-48:48
      Will use 3 x 4 mesh points
      Marker: M557 X-23:23 Y-58:58 P3:4
      Inserted: M557 X-23:23 Y-58:58 P3:4
      

      Does it work for you now or are there still problems?

      Edit: for your question the -- flags should be specified immediately after the .py script name.

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

        @tcj Great! I'll give it a try on my next print.

        Do you think it will use the Delta probe interval for the new area or one specified by the gcode?

        1 Reply Last reply Reply Quote 0
        • 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