From 120e866a01f7c2034a28f1a960d3e0b01e511577 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 28 Oct 2019 23:14:40 +0200 Subject: [PATCH] - working on the Calibrate Excellon Tool - converted Excellon Editor to usage of SpinBoxes --- README.md | 2 + camlib.py | 4 +- flatcamEditors/FlatCAMExcEditor.py | 75 +++++++++---- flatcamTools/ToolCalibrateExcellon.py | 145 ++++++++++++++++++++++++-- 4 files changed, 194 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 67f4a71a..15fc6a03 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ CAD program, and create G-Code for Isolation routing. - in legacy2D graphic engine, adding an utility geometry no longer draw the older ones, overwriting them - fixed some issues in the Gerber Editor (Aperture add was double adding an aperture) - converted Gerber Editor to usage of SpinBoxes +- working on the Calibrate Excellon Tool +- converted Excellon Editor to usage of SpinBoxes 27.10.2019 diff --git a/camlib.py b/camlib.py index adb41c0e..a777d30b 100644 --- a/camlib.py +++ b/camlib.py @@ -2448,7 +2448,7 @@ class CNCjob(Geometry): except KeyError: points[drill['tool']] = [drill['point']] - #log.debug("Found %d drills." % len(points)) + # log.debug("Found %d drills." % len(points)) self.gcode = [] @@ -2633,7 +2633,7 @@ class CNCjob(Geometry): # Drillling! for Absolute coordinates type G90 # variables to display the percentage of work done geo_len = len(node_list) - disp_number = 0 + old_disp_number = 0 log.warning("Number of drills for which to generate GCode: %s" % str(geo_len)) diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py index 2461bc8f..2c4280b9 100644 --- a/flatcamEditors/FlatCAMExcEditor.py +++ b/flatcamEditors/FlatCAMExcEditor.py @@ -9,7 +9,7 @@ from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5.QtCore import Qt, QSettings from camlib import distance, arc, FlatCAMRTreeStorage -from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, LengthEntry, RadioSet, SpinBoxDelegate +from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, RadioSet, FCSpinner from flatcamEditors.FlatCAMGeoEditor import FCShapeTool, DrawTool, DrawToolShape, DrawToolUtilityShape, FlatCAMGeoEditor from flatcamParsers.ParseExcellon import Excellon import FlatCAMApp @@ -1445,6 +1445,9 @@ class FlatCAMExcEditor(QtCore.QObject): self.app = app self.canvas = self.app.plotcanvas + # Number of decimals used by tools in this class + self.decimals = 4 + # ## Current application units in Upper Case self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() @@ -1518,6 +1521,8 @@ class FlatCAMExcEditor(QtCore.QObject): grid1 = QtWidgets.QGridLayout() self.tools_box.addLayout(grid1) + grid1.setColumnStretch(0, 0) + grid1.setColumnStretch(1, 1) addtool_entry_lbl = QtWidgets.QLabel('%s:' % _('Tool Dia')) addtool_entry_lbl.setToolTip( @@ -1525,8 +1530,10 @@ class FlatCAMExcEditor(QtCore.QObject): ) hlay = QtWidgets.QHBoxLayout() - self.addtool_entry = FCEntry() - self.addtool_entry.setValidator(QtGui.QDoubleValidator(0.0001, 99.9999, 4)) + self.addtool_entry = FCDoubleSpinner() + self.addtool_entry.set_precision(self.decimals) + self.addtool_entry.set_range(0.0000, 9999.9999) + hlay.addWidget(self.addtool_entry) self.addtool_btn = QtWidgets.QPushButton(_('Add Tool')) @@ -1579,7 +1586,10 @@ class FlatCAMExcEditor(QtCore.QObject): grid3.addWidget(res_entry_lbl, 0, 0) hlay2 = QtWidgets.QHBoxLayout() - self.resdrill_entry = LengthEntry() + self.resdrill_entry = FCDoubleSpinner() + self.resdrill_entry.set_precision(self.decimals) + self.resdrill_entry.set_range(0.0000, 9999.9999) + hlay2.addWidget(self.resdrill_entry) self.resize_btn = QtWidgets.QPushButton(_('Resize')) @@ -1633,7 +1643,8 @@ class FlatCAMExcEditor(QtCore.QObject): self.drill_array_size_label.setToolTip(_("Specify how many drills to be in the array.")) self.drill_array_size_label.setMinimumWidth(100) - self.drill_array_size_entry = LengthEntry() + self.drill_array_size_entry = FCSpinner() + self.drill_array_size_entry.set_range(1, 9999) self.array_form.addRow(self.drill_array_size_label, self.drill_array_size_entry) self.array_linear_frame = QtWidgets.QFrame() @@ -1668,7 +1679,10 @@ class FlatCAMExcEditor(QtCore.QObject): ) self.drill_pitch_label.setMinimumWidth(100) - self.drill_pitch_entry = LengthEntry() + self.drill_pitch_entry = FCDoubleSpinner() + self.drill_pitch_entry.set_precision(self.decimals) + self.drill_pitch_entry.set_range(0.0000, 9999.9999) + self.linear_form.addRow(self.drill_pitch_label, self.drill_pitch_entry) # Linear Drill Array angle @@ -1676,15 +1690,15 @@ class FlatCAMExcEditor(QtCore.QObject): self.linear_angle_label.setToolTip( _("Angle at which the linear array is placed.\n" "The precision is of max 2 decimals.\n" - "Min value is: -359.99 degrees.\n" + "Min value is: -360 degrees.\n" "Max value is: 360.00 degrees.") ) self.linear_angle_label.setMinimumWidth(100) self.linear_angle_spinner = FCDoubleSpinner() - self.linear_angle_spinner.set_precision(2) + self.linear_angle_spinner.set_precision(self.decimals) self.linear_angle_spinner.setSingleStep(1.0) - self.linear_angle_spinner.setRange(-359.99, 360.00) + self.linear_angle_spinner.setRange(-360.00, 360.00) self.linear_form.addRow(self.linear_angle_label, self.linear_angle_spinner) self.array_circular_frame = QtWidgets.QFrame() @@ -1710,7 +1724,11 @@ class FlatCAMExcEditor(QtCore.QObject): self.drill_angle_label.setToolTip(_("Angle at which each element in circular array is placed.")) self.drill_angle_label.setMinimumWidth(100) - self.drill_angle_entry = LengthEntry() + self.drill_angle_entry = FCDoubleSpinner() + self.drill_angle_entry.set_precision(self.decimals) + self.drill_angle_entry.setSingleStep(1.0) + self.drill_angle_entry.setRange(-360.00, 360.00) + self.circular_form.addRow(self.drill_angle_label, self.drill_angle_entry) self.array_circular_frame.hide() @@ -1754,7 +1772,11 @@ class FlatCAMExcEditor(QtCore.QObject): ) self.slot_length_label.setMinimumWidth(100) - self.slot_length_entry = LengthEntry() + self.slot_length_entry = FCDoubleSpinner() + self.slot_length_entry.set_precision(self.decimals) + self.slot_length_entry.setSingleStep(0.1) + self.slot_length_entry.setRange(0.0000, 9999.9999) + self.slot_form.addRow(self.slot_length_label, self.slot_length_entry) # Slot direction @@ -1777,15 +1799,15 @@ class FlatCAMExcEditor(QtCore.QObject): self.slot_angle_label.setToolTip( _("Angle at which the slot is placed.\n" "The precision is of max 2 decimals.\n" - "Min value is: -359.99 degrees.\n" + "Min value is: -360 degrees.\n" "Max value is: 360.00 degrees.") ) self.slot_angle_label.setMinimumWidth(100) self.slot_angle_spinner = FCDoubleSpinner() - self.slot_angle_spinner.set_precision(2) + self.slot_angle_spinner.set_precision(self.decimals) self.slot_angle_spinner.setWrapping(True) - self.slot_angle_spinner.setRange(-359.99, 360.00) + self.slot_angle_spinner.setRange(-360.00, 360.00) self.slot_angle_spinner.setSingleStep(1.0) self.slot_form.addRow(self.slot_angle_label, self.slot_angle_spinner) @@ -1835,7 +1857,9 @@ class FlatCAMExcEditor(QtCore.QObject): self.slot_array_size_label.setToolTip(_("Specify how many slots to be in the array.")) self.slot_array_size_label.setMinimumWidth(100) - self.slot_array_size_entry = LengthEntry() + self.slot_array_size_entry = FCSpinner() + self.slot_array_size_entry.set_range(0, 9999) + self.slot_array_form.addRow(self.slot_array_size_label, self.slot_array_size_entry) self.slot_array_linear_frame = QtWidgets.QFrame() @@ -1870,7 +1894,11 @@ class FlatCAMExcEditor(QtCore.QObject): ) self.slot_array_pitch_label.setMinimumWidth(100) - self.slot_array_pitch_entry = LengthEntry() + self.slot_array_pitch_entry = FCDoubleSpinner() + self.slot_array_pitch_entry.set_precision(self.decimals) + self.slot_array_pitch_entry.setSingleStep(0.1) + self.slot_array_pitch_entry.setRange(0.0000, 9999.9999) + self.slot_array_linear_form.addRow(self.slot_array_pitch_label, self.slot_array_pitch_entry) # Linear Slot Array angle @@ -1878,15 +1906,15 @@ class FlatCAMExcEditor(QtCore.QObject): self.slot_array_linear_angle_label.setToolTip( _("Angle at which the linear array is placed.\n" "The precision is of max 2 decimals.\n" - "Min value is: -359.99 degrees.\n" + "Min value is: -360 degrees.\n" "Max value is: 360.00 degrees.") ) self.slot_array_linear_angle_label.setMinimumWidth(100) self.slot_array_linear_angle_spinner = FCDoubleSpinner() - self.slot_array_linear_angle_spinner.set_precision(2) + self.slot_array_linear_angle_spinner.set_precision(self.decimals) self.slot_array_linear_angle_spinner.setSingleStep(1.0) - self.slot_array_linear_angle_spinner.setRange(-359.99, 360.00) + self.slot_array_linear_angle_spinner.setRange(-360.00, 360.00) self.slot_array_linear_form.addRow(self.slot_array_linear_angle_label, self.slot_array_linear_angle_spinner) self.slot_array_circular_frame = QtWidgets.QFrame() @@ -1912,7 +1940,11 @@ class FlatCAMExcEditor(QtCore.QObject): self.slot_array_angle_label.setToolTip(_("Angle at which each element in circular array is placed.")) self.slot_array_angle_label.setMinimumWidth(100) - self.slot_array_angle_entry = LengthEntry() + self.slot_array_angle_entry = FCDoubleSpinner() + self.slot_array_angle_entry.set_precision(self.decimals) + self.slot_array_angle_entry.setSingleStep(1) + self.slot_array_angle_entry.setRange(-360.00, 360.00) + self.slot_array_circular_form.addRow(self.slot_array_angle_label, self.slot_array_angle_entry) self.slot_array_linear_angle_spinner.hide() @@ -2050,9 +2082,6 @@ class FlatCAMExcEditor(QtCore.QObject): self.complete = False - # Number of decimals used by tools in this class - self.decimals = 4 - def make_callback(thetool): def f(): self.on_tool_select(thetool) diff --git a/flatcamTools/ToolCalibrateExcellon.py b/flatcamTools/ToolCalibrateExcellon.py index f1d0625e..a0aa3e0f 100644 --- a/flatcamTools/ToolCalibrateExcellon.py +++ b/flatcamTools/ToolCalibrateExcellon.py @@ -8,7 +8,7 @@ from PyQt5 import QtWidgets, QtCore from FlatCAMTool import FlatCAMTool -from flatcamGUI.GUIElements import FCDoubleSpinner, EvalEntry, FCCheckBox +from flatcamGUI.GUIElements import FCDoubleSpinner, EvalEntry, FCCheckBox, OptionalInputSection from shapely.geometry import Point from shapely.geometry.base import * @@ -80,6 +80,9 @@ class ToolCalibrateExcellon(FlatCAMTool): # Travel Z entry travelz_lbl = QtWidgets.QLabel('%s:' % _("Travel Z")) + travelz_lbl.setToolTip( + _("Height (Z) for travelling between the points.") + ) self.travelz_entry = FCDoubleSpinner() self.travelz_entry.set_range(-9999.9999, 9999.9999) @@ -91,6 +94,9 @@ class ToolCalibrateExcellon(FlatCAMTool): # Verification Z entry verz_lbl = QtWidgets.QLabel('%s:' % _("Verification Z")) + verz_lbl.setToolTip( + _("Height (Z) for checking the point.") + ) self.verz_entry = FCDoubleSpinner() self.verz_entry.set_range(-9999.9999, 9999.9999) @@ -103,12 +109,29 @@ class ToolCalibrateExcellon(FlatCAMTool): # Zero the Z of the verification tool self.zeroz_cb = FCCheckBox('%s' % _("Zero Z tool")) self.zeroz_cb.setToolTip( - _("Include a secquence to zero the height (Z)\n" + _("Include a sequence to zero the height (Z)\n" "of the verification tool.") ) + i_grid_lay.addWidget(self.zeroz_cb, 4, 0, 1, 3) - i_grid_lay.addWidget(QtWidgets.QLabel(''), 5, 0, 1, 3) + # Toochange Z entry + toolchangez_lbl = QtWidgets.QLabel('%s:' % _("Toolchange Z")) + toolchangez_lbl.setToolTip( + _("Height (Z) for mounting the verification probe.") + ) + + self.toolchangez_entry = FCDoubleSpinner() + self.toolchangez_entry.set_range(0.0000, 9999.9999) + self.toolchangez_entry.set_precision(self.decimals) + self.toolchangez_entry.setSingleStep(0.1) + + i_grid_lay.addWidget(toolchangez_lbl, 5, 0) + i_grid_lay.addWidget(self.toolchangez_entry, 5, 1, 1, 2) + + self.z_ois = OptionalInputSection(self.zeroz_cb, [toolchangez_lbl, self.toolchangez_entry]) + + i_grid_lay.addWidget(QtWidgets.QLabel(''), 6, 0, 1, 3) # ## Grid Layout grid_lay = QtWidgets.QGridLayout() @@ -402,10 +425,14 @@ class ToolCalibrateExcellon(FlatCAMTool): # here store 4 points to be used for calibration self.click_points = list() + # store the status of the grid + self.grid_status_memory = None + self.exc_obj = None # ## Signals self.start_button.clicked.connect(self.on_start_collect_points) + self.gcode_button.clicked.connect(self.generate_verification_gcode) def run(self, toggle=True): self.app.report_usage("ToolCalibrateExcellon()") @@ -445,6 +472,13 @@ class ToolCalibrateExcellon(FlatCAMTool): # self.mm_entry.set_value('%.*f' % (self.decimals, 0)) def on_start_collect_points(self): + # disengage the grid snapping since it will be hard to find the drills on grid + if self.app.ui.grid_snap_btn.isChecked(): + self.grid_status_memory = True + self.app.ui.grid_snap_btn.trigger() + else: + self.grid_status_memory = False + self.mr = self.canvas.graph_event_connect('mouse_release', self.on_mouse_click_release) if self.app.is_legacy is False: @@ -502,9 +536,7 @@ class ToolCalibrateExcellon(FlatCAMTool): self.top_right_coordy_tgt.set_value(self.click_points[3][1]) self.app.inform.emit('[success] %s' % _("Done. All four points have been acquired.")) self.disconnect_cal_events() - - def generate_verification_gcode(self): - pass + self.app.ui.grid_snap_btn.setChecked(self.grid_status_memory) def gcode_header(self): log.debug("ToolCalibrateExcellon.gcode_header()") @@ -517,9 +549,108 @@ class ToolCalibrateExcellon(FlatCAMTool): gcode += '(Units: ' + self.units.upper() + ')\n' + "\n" gcode += '(Created on ' + time_str + ')\n' + '\n' - + gcode += 'G20\n' if self.units.upper() == 'IN' else 'G21\n' + gcode += 'G90\n' + gcode += 'G17\n' + gcode += 'G94\n\n' return gcode + def generate_verification_gcode(self): + travel_z = '%.*f' % (self.decimals, self.travelz_entry.get_value()) + toolchange_z = '%.*f' % (self.decimals, self.toolchangez_entry.get_value()) + verification_z = '%.*f' % (self.decimals, self.verz_entry.get_value()) + + if len(self.click_points) != 4: + self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled. Four points are needed for GCode generation.")) + return 'fail' + + gcode = self.gcode_header() + if self.zeroz_cb.get_value(): + gcode += 'M5\n' + gcode += f'G00 Z{toolchange_z}\n' + gcode += 'M0\n' + gcode += 'G01 Z0\n' + gcode += 'M0\n' + gcode += f'G00 Z{toolchange_z}\n' + gcode += 'M0\n' + + gcode += f'G00 Z{travel_z}\n' + gcode += f'G00 X{self.click_points[0][0]} Y{self.click_points[0][1]}\n' + gcode += f'G01 Z{verification_z}\n' + gcode += 'M0\n' + + gcode += f'G00 Z{travel_z}\n' + gcode += f'G00 X{self.click_points[2][0]} Y{self.click_points[2][1]}\n' + gcode += f'G01 Z{verification_z}\n' + gcode += 'M0\n' + + gcode += f'G00 Z{travel_z}\n' + gcode += f'G00 X{self.click_points[3][0]} Y{self.click_points[3][1]}\n' + gcode += f'G01 Z{verification_z}\n' + gcode += 'M0\n' + + gcode += f'G00 Z{travel_z}\n' + gcode += f'G00 X{self.click_points[1][0]} Y{self.click_points[1][1]}\n' + gcode += f'G01 Z{verification_z}\n' + gcode += 'M0\n' + + gcode += f'G00 Z{travel_z}\n' + gcode += f'G00 X0 Y0\n' + gcode += f'G00 Z{toolchange_z}\n' + + gcode += 'M2' + + _filter_ = "G-Code Files (*.nc);;All Files (*.*)" + + try: + dir_file_to_save = self.app.get_last_save_folder() + '/' + 'ver_gcode' + filename, _f = QtWidgets.QFileDialog.getSaveFileName( + caption=_("Export Machine Code ..."), + directory=dir_file_to_save, + filter=_filter_ + ) + except TypeError: + filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export Machine Code ..."), filter=_filter_) + + filename = str(filename) + + if filename == '': + self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export Machine Code cancelled ...")) + return + + with open(filename, 'w') as f: + f.write(gcode) + + def calculate_factors(self): + origin_x = self.click_points[0][0] + origin_y = self.click_points[0][1] + + top_left_x = float('%.*f' % (self.decimals, self.click_points[2][0])) + top_left_y = float('%.*f' % (self.decimals, self.click_points[2][1])) + + top_left_dx = float('%.*f' % (self.decimals, self.top_left_coordx_found.get_value())) + top_left_dy = float('%.*f' % (self.decimals, self.top_left_coordy_found.get_value())) + + top_right_x = float('%.*f' % (self.decimals, self.click_points[3][0])) + top_right_y = float('%.*f' % (self.decimals, self.click_points[3][1])) + + top_right_dx = float('%.*f' % (self.decimals, self.top_right_coordx_found.get_value())) + top_right_dy = float('%.*f' % (self.decimals, self.top_right_coordy_found.get_value())) + + bot_right_x = float('%.*f' % (self.decimals, self.click_points[1][0])) + bot_right_y = float('%.*f' % (self.decimals, self.click_points[1][1])) + + bot_right_dx = float('%.*f' % (self.decimals, self.bottom_right_coordx_found.get_value())) + bot_right_dy = float('%.*f' % (self.decimals, self.bottom_right_coordy_found.get_value())) + + if top_left_dy != top_left_y: + scale_y = (top_left_dy - origin_y) / (top_left_y - origin_y) + self.scaley_entry.set_value(scale_y) + + if top_right_dx != top_right_x: + scale_x = (top_right_dx - origin_x) / (top_right_x - origin_x) + self.scalex_entry.set_value(scale_x) + def disconnect_cal_events(self): self.app.mr = self.canvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot)