diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4fd3f82c..0fb3379e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,16 @@ CHANGELOG for FlatCAM beta
=================================================
+11.12.2020
+
+- updated the 'Default_no_M6' preprocessor by removing the Tx command in the Toolchange section to make it compatible with GRBL controllers
+- added a new preprocessor named 'Check_points' which is to be used to check if the PCB is well aligned in position (used by at least the Corners Tool)
+- Tool Corners - added a new feature that creates a verification GCode by moving in the locations positions; modfied the UI a bit
+- Drilling Tool - removed the mandatory Toolchange event added even if the Toolchange was not selected
+- Excellon and Geometry objects no longer have the self.options dict overwritten with the application defaults
+- Drilling Tool - first tool that benefit from using the object options instead of application defaults; this is useful if an object is recreated on project load
+- Drilling Tool - fixed it to update the UI form also for common parameters on object change
+
10.12.2020
- NCC Tool - remade the 'Beginner/Advanced' Mode
diff --git a/appObjects/AppObject.py b/appObjects/AppObject.py
index 9a8a32f8..9549ebf4 100644
--- a/appObjects/AppObject.py
+++ b/appObjects/AppObject.py
@@ -217,131 +217,6 @@ class AppObject(QtCore.QObject):
return obj
- def new_excellon_object(self):
- """
- Creates a new, blank Excellon object.
-
- :return: None
- """
-
- outname = 'new_exc'
-
- def obj_init(new_obj, app_obj):
- new_obj.tools = {}
- new_obj.source_file = ''
- new_obj.solid_geometry = []
-
- self.new_object('excellon', outname, obj_init, plot=False)
-
- def new_geometry_object(self):
- """
- Creates a new, blank and single-tool Geometry object.
-
- :return: None
- """
- outname = 'new_geo'
-
- def initialize(new_obj, app):
- new_obj.multitool = True
- new_obj.multigeo = True
-
- # store here the default data for Geometry Data
- default_data = {}
- for opt_key, opt_val in app.options.items():
- if opt_key.find('geometry' + "_") == 0:
- oname = opt_key[len('geometry') + 1:]
- default_data[oname] = self.app.options[opt_key]
- if opt_key.find('tools_') == 0:
- default_data[opt_key] = self.app.options[opt_key]
-
- new_obj.tools = {
- 1: {
- 'tooldia': float(app.defaults["tools_mill_tooldia"]),
- 'offset': 'Path',
- 'offset_value': 0.0,
- 'type': 'Rough',
- 'tool_type': 'C1',
- 'data': deepcopy(default_data),
- 'solid_geometry': []
- }
- }
-
- new_obj.tools[1]['data']['name'] = outname
-
- new_obj.source_file = ''
-
- self.new_object('geometry', outname, initialize, plot=False)
-
- def new_gerber_object(self):
- """
- Creates a new, blank Gerber object.
-
- :return: None
- """
-
- def initialize(new_obj, app):
- new_obj.multitool = False
- new_obj.source_file = ''
- new_obj.multigeo = False
- new_obj.follow = False
- new_obj.apertures = {}
- new_obj.solid_geometry = []
- new_obj.follow_geometry = []
-
- try:
- new_obj.options['xmin'] = 0
- new_obj.options['ymin'] = 0
- new_obj.options['xmax'] = 0
- new_obj.options['ymax'] = 0
- except KeyError:
- pass
-
- self.new_object('gerber', 'new_grb', initialize, plot=False)
-
- def new_script_object(self):
- """
- Creates a new, blank TCL Script object.
-
- :return: None
- """
-
- # commands_list = "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, " \
- # "AlignDrillGrid, Bbox, Bounds, ClearShell, CopperClear,\n" \
- # "# Cncjob, Cutout, Delete, Drillcncjob, ExportDXF, ExportExcellon, ExportGcode,\n" \
- # "# ExportGerber, ExportSVG, Exteriors, Follow, GeoCutout, GeoUnion, GetNames,\n" \
- # "# GetSys, ImportSvg, Interiors, Isolate, JoinExcellon, JoinGeometry, " \
- # "ListSys, MillDrills,\n" \
- # "# MillSlots, Mirror, New, NewExcellon, NewGeometry, NewGerber, Nregions, " \
- # "Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n" \
- # "# Options, Paint, Panelize, PlotAl, PlotObjects, SaveProject, " \
- # "SaveSys, Scale, SetActive, SetSys, SetOrigin, Skew, SubtractPoly,\n" \
- # "# SubtractRectangle, Version, WriteGCode\n"
-
- new_source_file = '# %s\n' % _('CREATE A NEW FLATCAM TCL SCRIPT') + \
- '# %s:\n' % _('TCL Tutorial is here') + \
- '# https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n' + '\n\n' + \
- '# %s:\n' % _("FlatCAM commands list")
- new_source_file += '# %s\n\n' % _("Type >help< followed by Run Code for a list of FlatCAM Tcl Commands "
- "(displayed in Tcl Shell).")
-
- def initialize(new_obj, app):
- new_obj.source_file = deepcopy(new_source_file)
-
- outname = 'new_script'
- self.new_object('script', outname, initialize, plot=False)
-
- def new_document_object(self):
- """
- Creates a new, blank Document object.
-
- :return: None
- """
-
- def initialize(new_obj, app):
- new_obj.source_file = ""
-
- self.new_object('document', 'new_document', initialize, plot=False)
-
def on_object_created(self, obj, plot, auto_select, callback, callback_params):
"""
Event callback for object creation.
@@ -359,6 +234,9 @@ class AppObject(QtCore.QObject):
t0 = time.time() # DEBUG
log.debug("on_object_created()")
+ # #############################################################################################################
+ # ############################### Add the new object to the Collection ######################################
+ # #############################################################################################################
# The Collection might change the name if there is a collision
self.app.collection.append(obj)
@@ -513,3 +391,128 @@ class AppObject(QtCore.QObject):
:return: None
"""
self.app.on_zoom_fit()
+
+ def new_excellon_object(self):
+ """
+ Creates a new, blank Excellon object.
+
+ :return: None
+ """
+
+ outname = 'new_exc'
+
+ def obj_init(new_obj, app_obj):
+ new_obj.tools = {}
+ new_obj.source_file = ''
+ new_obj.solid_geometry = []
+
+ self.new_object('excellon', outname, obj_init, plot=False)
+
+ def new_geometry_object(self):
+ """
+ Creates a new, blank and single-tool Geometry object.
+
+ :return: None
+ """
+ outname = 'new_geo'
+
+ def initialize(new_obj, app):
+ new_obj.multitool = True
+ new_obj.multigeo = True
+
+ # store here the default data for Geometry Data
+ default_data = {}
+ for opt_key, opt_val in app.options.items():
+ if opt_key.find('geometry' + "_") == 0:
+ oname = opt_key[len('geometry') + 1:]
+ default_data[oname] = self.app.options[opt_key]
+ if opt_key.find('tools_') == 0:
+ default_data[opt_key] = self.app.options[opt_key]
+
+ new_obj.tools = {
+ 1: {
+ 'tooldia': float(app.defaults["tools_mill_tooldia"]),
+ 'offset': 'Path',
+ 'offset_value': 0.0,
+ 'type': 'Rough',
+ 'tool_type': 'C1',
+ 'data': deepcopy(default_data),
+ 'solid_geometry': []
+ }
+ }
+
+ new_obj.tools[1]['data']['name'] = outname
+
+ new_obj.source_file = ''
+
+ self.new_object('geometry', outname, initialize, plot=False)
+
+ def new_gerber_object(self):
+ """
+ Creates a new, blank Gerber object.
+
+ :return: None
+ """
+
+ def initialize(new_obj, app):
+ new_obj.multitool = False
+ new_obj.source_file = ''
+ new_obj.multigeo = False
+ new_obj.follow = False
+ new_obj.apertures = {}
+ new_obj.solid_geometry = []
+ new_obj.follow_geometry = []
+
+ try:
+ new_obj.options['xmin'] = 0
+ new_obj.options['ymin'] = 0
+ new_obj.options['xmax'] = 0
+ new_obj.options['ymax'] = 0
+ except KeyError:
+ pass
+
+ self.new_object('gerber', 'new_grb', initialize, plot=False)
+
+ def new_script_object(self):
+ """
+ Creates a new, blank TCL Script object.
+
+ :return: None
+ """
+
+ # commands_list = "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, " \
+ # "AlignDrillGrid, Bbox, Bounds, ClearShell, CopperClear,\n" \
+ # "# Cncjob, Cutout, Delete, Drillcncjob, ExportDXF, ExportExcellon, ExportGcode,\n" \
+ # "# ExportGerber, ExportSVG, Exteriors, Follow, GeoCutout, GeoUnion, GetNames,\n" \
+ # "# GetSys, ImportSvg, Interiors, Isolate, JoinExcellon, JoinGeometry, " \
+ # "ListSys, MillDrills,\n" \
+ # "# MillSlots, Mirror, New, NewExcellon, NewGeometry, NewGerber, Nregions, " \
+ # "Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n" \
+ # "# Options, Paint, Panelize, PlotAl, PlotObjects, SaveProject, " \
+ # "SaveSys, Scale, SetActive, SetSys, SetOrigin, Skew, SubtractPoly,\n" \
+ # "# SubtractRectangle, Version, WriteGCode\n"
+
+ new_source_file = '# %s\n' % _('CREATE A NEW FLATCAM TCL SCRIPT') + \
+ '# %s:\n' % _('TCL Tutorial is here') + \
+ '# https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n' + '\n\n' + \
+ '# %s:\n' % _("FlatCAM commands list")
+ new_source_file += '# %s\n\n' % _("Type >help< followed by Run Code for a list of FlatCAM Tcl Commands "
+ "(displayed in Tcl Shell).")
+
+ def initialize(new_obj, app):
+ new_obj.source_file = deepcopy(new_source_file)
+
+ outname = 'new_script'
+ self.new_object('script', outname, initialize, plot=False)
+
+ def new_document_object(self):
+ """
+ Creates a new, blank Document object.
+
+ :return: None
+ """
+
+ def initialize(new_obj, app):
+ new_obj.source_file = ""
+
+ self.new_object('document', 'new_document', initialize, plot=False)
diff --git a/appObjects/FlatCAMExcellon.py b/appObjects/FlatCAMExcellon.py
index 70466073..54c74a30 100644
--- a/appObjects/FlatCAMExcellon.py
+++ b/appObjects/FlatCAMExcellon.py
@@ -123,15 +123,15 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.units = self.app.defaults['units'].upper()
- # fill in self.options values for the Drilling Tool from self.app.options
- for opt_key, opt_val in self.app.options.items():
- if opt_key.find('tools_drill_') == 0:
- self.options[opt_key] = deepcopy(opt_val)
-
- # fill in self.default_data values from self.options
- for opt_key, opt_val in self.app.options.items():
- if opt_key.find('excellon_') == 0 or opt_key.find('tools_drill_') == 0:
- self.default_data[opt_key] = deepcopy(opt_val)
+ # # fill in self.options values for the Drilling Tool from self.app.options
+ # for opt_key, opt_val in self.app.options.items():
+ # if opt_key.find('tools_drill_') == 0:
+ # self.options[opt_key] = deepcopy(opt_val)
+ #
+ # # fill in self.default_data values from self.options
+ # for opt_key, opt_val in self.app.options.items():
+ # if opt_key.find('excellon_') == 0 or opt_key.find('tools_drill_') == 0:
+ # self.default_data[opt_key] = deepcopy(opt_val)
self.form_fields.update({
"plot": self.ui.plot_cb,
diff --git a/appObjects/FlatCAMGeometry.py b/appObjects/FlatCAMGeometry.py
index 9baa932d..59796360 100644
--- a/appObjects/FlatCAMGeometry.py
+++ b/appObjects/FlatCAMGeometry.py
@@ -520,18 +520,15 @@ class GeometryObject(FlatCAMObj, Geometry):
# store here the default data for Geometry Data
self.default_data = {}
- for opt_key, opt_val in self.app.options.items():
- if opt_key.find('geometry' + "_") == 0:
- oname = opt_key[len('geometry') + 1:]
- self.default_data[oname] = self.app.options[opt_key]
- elif opt_key.find('tools_') == 0:
- self.default_data[opt_key] = self.app.options[opt_key]
+ # for opt_key, opt_val in self.options.items():
+ # if opt_key.find('geometry' + "_") == 0:
+ # oname = opt_key[len('geometry') + 1:]
+ # self.default_data[oname] = self.app.options[opt_key]
+ # elif opt_key.find('tools_') == 0:
+ # self.default_data[opt_key] = self.app.options[opt_key]
# fill in self.default_data values from self.options
- for def_key in self.default_data:
- for opt_key, opt_val in self.options.items():
- if def_key == opt_key:
- self.default_data[def_key] = deepcopy(opt_val)
+ self.default_data.update(self.options)
if type(self.options["tools_mill_tooldia"]) == float:
tools_list = [self.options["tools_mill_tooldia"]]
diff --git a/appObjects/ObjectCollection.py b/appObjects/ObjectCollection.py
index 9271c989..5cbe5220 100644
--- a/appObjects/ObjectCollection.py
+++ b/appObjects/ObjectCollection.py
@@ -582,7 +582,11 @@ class ObjectCollection(QtCore.QAbstractItemModel):
# ############################################################################################################
self.app.myKeywords.append(name)
+ # ############################################################################################################
+ # ############################# Set the Object UI (Properties Tab) ###########################################
+ # ############################################################################################################
obj.set_ui(obj.ui_type(app=self.app))
+
# a way to signal that the object was fully loaded
obj.load_complete = True
diff --git a/appTools/ToolCorners.py b/appTools/ToolCorners.py
index 0715514d..9db0f7c1 100644
--- a/appTools/ToolCorners.py
+++ b/appTools/ToolCorners.py
@@ -62,6 +62,7 @@ class ToolCorners(AppTool):
self.ui.add_marker_button.clicked.connect(self.add_markers)
self.ui.toggle_all_cb.toggled.connect(self.on_toggle_all)
self.ui.drill_button.clicked.connect(self.on_create_drill_object)
+ self.ui.check_button.clicked.connect(self.on_create_check_object)
def run(self, toggle=True):
self.app.defaults.report_usage("ToolCorners()")
@@ -435,6 +436,108 @@ class ToolCorners(AppTool):
else:
self.app.inform.emit('[success] %s' % _("Excellon object with corner drills created."))
+ def on_create_check_object(self):
+ self.app.call_source = "corners_tool"
+
+ tooldia = self.ui.drill_dia_entry.get_value()
+
+ if tooldia == 0:
+ self.app.inform.emit('[WARNING_NOTCL] %s %s' % (_("Cancelled."), _("The tool diameter is zero.")))
+ return
+
+ line_thickness = self.ui.thick_entry.get_value()
+ margin = self.ui.margin_entry.get_value()
+ tl_state = self.ui.tl_cb.get_value()
+ tr_state = self.ui.tr_cb.get_value()
+ bl_state = self.ui.bl_cb.get_value()
+ br_state = self.ui.br_cb.get_value()
+
+ # get the Gerber object on which the corner marker will be inserted
+ selection_index = self.ui.object_combo.currentIndex()
+ model_index = self.app.collection.index(selection_index, 0, self.ui.object_combo.rootModelIndex())
+
+ try:
+ self.grb_object = model_index.internalPointer().obj
+ except Exception as e:
+ log.debug("ToolCorners.add_markers() --> %s" % str(e))
+ self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
+ self.app.call_source = "app"
+ return
+
+ if tl_state is False and tr_state is False and bl_state is False and br_state is False:
+ self.app.inform.emit("[ERROR_NOTCL] %s." % _("Please select at least a location"))
+ self.app.call_source = "app"
+ return
+
+ xmin, ymin, xmax, ymax = self.grb_object.bounds()
+
+ # list of (x,y) tuples. Store here the drill coordinates
+ drill_list = []
+
+ if tl_state:
+ x = xmin - margin - line_thickness / 2.0
+ y = ymax + margin + line_thickness / 2.0
+ drill_list.append(
+ Point((x, y))
+ )
+
+ if tr_state:
+ x = xmax + margin + line_thickness / 2.0
+ y = ymax + margin + line_thickness / 2.0
+ drill_list.append(
+ Point((x, y))
+ )
+
+ if bl_state:
+ x = xmin - margin - line_thickness / 2.0
+ y = ymin - margin - line_thickness / 2.0
+ drill_list.append(
+ Point((x, y))
+ )
+
+ if br_state:
+ x = xmax + margin + line_thickness / 2.0
+ y = ymin - margin - line_thickness / 2.0
+ drill_list.append(
+ Point((x, y))
+ )
+
+ tools = {
+ 1: {
+ "tooldia": 0.1 if self.units == 'MM' else 0.0254,
+ "drills": drill_list,
+ 'data': {},
+ "solid_geometry": []
+ }
+ }
+
+ def obj_init(new_obj, app_inst):
+ new_obj.tools = deepcopy(tools)
+
+ # make sure we use the special preprocessor for checking
+ for tool in tools:
+ new_obj.tools[tool]['data']['tools_drill_ppname_e'] = 'Check_points'
+
+ new_obj.create_geometry()
+ new_obj.options.update({
+ 'name': outname,
+ 'tools_drill_cutz': -0.1,
+ 'tools_drill_ppname_e': 'Check_points'
+ })
+ new_obj.source_file = app_inst.f_handlers.export_excellon(obj_name=new_obj.options['name'],
+ local_use=new_obj,
+ filename=None,
+ use_thread=False)
+
+ outname = '%s_%s' % (str(self.grb_object.options['name']), 'corner_drills')
+ ret_val = self.app.app_obj.new_object("excellon", outname, obj_init)
+
+ self.app.call_source = "app"
+ if ret_val == 'fail':
+ self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
+ else:
+ self.app.inform.emit('[success] %s' % _("Excellon object with corner drills created."))
+
def replot(self, obj, run_thread=True):
def worker_task():
with self.app.proc_container.new('%s ...' % _("Plotting")):
@@ -511,7 +614,7 @@ class CornersUI:
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.layout.addWidget(separator_line)
- self.points_label = FCLabel('%s:' % _('Locations'))
+ self.points_label = FCLabel('%s' % _('Locations').upper())
self.points_label.setToolTip(
_("Locations where to place corner markers.")
)
@@ -642,7 +745,7 @@ class CornersUI:
grid_lay.addWidget(separator_line_2, 14, 0, 1, 2)
# Drill is corners
- self.drills_label = FCLabel('%s:' % _('Drills in Corners'))
+ self.drills_label = FCLabel('%s' % _('Drills in Locations').upper())
grid_lay.addWidget(self.drills_label, 16, 0, 1, 2)
# Drill Tooldia #
@@ -672,6 +775,32 @@ class CornersUI:
""")
grid_lay.addWidget(self.drill_button, 20, 0, 1, 2)
+ separator_line_2 = QtWidgets.QFrame()
+ separator_line_2.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid_lay.addWidget(separator_line_2, 22, 0, 1, 2)
+
+ # Check is corners
+ self.check_label = FCLabel('%s' % _('Check in Locations').upper())
+ grid_lay.addWidget(self.check_label, 24, 0, 1, 2)
+
+ # ## Create an Excellon object for checking the positioning
+ self.check_button = FCButton(_("Create Excellon Object"))
+ self.check_button.setIcon(QtGui.QIcon(self.app.resource_location + '/drill32.png'))
+ self.check_button.setToolTip(
+ _("Will create an Excellon object using a special preprocessor.\n"
+ "The spindle will not start and the mounted probe will move to\n"
+ "the corner locations, wait for the user interaction and then\n"
+ "move to the next location until the last one.")
+ )
+ self.check_button.setStyleSheet("""
+ QPushButton
+ {
+ font-weight: bold;
+ }
+ """)
+ grid_lay.addWidget(self.check_button, 26, 0, 1, 2)
+
self.layout.addStretch()
# ## Reset Tool
diff --git a/appTools/ToolDrilling.py b/appTools/ToolDrilling.py
index dee9e143..1c579eff 100644
--- a/appTools/ToolDrilling.py
+++ b/appTools/ToolDrilling.py
@@ -146,7 +146,7 @@ class ToolDrilling(AppTool, Excellon):
"tools_drill_drill_slots": self.ui.drill_slots_cb,
"tools_drill_drill_overlap": self.ui.drill_overlap_entry,
- "tools_drill_last_drill": self.ui.last_drill_cb
+ "tools_drill_last_drill": self.ui.last_drill_cb,
}
self.general_form_fields = {
@@ -331,15 +331,14 @@ class ToolDrilling(AppTool, Excellon):
for it in range(self.ui.pp_excellon_name_cb.count()):
self.ui.pp_excellon_name_cb.setItemData(it, self.ui.pp_excellon_name_cb.itemText(it), QtCore.Qt.ToolTipRole)
- # Show/Hide Advanced Options
- app_mode = self.app.defaults["global_app_level"]
- self.change_level(app_mode)
-
- self.ui.tools_frame.show()
-
self.ui.order_radio.set_value(self.app.defaults["tools_drill_tool_order"])
- loaded_obj = self.app.collection.get_by_name(self.ui.object_combo.get_value())
+ try:
+ loaded_obj = self.app.collection.get_by_name(self.ui.object_combo.get_value())
+ except Exception as err:
+ self.app.log.debug("ToolDrilling -> Loaded Excellon object error. %s" % str(err))
+ return
+
if loaded_obj:
outname = loaded_obj.options['name']
else:
@@ -347,62 +346,70 @@ class ToolDrilling(AppTool, Excellon):
# init the working variables
self.default_data.clear()
- self.default_data = {
- "name": outname + '_drill',
- "plot": self.app.defaults["excellon_plot"],
- "solid": self.app.defaults["excellon_solid"],
- "multicolored": self.app.defaults["excellon_multicolored"],
- "merge_fuse_tools": self.app.defaults["excellon_merge_fuse_tools"],
- "format_upper_in": self.app.defaults["excellon_format_upper_in"],
- "format_lower_in": self.app.defaults["excellon_format_lower_in"],
- "format_upper_mm": self.app.defaults["excellon_format_upper_mm"],
- "lower_mm": self.app.defaults["excellon_format_lower_mm"],
- "zeros": self.app.defaults["excellon_zeros"],
-
- "tools_drill_tool_order": self.app.defaults["tools_drill_tool_order"],
- "tools_drill_cutz": self.app.defaults["tools_drill_cutz"],
- "tools_drill_multidepth": self.app.defaults["tools_drill_multidepth"],
- "tools_drill_depthperpass": self.app.defaults["tools_drill_depthperpass"],
-
- "tools_drill_travelz": self.app.defaults["tools_drill_travelz"],
- "tools_drill_endz": self.app.defaults["tools_drill_endz"],
- "tools_drill_endxy": self.app.defaults["tools_drill_endxy"],
- "tools_drill_feedrate_z": self.app.defaults["tools_drill_feedrate_z"],
-
- "tools_drill_spindlespeed": self.app.defaults["tools_drill_spindlespeed"],
- "tools_drill_dwell": self.app.defaults["tools_drill_dwell"],
- "tools_drill_dwelltime": self.app.defaults["tools_drill_dwelltime"],
-
- "tools_drill_toolchange": self.app.defaults["tools_drill_toolchange"],
- "tools_drill_toolchangez": self.app.defaults["tools_drill_toolchangez"],
- "tools_drill_ppname_e": self.app.defaults["tools_drill_ppname_e"],
-
- # Drill Slots
- "tools_drill_drill_slots": self.app.defaults["tools_drill_drill_slots"],
- "tools_drill_drill_overlap": self.app.defaults["tools_drill_drill_overlap"],
- "tools_drill_last_drill": self.app.defaults["tools_drill_last_drill"],
-
- # Advanced Options
- "tools_drill_offset": self.app.defaults["tools_drill_offset"],
- "tools_drill_toolchangexy": self.app.defaults["tools_drill_toolchangexy"],
- "tools_drill_startz": self.app.defaults["tools_drill_startz"],
- "tools_drill_feedrate_rapid": self.app.defaults["tools_drill_feedrate_rapid"],
- "tools_drill_z_pdepth": self.app.defaults["tools_drill_z_pdepth"],
- "tools_drill_feedrate_probe": self.app.defaults["tools_drill_feedrate_probe"],
- "tools_drill_spindledir": self.app.defaults["tools_drill_spindledir"],
- "tools_drill_f_plunge": self.app.defaults["tools_drill_f_plunge"],
- "tools_drill_f_retract": self.app.defaults["tools_drill_f_retract"],
-
- "tools_drill_area_exclusion": self.app.defaults["tools_drill_area_exclusion"],
- "tools_drill_area_shape": self.app.defaults["tools_drill_area_shape"],
- "tools_drill_area_strategy": self.app.defaults["tools_drill_area_strategy"],
- "tools_drill_area_overz": self.app.defaults["tools_drill_area_overz"],
- }
# fill in self.default_data values from self.options
for opt_key, opt_val in self.app.options.items():
- if opt_key.find('excellon_') == 0 or opt_key.find('tools_drill_') == 0:
+ if opt_key.find('excellon_') == 0:
+ oname = opt_key[len('excellon_'):]
+ self.default_data[oname] = deepcopy(opt_val)
+ if opt_key.find('tools_drill_') == 0:
self.default_data[opt_key] = deepcopy(opt_val)
+ if opt_key.find('tools_mill_') == 0:
+ self.default_data[opt_key] = deepcopy(opt_val)
+
+ self.default_data.update(
+ {
+ "name": outname + '_drill',
+ "plot": loaded_obj.options["plot"],
+ "solid": loaded_obj.options["solid"],
+ "multicolored": loaded_obj.options["multicolored"],
+ "merge_fuse_tools": loaded_obj.options["merge_fuse_tools"],
+ "format_upper_in": loaded_obj.options["format_upper_in"],
+ "format_lower_in": loaded_obj.options["format_lower_in"],
+ "format_upper_mm": loaded_obj.options["format_upper_mm"],
+ "lower_mm": loaded_obj.options["format_lower_mm"],
+ "zeros": loaded_obj.options["zeros"],
+
+ "tools_drill_tool_order": loaded_obj.options["tools_drill_tool_order"],
+ "tools_drill_cutz": loaded_obj.options["tools_drill_cutz"],
+ "tools_drill_multidepth": loaded_obj.options["tools_drill_multidepth"],
+ "tools_drill_depthperpass": loaded_obj.options["tools_drill_depthperpass"],
+
+ "tools_drill_travelz": loaded_obj.options["tools_drill_travelz"],
+ "tools_drill_endz": loaded_obj.options["tools_drill_endz"],
+ "tools_drill_endxy": loaded_obj.options["tools_drill_endxy"],
+ "tools_drill_feedrate_z": loaded_obj.options["tools_drill_feedrate_z"],
+
+ "tools_drill_spindlespeed": loaded_obj.options["tools_drill_spindlespeed"],
+ "tools_drill_dwell": loaded_obj.options["tools_drill_dwell"],
+ "tools_drill_dwelltime": loaded_obj.options["tools_drill_dwelltime"],
+
+ "tools_drill_toolchange": loaded_obj.options["tools_drill_toolchange"],
+ "tools_drill_toolchangez": loaded_obj.options["tools_drill_toolchangez"],
+ "tools_drill_ppname_e": loaded_obj.options["tools_drill_ppname_e"],
+
+ # Drill Slots
+ "tools_drill_drill_slots": loaded_obj.options["tools_drill_drill_slots"],
+ "tools_drill_drill_overlap": loaded_obj.options["tools_drill_drill_overlap"],
+ "tools_drill_last_drill": loaded_obj.options["tools_drill_last_drill"],
+
+ # Advanced Options
+ "tools_drill_offset": loaded_obj.options["tools_drill_offset"],
+ "tools_drill_toolchangexy": loaded_obj.options["tools_drill_toolchangexy"],
+ "tools_drill_startz": loaded_obj.options["tools_drill_startz"],
+ "tools_drill_feedrate_rapid": loaded_obj.options["tools_drill_feedrate_rapid"],
+ "tools_drill_z_pdepth": loaded_obj.options["tools_drill_z_pdepth"],
+ "tools_drill_feedrate_probe": loaded_obj.options["tools_drill_feedrate_probe"],
+ "tools_drill_spindledir": loaded_obj.options["tools_drill_spindledir"],
+ "tools_drill_f_plunge": loaded_obj.options["tools_drill_f_plunge"],
+ "tools_drill_f_retract": loaded_obj.options["tools_drill_f_retract"],
+
+ "tools_drill_area_exclusion": loaded_obj.options["tools_drill_area_exclusion"],
+ "tools_drill_area_shape": loaded_obj.options["tools_drill_area_shape"],
+ "tools_drill_area_strategy": loaded_obj.options["tools_drill_area_strategy"],
+ "tools_drill_area_overz": loaded_obj.options["tools_drill_area_overz"],
+ }
+ )
self.first_click = False
self.cursor_pos = None
@@ -431,45 +438,47 @@ class ToolDrilling(AppTool, Excellon):
# ####### Fill in the parameters #########
# ########################################
# ########################################
- self.ui.cutz_entry.set_value(self.app.defaults["tools_drill_cutz"])
- self.ui.mpass_cb.set_value(self.app.defaults["tools_drill_multidepth"])
- self.ui.maxdepth_entry.set_value(self.app.defaults["tools_drill_depthperpass"])
- self.ui.travelz_entry.set_value(self.app.defaults["tools_drill_travelz"])
- self.ui.feedrate_z_entry.set_value(self.app.defaults["tools_drill_feedrate_z"])
- self.ui.feedrate_rapid_entry.set_value(self.app.defaults["tools_drill_feedrate_rapid"])
- self.ui.spindlespeed_entry.set_value(self.app.defaults["tools_drill_spindlespeed"])
- self.ui.dwell_cb.set_value(self.app.defaults["tools_drill_dwell"])
- self.ui.dwelltime_entry.set_value(self.app.defaults["tools_drill_dwelltime"])
- self.ui.offset_entry.set_value(self.app.defaults["tools_drill_offset"])
- self.ui.toolchange_cb.set_value(self.app.defaults["tools_drill_toolchange"])
- self.ui.toolchangez_entry.set_value(self.app.defaults["tools_drill_toolchangez"])
- self.ui.estartz_entry.set_value(self.app.defaults["tools_drill_startz"])
- self.ui.endz_entry.set_value(self.app.defaults["tools_drill_endz"])
- self.ui.endxy_entry.set_value(self.app.defaults["tools_drill_endxy"])
- self.ui.pdepth_entry.set_value(self.app.defaults["tools_drill_z_pdepth"])
- self.ui.feedrate_probe_entry.set_value(self.app.defaults["tools_drill_feedrate_probe"])
+ self.ui.cutz_entry.set_value(loaded_obj.options["tools_drill_cutz"])
+ self.ui.mpass_cb.set_value(loaded_obj.options["tools_drill_multidepth"])
+ self.ui.maxdepth_entry.set_value(loaded_obj.options["tools_drill_depthperpass"])
+ self.ui.travelz_entry.set_value(loaded_obj.options["tools_drill_travelz"])
+ self.ui.feedrate_z_entry.set_value(loaded_obj.options["tools_drill_feedrate_z"])
+ self.ui.feedrate_rapid_entry.set_value(loaded_obj.options["tools_drill_feedrate_rapid"])
+ self.ui.spindlespeed_entry.set_value(loaded_obj.options["tools_drill_spindlespeed"])
+ self.ui.dwell_cb.set_value(loaded_obj.options["tools_drill_dwell"])
+ self.ui.dwelltime_entry.set_value(loaded_obj.options["tools_drill_dwelltime"])
+ self.ui.offset_entry.set_value(loaded_obj.options["tools_drill_offset"])
+ self.ui.toolchange_cb.set_value(loaded_obj.options["tools_drill_toolchange"])
+ self.ui.toolchangez_entry.set_value(loaded_obj.options["tools_drill_toolchangez"])
+ self.ui.estartz_entry.set_value(loaded_obj.options["tools_drill_startz"])
+ self.ui.endz_entry.set_value(loaded_obj.options["tools_drill_endz"])
+ self.ui.endxy_entry.set_value(loaded_obj.options["tools_drill_endxy"])
+ self.ui.pdepth_entry.set_value(loaded_obj.options["tools_drill_z_pdepth"])
+ self.ui.feedrate_probe_entry.set_value(loaded_obj.options["tools_drill_feedrate_probe"])
- self.ui.pp_excellon_name_cb.set_value(self.app.defaults["tools_drill_ppname_e"])
+ if loaded_obj.options["tools_drill_ppname_e"] in pp_list:
+ sel_ppname_e = loaded_obj.options["tools_drill_ppname_e"]
+ else:
+ sel_ppname_e = 'default'
+ self.ui.pp_excellon_name_cb.set_value(sel_ppname_e)
- self.ui.exclusion_cb.set_value(self.app.defaults["tools_drill_area_exclusion"])
- self.ui.strategy_radio.set_value(self.app.defaults["tools_drill_area_strategy"])
- self.ui.over_z_entry.set_value(self.app.defaults["tools_drill_area_overz"])
- self.ui.area_shape_radio.set_value(self.app.defaults["tools_drill_area_shape"])
+ self.ui.exclusion_cb.set_value(loaded_obj.options["tools_drill_area_exclusion"])
+ self.ui.strategy_radio.set_value(loaded_obj.options["tools_drill_area_strategy"])
+ self.ui.over_z_entry.set_value(loaded_obj.options["tools_drill_area_overz"])
+ self.ui.area_shape_radio.set_value(loaded_obj.options["tools_drill_area_shape"])
# Drill slots - part of the Advanced Excellon params
- self.ui.drill_overlap_entry.set_value(self.app.defaults["tools_drill_drill_overlap"])
- self.ui.last_drill_cb.set_value(self.app.defaults["tools_drill_last_drill"])
+ self.ui.drill_overlap_entry.set_value(loaded_obj.options["tools_drill_drill_overlap"])
+ self.ui.last_drill_cb.set_value(loaded_obj.options["tools_drill_last_drill"])
self.ui.drill_overlap_label.hide()
self.ui.drill_overlap_entry.hide()
self.ui.last_drill_cb.hide()
- # if the app mode is Basic then disable this feature
- if app_mode == 'b':
- self.ui.drill_slots_cb.set_value(False)
- self.ui.drill_slots_cb.hide()
- else:
- self.ui.drill_slots_cb.show()
- self.ui.drill_slots_cb.set_value(self.app.defaults["tools_drill_drill_slots"])
+ # Show/Hide Advanced Options
+ app_mode = self.app.defaults["global_app_level"]
+ self.change_level(app_mode)
+
+ self.ui.tools_frame.show()
try:
self.ui.object_combo.currentTextChanged.disconnect()
@@ -493,7 +502,11 @@ class ToolDrilling(AppTool, Excellon):
def on_level_changed(self, checked):
- loaded_obj = self.app.collection.get_by_name(self.ui.object_combo.get_value())
+ try:
+ loaded_obj = self.app.collection.get_by_name(self.ui.object_combo.get_value())
+ except Exception as err:
+ self.app.log.debug("ToolDrilling -> Loaded Excellon object error. %s" % str(err))
+ return
if not checked:
self.ui.level.setText('%s' % _('Beginner'))
@@ -552,16 +565,16 @@ class ToolDrilling(AppTool, Excellon):
# Tool parameters section
if loaded_obj:
- app_defaults = self.app.defaults
+ options = loaded_obj.options
for tool in loaded_obj.tools:
tool_data = loaded_obj.tools[tool]['data']
- tool_data['tools_drill_multidepth'] = app_defaults['tools_drill_multidepth']
- tool_data['tools_drill_dwell'] = app_defaults['tools_drill_dwell']
- tool_data['tools_drill_drill_slots'] = app_defaults['tools_drill_drill_slots']
+ tool_data['tools_drill_multidepth'] = options['tools_drill_multidepth']
+ tool_data['tools_drill_dwell'] = options['tools_drill_dwell']
+ tool_data['tools_drill_drill_slots'] = options['tools_drill_drill_slots']
- tool_data['tools_drill_toolchangexy'] = app_defaults['tools_drill_toolchangexy']
- tool_data['tools_drill_area_exclusion'] = app_defaults['tools_drill_area_exclusion']
+ tool_data['tools_drill_toolchangexy'] = options['tools_drill_toolchangexy']
+ tool_data['tools_drill_area_exclusion'] = options['tools_drill_area_exclusion']
self.ui.search_load_db_btn.show()
@@ -902,6 +915,8 @@ class ToolDrilling(AppTool, Excellon):
self.excellon_tools = self.excellon_obj.tools
self.build_tool_ui()
+ self.update_ui()
+
sel_rows = set()
table_items = self.ui.tools_table.selectedItems()
if table_items:
@@ -1184,6 +1199,7 @@ class ToolDrilling(AppTool, Excellon):
def update_ui(self):
self.blockSignals(True)
+ self.ui_disconnect()
sel_rows = set()
table_items = self.ui.tools_table.selectedItems()
@@ -1199,6 +1215,7 @@ class ToolDrilling(AppTool, Excellon):
"%s: %s" % (_('Parameters for'), _("No Tool Selected"))
)
self.blockSignals(False)
+ self.ui_connect()
return
else:
self.ui.generate_cnc_button.setDisabled(False)
@@ -1224,12 +1241,15 @@ class ToolDrilling(AppTool, Excellon):
self.storage_to_form(self.excellon_tools[tooluid]['data'])
else:
self.blockSignals(False)
+ self.ui_connect()
return
except Exception as e:
log.debug("Tool missing. Add a tool in the Tool Table. %s" % str(e))
self.blockSignals(False)
+ self.ui_connect()
return
self.blockSignals(False)
+ self.ui_connect()
def storage_to_form(self, dict_storage):
"""
@@ -1240,6 +1260,8 @@ class ToolDrilling(AppTool, Excellon):
:return: None
:rtype:
"""
+
+ # update the Tool parameters
for form_key in self.tool_form_fields:
for storage_key in dict_storage:
if form_key == storage_key and form_key not in \
@@ -1250,6 +1272,16 @@ class ToolDrilling(AppTool, Excellon):
log.debug("ToolDrilling.storage_to_form() --> %s" % str(e))
pass
+ # update the Common parameters
+ for form_key in self.general_form_fields:
+ for storage_key in dict_storage:
+ if form_key == storage_key:
+ try:
+ self.general_form_fields[form_key].set_value(dict_storage[form_key])
+ except Exception as e:
+ log.debug("ToolDrilling.storage_to_form() -> common parameters --> %s" % str(e))
+ pass
+
def form_to_storage(self):
"""
Will update the 'storage' attribute which is the dict self.tools with data collected from GUI
@@ -1886,10 +1918,10 @@ class ToolDrilling(AppTool, Excellon):
# #############################################################################################################
# General Parameters
# #############################################################################################################
- used_excellon_optimization_type = self.app.defaults["excellon_optimization_type"]
+ used_exc_optim_type = self.app.defaults["excellon_optimization_type"]
current_platform = platform.architecture()[0]
if current_platform != '64bit':
- used_excellon_optimization_type = 'T'
+ used_exc_optim_type = 'T'
# #############################################################################################################
# #############################################################################################################
@@ -2064,8 +2096,8 @@ class ToolDrilling(AppTool, Excellon):
first_pt=first_drill_point,
is_first=True,
is_last=True,
- opt_type=used_excellon_optimization_type,
- toolchange=True)
+ opt_type=used_exc_optim_type,
+ toolchange=False)
# parse the Gcode
tool_gcode_parsed = job_obj.excellon_tool_gcode_parse(used_tooldia, gcode=tool_gcode,
@@ -2116,13 +2148,13 @@ class ToolDrilling(AppTool, Excellon):
is_first_tool = True if tool == sel_tools[0] else False
# Generate Gcode for the current tool
- tool_gcode, last_pt, start_gcode = job_obj.excellon_tool_gcode_gen(
- tool, tool_points, self.excellon_tools,
- first_pt=first_drill_point,
- is_first=is_first_tool,
- is_last=is_last_tool,
- opt_type=used_excellon_optimization_type,
- toolchange=True)
+ tool_gcode, last_pt, start_gcode = job_obj.excellon_tool_gcode_gen(tool, tool_points,
+ self.excellon_tools,
+ first_pt=first_drill_point,
+ is_first=is_first_tool,
+ is_last=is_last_tool,
+ opt_type=used_exc_optim_type,
+ toolchange=True)
# parse Gcode for the current tool
tool_gcode_parsed = job_obj.excellon_tool_gcode_parse(used_tooldia, gcode=tool_gcode,
@@ -2149,13 +2181,13 @@ class ToolDrilling(AppTool, Excellon):
# FIXME is it necessary? didn't we do it previously when filling data in self.exc_cnc_tools dictionary?
job_obj.create_geometry()
- if used_excellon_optimization_type == 'M':
+ if used_exc_optim_type == 'M':
log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" %
str(job_obj.measured_distance))
- elif used_excellon_optimization_type == 'B':
+ elif used_exc_optim_type == 'B':
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" %
str(job_obj.measured_distance))
- elif used_excellon_optimization_type == 'T':
+ elif used_exc_optim_type == 'T':
log.debug(
"The total travel distance with Travelling Salesman Algorithm is: %s" %
str(job_obj.measured_distance))
diff --git a/camlib.py b/camlib.py
index 46581d1f..771261ff 100644
--- a/camlib.py
+++ b/camlib.py
@@ -3301,9 +3301,12 @@ class CNCjob(Geometry):
# t_gcode += start_gcode
# do the ToolChange event
- t_gcode += self.doformat(p.z_feedrate_code)
- t_gcode += self.doformat(p.toolchange_code, toolchangexy=(temp_locx, temp_locy))
- t_gcode += self.doformat(p.z_feedrate_code)
+ if toolchange:
+ t_gcode += self.doformat(p.z_feedrate_code)
+ t_gcode += self.doformat(p.toolchange_code, toolchangexy=(temp_locx, temp_locy))
+ t_gcode += self.doformat(p.z_feedrate_code)
+ else:
+ t_gcode += self.doformat(p.lift_code)
# Spindle start
t_gcode += self.doformat(p.spindle_code)
diff --git a/preprocessors/Check_points.py b/preprocessors/Check_points.py
new file mode 100644
index 00000000..fe5c6a6b
--- /dev/null
+++ b/preprocessors/Check_points.py
@@ -0,0 +1,252 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing #
+# http://flatcam.org #
+# File Author: Marius Stanciu #
+# Date: 11-Dec-2020 #
+# MIT Licence #
+# ##########################################################
+
+from appPreProcessor import *
+
+
+class Check_points(PreProc):
+
+ include_header = True
+ coordinate_format = "%.*f"
+ feedrate_format = '%.*f'
+
+ def start_code(self, p):
+ units = ' ' + str(p['units']).lower()
+ coords_xy = p['xy_toolchange']
+ end_coords_xy = p['xy_end']
+ gcode = '(This preprocessor is used to check the positioning of the PCB,)\n'
+ gcode += '(by moving a probe - possible a fine drill bit - to custom locations)\n'
+ gcode += '(and wait for user interaction in order to continue to the next point.)\n\n'
+
+ xmin = '%.*f' % (p.coords_decimals, p['options']['xmin'])
+ xmax = '%.*f' % (p.coords_decimals, p['options']['xmax'])
+ ymin = '%.*f' % (p.coords_decimals, p['options']['ymin'])
+ ymax = '%.*f' % (p.coords_decimals, p['options']['ymax'])
+
+ if str(p['options']['type']) == 'Geometry':
+ gcode += '(TOOL DIAMETER: ' + str(p['options']['tool_dia']) + units + ')\n'
+ gcode += '(Feedrate_XY: ' + str(p['feedrate']) + units + '/min' + ')\n'
+ gcode += '(Feedrate_Z: ' + str(p['z_feedrate']) + units + '/min' + ')\n'
+ gcode += '(Feedrate rapids ' + str(p['feedrate_rapid']) + units + '/min' + ')\n' + '\n'
+ gcode += '(Z_Cut: ' + str(p['z_cut']) + units + ')\n'
+ if p['multidepth'] is True:
+ gcode += '(DepthPerCut: ' + str(p['z_depthpercut']) + units + ' <=>' + \
+ str(math.ceil(abs(p['z_cut']) / p['z_depthpercut'])) + ' passes' + ')\n'
+ gcode += '(Z_Move: ' + str(p['z_move']) + units + ')\n'
+
+ elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True:
+ gcode += '\n(TOOLS DIAMETER: )\n'
+ for tool, val in p['exc_tools'].items():
+ gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n'
+
+ gcode += '\n(FEEDRATE Z: )\n'
+ for tool, val in p['exc_tools'].items():
+ gcode += '(Tool: %s -> ' % str(tool) + 'Feedrate: %s' % \
+ str(val['data']["tools_drill_feedrate_z"]) + ')\n'
+
+ gcode += '\n(FEEDRATE RAPIDS: )\n'
+ for tool, val in p['exc_tools'].items():
+ gcode += '(Tool: %s -> ' % str(tool) + 'Feedrate Rapids: %s' % \
+ str(val['data']["tools_drill_feedrate_rapid"]) + ')\n'
+
+ gcode += '\n(Z_CUT: )\n'
+ for tool, val in p['exc_tools'].items():
+ gcode += '(Tool: %s -> ' % str(tool) + 'Z_Cut: %s' % str(val['data']["tools_drill_cutz"]) + ')\n'
+
+ gcode += '\n(Tools Offset: )\n'
+ for tool, val in p['exc_cnc_tools'].items():
+ gcode += '(Tool: %s -> ' % str(val['tool']) + 'Offset Z: %s' % \
+ str(val['data']["tools_drill_offset"]) + ')\n'
+
+ if p['multidepth'] is True:
+ gcode += '\n(DEPTH_PER_CUT: )\n'
+ for tool, val in p['exc_tools'].items():
+ gcode += '(Tool: %s -> ' % str(tool) + 'DeptPerCut: %s' % \
+ str(val['data']["tools_drill_depthperpass"]) + ')\n'
+
+ gcode += '\n(Z_MOVE: )\n'
+ for tool, val in p['exc_tools'].items():
+ gcode += '(Tool: %s -> ' % str(tool) + 'Z_Move: %s' % str(val['data']["tools_drill_travelz"]) + ')\n'
+ gcode += '\n'
+
+ if p['toolchange'] is True:
+ gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
+
+ if coords_xy is not None:
+ gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
+ p.decimals, coords_xy[1]) + units + ')\n'
+ else:
+ gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
+
+ gcode += '(Z Start: ' + str(p['startz']) + units + ')\n'
+ gcode += '(Z End: ' + str(p['z_end']) + units + ')\n'
+ if end_coords_xy is not None:
+ gcode += '(X,Y End: ' + "%.*f, %.*f" % (p.decimals, end_coords_xy[0],
+ p.decimals, end_coords_xy[1]) + units + ')\n'
+ else:
+ gcode += '(X,Y End: ' + "None" + units + ')\n'
+ gcode += '(Steps per circle: ' + str(p['steps_per_circle']) + ')\n'
+
+ if str(p['options']['type']) == 'Excellon' or str(p['options']['type']) == 'Excellon Geometry':
+ gcode += '(Preprocessor Excellon: ' + str(p['pp_excellon_name']) + ')\n' + '\n'
+ else:
+ gcode += '(Preprocessor Geometry: ' + str(p['pp_geometry_name']) + ')\n' + '\n'
+
+ gcode += '(X range: ' + '{: >9s}'.format(xmin) + ' ... ' + '{: >9s}'.format(xmax) + ' ' + units + ')\n'
+ gcode += '(Y range: ' + '{: >9s}'.format(ymin) + ' ... ' + '{: >9s}'.format(ymax) + ' ' + units + ')\n\n'
+
+ gcode += '(Spindle Speed: %s RPM)\n' % str(p['spindlespeed'])
+
+ gcode += ('G20\n' if p.units.upper() == 'IN' else 'G21\n')
+ gcode += 'G90\n'
+ gcode += 'G94'
+
+ return gcode
+
+ def startz_code(self, p):
+ if p.startz is not None:
+ return 'G00 Z' + self.coordinate_format % (p.coords_decimals, p.startz)
+ else:
+ return ''
+
+ def lift_code(self, p):
+ return 'G00 Z' + self.coordinate_format % (p.coords_decimals, p.z_move)
+
+ def down_code(self, p):
+ # make sure that the probe will always be above the material
+ cutz_val = -p.z_cut if p.z_cut < 0 else p.z_cut
+ gcode = 'G01 Z' + self.coordinate_format % (p.coords_decimals, cutz_val) + '\n'
+ # wait for user interaction
+ gcode += 'M0'
+ return gcode
+
+ def toolchange_code(self, p):
+ z_toolchange = p.z_toolchange
+ toolchangexy = p.xy_toolchange
+ f_plunge = p.f_plunge
+
+ if toolchangexy is not None:
+ x_toolchange = toolchangexy[0]
+ y_toolchange = toolchangexy[1]
+ else:
+ x_toolchange = 0.0
+ y_toolchange = 0.0
+
+ if int(p.tool) == 1 and p.startz is not None:
+ z_toolchange = p.startz
+
+ if str(p['options']['type']) == 'Excellon':
+ if toolchangexy is not None:
+ gcode = """
+M5
+G00 Z{z_toolchange}
+G00 X{x_toolchange} Y{y_toolchange}
+(MSG, Change to Tool T{tool}. WARNING: the following move is FAST G0)
+M0
+G00 Z{z_move}
+G01 Z0
+(MSG, Adjust the tool T{tool} to touch the material and then tighten it.)
+M0
+(MSG, Changed to Tool T{tool})
+""".format(x_toolchange=self.coordinate_format % (p.coords_decimals, x_toolchange),
+ y_toolchange=self.coordinate_format % (p.coords_decimals, y_toolchange),
+ z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
+ z_move=self.coordinate_format % (p.coords_decimals, p.z_move),
+ tool=int(p.tool))
+
+ else:
+ gcode = """
+M5
+G00 Z{z_toolchange}
+(MSG, Change to Tool T{tool}. WARNING: the following move is FAST G0)
+M0
+G00 Z{z_move}
+G01 Z0
+(MSG, Adjust the tool T{tool} to touch the material and then tighten it.)
+M0
+(MSG, Changed to Tool T{tool})
+""".format(z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
+ z_move=self.coordinate_format % (p.coords_decimals, p.z_move),
+ tool=int(p.tool))
+
+ if f_plunge is True:
+ gcode += '\nG00 Z%.*f' % (p.coords_decimals, p.z_move)
+ return gcode
+
+ else:
+ if toolchangexy is not None:
+ gcode = """
+M5
+G00 Z{z_toolchange}
+G00 X{x_toolchange}Y{y_toolchange}
+(MSG, Change to Tool T{tool}. WARNING: the following move is FAST G0)
+M0
+G00 Z{z_move}
+G01 Z0
+(MSG, Adjust the tool T{tool} to touch the material and then tighten it.)
+M0
+(MSG, Changed to Tool T{tool})
+""".format(x_toolchange=self.coordinate_format % (p.coords_decimals, x_toolchange),
+ y_toolchange=self.coordinate_format % (p.coords_decimals, y_toolchange),
+ z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
+ z_move=self.coordinate_format % (p.coords_decimals, p.z_move),
+ tool=int(p.tool))
+ else:
+ gcode = """
+M5
+G00 Z{z_toolchange}
+(MSG, Change to Tool T{tool}. WARNING: the following move is FAST G0)
+M0
+G00 Z{z_move}
+G01 Z0
+(MSG, Adjust the tool T{tool} to touch the material and then tighten it.)
+M0
+(MSG, Changed to Tool T{tool})
+""".format(z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
+ z_move=self.coordinate_format % (p.coords_decimals, p.z_move),
+ tool=int(p.tool))
+
+ if f_plunge is True:
+ gcode += '\nG00 Z%.*f' % (p.coords_decimals, p.z_move)
+ return gcode
+
+ def up_to_zero_code(self, p):
+ return ''
+
+ def position_code(self, p):
+ return ('X' + self.coordinate_format + ' Y' + self.coordinate_format) % \
+ (p.coords_decimals, p.x, p.coords_decimals, p.y)
+
+ def rapid_code(self, p):
+ return ('G00 ' + self.position_code(p)).format(**p)
+
+ def linear_code(self, p):
+ return ('G00 ' + self.position_code(p)).format(**p)
+
+ def end_code(self, p):
+ end_coords_xy = p['xy_end']
+ gcode = ('G00 Z' + self.feedrate_format % (p.fr_decimals, p.z_end) + "\n")
+
+ if end_coords_xy and end_coords_xy != '':
+ gcode += 'G00 X{x} Y{y}'.format(x=end_coords_xy[0], y=end_coords_xy[1]) + "\n"
+ return gcode
+
+ def feedrate_code(self, p):
+ return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.feedrate))
+
+ def z_feedrate_code(self, p):
+ return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.z_feedrate))
+
+ def spindle_code(self, p):
+ return ''
+
+ def dwell_code(self, p):
+ return ''
+
+ def spindle_stop_code(self, p):
+ return 'M05'
diff --git a/preprocessors/Default_no_M6.py b/preprocessors/Default_no_M6.py
index 2b001364..9f257dbd 100644
--- a/preprocessors/Default_no_M6.py
+++ b/preprocessors/Default_no_M6.py
@@ -147,7 +147,6 @@ class Default_no_M6(PreProc):
gcode = """
M5
G00 Z{z_toolchange}
-T{tool}
G00 X{x_toolchange} Y{y_toolchange}
(MSG, Change to Tool Dia = {toolC} ||| Total drills for tool T{tool} = {t_drills})
M0
@@ -162,7 +161,6 @@ G00 Z{z_toolchange}
gcode = """
M5
G00 Z{z_toolchange}
-T{tool}
(MSG, Change to Tool Dia = {toolC} ||| Total drills for tool T{tool} = {t_drills})
M0
G00 Z{z_toolchange}
@@ -181,7 +179,6 @@ G00 Z{z_toolchange}
M5
G00 Z{z_toolchange}
G00 X{x_toolchange} Y{y_toolchange}
-T{tool}
(MSG, Change to Tool Dia = {toolC})
M0
G00 Z{z_toolchange}
@@ -195,7 +192,6 @@ G00 Z{z_toolchange}
gcode = """
M5
G00 Z{z_toolchange}
-T{tool}
(MSG, Change to Tool Dia = {toolC})
M0
G00 Z{z_toolchange}