From e49bc2c77f93ee08e9cd6700296df87a46c2347b Mon Sep 17 00:00:00 2001 From: daid303 Date: Tue, 2 Oct 2012 10:58:57 +0200 Subject: [PATCH] Open the serial port in the thread, so it no longer blocks the GUI during auto-detection. Add a 10 second write timeout, so we no longer get timeouts under windows. Remove the M109/M190 heatup wait time from the total printing time. --- Cura/avr_isp/stk500v2.py | 2 +- Cura/gui/printWindow.py | 43 ++++++++++---- Cura/gui/simpleMode.py | 4 +- Cura/util/machineCom.py | 123 +++++++++++++++++++++++---------------- 4 files changed, 107 insertions(+), 65 deletions(-) diff --git a/Cura/avr_isp/stk500v2.py b/Cura/avr_isp/stk500v2.py index bfdcb4e4..245db8e4 100644 --- a/Cura/avr_isp/stk500v2.py +++ b/Cura/avr_isp/stk500v2.py @@ -15,7 +15,7 @@ class Stk500v2(ispBase.IspBase): if self.serial != None: self.close() try: - self.serial = Serial(port, speed, timeout=1) + self.serial = Serial(port, speed, timeout=1, writeTimeout=10000) except SerialException as e: raise ispBase.IspError("Failed to open serial port") except: diff --git a/Cura/gui/printWindow.py b/Cura/gui/printWindow.py index 83642b18..9cf50289 100644 --- a/Cura/gui/printWindow.py +++ b/Cura/gui/printWindow.py @@ -328,7 +328,7 @@ class printWindow(wx.Frame): self.cancelButton.Enable(self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused())) self.temperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational()) self.bedTemperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational()) - self.directControlPanel.Enable(self.machineCom != None and self.machineCom.isOperational()) + self.directControlPanel.Enable(self.machineCom != None and self.machineCom.isOperational() and not self.machineCom.isPrinting()) self.machineLogButton.Show(self.machineCom != None and self.machineCom.isError()) def UpdateProgress(self): @@ -349,8 +349,9 @@ class printWindow(wx.Frame): printTime = self.machineCom.getPrintTime() / 60 printTimeTotal = printTime * len(self.gcodeList) / self.machineCom.getPrintPos() printTimeLeft = printTimeTotal - printTime - status += 'Line: %d/%d\n' % (self.machineCom.getPrintPos(), len(self.gcodeList)) - status += 'Height: %f\n' % (self.currentZ) + status += 'Line: %d/%d %d%%\n' % (self.machineCom.getPrintPos(), len(self.gcodeList), self.machineCom.getPrintPos() * 100 / len(self.gcodeList)) + if self.currentZ > 0: + status += 'Height: %0.1f\n' % (self.currentZ) status += 'Print time: %02d:%02d\n' % (int(printTime / 60), int(printTime % 60)) status += 'Print time left: %02d:%02d\n' % (int(printTimeLeft / 60), int(printTimeLeft % 60)) self.progress.SetValue(self.machineCom.getPrintPos()) @@ -558,11 +559,6 @@ class temperatureGraph(wx.Panel): dc.SelectObject(self.backBuffer) dc.Clear() w, h = self.GetSizeTuple() - x0 = 0 - t0 = 0 - bt0 = 0 - tSP0 = 0 - btSP0 = 0 bgLinePen = wx.Pen('#A0A0A0') tempPen = wx.Pen('#FF4040') tempSPPen = wx.Pen('#FFA0A0') @@ -570,6 +566,28 @@ class temperatureGraph(wx.Panel): bedTempPen = wx.Pen('#4040FF') bedTempSPPen = wx.Pen('#A0A0FF') bedTempPenBG = wx.Pen('#D0D0FF') + + x0 = 0 + t0 = 0 + bt0 = 0 + tSP0 = 0 + btSP0 = 0 + for temp, tempSP, bedTemp, bedTempSP, t in self.points: + x1 = int(w - (now - t)) + for x in xrange(x0, x1 + 1): + t = float(x - x0) / float(x1 - x0 + 1) * (temp - t0) + t0 + bt = float(x - x0) / float(x1 - x0 + 1) * (bedTemp - bt0) + bt0 + dc.SetPen(tempPenBG) + dc.DrawLine(x, h, x, h - (t * h / 300)) + dc.SetPen(bedTempPenBG) + dc.DrawLine(x, h, x, h - (bt * h / 300)) + t0 = temp + bt0 = bedTemp + tSP0 = tempSP + btSP0 = bedTempSP + x0 = x1 + 1 + + #Draw the grid for x in xrange(w, 0, -30): dc.SetPen(bgLinePen) dc.DrawLine(x, 0, x, h) @@ -579,6 +597,11 @@ class temperatureGraph(wx.Panel): dc.DrawLine(0, 0, w, 0) dc.DrawLine(0, 0, 0, h) + x0 = 0 + t0 = 0 + bt0 = 0 + tSP0 = 0 + btSP0 = 0 for temp, tempSP, bedTemp, bedTempSP, t in self.points: x1 = int(w - (now - t)) for x in xrange(x0, x1 + 1): @@ -586,10 +609,6 @@ class temperatureGraph(wx.Panel): bt = float(x - x0) / float(x1 - x0 + 1) * (bedTemp - bt0) + bt0 tSP = float(x - x0) / float(x1 - x0 + 1) * (tempSP - tSP0) + tSP0 btSP = float(x - x0) / float(x1 - x0 + 1) * (bedTempSP - btSP0) + btSP0 - dc.SetPen(tempPenBG) - dc.DrawLine(x, h, x, h - (t * h / 300)) - dc.SetPen(bedTempPenBG) - dc.DrawLine(x, h, x, h - (bt * h / 300)) dc.SetPen(tempSPPen) dc.DrawPoint(x, h - (tSP * h / 300)) dc.SetPen(bedTempSPPen) diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index c9890748..acabd652 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -176,7 +176,7 @@ class simpleModeWindow(configBase.configWindowBase): put('skirt_line_count', '1') put('skirt_gap', '6.0') put('print_speed', '50') - put('print_temperature', '230') + put('print_temperature', '220') put('support', 'None') #put('machine_center_x', '100') #put('machine_center_y', '100') @@ -229,7 +229,7 @@ class simpleModeWindow(configBase.configWindowBase): put('print_speed', '80') put('bottom_layer_speed', '40') elif self.printTypeHigh.GetValue(): - put('wall_thickness', nozzle_size * 3.0) + put('wall_thickness', nozzle_size * 2.0) put('layer_height', '0.1') put('fill_density', '30') put('bottom_layer_speed', '15') diff --git a/Cura/util/machineCom.py b/Cura/util/machineCom.py index 2be74533..521804e5 100644 --- a/Cura/util/machineCom.py +++ b/Cura/util/machineCom.py @@ -120,14 +120,16 @@ class MachineComPrintCallback(object): class MachineCom(object): STATE_NONE = 0 - STATE_DETECT_BAUDRATE = 1 - STATE_CONNECTING = 2 - STATE_OPERATIONAL = 3 - STATE_PRINTING = 4 - STATE_PAUSED = 5 - STATE_CLOSED = 6 - STATE_ERROR = 7 - STATE_CLOSED_WITH_ERROR = 8 + STATE_OPEN_SERIAL = 1 + STATE_DETECT_SERIAL = 2 + STATE_DETECT_BAUDRATE = 3 + STATE_CONNECTING = 4 + STATE_OPERATIONAL = 5 + STATE_PRINTING = 6 + STATE_PAUSED = 7 + STATE_CLOSED = 8 + STATE_ERROR = 9 + STATE_CLOSED_WITH_ERROR = 10 def __init__(self, port = None, baudrate = None, callbackObject = None): if port == None: @@ -140,6 +142,8 @@ class MachineCom(object): if callbackObject == None: callbackObject = MachineComPrintCallback() + self._port = port + self._baudrate = baudrate self._callback = callbackObject self._state = self.STATE_NONE self._serial = None @@ -153,44 +157,9 @@ class MachineCom(object): self._logQueue = queue.Queue(256) self._feedRateModifier = {} self._currentZ = -1 + self._heatupWaitStartTime = 0 + self._heatupWaitTimeLost = 0.0 - if port == 'AUTO': - programmer = stk500v2.Stk500v2() - self._log("Serial port list: %s" % (str(serialList()))) - for p in serialList(): - try: - self._log("Connecting to: %s" % (p)) - programmer.connect(p) - self._serial = programmer.leaveISP() - profile.putPreference('serial_port_auto', p) - break - except ispBase.IspError as (e): - self._log("Error while connecting to %s: %s" % (p, str(e))) - pass - except: - self._log("Unexpected error while connecting to serial port: %s %s" % (p, getExceptionString())) - programmer.close() - elif port == 'VIRTUAL': - self._serial = VirtualPrinter() - else: - try: - self._log("Connecting to: %s" % (port)) - if baudrate == 0: - self._serial = Serial(port, 115200, timeout=0.1) - else: - self._serial = Serial(port, baudrate, timeout=2) - except: - self._log("Unexpected error while connecting to serial port: %s %s" % (port, getExceptionString())) - if self._serial == None: - self._log("Failed to open serial port (%s)" % (port)) - self._errorValue = 'Failed to autodetect serial port.' - self._changeState(self.STATE_ERROR) - return - self._log("Connected to: %s, starting monitor" % (self._serial)) - if baudrate == 0: - self._changeState(self.STATE_DETECT_BAUDRATE) - else: - self._changeState(self.STATE_CONNECTING) self.thread = threading.Thread(target=self._monitor) self.thread.daemon = True self.thread.start() @@ -209,8 +178,12 @@ class MachineCom(object): def getStateString(self): if self._state == self.STATE_NONE: return "Offline" + if self._state == self.STATE_OPEN_SERIAL: + return "Opening serial port" + if self._state == self.STATE_DETECT_SERIAL: + return "Detecting serial port" if self._state == self.STATE_DETECT_BAUDRATE: - return "Detect baudrate" + return "Detecting baudrate" if self._state == self.STATE_CONNECTING: return "Connecting" if self._state == self.STATE_OPERATIONAL: @@ -243,7 +216,7 @@ class MachineCom(object): return self._gcodePos def getPrintTime(self): - return time.time() - self._printStartTime + return time.time() - self._printStartTime - self._heatupWaitTimeLost def isPaused(self): return self._state == self.STATE_PAUSED @@ -263,6 +236,49 @@ class MachineCom(object): return ret def _monitor(self): + #Open the serial port. + if self._port == 'AUTO': + self._changeState(self.STATE_DETECT_SERIAL) + programmer = stk500v2.Stk500v2() + self._log("Serial port list: %s" % (str(serialList()))) + for p in serialList(): + try: + self._log("Connecting to: %s" % (p)) + programmer.connect(p) + self._serial = programmer.leaveISP() + profile.putPreference('serial_port_auto', p) + break + except ispBase.IspError as (e): + self._log("Error while connecting to %s: %s" % (p, str(e))) + pass + except: + self._log("Unexpected error while connecting to serial port: %s %s" % (p, getExceptionString())) + programmer.close() + elif self._port == 'VIRTUAL': + self._changeState(self.STATE_OPEN_SERIAL) + self._serial = VirtualPrinter() + else: + self._changeState(self.STATE_OPEN_SERIAL) + try: + self._log("Connecting to: %s" % (self._port)) + if self._baudrate == 0: + self._serial = Serial(self._port, 115200, timeout=0.1, writeTimeout=10000) + else: + self._serial = Serial(self._port, self._baudrate, timeout=2, writeTimeout=10000) + except: + self._log("Unexpected error while connecting to serial port: %s %s" % (self._port, getExceptionString())) + if self._serial == None: + self._log("Failed to open serial port (%s)" % (self._port)) + self._errorValue = 'Failed to autodetect serial port.' + self._changeState(self.STATE_ERROR) + return + self._log("Connected to: %s, starting monitor" % (self._serial)) + if self._baudrate == 0: + self._changeState(self.STATE_DETECT_BAUDRATE) + else: + self._changeState(self.STATE_CONNECTING) + + #Start monitoring the serial port. timeout = time.time() + 5 tempRequestTimeout = timeout while True: @@ -280,12 +296,17 @@ class MachineCom(object): line = line.rstrip() + self._readline() self._errorValue = line self._changeState(self.STATE_ERROR) - if ' T:' in line: - self._temp = float(re.search("[0-9\.]*", line.split(' T:')[1]).group(0)) + if ' T:' in line or line.startswith('T:'): + self._temp = float(re.search("[0-9\.]*", line.split('T:')[1]).group(0)) if ' B:' in line: self._bedTemp = float(re.search("[0-9\.]*", line.split(' B:')[1]).group(0)) self._callback.mcTempUpdate(self._temp, self._bedTemp) - elif line.strip() != 'ok': + #If we are waiting for an M109 or M190 then measure the time we lost during heatup, so we can remove that time from our printing time estimate. + if not 'ok' in line and self._heatupWaitStartTime != 0: + t = time.time() + self._heatupWaitTimeLost = t - self._heatupWaitStartTime + self._heatupWaitStartTime = t + elif line.strip() != 'ok' and self.isOperational(): self._callback.mcMessage(line) if self._state == self.STATE_DETECT_BAUDRATE: @@ -387,6 +408,8 @@ class MachineCom(object): def _sendCommand(self, cmd): if self._serial == None: return + if 'M109' in cmd or 'M190' in cmd: + self._heatupWaitStartTime = time.time() self._log('Send: %s' % (cmd)) try: #TODO: This can throw a write timeout exception, but we do not want timeout on writes. Find a fix for this. -- 2.30.2