Thought it would be a fun project to learn Python and modified CCS86's script to work with Simplify3D. It was created with Python 3.8.1 on a Mac running Catalina and S3D 4.1.2 and tested with a 6mb gcode file. It will not work with Python2.
All you should need to do is copy the script to your computer (removing the .txt), make sure your starting script contains probing grid definition (ie M557 X30:300 Y30:300 S13.5) and add the following to the post processing.
python3 <full path to folder>/meshgrid.py "[output_filepath]" (quotes around [output_filepath] are manditory)
The script will read the first layer to obtain the print boundaries, verify it fits within the bed size specified in S3D, find the existing M557 and rewrite the min and max X Y coordinates. It might need some fine-tuning if used on a printer with 0,0 in the center of the bed.
Enjoy!
Edit: The forum server is not allowing the upload of txt files. Paste the code below into a text editor and save it as meshgrid.py .
#!/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.
Usage:
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).
Args:
Path: Complete path to the gcode file created by Simplify 3d.
Requirements:
Tested using Python 3.8.1.
Credit:
Adapted from code originally posted by CCS86 on https://forum.duet3d.com/topic/15302/cura-script-to-automatically-probe-only-printed-area?_=1587348242875.
"""
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()