From 7ad091e163ca88e06801ab242565a2b3c1c90010 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 16 Dec 2019 00:12:04 +0200 Subject: [PATCH] - modified the export_gcode() method and the preprocessors such that the preprocessors now have the information if to include the gcode header - RELEASE 8.99 --- FlatCAMObj.py | 215 ++++++++++++++++-------- README.md | 1 + camlib.py | 6 + preprocessors/Berta_CNC.py | 9 +- preprocessors/ISEL_CNC.py | 2 +- preprocessors/ISEL_ICP_CNC.py | 5 +- preprocessors/Paste_1.py | 1 + preprocessors/Repetier.py | 2 + preprocessors/Roland_MDX_20.py | 1 + preprocessors/Toolchange_Custom.py | 1 + preprocessors/Toolchange_Probe_MACH3.py | 9 +- preprocessors/Toolchange_manual.py | 1 + preprocessors/default.py | 1 + preprocessors/grbl_11.py | 3 +- preprocessors/grbl_laser.py | 7 +- preprocessors/hpgl.py | 2 +- preprocessors/line_xyz.py | 1 + preprocessors/marlin.py | 2 + 18 files changed, 182 insertions(+), 87 deletions(-) diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 37c620ca..5c72c6f6 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -6621,10 +6621,12 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): :param to_file: if False then no actual file is saved but the app will know that a file was created :return: None """ - gcode = '' - roland = False - hpgl = False - isel_icp = False + # gcode = '' + # roland = False + # hpgl = False + # isel_icp = False + + include_header = True try: if self.special_group: @@ -6636,86 +6638,153 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): except AttributeError: pass - # detect if using Roland preprocessor - try: - for key in self.cnc_tools: - if self.cnc_tools[key]['data']['ppname_g'] == 'Roland_MDX_20': - roland = True - break - except Exception: - try: - for key in self.cnc_tools: - if self.cnc_tools[key]['data']['ppname_e'] == 'Roland_MDX_20': - roland = True - break - except Exception: - pass + # if this dict is not empty then the object is a Geometry object + if self.cnc_tools: + first_key = next(iter(self.cnc_tools)) + include_header = self.app.preprocessors[self.cnc_tools[first_key]['data']['ppname_g']].include_header - # detect if using HPGL preprocessor - try: - for key in self.cnc_tools: - if self.cnc_tools[key]['data']['ppname_g'] == 'hpgl': - hpgl = True - break - except Exception: - try: - for key in self.cnc_tools: - if self.cnc_tools[key]['data']['ppname_e'] == 'hpgl': - hpgl = True - break - except Exception: - pass + # if this dict is not empty then the object is an Excellon object + if self.exc_cnc_tools: + first_key = next(iter(self.exc_cnc_tools)) + include_header = self.app.preprocessors[self.exc_cnc_tools[first_key]['data']['ppname_e']].include_header - # detect if using ISEL_ICP_CNC preprocessor - try: - for key in self.cnc_tools: - if 'ISEL_ICP' in self.cnc_tools[key]['data']['ppname_g'].upper(): - isel_icp = True - break - except Exception: - try: - for key in self.cnc_tools: - if 'ISEL_ICP' in self.cnc_tools[key]['data']['ppname_e'].upper(): - isel_icp = True - break - except Exception: - pass + # # detect if using Roland preprocessor + # try: + # for key in self.cnc_tools: + # if self.cnc_tools[key]['data']['ppname_g'] == 'Roland_MDX_20': + # roland = True + # break + # except Exception: + # try: + # for key in self.cnc_tools: + # if self.cnc_tools[key]['data']['ppname_e'] == 'Roland_MDX_20': + # roland = True + # break + # except Exception: + # pass + # + # # detect if using HPGL preprocessor + # try: + # for key in self.cnc_tools: + # if self.cnc_tools[key]['data']['ppname_g'] == 'hpgl': + # hpgl = True + # break + # except Exception: + # try: + # for key in self.cnc_tools: + # if self.cnc_tools[key]['data']['ppname_e'] == 'hpgl': + # hpgl = True + # break + # except Exception: + # pass + # + # # detect if using ISEL_ICP_CNC preprocessor + # try: + # for key in self.cnc_tools: + # if 'ISEL_ICP' in self.cnc_tools[key]['data']['ppname_g'].upper(): + # isel_icp = True + # break + # except Exception: + # try: + # for key in self.cnc_tools: + # if 'ISEL_ICP' in self.cnc_tools[key]['data']['ppname_e'].upper(): + # isel_icp = True + # break + # except Exception: + # pass # do not add gcode_header when using the Roland preprocessor, add it for every other preprocessor - if roland is False and hpgl is False and isel_icp is False: - gcode = self.gcode_header() + # if roland is False and hpgl is False and isel_icp is False: + # gcode = self.gcode_header() - # detect if using multi-tool and make the Gcode summation correctly for each case - if self.multitool is True: - for tooluid_key in self.cnc_tools: - for key, value in self.cnc_tools[tooluid_key].items(): - if key == 'gcode': - gcode += value - break - else: - gcode += self.gcode + # do not add gcode_header when using the Roland, HPGL or ISEP_ICP_CNC preprocessor (or any other preprocessor + # that has the include_header attribute set as False, add it for every other preprocessor + # if include_header: + # gcode = self.gcode_header() + # else: + # gcode = '' - if roland is True: - g = preamble + gcode + postamble - elif hpgl is True: - g = self.gcode_header() + preamble + gcode + postamble + # # detect if using multi-tool and make the Gcode summation correctly for each case + # if self.multitool is True: + # for tooluid_key in self.cnc_tools: + # for key, value in self.cnc_tools[tooluid_key].items(): + # if key == 'gcode': + # gcode += value + # break + # else: + # gcode += self.gcode + + # if roland is True: + # g = preamble + gcode + postamble + # elif hpgl is True: + # g = self.gcode_header() + preamble + gcode + postamble + # else: + # # fix so the preamble gets inserted in between the comments header and the actual start of GCODE + # g_idx = gcode.rfind('G20') + # + # # if it did not find 'G20' then search for 'G21' + # if g_idx == -1: + # g_idx = gcode.rfind('G21') + # + # # if it did not find 'G20' and it did not find 'G21' then there is an error and return + # # but only when the preprocessor is not ISEL_ICP who is allowed not to have the G20/G21 command + # if g_idx == -1 and isel_icp is False: + # self.app.inform.emit('[ERROR_NOTCL] %s' % _("G-code does not have a units code: either G20 or G21")) + # return + # + # footer = self.app.defaults['cncjob_footer'] + # end_gcode = self.gcode_footer() if footer is True else '' + # g = gcode[:g_idx] + preamble + '\n' + gcode[g_idx:] + postamble + end_gcode + + gcode = '' + if include_header is False: + g = preamble + # detect if using multi-tool and make the Gcode summation correctly for each case + if self.multitool is True: + for tooluid_key in self.cnc_tools: + for key, value in self.cnc_tools[tooluid_key].items(): + if key == 'gcode': + gcode += value + break + else: + gcode += self.gcode + + g = g + gcode + postamble else: + # search for the GCode beginning which is usually a G20 or G21 # fix so the preamble gets inserted in between the comments header and the actual start of GCODE - g_idx = gcode.rfind('G20') + # g_idx = gcode.rfind('G20') + # + # # if it did not find 'G20' then search for 'G21' + # if g_idx == -1: + # g_idx = gcode.rfind('G21') + # + # # if it did not find 'G20' and it did not find 'G21' then there is an error and return + # if g_idx == -1: + # self.app.inform.emit('[ERROR_NOTCL] %s' % _("G-code does not have a units code: either G20 or G21")) + # return - # if it did not find 'G20' then search for 'G21' - if g_idx == -1: - g_idx = gcode.rfind('G21') + # detect if using multi-tool and make the Gcode summation correctly for each case + if self.multitool is True: + for tooluid_key in self.cnc_tools: + for key, value in self.cnc_tools[tooluid_key].items(): + if key == 'gcode': + gcode += value + break + else: + gcode += self.gcode - # if it did not find 'G20' and it did not find 'G21' then there is an error and return - # but only when the preprocessor is not ISEL_ICP who is allowed not to have the G20/G21 command - if g_idx == -1 and isel_icp is False: - self.app.inform.emit('[ERROR_NOTCL] %s' % _("G-code does not have a units code: either G20 or G21")) - return + end_gcode = self.gcode_footer() if self.app.defaults['cncjob_footer'] is True else '' - footer = self.app.defaults['cncjob_footer'] - end_gcode = self.gcode_footer() if footer is True else '' - g = gcode[:g_idx] + preamble + '\n' + gcode[g_idx:] + postamble + end_gcode + try: + g_idx = gcode.index('G94') + g = self.gcode_header() + gcode[:g_idx + 3] + '\n\n' + preamble + '\n' + \ + gcode[(g_idx + 3):] + postamble + end_gcode + except ValueError: + self.app.inform.emit('[ERROR_NOTCL] %s' % + _("G-code does not have a G94 code and we will not include the code in the " + "'Prepend to GCode' text box")) + g = self.gcode_header() + '\n' + gcode + postamble + end_gcode # if toolchange custom is used, replace M6 code with the code from the Toolchange Custom Text box if self.ui.toolchange_cb.get_value() is True: diff --git a/README.md b/README.md index de3bb450..ca601101 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ CAD program, and create G-Code for Isolation routing. - fixed layout on first launch of the app - fixed some issues with the recent preparation for dark icons resource usage - added a new preprocessor file contributed by Daniel Friderich and added fixes for it +- modified the export_gcode() method and the preprocessors such that the preprocessors now have the information if to include the gcode header - RELEASE 8.99 14.12.2019 diff --git a/camlib.py b/camlib.py index 8da7052e..b11b3d67 100644 --- a/camlib.py +++ b/camlib.py @@ -2448,11 +2448,17 @@ class CNCjob(Geometry): except KeyError: z_off = 0 + default_data = dict() + for k, v in list(self.options.items()): + default_data[k] = deepcopy(v) + self.exc_cnc_tools[it[1]] = dict() self.exc_cnc_tools[it[1]]['tool'] = it[0] self.exc_cnc_tools[it[1]]['nr_drills'] = drill_no self.exc_cnc_tools[it[1]]['nr_slots'] = slot_no self.exc_cnc_tools[it[1]]['offset_z'] = z_off + self.exc_cnc_tools[it[1]]['data'] = default_data + self.exc_cnc_tools[it[1]]['solid_geometry'] = deepcopy(sol_geo) self.app.inform.emit(_("Creating a list of points to drill...")) diff --git a/preprocessors/Berta_CNC.py b/preprocessors/Berta_CNC.py index 5d905da9..d8d5000e 100644 --- a/preprocessors/Berta_CNC.py +++ b/preprocessors/Berta_CNC.py @@ -14,6 +14,8 @@ from FlatCAMPostProc import * class Berta_CNC(FlatCAMPostProc): + + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' @@ -66,18 +68,19 @@ class Berta_CNC(FlatCAMPostProc): gcode += '(Spindle Speed: %s RPM)\n' % str(p['spindlespeed']) - gcode += '(Berta)\n' - gcode += 'G90 G94 G17 G91.1' gcode += ( # This line allow you to sets the machine to METRIC / INCH in the GUI - 'G20\n' if p.units.upper() == 'IN' else 'G21\n') + 'G20\n' if p.units.upper() == 'IN' else 'G21\n') + '\n' # gcode += 'G21\n' # This line sets the machine to METRIC ONLY # gcode += 'G20\n' # This line sets the machine to INCH ONLY + + gcode += 'G90 G17 G91.1\n' gcode += 'G64 P0.03\n' gcode += 'M110\n' gcode += 'G54\n' gcode += 'G0\n' gcode += '(Berta)\n' + gcode += 'G94\n' return gcode diff --git a/preprocessors/ISEL_CNC.py b/preprocessors/ISEL_CNC.py index afa42e02..fe089f54 100644 --- a/preprocessors/ISEL_CNC.py +++ b/preprocessors/ISEL_CNC.py @@ -10,7 +10,7 @@ from FlatCAMPostProc import * class ISEL_CNC(FlatCAMPostProc): - + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' diff --git a/preprocessors/ISEL_ICP_CNC.py b/preprocessors/ISEL_ICP_CNC.py index e4759135..8878cc18 100644 --- a/preprocessors/ISEL_ICP_CNC.py +++ b/preprocessors/ISEL_ICP_CNC.py @@ -9,7 +9,10 @@ from FlatCAMPostProc import * -class ISEL_ICP_CNC(FlatCAMPostProc): +class ISEL_ICP_CNC(FlatCAMPostProc): + + include_header = False + def start_code(self, p): units = ' ' + str(p['units']).lower() coords_xy = p['xy_toolchange'] diff --git a/preprocessors/Paste_1.py b/preprocessors/Paste_1.py index 9d6739a8..66d4cb4e 100644 --- a/preprocessors/Paste_1.py +++ b/preprocessors/Paste_1.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class Paste_1(FlatCAMPostProc_Tools): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' diff --git a/preprocessors/Repetier.py b/preprocessors/Repetier.py index 5906035a..eaaba5b6 100644 --- a/preprocessors/Repetier.py +++ b/preprocessors/Repetier.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class Repetier(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' feedrate_rapid_format = feedrate_format @@ -66,6 +67,7 @@ class Repetier(FlatCAMPostProc): gcode += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n" gcode += 'G90\n' + gcode += 'G94\n' return gcode diff --git a/preprocessors/Roland_MDX_20.py b/preprocessors/Roland_MDX_20.py index e08e8a5b..b80ccf5e 100644 --- a/preprocessors/Roland_MDX_20.py +++ b/preprocessors/Roland_MDX_20.py @@ -13,6 +13,7 @@ from FlatCAMPostProc import * # the same) to contain the following keyword, case-sensitive: 'Roland' without the quotes. class Roland_MDX_20(FlatCAMPostProc): + include_header = False coordinate_format = "%.1f" feedrate_format = '%.1f' feedrate_rapid_format = '%.1f' diff --git a/preprocessors/Toolchange_Custom.py b/preprocessors/Toolchange_Custom.py index 9c3aacd3..27d2d097 100644 --- a/preprocessors/Toolchange_Custom.py +++ b/preprocessors/Toolchange_Custom.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class Toolchange_Custom(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' diff --git a/preprocessors/Toolchange_Probe_MACH3.py b/preprocessors/Toolchange_Probe_MACH3.py index ab21f169..617072c8 100644 --- a/preprocessors/Toolchange_Probe_MACH3.py +++ b/preprocessors/Toolchange_Probe_MACH3.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class Toolchange_Probe_MACH3(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' @@ -69,14 +70,14 @@ class Toolchange_Probe_MACH3(FlatCAMPostProc): gcode += 'G90\n' gcode += 'G17\n' gcode += 'G94\n' - gcode += '(MSG, WARNING: Make sure you do zero on all axis. ' \ - 'For Z axis, since it will be probed, make a rough estimate and do a zero.)\n' - gcode += 'M0' return gcode def startz_code(self, p): - return '' + g = '(MSG, WARNING: Make sure you do zero on all axis. ' \ + 'For Z axis, since it will be probed, make a rough estimate and do a zero.)\n' + g += 'M0' + return g def lift_code(self, p): return 'G00 Z' + self.coordinate_format%(p.coords_decimals, p.z_move) diff --git a/preprocessors/Toolchange_manual.py b/preprocessors/Toolchange_manual.py index b4593ab5..4f46ac9e 100644 --- a/preprocessors/Toolchange_manual.py +++ b/preprocessors/Toolchange_manual.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class Toolchange_manual(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' diff --git a/preprocessors/default.py b/preprocessors/default.py index a924d0fa..ad0ef3ec 100644 --- a/preprocessors/default.py +++ b/preprocessors/default.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class default(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' diff --git a/preprocessors/grbl_11.py b/preprocessors/grbl_11.py index c6b1214e..48c6f244 100644 --- a/preprocessors/grbl_11.py +++ b/preprocessors/grbl_11.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class grbl_11(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' @@ -63,8 +64,8 @@ class grbl_11(FlatCAMPostProc): gcode += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n" gcode += 'G90\n' - gcode += 'G94\n' gcode += 'G17\n' + gcode += 'G94\n' return gcode diff --git a/preprocessors/grbl_laser.py b/preprocessors/grbl_laser.py index 5059a7a4..6b7ec648 100644 --- a/preprocessors/grbl_laser.py +++ b/preprocessors/grbl_laser.py @@ -14,6 +14,7 @@ from FlatCAMPostProc import * class grbl_laser(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' @@ -34,15 +35,15 @@ class grbl_laser(FlatCAMPostProc): if str(p['options']['type']) == 'Excellon' or str(p['options']['type']) == 'Excellon Geometry': gcode += '(Preprocessor Excellon: ' + str(p['pp_excellon_name']) + ')\n' else: - gcode += '(Preprocessor Geometry: ' + str(p['pp_geometry_name']) + ')\n' - gcode += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n" + '\n' + 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 += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n" gcode += 'G90\n' - gcode += 'G94\n' gcode += 'G17\n' + gcode += 'G94\n' return gcode diff --git a/preprocessors/hpgl.py b/preprocessors/hpgl.py index 494ed8b4..4a8b543d 100644 --- a/preprocessors/hpgl.py +++ b/preprocessors/hpgl.py @@ -12,7 +12,7 @@ from FlatCAMPostProc import * # for Roland Preprocessors it is mandatory for the preprocessor name (python file and class name, both of them must be # the same) to contain the following keyword, case-sensitive: 'Roland' without the quotes. class hpgl(FlatCAMPostProc): - + include_header = True coordinate_format = "%.*f" def start_code(self, p): diff --git a/preprocessors/line_xyz.py b/preprocessors/line_xyz.py index 5a0803ba..a96be12c 100644 --- a/preprocessors/line_xyz.py +++ b/preprocessors/line_xyz.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class line_xyz(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' diff --git a/preprocessors/marlin.py b/preprocessors/marlin.py index ed80f7f6..c7f4b90f 100644 --- a/preprocessors/marlin.py +++ b/preprocessors/marlin.py @@ -11,6 +11,7 @@ from FlatCAMPostProc import * class marlin(FlatCAMPostProc): + include_header = True coordinate_format = "%.*f" feedrate_format = '%.*f' feedrate_rapid_format = feedrate_format @@ -66,6 +67,7 @@ class marlin(FlatCAMPostProc): gcode += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n" gcode += 'G90\n' + gcode += 'G94\n' return gcode