From f8eba0084df32ea1c1fe5aba5e2142486b885c47 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 24 Aug 2020 02:13:13 +0300 Subject: [PATCH] - in CNCJob UI Autolevelling - GRBL controller - added the probing method --- CHANGELOG.md | 2 + appGUI/ObjectUI.py | 137 ++++++++++++++++++------------------ appObjects/FlatCAMCNCJob.py | 57 ++++++++++++++- 3 files changed, 126 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9699d4dc..91986276 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ CHANGELOG for FlatCAM beta - in CNCJob UI Autolevelling - changed how the probing code is generated and when - changed some strings in CNCJob UI Autolevelling - made sure that when doing units conversion keep only the decimals specified in the application decimals setting (should differentiate between values and display?) +- in CNCJob UI Autolevelling - some UI changes +- in CNCJob UI Autolevelling - GRBL controller - added the probing method 23.08.2020 diff --git a/appGUI/ObjectUI.py b/appGUI/ObjectUI.py index 4c774a07..e904ae35 100644 --- a/appGUI/ObjectUI.py +++ b/appGUI/ObjectUI.py @@ -1949,47 +1949,6 @@ class CNCObjectUI(ObjectUI): separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) grid0.addWidget(separator_line, 5, 0, 1, 2) - al_mode_lbl = FCLabel('%s:' % _("Mode")) - al_mode_lbl.setToolTip(_("Choose a mode for height map generation.\n" - "- Manual: will pick a selection of probe points by clicking on canvas\n" - "- Grid: will automatically generate a grid of probe points")) - - self.al_mode_radio = RadioSet( - [ - {'label': _('Manual'), 'value': 'manual'}, - {'label': _('Grid'), 'value': 'grid'} - ]) - grid0.addWidget(al_mode_lbl, 7, 0) - grid0.addWidget(self.al_mode_radio, 7, 1) - - # ## Columns - self.al_columns_entry = FCSpinner() - - self.al_columns_label = QtWidgets.QLabel('%s:' % _("Columns")) - self.al_columns_label.setToolTip( - _("The number of grid columns.") - ) - grid0.addWidget(self.al_columns_label, 9, 0) - grid0.addWidget(self.al_columns_entry, 9, 1) - - # ## Rows - self.al_rows_entry = FCSpinner() - - self.al_rows_label = QtWidgets.QLabel('%s:' % _("Rows")) - self.al_rows_label.setToolTip( - _("The number of gird rows.") - ) - grid0.addWidget(self.al_rows_label, 11, 0) - grid0.addWidget(self.al_rows_entry, 11, 1) - - self.al_add_button = FCButton(_("Add Probe Points")) - grid0.addWidget(self.al_add_button, 13, 0, 1, 2) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 14, 0, 1, 2) - # ############################################################################################################# # ############### Probe GCode Generation ###################################################################### # ############################################################################################################# @@ -2000,7 +1959,7 @@ class CNCObjectUI(ObjectUI): "either through a file or directly, with the intent to get the height map\n" "that is to modify the original GCode to level the cutting height.") ) - grid0.addWidget(self.probe_gc_label, 16, 0, 1, 2) + grid0.addWidget(self.probe_gc_label, 7, 0, 1, 2) # Travel Z Probe self.ptravelz_label = QtWidgets.QLabel('%s:' % _("Probe Z travel")) @@ -2011,8 +1970,8 @@ class CNCObjectUI(ObjectUI): self.ptravelz_entry.set_precision(self.decimals) self.ptravelz_entry.set_range(0.0000, 9999.9999) - grid0.addWidget(self.ptravelz_label, 18, 0) - grid0.addWidget(self.ptravelz_entry, 18, 1) + grid0.addWidget(self.ptravelz_label, 9, 0) + grid0.addWidget(self.ptravelz_entry, 9, 1) # Probe depth self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth")) @@ -2024,8 +1983,8 @@ class CNCObjectUI(ObjectUI): self.pdepth_entry.set_precision(self.decimals) self.pdepth_entry.set_range(-99999.9999, 0.0000) - grid0.addWidget(self.pdepth_label, 20, 0) - grid0.addWidget(self.pdepth_entry, 20, 1) + grid0.addWidget(self.pdepth_label, 11, 0) + grid0.addWidget(self.pdepth_entry, 11, 1) # Probe feedrate self.feedrate_probe_label = QtWidgets.QLabel('%s:' % _("Probe Feedrate")) @@ -2036,13 +1995,54 @@ class CNCObjectUI(ObjectUI): self.feedrate_probe_entry.set_precision(self.decimals) self.feedrate_probe_entry.set_range(0, 99999.9999) - grid0.addWidget(self.feedrate_probe_label, 22, 0) - grid0.addWidget(self.feedrate_probe_entry, 22, 1) + grid0.addWidget(self.feedrate_probe_label, 13, 0) + grid0.addWidget(self.feedrate_probe_entry, 13, 1) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 23, 0, 1, 2) + grid0.addWidget(separator_line, 15, 0, 1, 2) + + al_mode_lbl = FCLabel('%s:' % _("Mode")) + al_mode_lbl.setToolTip(_("Choose a mode for height map generation.\n" + "- Manual: will pick a selection of probe points by clicking on canvas\n" + "- Grid: will automatically generate a grid of probe points")) + + self.al_mode_radio = RadioSet( + [ + {'label': _('Manual'), 'value': 'manual'}, + {'label': _('Grid'), 'value': 'grid'} + ]) + grid0.addWidget(al_mode_lbl, 17, 0) + grid0.addWidget(self.al_mode_radio, 17, 1) + + # ## Columns + self.al_columns_entry = FCSpinner() + + self.al_columns_label = QtWidgets.QLabel('%s:' % _("Columns")) + self.al_columns_label.setToolTip( + _("The number of grid columns.") + ) + grid0.addWidget(self.al_columns_label, 19, 0) + grid0.addWidget(self.al_columns_entry, 19, 1) + + # ## Rows + self.al_rows_entry = FCSpinner() + + self.al_rows_label = QtWidgets.QLabel('%s:' % _("Rows")) + self.al_rows_label.setToolTip( + _("The number of gird rows.") + ) + grid0.addWidget(self.al_rows_label, 21, 0) + grid0.addWidget(self.al_rows_entry, 21, 1) + + self.al_add_button = FCButton(_("Add Probe Points")) + grid0.addWidget(self.al_add_button, 23, 0, 1, 2) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 25, 0, 1, 2) self.al_controller_label = FCLabel('%s:' % _("Controller")) self.al_controller_label.setToolTip( @@ -2052,15 +2052,15 @@ class CNCObjectUI(ObjectUI): self.al_controller_combo = FCComboBox() self.al_controller_combo.addItems(["MACH3", "MACH4", "LinuxCNC", "GRBL"]) - grid0.addWidget(self.al_controller_label, 24, 0) - grid0.addWidget(self.al_controller_combo, 24, 1) + grid0.addWidget(self.al_controller_label, 27, 0) + grid0.addWidget(self.al_controller_combo, 27, 1) # ############################################################################################################# # ########################## GRBL frame ####################################################################### # ############################################################################################################# self.grbl_frame = QtWidgets.QFrame() self.grbl_frame.setContentsMargins(0, 0, 0, 0) - grid0.addWidget(self.grbl_frame, 26, 0, 1, 2) + grid0.addWidget(self.grbl_frame, 29, 0, 1, 2) self.grbl_box = QtWidgets.QVBoxLayout() self.grbl_box.setContentsMargins(0, 0, 0, 0) @@ -2121,7 +2121,6 @@ class CNCObjectUI(ObjectUI): grbl_conn_grid.setColumnStretch(1, 1) grbl_conn_grid.setColumnStretch(2, 0) self.gr_conn_tab_layout.addLayout(grbl_conn_grid) - self.gr_conn_tab_layout.addStretch(1) # COM list self.com_list_label = FCLabel('%s:' % _("COM list")) @@ -2191,6 +2190,7 @@ class CNCObjectUI(ObjectUI): self.com_connect_button.setStyleSheet("QPushButton {background-color: red;}") ctrl_hlay.addWidget(self.com_connect_button) + grbl_conn_grid.addWidget(FCLabel(""), 9, 0, 1, 3) grbl_conn_grid.setRowStretch(9, 1) grbl_conn_grid.addLayout(ctrl_hlay, 10, 0, 1, 3) @@ -2329,7 +2329,7 @@ class CNCObjectUI(ObjectUI): # Get Parameter self.grbl_get_param_label = FCLabel('%s:' % _("Get Config parameter")) self.grbl_get_param_label.setToolTip( - _("A GRBL parameter.") + _("A GRBL configuration parameter.") ) grbl_send_grid.addWidget(self.grbl_get_param_label, 6, 0, 1, 2) @@ -2344,6 +2344,8 @@ class CNCObjectUI(ObjectUI): grbl_send_grid.addWidget(self.grbl_parameter_entry, 8, 0) grbl_send_grid.addWidget(self.grbl_get_param_button, 8, 1) + grbl_send_grid.setRowStretch(9, 1) + # GET Report self.grbl_report_button = FCButton(_("Get Report")) self.grbl_report_button.setToolTip( @@ -2352,10 +2354,11 @@ class CNCObjectUI(ObjectUI): grbl_send_grid.addWidget(self.grbl_report_button, 10, 0, 1, 2) # GET HEIGHT MAP - self.grbl_get_heightmap_button = FCButton(_("Get Height Map")) + self.grbl_get_heightmap_button = FCButton(_("Apply AutoLevelling")) self.grbl_get_heightmap_button.setToolTip( - _("Will send the probing GCode to the GRBL controller\n" - "and wait for the Z probing data.") + _("Will send the probing GCode to the GRBL controller,\n" + "wait for the Z probing data and then apply this data\n" + "over the original GCode therefore doing autolevelling.") ) grbl_send_grid.addWidget(self.grbl_get_heightmap_button, 12, 0, 1, 2) @@ -2376,26 +2379,24 @@ class CNCObjectUI(ObjectUI): # height_lay.addStretch() height_lay.addWidget(self.view_h_gcode_button) - grid0.addLayout(height_lay, 28, 0, 1, 2) + grid0.addLayout(height_lay, 31, 0, 1, 2) self.import_heights_button = FCButton(_("Import Height Map")) - grid0.addWidget(self.import_heights_button, 30, 0, 1, 2) + self.import_heights_button.setToolTip( + _("Import the file that has the Z heights\n" + "obtained through probing and then apply this data\n" + "over the original GCode therefore\n" + "doing autolevelling.") + ) + grid0.addWidget(self.import_heights_button, 33, 0, 1, 2) self.h_gcode_button.hide() self.import_heights_button.hide() - # separator_line = QtWidgets.QFrame() - # separator_line.setFrameShape(QtWidgets.QFrame.HLine) - # separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - # grid0.addWidget(separator_line, 31, 0, 1, 2) - - self.al_button = FCButton(_("Apply Autolevel map")) - grid0.addWidget(self.al_button, 32, 0, 1, 2) - separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 34, 0, 1, 2) + grid0.addWidget(separator_line, 35, 0, 1, 2) # ############################################################################################################# # ## Export G-Code ## diff --git a/appObjects/FlatCAMCNCJob.py b/appObjects/FlatCAMCNCJob.py index e69bf114..ada561f1 100644 --- a/appObjects/FlatCAMCNCJob.py +++ b/appObjects/FlatCAMCNCJob.py @@ -593,6 +593,7 @@ class CNCJobObject(FlatCAMObj, CNCjob): self.ui.h_gcode_button.clicked.connect(self.on_save_probing_gcode) self.ui.import_heights_button.clicked.connect(self.on_import_height_map) self.ui.pause_resume_button.clicked.connect(self.on_grbl_pause_resume) + self.ui.grbl_get_heightmap_button.clicked.connect(self.on_grbl_autolevel) self.build_al_table_sig.connect(self.build_al_table) @@ -1101,6 +1102,15 @@ class CNCJobObject(FlatCAMObj, CNCjob): self.app.worker_task.emit({'fcn': worker_task, 'params': []}) def send_grbl_command(self, command, echo=True): + """ + + :param command: GCode command + :type command: str + :param echo: if to send a '\n' char after + :type echo: bool + :return: the text returned by the GRBL controller after each command + :rtype: str + """ stripped_cmd = command.strip() cmd = stripped_cmd.rpartition('\n')[0] @@ -1112,7 +1122,7 @@ class CNCJobObject(FlatCAMObj, CNCjob): self.grbl_ser_port.write(snd.encode('utf-8')) grbl_out = self.grbl_ser_port.readlines() - result = False + result = '' for line in grbl_out: if echo: try: @@ -1120,7 +1130,7 @@ class CNCJobObject(FlatCAMObj, CNCjob): except Exception as e: log.debug("CNCJobObject.send_grbl_command() --> %s" % str(e)) if 'ok' in line: - result = True + result = grbl_out return result @@ -1498,6 +1508,49 @@ class CNCJobObject(FlatCAMObj, CNCjob): self.build_al_table_sig.emit() + def on_grbl_autolevel(self): + # show the Shell Dock + self.app.ui.shell_dock.show() + + def worker_task(): + with self.app.proc_container.new(_("Sending GCode...")): + probe_result = '' + pr_travelz = str(self.ui.ptravelz_entry.get_value()) + probe_fr = str(self.ui.feedrate_probe_entry.get_value()) + pr_depth = str(self.ui.pdepth_entry.get_value()) + + cmd = 'G21\n' + self.send_grbl_command(command=cmd) + cmd = 'G90\n' + self.send_grbl_command(command=cmd) + + for pt_key in self.al_geometry_dict: + x = str(self.al_geometry_dict[pt_key]['point'].x) + y = str(self.al_geometry_dict[pt_key]['point'].y) + + cmd = 'G0 Z%s\n' % pr_travelz + self.send_grbl_command(command=cmd) + cmd = 'G0 X%s Y%s\n' % (x, y) + self.send_grbl_command(command=cmd) + cmd = 'G38.2 Z%s F%s' % (pr_depth, probe_fr) + output = self.send_grbl_command(command=cmd) + + probe_result += output + '\n' + + cmd = 'M2\n' + self.send_grbl_command(command=cmd) + self.app.inform.emit('%s' % _("Finished probing. Doing the autolevelling.")) + + # apply autolevel here + self.do_grbl_autolevel() + + self.app.inform.emit('%s' % _("Sending probing GCode to the GRBL controller.")) + self.app.worker_task.emit({'fcn': worker_task, 'params': []}) + + def do_grbl_autolevel(self): + # TODO here we call the autovell method + self.app.inform.emit('%s' % _("Finished autolevelling.")) + def on_updateplot_button_click(self, *args): """ Callback for the "Updata Plot" button. Reads the form for updates