How to leave small gaps in cutting paths?
Forum rules
and Helpful information
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help
Also, be nice to others! Read the FreeCAD code of conduct!
Also, be nice to others! Read the FreeCAD code of conduct!
-
- Posts: 73
- Joined: Sat Feb 24, 2018 6:09 pm
How to leave small gaps in cutting paths?
I'd like to prevent cut out parts from blocking the plotter. Is there a way to add small gaps in the (laser) contour cuts?
Re: How to leave small gaps in cutting paths?
In Path Workbench > Path > Path Dressup > Tag Dress-up. That will get you what your looking for.leonardshelby wrote: ↑Sun Jun 23, 2019 3:03 pm I'd like to prevent cut out parts from blocking the plotter. Is there a way to add small gaps in the (laser) contour cuts?
WhatsApp Image 2019-06-23 at 16.28.15.jpeg
Mark
This post made with 0.0% Micro$oft products - GOT LINUX?
-
- Posts: 73
- Joined: Sat Feb 24, 2018 6:09 pm
Re: How to leave small gaps in cutting paths?
Hey Mark,
thanks, that seems to be what I was looking for. I'll give it a try
Also, is there a way to remove the third axis in gcode? I am removing gcode manually in a text editor for now.
thanks, that seems to be what I was looking for. I'll give it a try
Also, is there a way to remove the third axis in gcode? I am removing gcode manually in a text editor for now.
Re: How to leave small gaps in cutting paths?
There was a thread on this - https://forum.freecadweb.org/viewtopic.php?f=15&t=32658 but for now, there is no laser/plasma/waterjet/etc tool or post processor in path. If your handy at coding, you can always take a run at adding it to the path workbench. I'm sure your effort would be received well by the guys that are working on it now.leonardshelby wrote: ↑Sun Jun 23, 2019 3:37 pm Hey Mark,
thanks, that seems to be what I was looking for. I'll give it a try
Also, is there a way to remove the third axis in gcode? I am removing gcode manually in a text editor for now.
Mark
This post made with 0.0% Micro$oft products - GOT LINUX?
-
- Posts: 73
- Joined: Sat Feb 24, 2018 6:09 pm
Re: How to leave small gaps in cutting paths?
I don't think I'll be able to help as I can't code. The tag feature doesn't work for laser/plasma/.. other cutting tools as well. It would require a G0 movement instead of Z changes. I will try to edit these by hand, too :/
I'll have a look at the code though, once I have spare time
I'll have a look at the code though, once I have spare time
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: How to leave small gaps in cutting paths?
Which postprocessor do you use?leonardshelby wrote: ↑Sun Jun 23, 2019 3:37 pm Hey Mark,
thanks, that seems to be what I was looking for. I'll give it a try
Also, is there a way to remove the third axis in gcode? I am removing gcode manually in a text editor for now.
-
- Posts: 73
- Joined: Sat Feb 24, 2018 6:09 pm
Re: How to leave small gaps in cutting paths?
I'm running grbl 1.1f on an arduino, so I have set the Processor to grbl in FreeCADs job settings. If that is the postprocessor you are referring to?
Re: How to leave small gaps in cutting paths?
You control this with the depth parameters and stepdown of the operations.
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
-
- Posts: 73
- Joined: Sat Feb 24, 2018 6:09 pm
Re: How to leave small gaps in cutting paths?
@chrisb This does not work with lasercutters - often times they don't even have a Z axis (and if they do, it is used for focusing). The laser has to move without being turned on (G0) to leave gaps in the material. Alternatively you could travel faster in xy and/or reduce the laserpower to leave an "engraved gap".
-
- Veteran
- Posts: 5513
- Joined: Thu Apr 05, 2018 1:53 am
Re: How to leave small gaps in cutting paths?
Attached is a patched grbl.py postprocessor file. You would need to replace your file with this one in FreeCAD/Mod/Path/PathScripts/post/grbl_post.py (Probably should rename the original to something like grbl_post.py.backup)leonardshelby wrote: ↑Sun Jun 23, 2019 7:36 pm I'm running grbl 1.1f on an arduino, so I have set the Processor to grbl in FreeCADs job settings. If that is the postprocessor you are referring to?
Code: Select all
#***************************************************************************
#* (c) sliptonic (shopinthewoods@gmail.com) 2014 *
#* *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* FreeCAD is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Lesser General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with FreeCAD; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************/
TOOLTIP='''
Generate g-code from a Path that is compatible with the grbl controller.
import grbl_post
grbl_post.export(object,"/path/to/file.ncc")
'''
import FreeCAD
import PathScripts.PostUtils as PostUtils
import argparse
import datetime
import shlex
import traceback
now = datetime.datetime.now()
parser = argparse.ArgumentParser(prog='grbl', add_help=False)
parser.add_argument('--header', action='store_true', help='output headers (default)')
parser.add_argument('--no-header', action='store_true', help='suppress header output')
parser.add_argument('--comments', action='store_true', help='output comment (default)')
parser.add_argument('--no-comments', action='store_true', help='suppress comment output')
parser.add_argument('--line-numbers', action='store_true', help='prefix with line numbers')
parser.add_argument('--no-line-numbers', action='store_true', help='don\'t prefix with line numbers (default)')
parser.add_argument('--show-editor', action='store_true', help='pop up editor before writing output (default)')
parser.add_argument('--no-show-editor', action='store_true', help='don\'t pop up editor before writing output')
parser.add_argument('--precision', default='4', help='number of digits of precision, default=4')
parser.add_argument('--preamble', help='set commands to be issued before the first command, default="G17\nG90"')
parser.add_argument('--postamble', help='set commands to be issued after the last command, default="M05\nG17 G90\n; M2"')
parser.add_argument('--tool-change', help='0 ... suppress all tool change commands\n1 ... insert M6 for all tool changes\n2 ... insert M6 for all tool changes except the initial tool')
parser.add_argument('--no_z', action='store_true', help='eliminate z axis operations from gcode\n')
TOOLTIP_ARGS=parser.format_help()
#These globals set common customization preferences
OUTPUT_COMMENTS = True
OUTPUT_HEADER = True
OUTPUT_LINE_NUMBERS = False
OUTPUT_TOOL_CHANGE = False
SHOW_EDITOR = True
MODAL = False #if true commands are suppressed if the same as previous line.
COMMAND_SPACE = " "
LINENR = 100 #line number starting value
#These globals will be reflected in the Machine configuration of the project
UNITS = "G21" #G21 for metric, G20 for us standard
MACHINE_NAME = "GRBL"
CORNER_MIN = {'x':0, 'y':0, 'z':0 }
CORNER_MAX = {'x':500, 'y':300, 'z':300 }
PRECISION = 4
NO_Z = False
RAPID_MOVES = ['G0', 'G00']
#Preamble text will appear at the beginning of the GCODE output file.
PREAMBLE = '''G17 G90
'''
#Postamble text will appear following the last operation.
POSTAMBLE = '''M5
G17 G90
; M2
'''
# These commands are ignored by commenting them out
SUPPRESS_COMMANDS = [ 'G98', 'G80' ]
#Pre operation text will be inserted before every operation
PRE_OPERATION = ''''''
#Post operation text will be inserted after every operation
POST_OPERATION = ''''''
#Tool Change commands will be inserted before a tool change
TOOL_CHANGE = ''''''
SUPPRESS_TOOL_CHANGE=0
# to distinguish python built-in open function from the one declared below
if open.__module__ in ['__builtin__','io']:
pythonopen = open
def processArguments(argstring):
global OUTPUT_HEADER
global OUTPUT_COMMENTS
global OUTPUT_LINE_NUMBERS
global OUTPUT_TOOL_CHANGE
global SHOW_EDITOR
global PRECISION
global PREAMBLE
global POSTAMBLE
global SUPPRESS_TOOL_CHANGE
global NO_Z
try:
args = parser.parse_args(shlex.split(argstring))
if args.no_header:
OUTPUT_HEADER = False
if args.header:
OUTPUT_HEADER = True
if args.no_comments:
OUTPUT_COMMENTS = False
if args.comments:
OUTPUT_COMMENTS = True
if args.no_line_numbers:
OUTPUT_LINE_NUMBERS = False
if args.line_numbers:
OUTPUT_LINE_NUMBERS = True
if args.no_show_editor:
SHOW_EDITOR = False
if args.show_editor:
SHOW_EDITOR = True
print("Show editor = %d" % SHOW_EDITOR)
PRECISION = args.precision
if not args.preamble is None:
PREAMBLE = args.preamble
if not args.postamble is None:
POSTAMBLE = args.postamble
if not args.tool_change is None:
OUTPUT_TOOL_CHANGE = int(args.tool_change) > 0
SUPPRESS_TOOL_CHANGE = min(1, int(args.tool_change) - 1)
if args.no_z:
NO_Z = True
CORNER_MIN = {'x':0, 'y':0 }
CORNER_MAX = {'x':500, 'y':300 }
except Exception as e:
traceback.print_exc(e)
return False
return True
def export(objectslist,filename,argstring):
if not processArguments(argstring):
return None
global UNITS
for obj in objectslist:
if not hasattr(obj,"Path"):
print("the object " + obj.Name + " is not a path. Please select only path and Compounds.")
return
print("postprocessing...")
gcode = ""
#Find the machine.
#The user my have overridden post processor defaults in the GUI. Make sure we're using the current values in the Machine Def.
myMachine = None
for pathobj in objectslist:
if hasattr(pathobj,"Group"): #We have a compound or project.
for p in pathobj.Group:
if p.Name == "Machine":
myMachine = p
if myMachine is None:
print("No machine found in this project")
else:
if myMachine.MachineUnits == "Metric":
UNITS = "G21"
else:
UNITS = "G20"
# write header
if OUTPUT_HEADER:
gcode += linenumber() + "(Exported by FreeCAD)\n"
gcode += linenumber() + "(Post Processor: " + __name__ +")\n"
gcode += linenumber() + "(Output Time:"+str(now)+")\n"
#Write the preamble
if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n"
for line in PREAMBLE.splitlines(True):
gcode += linenumber() + line
gcode += linenumber() + UNITS + "\n"
for obj in objectslist:
#do the pre_op
if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n"
for line in PRE_OPERATION.splitlines(True):
gcode += linenumber() + line
gcode += parse(obj)
#do the post_op
if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n"
for line in POST_OPERATION.splitlines(True):
gcode += linenumber() + line
#do the post_amble
if OUTPUT_COMMENTS: gcode += "(begin postamble)\n"
for line in POSTAMBLE.splitlines(True):
gcode += linenumber() + line
if FreeCAD.GuiUp and SHOW_EDITOR:
dia = PostUtils.GCodeEditorDialog()
dia.editor.setText(gcode)
result = dia.exec_()
if result:
final = dia.editor.toPlainText()
else:
final = gcode
else:
final = gcode
print("done postprocessing.")
gfile = pythonopen(filename,"w")
gfile.write(gcode)
gfile.close()
def linenumber():
global LINENR
if OUTPUT_LINE_NUMBERS == True:
LINENR += 10
return "N" + str(LINENR) + " "
return ""
def parse(pathobj):
out = ""
lastcommand = None
precision_string = '.' + str(PRECISION) +'f'
global SUPPRESS_TOOL_CHANGE
global NO_Z
#params = ['X','Y','Z','A','B','I','J','K','F','S'] #This list control the order of parameters
params = ['X','Y','Z','A','B','I','J','F','S','T','Q','R','L'] #linuxcnc doesn't want K properties on XY plane Arcs need work.
if NO_Z:
params = ['X','Y','A','B','I','J','F','S','T','Q','R','L'] #remove the Z
if hasattr(pathobj,"Group"): #We have a compound or project.
if OUTPUT_COMMENTS: out += linenumber() + "(compound: " + pathobj.Label + ")\n"
for p in pathobj.Group:
out += parse(p)
return out
else: #parsing simple path
if not hasattr(pathobj,"Path"): #groups might contain non-path things like stock.
return out
if OUTPUT_COMMENTS: out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
outstring = []
command = c.Name
outstring.append(command)
# if modal: only print the command if it is not the same as the last one
if MODAL == True:
if command == lastcommand:
outstring.pop(0)
# Now add the remaining parameters in order
for param in params:
if param in c.Parameters:
if param == 'F':
if command not in RAPID_MOVES:
outstring.append(param + format(c.Parameters['F'] * 60, '.2f'))
elif param == 'T':
outstring.append(param + str(int(c.Parameters['T'])))
else:
outstring.append(param + format(c.Parameters[param], precision_string))
# store the latest command
lastcommand = command
# Check for Tool Change:
if command == 'M6':
if OUTPUT_COMMENTS:
out += linenumber() + "(begin toolchange)\n"
if not OUTPUT_TOOL_CHANGE or SUPPRESS_TOOL_CHANGE > 0:
outstring.insert(0, ";")
SUPPRESS_TOOL_CHANGE = SUPPRESS_TOOL_CHANGE - 1
else:
for line in TOOL_CHANGE.splitlines(True):
out += linenumber() + line
if command == "message":
if OUTPUT_COMMENTS == False:
out = []
else:
outstring.pop(0) #remove the command
if command in SUPPRESS_COMMANDS:
outstring.insert(0, ";")
#prepend a line number and append a newline
if len(outstring) >= 1:
if OUTPUT_LINE_NUMBERS:
outstring.insert(0,(linenumber()))
#append the line to the final output
for w in outstring:
out += w + COMMAND_SPACE
out = out.strip() + "\n"
return out
print(__name__ + " gcode postprocessor loaded.")
I can't really test this except by generating gcode and checking to see if it contains any z coordinates, which I did and which it did not have in my test. Since you're using an arduino it's possible this might get bypassed or something, not sure.
Note: when previewing the gcode you might still see some z moves, but in the output gcode file they should all be gone.