Ver código fonte

- in CNCJob UI Autolevelling - GRBL Sender - now only a single command can be sent
- in CNCJob UI Autolevelling - GRBL controller - changed the UI
- in CNCJob UI Autolevelling - added some VOronoi poly calculations

Marius Stanciu 5 anos atrás
pai
commit
a75e7e5cf8
3 arquivos alterados com 146 adições e 72 exclusões
  1. 3 0
      CHANGELOG.md
  2. 47 45
      appGUI/ObjectUI.py
  3. 96 27
      appObjects/FlatCAMCNCJob.py

+ 3 - 0
CHANGELOG.md

@@ -12,6 +12,9 @@ CHANGELOG for FlatCAM beta
 - in CNCJob UI Autolevelling - sending GCode/GRBL commands is now threaded
 - in CNCJob UI Autolevelling - Grbl Connect tab colors will change with the connection status
 - in CNCJob UI Autolevelling - GRBL Control and Sender tabs are disabled when the serial port is disconnected
+- in CNCJob UI Autolevelling - GRBL Sender - now only a single command can be sent 
+- in CNCJob UI Autolevelling - GRBL controller - changed the UI
+- in CNCJob UI Autolevelling - added some VOronoi poly calculations
 
 18.08.2020
 

+ 47 - 45
appGUI/ObjectUI.py

@@ -2072,7 +2072,7 @@ class CNCObjectUI(ObjectUI):
         self.al_toolbar = FCDetachableTab(protect=True, parent=self)
         self.al_toolbar.setTabsClosable(False)
         self.al_toolbar.useOldIndex(True)
-
+        self.al_toolbar.set_detachable(val=False)
         self.grbl_box.addWidget(self.al_toolbar)
 
         # GRBL Connect TAB
@@ -2176,8 +2176,9 @@ class CNCObjectUI(ObjectUI):
         ctrl_hlay = QtWidgets.QHBoxLayout()
         self.controller_reset_button = FCButton(_("Reset"))
         self.controller_reset_button.setToolTip(
-            _("SW reset the controller. CTRL+X command.")
+            _("Software reset of the controller.")
         )
+        self.controller_reset_button.setDisabled(True)
         ctrl_hlay.addWidget(self.controller_reset_button)
 
         self.com_connect_button = FCButton()
@@ -2206,11 +2207,13 @@ class CNCObjectUI(ObjectUI):
         grbl_jog_grid.setColumnStretch(2, 0)
         grbl_jog_grid.setColumnStretch(3, 0)
         grbl_jog_grid.setColumnStretch(4, 1)
+        grbl_jog_grid.setColumnStretch(5, 0)
+
         grbl_jog_grid.setRowStretch(0, 0)
         grbl_jog_grid.setRowStretch(1, 0)
         grbl_jog_grid.setRowStretch(2, 0)
         grbl_jog_grid.setRowStretch(3, 0)
-        grbl_jog_grid.setColumnStretch(4, 1)
+
         grbl_ctrl_grid.addLayout(grbl_jog_grid, 8, 0, 1, 3)
 
         # JOG Y Up
@@ -2270,45 +2273,52 @@ class CNCObjectUI(ObjectUI):
         grbl_zero_grid.setColumnStretch(0, 0)
         grbl_zero_grid.setColumnStretch(1, 0)
         grbl_zero_grid.setColumnStretch(2, 0)
-        grbl_ctrl_grid.addLayout(grbl_zero_grid, 10, 0, 1, 3)
+        grbl_jog_grid.addLayout(grbl_zero_grid, 0, 5, 3, 1)
 
         # Zero X axis
-        self.grbl_zerox_button = FCButton(_("ZERO X axes"))
+        self.grbl_zerox_button = QtWidgets.QToolButton()
+        self.grbl_zerox_button.setText(_("X"))
         self.grbl_zerox_button.setToolTip(
             _("Zero the CNC X axes at current position.")
         )
         grbl_zero_grid.addWidget(self.grbl_zerox_button, 0, 0)
         # Zero Y axis
