chiark / gitweb /
Add a park toolhead on Pause feature
authorYouness Alaoui <kakaroto@kakaroto.homelinux.net>
Fri, 6 Nov 2015 19:50:19 +0000 (14:50 -0500)
committerYouness Alaoui <kakaroto@kakaroto.homelinux.net>
Fri, 6 Nov 2015 19:50:19 +0000 (14:50 -0500)
This will add a park toolhead feature when Pause is clicked.
The park position is at 10 mm from the x/y limits and 10mm above the
current Z unless we're 10mm away from the max height of the printer.
On resume, the E position is reset, last feedrate value is restored
and the toolhead is primed for new filament before being moved back
into position.

The print window will now also display a "Please wait" for 10 seconds
while disabling the pause/resume button to avoid excessive commands
being sent while the printer is still busy with a move.
This also helps the user realize that pausing is not an instantenous feature.
The serial connection has been fixed to send queued commands when in paused state.
Feature was taken in part from the pauseAtZ plugin.
Only E movements are now allowd in paused state.

Hopefully fixes T220 and makes everyone happy

Cura/gui/printWindow.py
Cura/util/machineCom.py
Cura/util/printerConnection/serialConnection.py

index fc9523f93e40f20126784f1cef75bd6750dd474e..e6ae50f01d4db6626b504a83a522ac210b09f53a 100644 (file)
@@ -346,13 +346,24 @@ class printWindowPlugin(wx.Frame):
                                        if not self._printerConnection.hasActiveConnection() or \
                                           self._printerConnection.isActiveConnectionOpen():
                                                if self._printerConnection.isPrinting():
-                                                       button.SetLabel(_("Pause"))
+                                                       if self.pauseTimer.IsRunning():
+                                                               self.printButton.Enable(False)
+                                                               self.printButton.SetLabel(_("Please wait..."))
+                                                       else:
+                                                               self.printButton.Enable(True)
+                                                               button.SetLabel(_("Pause"))
                                                else:
                                                        if self._printerConnection.isPaused():
-                                                               button.SetLabel(_("Resume"))
+                                                               if self.pauseTimer.IsRunning():
+                                                                       self.printButton.Enable(False)
+                                                                       self.printButton.SetLabel(_("Please wait..."))
+                                                               else:
+                                                                       self.printButton.Enable(True)
+                                                                       button.SetLabel(_("Resume"))
                                                        else:
                                                                button.SetLabel(_("Print"))
-                                               button.Enable(True)
+                                                               button.Enable(True)
+                                                               self.pauseTimer.Stop()
                                        else:
                                                button.Enable(False)
                        elif button.command == self.script_cancelPrint:
@@ -452,6 +463,9 @@ class printWindowBasic(wx.Frame):
                self.errorLogButton = wx.Button(self.panel, -1, _("Error log"))
                self.progress = wx.Gauge(self.panel, -1, range=1000)
 
+               self.pauseTimer = wx.Timer(self)
+               self.Bind(wx.EVT_TIMER, self.OnPauseTimer, self.pauseTimer)
+
                self.sizer.Add(self.powerWarningText, pos=(0, 0), span=(1, 5), flag=wx.EXPAND|wx.BOTTOM, border=5)
                self.sizer.Add(self.statsText, pos=(1, 0), span=(1, 5), flag=wx.LEFT, border=5)
                self.sizer.Add(self.connectButton, pos=(2, 0))
@@ -506,6 +520,8 @@ class printWindowBasic(wx.Frame):
                self._printerConnection.removeCallback(self._doPrinterConnectionUpdate)
                #TODO: When multiple printer windows are open, closing one will enable sleeping again.
                preventComputerFromSleeping(self, False)
+               self.powerWarningTimer.Stop()
+               self.pauseTimer.Stop()
                self.Destroy()
 
        def OnConnect(self, e):
@@ -522,6 +538,14 @@ class printWindowBasic(wx.Frame):
 
        def OnPause(self, e):
                self._printerConnection.pause(not self._printerConnection.isPaused())
+               self.pauseButton.Enable(False)
+               self.pauseTimer.Stop()
+               self.pauseTimer.Start(10000)
+
+       def OnPauseTimer(self, e):
+               self.pauseButton.Enable(True)
+               self.pauseTimer.Stop()
+               self._updateButtonStates()
 
        def OnErrorLog(self, e):
                LogWindow(self._printerConnection.getErrorLog())
@@ -658,6 +682,9 @@ class printWindowAdvanced(wx.Frame):
                self.OnPowerWarningChange(None)
                self.powerWarningTimer.Start(10000)
 
+               self.pauseTimer = wx.Timer(self)
+               self.Bind(wx.EVT_TIMER, self.OnPauseTimer, self.pauseTimer)
+
                self.connectButton = wx.Button(self.toppanel, -1, _("Connect"), size=(125, 30))
                self.printButton = wx.Button(self.toppanel, -1, _("Print"), size=(125, 30))
                self.cancelButton = wx.Button(self.toppanel, -1, _("Cancel"), size=(125, 30))
