Inital commit and working draft
This commit is contained in:
parent
e1747dd14b
commit
e6d2b3c9af
|
|
@ -0,0 +1,333 @@
|
|||
# *****************************************************************************
|
||||
# * Copyright (c) 2024 Marcel Dahl *
|
||||
# * *
|
||||
# * 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 *
|
||||
# * *
|
||||
# ****************************************************************************/
|
||||
"""Postprocessor to output real GCode for Max Computer GmbH nccad7.5."""
|
||||
import FreeCAD
|
||||
import Path.Post.Utils as PostUtils
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
import datetime
|
||||
|
||||
|
||||
TOOLTIP = """
|
||||
This is a postprocessor file for the Path workbench.
|
||||
It is used to output real G-code suitable for the KOSY CNC devices.
|
||||
|
||||
Some G and M codes are not supported. Please review result.
|
||||
|
||||
Preconditions:
|
||||
metric values (check settings)
|
||||
Entered filename without suffix. Will be stored as .knc (nccad file extension for gcode)
|
||||
"""
|
||||
|
||||
MACHINE_NAME = """Max Computer GmbH nccad MCS/KOSY"""
|
||||
|
||||
# gCode for changing tools
|
||||
# M01 <String> ; Displays <String> and waits for user interaction
|
||||
TOOL_CHANGE = """G77 ; Move to release position
|
||||
M10 O6.0 ; Stop spindle
|
||||
M01 Insert tool TOOL
|
||||
G76 ; Move to reference point / WNP
|
||||
M10 O6.1 ; Start spindle / relais 6 on"""
|
||||
|
||||
|
||||
# gCode finishing the program
|
||||
POSTAMBLE = """G77 ; Move to release position fast
|
||||
M10 O6.0 ; Stop spindle relais 6 off
|
||||
G99 ;end program module"""
|
||||
|
||||
|
||||
# gCode header with information about CAD-software, post-processor
|
||||
# and date/time
|
||||
if FreeCAD.ActiveDocument:
|
||||
cam_file = FreeCAD.ActiveDocument.FileName
|
||||
else:
|
||||
cam_file = "<None>"
|
||||
|
||||
HEADER = """;Exported by FreeCAD
|
||||
;Post Processor: {}
|
||||
;CAM file: {}
|
||||
;Output Time: {}
|
||||
""".format(
|
||||
__name__, cam_file, str(datetime.datetime.now())
|
||||
)
|
||||
|
||||
# ***************************************************************************
|
||||
# * Internal global variables
|
||||
# ***************************************************************************
|
||||
RAPID_MOVES = ["G0", "G00"] # Rapid moves gCode commands definition
|
||||
# Global variables storing current position
|
||||
CURRENT_X = 0
|
||||
CURRENT_Y = 0
|
||||
CURRENT_Z = 0
|
||||
CURRENT_F = 0
|
||||
|
||||
|
||||
def export(objectslist, filename, argstring):
|
||||
"""Export the list of objects into a filename.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
objectslists: list
|
||||
List of objects.
|
||||
|
||||
filename: str
|
||||
Name of the output file without
|
||||
"""
|
||||
gcode = HEADER
|
||||
|
||||
for obj in objectslist:
|
||||
gcode+= parse(obj)
|
||||
gcode += "\n"
|
||||
|
||||
gcode += POSTAMBLE + "\n"
|
||||
|
||||
# Open editor window
|
||||
if FreeCAD.GuiUp:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
dia.editor.setText(gcode)
|
||||
result = dia.exec_()
|
||||
if result:
|
||||
gcode = dia.editor.toPlainText()
|
||||
|
||||
# Save to file
|
||||
if filename != "-":
|
||||
nccadFileEnding = ".knc"
|
||||
if filename.endswith(".nc"): # freecad file suffix
|
||||
filename = nccadFileEnding.join(filename.rsplit(".nc", 1))
|
||||
gfile = open(filename, "w")
|
||||
gfile.write(gcode)
|
||||
gfile.close()
|
||||
|
||||
return filename
|
||||
|
||||
def parse(pathobj):
|
||||
|
||||
global CURRENT_X
|
||||
global CURRENT_Y
|
||||
global CURRENT_Z
|
||||
global CURRENT_F
|
||||
|
||||
out = ""
|
||||
lastcommand = None
|
||||
precision_string = ".2f" # Kosy support 0.01 mm steps
|
||||
|
||||
params = [
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"F",
|
||||
"S",
|
||||
"T",
|
||||
"Q",
|
||||
"R",
|
||||
"L",
|
||||
"P",
|
||||
]
|
||||
|
||||
# see KOSY help file NC-Kurzbefehlliste
|
||||
validCommands = [
|
||||
"G0",
|
||||
"G1",
|
||||
"G2",
|
||||
"G3",
|
||||
"G20",
|
||||
"G24",
|
||||
"G54",
|
||||
"G60",
|
||||
"G61",
|
||||
"G74",
|
||||
"G76",
|
||||
"G77",
|
||||
"G79",
|
||||
# G80 start manufacture specific custom g-codes
|
||||
"G81",
|
||||
"G87",
|
||||
# G89 end custom g-codes
|
||||
"G88",
|
||||
"G89",
|
||||
"G90",
|
||||
# "G91", # KOSY valid, but not checked if input of postprocessor / Freecad delivers relative points
|
||||
"G98",
|
||||
"G99",
|
||||
"M1",
|
||||
#"M2",
|
||||
#"M3",
|
||||
#"M4",
|
||||
"M5",
|
||||
"M10",
|
||||
"M20",
|
||||
"M25",
|
||||
"M30",
|
||||
"M35",
|
||||
]
|
||||
|
||||
if hasattr(pathobj, "Group"): # We have a compound or project.
|
||||
out += "(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
|
||||
|
||||
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
|
||||
outstring = []
|
||||
command = c.Name
|
||||
|
||||
if command[0] == ";(" : # command is a comment
|
||||
out += command + "\n"
|
||||
continue
|
||||
|
||||
if not command in validCommands:
|
||||
out += ";(Unsupported command <"+ command + "> for KOSY maschine. Check simulation! )\n"
|
||||
continue
|
||||
|
||||
# print the command if it is not the same as the last one
|
||||
if command == lastcommand:
|
||||
outstring.append(" ") # align / multiple spaces are ignored by machine
|
||||
else:
|
||||
outstring.append(command)
|
||||
|
||||
# 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:
|
||||
speed = c.Parameters[param]
|
||||
if speed > 0.0 and speed != CURRENT_F:
|
||||
CURRENT_F = speed
|
||||
# Multiply F parameter value by 10,
|
||||
# FreeCAD = mm/s, nccad = 1/10 mm/s
|
||||
# speed *= 10
|
||||
# Add command parameters and values and round float
|
||||
# as nccad9 does not support exponents
|
||||
outstring.append( param + format( float(speed),
|
||||
precision_string,
|
||||
)
|
||||
)
|
||||
elif param in ["T", "H", "S"]:
|
||||
outstring.append(param + str(int(c.Parameters[param])))
|
||||
elif param in ["D", "P", "L"]:
|
||||
outstring.append(param + str(c.Parameters[param]))
|
||||
elif param in ["A", "B", "C"]:
|
||||
outstring.append(
|
||||
param + format(c.Parameters[param], precision_string)
|
||||
)
|
||||
elif param == "K": # 2,5D KOSY doesnt support milling Z axis
|
||||
continue
|
||||
else: # [X, Y, Z, U, V, W, I, J, R, Q]
|
||||
pos = format( float(c.Parameters[param]), precision_string )
|
||||
skip = False
|
||||
|
||||
# improve code with
|
||||
# skip = sameCoordinate(pos, CURRENT_X)
|
||||
|
||||
|
||||
if param == "X":
|
||||
if pos == CURRENT_X:
|
||||
skip = True # same X coordinate
|
||||
else:
|
||||
CURRENT_X = pos # store new position
|
||||
|
||||
if param == "Y":
|
||||
if pos == CURRENT_Y:
|
||||
skip = True # same coordinate
|
||||
else:
|
||||
CURRENT_Y = pos # store new position
|
||||
|
||||
if param == "Z":
|
||||
if pos == CURRENT_Z:
|
||||
skip = True # same coordinate
|
||||
else:
|
||||
CURRENT_Z = pos # store new position
|
||||
|
||||
if not skip or ( command in ["G2", "G3"] and param != "Z"): # while rotating movements KOSY needs all x y parameter
|
||||
outstring.append(param + format( pos )
|
||||
)
|
||||
|
||||
# store the latest command
|
||||
lastcommand = command
|
||||
|
||||
# TODO
|
||||
# if command in ("G98", "G99"):
|
||||
# DRILL_RETRACT_MODE = command
|
||||
#
|
||||
#
|
||||
# if TRANSLATE_DRILL_CYCLES:
|
||||
# if command in ("G81", "G82", "G83"):
|
||||
# out += drill_translate(outstring, command, c.Parameters)
|
||||
# # Erase the line we just translated
|
||||
# outstring = []
|
||||
# TODO
|
||||
# if SPINDLE_WAIT > 0:
|
||||
# if command in ("M3", "M03", "M4", "M04"):
|
||||
# out += format_outstring(outstring) + "\n"
|
||||
# out += (
|
||||
# linenumber()
|
||||
# + format_outstring(["G4", "P%s" % SPINDLE_WAIT])
|
||||
# + "\n"
|
||||
# )
|
||||
# outstring = []
|
||||
|
||||
# # Check for Tool Change:
|
||||
# if command in ("M6", "M06"):
|
||||
# if OUTPUT_COMMENTS:
|
||||
# out += "(Begin toolchange)\n"
|
||||
# if not OUTPUT_TOOL_CHANGE:
|
||||
# outstring.insert(0, "(")
|
||||
# outstring.append(")")
|
||||
# else:
|
||||
# for line in TOOL_CHANGE.splitlines(True):
|
||||
# out += line
|
||||
|
||||
# prepend a line number and append a newline
|
||||
if len(outstring) >= 1:
|
||||
out += format_outstring(outstring) + "\n"
|
||||
|
||||
return out
|
||||
|
||||
# construct the line for the final output
|
||||
def format_outstring(strTable):
|
||||
s = ""
|
||||
for w in strTable:
|
||||
s += w + " "
|
||||
s = s.rstrip()
|
||||
return s
|
||||
|
||||
#store into global variable? how by reference?
|
||||
def sameCoordinate(position, lastPosition):
|
||||
if position == lastPosition:
|
||||
return True
|
||||
else:
|
||||
lastPosition = position
|
||||
return False
|
||||
|
||||
Loading…
Reference in New Issue