Cura Script to Automatically Probe Only Printed Area
-
@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?
-
@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.
-
@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.
-
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.
-
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 probingIs there something I am doing wrong?
-
@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?
-
@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.
-
@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.
-
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))
-
I'm trying to get this working in superslicer but get an error. Can anyone help?
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()
-
-
-
-
-
Thanks! I actually got this working, and its been great since I posted. But will take a look at your solution
-
-