@@ -742,6 +769,8 @@ class printWindowAdvanced(wx.Frame):
                #TODO: When multiple printer windows are open, closing one will enable sleeping again.
                preventComputerFromSleeping(self, False)
                self._printerConnection.cancelPrint()
+               self.powerWarningTimer.Stop()
+               self.pauseTimer.Stop()
                self.Destroy()
 
        def OnPowerWarningChange(self, e):
@@ -765,9 +794,17 @@ class printWindowAdvanced(wx.Frame):
        def OnPrint(self, e):
                if self._printerConnection.isPrinting() or self._printerConnection.isPaused():
                        self._printerConnection.pause(not self._printerConnection.isPaused())
+                       self.pauseTimer.Stop()
+                       self.printButton.Enable(False)
+                       self.pauseTimer.Start(10000)
                else:
                        self._printerConnection.startPrint()
 
+       def OnPauseTimer(self, e):
+               self.printButton.Enable(True)
+               self.pauseTimer.Stop()
+               self._updateButtonStates()
+
        def OnCancel(self, e):
                self._printerConnection.cancelPrint()
 
@@ -796,7 +833,7 @@ class printWindowAdvanced(wx.Frame):
                # Prevent Z movement when paused and all moves when printing
                if (not self._printerConnection.hasActiveConnection() or \
                        self._printerConnection.isActiveConnectionOpen()) and \
