Browse Source

Added dwell (G4) post processing option to gcode.

Juan Pablo Caram 9 years ago
parent
commit
6136afe84c
5 changed files with 114 additions and 14 deletions
  1. 10 3
      FlatCAMApp.py
  2. 20 0
      FlatCAMGUI.py
  3. 54 7
      FlatCAMObj.py
  4. 22 0
      ObjectUI.py
  5. 8 4
      camlib.py

+ 10 - 3
FlatCAMApp.py

@@ -245,7 +245,9 @@ class App(QtCore.QObject):
             "cncjob_plot": self.defaults_form.cncjob_group.plot_cb,
             "cncjob_tooldia": self.defaults_form.cncjob_group.tooldia_entry,
             "cncjob_prepend": self.defaults_form.cncjob_group.prepend_text,
-            "cncjob_append": self.defaults_form.cncjob_group.append_text
+            "cncjob_append": self.defaults_form.cncjob_group.append_text,
+            "cncjob_dwell": self.defaults_form.cncjob_group.dwell_cb,
+            "cncjob_dwelltime": self.defaults_form.cncjob_group.dwelltime_cb
         }
 
         self.defaults = LoudDict()
@@ -289,8 +291,13 @@ class App(QtCore.QObject):
             "cncjob_tooldia": 0.016,
             "cncjob_prepend": "",
             "cncjob_append": "",
-            "background_timeout": 300000, #default value is 5 minutes
-            "verbose_error_level": 0, # shell verbosity 0 = default(python trace only for unknown errors), 1 = show trace(show trace allways), 2 = (For the future).
+            "cncjob_dwell": True,
+            "cncjob_dwelltime": 1,
+            "background_timeout": 300000,  # Default value is 5 minutes
+            "verbose_error_level": 0,  # Shell verbosity 0 = default
+                                       # (python trace only for unknown errors),
+                                       # 1 = show trace(show trace allways),
+                                       # 2 = (For the future).
 
             # Persistence
             "last_folder": None,

+ 20 - 0
FlatCAMGUI.py

@@ -806,6 +806,26 @@ class CNCJobOptionsGroupUI(OptionsGroupUI):
         self.append_text = FCTextArea()
         self.layout.addWidget(self.append_text)
 