-        self.grbl_zeroy_button = FCButton(_("ZERO Y axes"))
+        self.grbl_zeroy_button = QtWidgets.QToolButton()
+        self.grbl_zeroy_button.setText(_("Y"))
+
         self.grbl_zeroy_button.setToolTip(
             _("Zero the CNC Y axes at current position.")
         )
-        grbl_zero_grid.addWidget(self.grbl_zeroy_button, 0, 1)
+        grbl_zero_grid.addWidget(self.grbl_zeroy_button, 1, 0)
         # Zero Z axis
-        self.grbl_zeroz_button = FCButton(_("ZERO Z axes"))
+        self.grbl_zeroz_button = QtWidgets.QToolButton()
+        self.grbl_zeroz_button.setText(_("Z"))
+
         self.grbl_zeroz_button.setToolTip(
             _("Zero the CNC Z axes at current position.")
         )
-        grbl_zero_grid.addWidget(self.grbl_zeroz_button, 0, 2)
+        grbl_zero_grid.addWidget(self.grbl_zeroz_button, 2, 0)
         # Zeroo all axes
-        self.grbl_zero_all_button = FCButton(_("ZERO all axes"))
+        self.grbl_zero_all_button = QtWidgets.QToolButton()
+        self.grbl_zero_all_button.setText(_("All"))
+
         self.grbl_zero_all_button.setToolTip(
             _("Zero all CNC axes at current position.")
         )
-        grbl_zero_grid.addWidget(self.grbl_zero_all_button, 2, 0, 1, 3)
+        grbl_zero_grid.addWidget(self.grbl_zero_all_button, 0, 1, 3, 1)
 
         # GRBL SENDER
         grbl_send_grid = QtWidgets.QGridLayout()
-        grbl_send_grid.setColumnStretch(0, 0)
-        grbl_send_grid.setColumnStretch(1, 1)
-        grbl_send_grid.setColumnStretch(2, 0)
+        grbl_send_grid.setColumnStretch(0, 1)
+        grbl_send_grid.setColumnStretch(1, 0)
         self.gr_send_tab_layout.addLayout(grbl_send_grid)
 
-        # CUSTOM COMMAND
-        self.grbl_command_label = FCLabel('%s:' % _("CMD"))
+        # Send CUSTOM COMMAND
+        self.grbl_command_label = FCLabel('%s:' % _("Send Command"))
         self.grbl_command_label.setToolTip(
             _("Send a custom command to GRBL.")
         )
+        grbl_send_grid.addWidget(self.grbl_command_label, 2, 0, 1, 2)
 
         self.grbl_command_entry = FCEntry()
 
@@ -2317,37 +2327,15 @@ class CNCObjectUI(ObjectUI):
         self.grbl_send_button.setToolTip(
             _("Send a custom command to GRBL.")
         )
-        grbl_send_grid.addWidget(self.grbl_command_label, 2, 0)
-        grbl_send_grid.addWidget(self.grbl_command_entry, 2, 1)
-        grbl_send_grid.addWidget(self.grbl_send_button, 2, 2)
-
-        # GET HEIGHT MAP
-        self.grbl_get_heightmap_button = FCButton(_("Get Height Map"))
-        self.grbl_get_heightmap_button.setToolTip(
-            _("Will send the probing GCode to the GRBL controller\n"
-              "and wait for the Z probing data.")
-        )
-        grbl_send_grid.addWidget(self.grbl_get_heightmap_button, 4, 0, 1, 3)
-
-        # GET Report
-        self.grbl_report_button = FCButton(_("Get Report"))
-        self.grbl_report_button.setToolTip(
-            _("Print in shell the GRBL report.")
-        )
-        grbl_send_grid.addWidget(self.grbl_report_button, 5, 0, 1, 3)
-
-        grbl_send2_grid = QtWidgets.QGridLayout()
-        grbl_send2_grid.setColumnStretch(0, 0)
-        grbl_send2_grid.setColumnStretch(1, 1)
-        grbl_send2_grid.setColumnStretch(2, 0)
-        self.gr_send_tab_layout.addLayout(grbl_send2_grid)
-        self.gr_send_tab_layout.addStretch(1)
+        grbl_send_grid.addWidget(self.grbl_command_entry, 4, 0)
+        grbl_send_grid.addWidget(self.grbl_send_button, 4, 1)
 
         # Get Parameter