-                       (not (self._printerConnection.isPaused() and motor == 'Z') and \
+                       (not (self._printerConnection.isPaused() and motor != 'E') and \
                         not self._printerConnection.isPrinting()):
                        self._printerConnection.sendCommand("G91")
                        self._printerConnection.sendCommand("G1 %s%.1f F%d" % (motor, step, feedrate))
@@ -903,13 +940,24 @@ class printWindowAdvanced(wx.Frame):
                        if not self._printerConnection.hasActiveConnection() or \
                           self._printerConnection.isActiveConnectionOpen():
                                if self._printerConnection.isPrinting():
-                                       self.printButton.SetLabel(_("Pause"))
+                                       if self.pauseTimer.IsRunning():
+                                               self.printButton.Enable(False)
+                                               self.printButton.SetLabel(_("Please wait..."))
+                                       else:
+                                               self.printButton.Enable(True)
+                                               self.printButton.SetLabel(_("Pause"))
                                else:
                                        if self._printerConnection.isPaused():
-                                               self.printButton.SetLabel(_("Resume"))
+                                               if self.pauseTimer.IsRunning():
+                                                       self.printButton.Enable(False)
+                                                       self.printButton.SetLabel(_("Please wait..."))
+                                               else:
+                                                       self.printButton.SetLabel(_("Resume"))
+                                                       self.printButton.Enable(True)
                                        else:
                                                self.printButton.SetLabel(_("Print"))
-                               self.printButton.Enable(True)
+                                               self.printButton.Enable(True)
+                                               self.pauseTimer.Stop()
                        else:
                                self.printButton.Enable(False)
                if not self._printerConnection.hasActiveConnection() or \
index 0db7ecb2a1971009a39facad0b16193badd1d3f7..0178bfb95efa29da69f03de8242fd73fb84330e4 100644 (file)
@@ -501,6 +501,11 @@ class MachineCom(object):
                                                self.cancelPrint()
                                        else:
                                                self._gcodePos = newPos
+                       elif self._state == self.STATE_PAUSED:
+                               if 'ok' in line:
+                                       timeout = time.time() + 5
+                                       if not self._commandQueue.empty():
+                                               self._sendCommand(self._commandQueue.get())
 
                self._log("Connection closed, closing down monitor")
 
@@ -584,7 +589,7 @@ class MachineCom(object):
                        self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
                        self._errorValue = getExceptionString()
                        self.close(True)
-       
+
        def _sendNext(self):
                if self._gcodePos >= len(self._gcodeList):
                        self._changeState(self.STATE_OPERATIONAL)
@@ -612,14 +617,14 @@ class MachineCom(object):
                self._sendCommand("N%d%s*%d" % (self._gcodePos, line, checksum))
                self._gcodePos += 1
                self._callback.mcProgress(self._gcodePos)
-       
+
        def sendCommand(self, cmd):
                cmd = cmd.encode('ascii', 'replace')
                if self.isPrinting():
                        self._commandQueue.put(cmd)
                elif self.isOperational():
                        self._sendCommand(cmd)
-       
+
        def printGCode(self, gcodeList):
                if not self.isOperational() or self.isPrinting():
                        return
index 1fd0485d65278b45f4aa07f0c932dd969b91056f..92344f70a3a4ac6b4226e1b004322c257a75dd96 100644 (file)
@@ -11,6 +11,7 @@ import os
 import sys
 import subprocess
 import json
+import re
 
 from Cura.util import profile
 from Cura.util import machineCom
@@ -69,6 +70,7 @@ class serialConnection(printerConnectionBase.printerConnectionBase):
                self._gcodeData = []
                self._printProgress = 0
                self._ZPosition = 0
+               self._pausePosition = None
 
        #Load the data into memory for printing, returns True on success
        def loadGCodeData(self, dataStream):
@@ -97,6 +99,7 @@ class serialConnection(printerConnectionBase.printerConnectionBase):
                self._process.stdin.write('START\n')
                self._printProgress = 0
                self._ZPosition = 0
+               self._pausePosition = None
 
        def coolDown(self):
                cooldown_toolhead = "M104 S0"
@@ -116,6 +119,8 @@ class serialConnection(printerConnectionBase.printerConnectionBase):
                        return
                self._process.stdin.write('STOP\n')
                self._printProgress = 0
+               self._ZPosition = 0
+               self._pausePosition = None
                self.coolDown()
                self.disableSteppers()
 
@@ -134,9 +139,80 @@ class serialConnection(printerConnectionBase.printerConnectionBase):
                if not (self.isPrinting() or self.isPaused()) or self._process is None:
                        return
                if value:
+                       start_gcode = profile.getAlterationFileContents('start.gcode')
+                       start_gcode_lines = len(start_gcode.split("\n"))
+                       parkX = profile.getMachineSettingFloat('machine_width') - 10
+                       parkY = profile.getMachineSettingFloat('machine_depth') - 10
+                       maxZ = profile.getMachineSettingFloat('machine_height') - 10
+                       #retract_amount = profile.getProfileSettingFloat('retraction_amount')
+                       retract_amount = 5.0
+                       moveZ = 10.0
+
+                       if self._printProgress - 5 > start_gcode_lines: # Substract 5 because of the marlin queue
+                               x = None
+                               y = None
+                               e = None
+                               f = None
+                               for i in xrange(self._printProgress - 1, start_gcode_lines, -1):
+                                       line = self._gcodeData[i]
+                                       if ('G0' in line or 'G1' in line) and 'X' in line and x is None:
+                                               x = float(re.search('X(-?[0-9\.]*)', line).group(1))
+                                       if ('G0' in line or 'G1' in line) and 'Y' in line and y is None:
+                                               y = float(re.search('Y(-?[0-9\.]*)', line).group(1))
+                                       if ('G0' in line or 'G1' in line) and 'E' in line and e is None:
+                                               e = float(re.search('E(-?[0-9\.]*)', line).group(1))
+                                       if ('G0' in line or 'G1' in line) and 'F' in line and f is None:
+                                               f = int(re.search('F(-?[0-9\.]*)', line).group(1))
+                                       if x is not None and y is not None and f is not None and e is not None:
+                                               break
+                               if f is None:
+                                       f = 1200
+
+                               if x is not None and y is not None:
+                                       # Set E relative positioning
+                                       self.sendCommand("M83")
+                                       # Retract 1mm
+                                       self.sendCommand("G1 E-%f F120" % retract_amount)
+
+                                       #Move the toolhead up
+                                       newZ = self._ZPosition + moveZ
+                                       if maxZ < newZ:
+                                               newZ = maxZ
+                                       if newZ > self._ZPosition:
+                                               self.sendCommand("G1 Z%f F200\n" % (newZ))
+
+                                       #Move the head away
+                                       self.sendCommand("G1 X%f Y%f F9000\n" % (parkX, parkY))
+
+                                       #Disable the E steppers
+                                       self.sendCommand("M84 E0\n")
+                                       # Set E absolute positioning
+                                       self.sendCommand("M82\n")
+
+                                       self._pausePosition = (x, y, self._ZPosition, f, e)
                        self._process.stdin.write("PAUSE\n")
                else:
+                       if self._pausePosition:
+                               retract_amount = profile.getProfileSettingFloat('retraction_amount')
+                               # Set E relative positioning
+                               self.sendCommand("M83")
+                               #Push the filament back, and retract again, the properly primes the nozzle when changing filament.
+                               self.sendCommand("G1 E%f F120\n" % (retract_amount))
+                               self.sendCommand("G1 E-%f F120\n" % (retract_amount))
+
+                               # Position the toolhead to the correct position again
+                               self.sendCommand("G1 X%f Y%f Z%f F%d\n" % self._pausePosition[0:4])
+
+                               # Prime the nozzle again
+                               self.sendCommand("G1 E%f F120\n" % (retract_amount))
+                               # Set proper feedrate
+                               self.sendCommand("G1 F%d\n" % (self._pausePosition[3]))
+                               # Set E absolute position to cancel out any extrude/retract that occured
+                               self.sendCommand("G92 E%f\n" % (self._pausePosition[4]))
+                               # Set E absolute positioning
+                               self.sendCommand("M82\n")
                        self._process.stdin.write("RESUME\n")
+                       self._pausePosition = None
 
        #Amount of progression of the current print file. 0.0 to 1.0
        def getPrintProgress(self):