+        # Dwell
+        grid1 = QtGui.QGridLayout()
+        self.layout.addLayout(grid1)
+
+        dwelllabel = QtGui.QLabel('Dwell:')
+        dwelllabel.setToolTip(
+            "Pause to allow the spindle to reach its\n"
+            "speed before cutting."
+        )
+        dwelltime = QtGui.QLabel('Duration [sec.]:')
+        dwelltime.setToolTip(
+            "Number of second to dwell."
+        )
+        self.dwell_cb = FCCheckBox()
+        self.dwelltime_cb = FCEntry()
+        grid1.addWidget(dwelllabel, 0, 0)
+        grid1.addWidget(self.dwell_cb, 0, 1)
+        grid1.addWidget(dwelltime, 1, 0)
+        grid1.addWidget(self.dwelltime_cb, 1, 1)
+
 
 class GlobalOptionsUI(QtGui.QWidget):
     """

+ 54 - 7
FlatCAMObj.py

@@ -1,3 +1,4 @@
+from cStringIO import StringIO
 from PyQt4 import QtCore
 from copy import copy
 from ObjectUI import *
@@ -981,7 +982,9 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
             "plot": True,
             "tooldia": 0.4 / 25.4,  # 0.4mm in inches
             "append": "",
-            "prepend": ""
+            "prepend": "",
+            "dwell": False,
+            "dwelltime": 1
         })
 
         # Attributes to be included in serialization
@@ -1001,7 +1004,9 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
             "plot": self.ui.plot_cb,
             "tooldia": self.ui.tooldia_entry,
             "append": self.ui.append_text,
-            "prepend": self.ui.prepend_text
+            "prepend": self.ui.prepend_text,
+            "dwell": self.ui.dwell_cb,
+            "dwelltime": self.ui.dwelltime_entry
         })
 
         self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
@@ -1019,6 +1024,8 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
     def on_exportgcode_button_click(self, *args):
         self.app.report_usage("cncjob_on_exportgcode_button")
 
+        self.read_form()
+
         try:
             filename = QtGui.QFileDialog.getSaveFileName(caption="Export G-Code ...",
                                                          directory=self.app.defaults["last_folder"])
@@ -1030,10 +1037,51 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
 
         self.export_gcode(filename, preamble=preamble, postamble=postamble)
 
+    def dwell_generator(self, lines):
+
+        log.debug("dwell_generator()...")
+
+        m3m4re = re.compile(r'^\s*[mM]0[34]')
+        g4re = re.compile(r'^\s*[gG]4\s+([\d\.\+\-e]+)')
+        bufline = None
+
+        for line in lines:
+            # If the buffer contains a G4, yield that.
+            # If current line is a G4, discard it.
+            if bufline is not None:
+                yield bufline
+                bufline = None
+
+                if not g4re.search(line):
+                    yield line
+
+                continue
+
+            # If start spindle, buffer a G4.
+            if m3m4re.search(line):
+                log.debug("Found M03/4")
+                bufline = "G4 {}\n".format(self.options['dwelltime'])
+
+            yield line
+
+        raise StopIteration
+
     def export_gcode(self, filename, preamble='', postamble=''):
-        f = open(filename, 'w')
-        f.write(preamble + '\n' + self.gcode + "\n" + postamble)
-        f.close()
+
+        lines = StringIO(self.gcode)
+
+        if self.options['dwell']:
+            log.debug("Will add G04!")
+            lines = self.dwell_generator(lines)
+
+        with open(filename, 'w') as f:
+            f.write(preamble + "\n")
+
+            for line in lines:
+
+                f.write(line)
+
+            f.write(postamble)
 
         # Just for adding it to the recent files list.
         self.app.file_opened.emit("cncjob", filename)
@@ -1309,8 +1357,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
             app_obj.progress.emit(80)
 
-
-        if  use_thread:
+        if use_thread:
             # To be run in separate thread
             def job_thread(app_obj):
                 with self.app.proc_container.new("Generating CNC Job."):

+ 22 - 0
ObjectUI.py

@@ -163,7 +163,9 @@ class CNCObjectUI(ObjectUI):
         )
         self.custom_box.addWidget(self.updateplot_button)
 
+        ##################
         ## Export G-Code
+        ##################
         self.export_gcode_label = QtGui.QLabel("<b>Export G-Code:</b>")
         self.export_gcode_label.setToolTip(
             "Export and save G-Code to\n"
@@ -194,6 +196,26 @@ class CNCObjectUI(ObjectUI):
         self.append_text = FCTextArea()
         self.custom_box.addWidget(self.append_text)
 
+        # Dwell
+        grid1 = QtGui.QGridLayout()
+        self.custom_box.addLayout(grid1)
+
+        dwelllabel = QtGui.QLabel('Dwell:')
+        dwelllabel.setToolTip(
+            "Pause to allow the spindle to reach its\n"
+            "speed before cutting."
+        )
+        dwelltime = QtGui.QLabel('Duration [sec.]:')
+        dwelltime.setToolTip(
+            "Number of second to dwell."
+        )
+        self.dwell_cb = FCCheckBox()
+        self.dwelltime_entry = FCEntry()
+        grid1.addWidget(dwelllabel, 0, 0)
+        grid1.addWidget(self.dwell_cb, 0, 1)
+        grid1.addWidget(dwelltime, 1, 0)
+        grid1.addWidget(self.dwelltime_entry, 1, 1)
+
         # GO Button
         self.export_gcode_button = QtGui.QPushButton('Export G-Code')
         self.export_gcode_button.setToolTip(

+ 8 - 4
camlib.py

@@ -2720,7 +2720,8 @@ class CNCjob(Geometry):
         self.feedrate = feedrate
         self.tooldia = tooldia
         self.unitcode = {"IN": "G20", "MM": "G21"}
-        self.pausecode = "G04 P1"
+        # TODO: G04 Does not exist. It's G4 and now we are handling in postprocessing.
+        #self.pausecode = "G04 P1"
         self.feedminutecode = "G94"
         self.absolutecode = "G90"
         self.gcode = ""
@@ -2818,7 +2819,7 @@ class CNCjob(Geometry):
         else:
             gcode += "M03\n"  # Spindle start
 
-        gcode += self.pausecode + "\n"
+        #gcode += self.pausecode + "\n"
 
         for tool in tools:
 
@@ -2915,7 +2916,7 @@ class CNCjob(Geometry):
             self.gcode += "M03 S%d\n" % int(self.spindlespeed)  # Spindle start with configured speed
         else:
             self.gcode += "M03\n"  # Spindle start
-        self.gcode += self.pausecode + "\n"
+        #self.gcode += self.pausecode + "\n"
 
         ## Iterate over geometry paths getting the nearest each time.
         log.debug("Starting G-Code...")
@@ -3031,6 +3032,8 @@ class CNCjob(Geometry):
         :param gtext: A single string with g-code
         """
 
+        log.debug("pre_parse()")
+
         # Units: G20-inches, G21-mm
         units_re = re.compile(r'^G2([01])')
 
@@ -3097,7 +3100,8 @@ class CNCjob(Geometry):
         
         # TODO: Merge into single parser?
         gobjs = self.pre_parse(self.gcode)
-        
+
+        log.debug("gcode_parse(): pre_parse() done.")
         # Last known instruction
         current = {'X': 0.0, 'Y': 0.0, 'Z': 0.0, 'G': 0}