-        self.grbl_get_param_label = FCLabel('%s:' % _("Parameter"))
+        self.grbl_get_param_label = FCLabel('%s:' % _("Get Config parameter"))
         self.grbl_get_param_label.setToolTip(
             _("A GRBL parameter.")
         )
+        grbl_send_grid.addWidget(self.grbl_get_param_label, 6, 0, 1, 2)
 
         self.grbl_parameter_entry = FCEntry()
 
@@ -2356,9 +2344,23 @@ class CNCObjectUI(ObjectUI):
         self.grbl_get_param_button.setToolTip(
             _("Get the value of a specified GRBL parameter.")
         )
-        grbl_send2_grid.addWidget(self.grbl_get_param_label, 2, 0)
-        grbl_send2_grid.addWidget(self.grbl_parameter_entry, 2, 1)
-        grbl_send2_grid.addWidget(self.grbl_get_param_button, 2, 2)
+        grbl_send_grid.addWidget(self.grbl_parameter_entry, 8, 0)
+        grbl_send_grid.addWidget(self.grbl_get_param_button, 8, 1)
+
+        # GET Report
+        self.grbl_report_button = FCButton(_("Get Report"))
+        self.grbl_report_button.setToolTip(
+            _("Print in shell the GRBL report.")
+        )
+        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.setToolTip(
+            _("Will send the probing GCode to the GRBL controller\n"
+              "and wait for the Z probing data.")
+        )
+        grbl_send_grid.addWidget(self.grbl_get_heightmap_button, 12, 0, 1, 2)
 
         self.grbl_frame.hide()
         # #############################################################################################################

+ 96 - 27
appObjects/FlatCAMCNCJob.py

@@ -198,6 +198,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
         }
         '''
         self.al_geometry_dict = {}
+        self.solid_geo = None
         self.grbl_ser_port = None
 
         # Attributes to be included in serialization
@@ -554,6 +555,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
         self.ui.sal_cb.stateChanged.connect(self.on_autolevelling)
         self.ui.al_mode_radio.activated_custom.connect(self.on_mode_radio)
         self.ui.al_controller_combo.currentIndexChanged.connect(self.on_controller_change)
+        self.ui.voronoi_cb.stateChanged.connect(self.show_voronoi_diagram)
         # GRBL
         self.ui.com_search_button.clicked.connect(self.on_search_ports)
         self.ui.add_bd_button.clicked.connect(self.on_add_baudrate_grbl)
@@ -654,8 +656,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
     def on_add_al_probepoints(self):
         # create the solid_geo
 
-        solid_geo = [geo['geom'] for geo in self.gcode_parsed if geo['kind'][0] == 'C']
-        solid_geo = unary_union(solid_geo)
+        self.solid_geo = unary_union([geo['geom'] for geo in self.gcode_parsed if geo['kind'][0] == 'C'])
 
         # reset al table
         self.ui.al_probe_points_table.setRowCount(0)
@@ -663,7 +664,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
         # reset the al dict
         self.al_geometry_dict.clear()
 
-        xmin, ymin, xmax, ymax = solid_geo.bounds
+        xmin, ymin, xmax, ymax = self.solid_geo.bounds
 
         if self.ui.al_mode_radio.get_value() == 'grid':
             width = abs(xmax - xmin)
@@ -684,14 +685,19 @@ class CNCJobObject(FlatCAMObj, CNCjob):
                     points.append((new_x, new_y))
 
             pt_id = 0
+            pts_list = []
             for point in points:
                 pt_id += 1
+                pt = Point(point)
+                pts_list.append(pt)
                 new_dict = {
-                    'point': Point(point),
+                    'point': pt,
                     'geo': None,
                     'height': 0.0
                 }
                 self.al_geometry_dict[pt_id] = deepcopy(new_dict)
+            self.calculate_voronoi_diagram(pts=pts_list)
+
         else:
             self.app.inform.emit(_("Click on canvas to add a Test Point..."))
 
@@ -709,13 +715,28 @@ class CNCJobObject(FlatCAMObj, CNCjob):
 
             self.mouse_events_connected = True
 
-            self.calculate_voronoi_diagram()
-
         self.build_al_table_sig.emit()
 
-    def calculate_voronoi_diagram(self):
-        pass
-        # return voronoi_diagram()
+    def show_voronoi_diagram(self, state):
+        if state:
+            pass
+        else:
+            pass
+
+    def calculate_voronoi_diagram(self, pts):
+        pts_union = unary_union(pts)
+        env = self.solid_geo.envelope
+        try:
+            voronoi_union = voronoi_diagram(geom=pts_union, envelope=env)
+            print(voronoi_union)
+        except Exception as e:
+            log.debug("CNCJobObject.calculate_voronoi_diagram() --> %s" % str(e))
+            return
+
+        for pt_key in list(self.al_geometry_dict.keys()):
+            for poly in voronoi_union:
+                if self.al_geometry_dict[pt_key]['point'].within(poly):
+                    self.al_geometry_dict[pt_key]['geo'] = poly
 
     # To be called after clicking on the plot.
     def on_mouse_click_release(self, event):
@@ -786,6 +807,11 @@ class CNCJobObject(FlatCAMObj, CNCjob):
 
             self.app.inform.emit(_("Finished manual adding of Test Point..."))
 
+            pts_list = []
+            for k in self.al_geometry_dict:
+                pts_list.append(self.al_geometry_dict[k]['point'])
+            self.calculate_voronoi_diagram(pts=pts_list)
+
             # rebuild the al table
             self.build_al_table_sig.emit()
 
@@ -952,17 +978,6 @@ class CNCJobObject(FlatCAMObj, CNCjob):
                                                        xonxoff=False,
                                                        rtscts=False)
 
-            self.app.inform.emit("%s: %s" % (_("Port connected"), port_name))
-            self.ui.com_connect_button.setStyleSheet("QPushButton {background-color: seagreen;}")
-            self.ui.com_connect_button.setText(_("Connected"))
-
-            for idx in range(self.ui.al_toolbar.count()):
-                if self.ui.al_toolbar.tabText(idx) == _("Connect"):
-                    self.ui.al_toolbar.tabBar.setTabTextColor(idx, QtGui.QColor('seagreen'))
-                if self.ui.al_toolbar.tabText(idx) == _("Control"):
-                    self.ui.al_toolbar.tabBar.setTabEnabled(idx, True)
-                if self.ui.al_toolbar.tabText(idx) == _("Sender"):
-                    self.ui.al_toolbar.tabBar.setTabEnabled(idx, True)
             # Toggle DTR to reset the controller loaded with GRBL (Arduino, ESP32, etc)
             try:
                 self.grbl_ser_port.dtr = False
@@ -975,12 +990,36 @@ class CNCJobObject(FlatCAMObj, CNCjob):
                 self.grbl_ser_port.dtr = True
             except IOError:
                 pass
+
+            answer = self.wake_grbl()
+            answer = ['ok']   # hack for development without a GRBL controller connected
+            for line in answer:
+                if 'ok' in line.lower():
+                    self.ui.com_connect_button.setStyleSheet("QPushButton {background-color: seagreen;}")
+                    self.ui.com_connect_button.setText(_("Connected"))
+                    self.ui.controller_reset_button.setDisabled(False)
+
+                    for idx in range(self.ui.al_toolbar.count()):
+                        if self.ui.al_toolbar.tabText(idx) == _("Connect"):
+                            self.ui.al_toolbar.tabBar.setTabTextColor(idx, QtGui.QColor('seagreen'))
+                        if self.ui.al_toolbar.tabText(idx) == _("Control"):
+                            self.ui.al_toolbar.tabBar.setTabEnabled(idx, True)
+                        if self.ui.al_toolbar.tabText(idx) == _("Sender"):
+                            self.ui.al_toolbar.tabBar.setTabEnabled(idx, True)
+
+                    self.app.inform.emit("%s: %s" % (_("Port connected"), port_name))
+                    return
+
+            self.grbl_ser_port.close()
+            self.app.inform.emit("[ERROR_NOTCL] %s: %s" % (_("Could not connect to GRBL on port"), port_name))
+
         except serial.SerialException:
             self.grbl_ser_port = serial.Serial()
             self.grbl_ser_port.port = port_name
             self.grbl_ser_port.close()
             self.ui.com_connect_button.setStyleSheet("QPushButton {background-color: red;}")
             self.ui.com_connect_button.setText(_("Disconnected"))
+            self.ui.controller_reset_button.setDisabled(True)
 
             for idx in range(self.ui.al_toolbar.count()):
                 if self.ui.al_toolbar.tabText(idx) == _("Connect"):
@@ -1006,12 +1045,16 @@ class CNCJobObject(FlatCAMObj, CNCjob):
     def wake_grbl(self):
         # Wake up grbl
         self.grbl_ser_port.write("\r\n\r\n".encode('utf-8'))
-        time.sleep(1)  # Wait for grbl to initialize
-        self.grbl_ser_port.flushInput()  # Flush startup text in serial input
+        # Wait for GRBL controller to initialize
+        time.sleep(1)
+
+        grbl_out = deepcopy(self.grbl_ser_port.readlines())
+        self.grbl_ser_port.reset_input_buffer()
+
+        return grbl_out
 
     def on_send_grbl_command(self):
         cmd = self.ui.grbl_command_entry.get_value()
-        self.wake_grbl()
 
         # show the Shell Dock
         self.app.ui.shell_dock.show()
@@ -1023,22 +1066,47 @@ class CNCJobObject(FlatCAMObj, CNCjob):
         self.app.worker_task.emit({'fcn': worker_task, 'params': []})
 
     def send_grbl_command(self, command, echo=True):
-        stripped_cmd = command.strip()  # Strip all EOL characters for consistency
+        stripped_cmd = command.strip()
+
+        cmd = stripped_cmd.rpartition('\n')[0]
+        if echo:
+            self.app.inform_shell[str, bool].emit(cmd, False)
+
+        # Send Gcode command to GRBL
+        snd = cmd + '\n'
+        self.grbl_ser_port.write(snd.encode('utf-8'))
+        grbl_out = self.grbl_ser_port.readlines()
+
+        result = False
+        for line in grbl_out:
+            if echo:
+                try:
+                    self.app.inform_shell.emit(' : ' + line.decode('utf-8').strip().upper())
+                except Exception as e:
+                    log.debug("CNCJobObject.send_grbl_command() --> %s" % str(e))
+            if 'ok' in line:
+                result = True
+
+        return result
+
+    def send_grbl_block(self, command, echo=True):
+        stripped_cmd = command.strip()
 
         for l in stripped_cmd.split('\n'):
             if echo:
                 self.app.inform_shell[str, bool].emit(l, False)
 
+            # Send Gcode block to GRBL
             snd = l + '\n'
-            self.grbl_ser_port.write(snd.encode('utf-8'))  # Send g-code block to grbl
-            grbl_out = self.grbl_ser_port.readlines()  # Wait for grbl response with carriage return
+            self.grbl_ser_port.write(snd.encode('utf-8'))
+            grbl_out = self.grbl_ser_port.readlines()
 
             for line in grbl_out:
                 if echo:
                     try:
                         self.app.inform_shell.emit(' : ' + line.decode('utf-8').strip().upper())
                     except Exception as e:
-                        log.debug("CNCJobObject.send_grbl_command() --> %s" % str(e))
+                        log.debug("CNCJobObject.send_grbl_block() --> %s" % str(e))
 
     def get_grbl_parameter(self, param):
         if '$' in param:
@@ -1080,6 +1148,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
         cmd = '\x18'
         self.wake_grbl()
         self.send_grbl_command(command=cmd)
+        self.app.inform.emit("%s" % _("GRBL software reset was sent."))
 
     def probing_gcode(self, coords, pr_travel, probe_fr, pr_depth, controller):
         """