self.cancelButton.Enable(self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused()))\r
self.temperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational())\r
self.bedTemperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational())\r
- self.directControlPanel.Enable(self.machineCom != None and self.machineCom.isOperational())\r
+ self.directControlPanel.Enable(self.machineCom != None and self.machineCom.isOperational() and not self.machineCom.isPrinting())\r
self.machineLogButton.Show(self.machineCom != None and self.machineCom.isError())\r
\r
def UpdateProgress(self):\r
printTime = self.machineCom.getPrintTime() / 60\r
printTimeTotal = printTime * len(self.gcodeList) / self.machineCom.getPrintPos()\r
printTimeLeft = printTimeTotal - printTime\r
- status += 'Line: %d/%d\n' % (self.machineCom.getPrintPos(), len(self.gcodeList))\r
- status += 'Height: %f\n' % (self.currentZ)\r
+ status += 'Line: %d/%d %d%%\n' % (self.machineCom.getPrintPos(), len(self.gcodeList), self.machineCom.getPrintPos() * 100 / len(self.gcodeList))\r
+ if self.currentZ > 0:\r
+ status += 'Height: %0.1f\n' % (self.currentZ)\r
status += 'Print time: %02d:%02d\n' % (int(printTime / 60), int(printTime % 60))\r
status += 'Print time left: %02d:%02d\n' % (int(printTimeLeft / 60), int(printTimeLeft % 60))\r
self.progress.SetValue(self.machineCom.getPrintPos())\r
dc.SelectObject(self.backBuffer)\r
dc.Clear()\r
w, h = self.GetSizeTuple()\r
- x0 = 0\r
- t0 = 0\r
- bt0 = 0\r
- tSP0 = 0\r
- btSP0 = 0\r
bgLinePen = wx.Pen('#A0A0A0')\r
tempPen = wx.Pen('#FF4040')\r
tempSPPen = wx.Pen('#FFA0A0')\r
bedTempPen = wx.Pen('#4040FF')\r
bedTempSPPen = wx.Pen('#A0A0FF')\r
bedTempPenBG = wx.Pen('#D0D0FF')\r
+\r
+ x0 = 0\r
+ t0 = 0\r
+ bt0 = 0\r
+ tSP0 = 0\r
+ btSP0 = 0\r
+ for temp, tempSP, bedTemp, bedTempSP, t in self.points:\r
+ x1 = int(w - (now - t))\r
+ for x in xrange(x0, x1 + 1):\r
+ t = float(x - x0) / float(x1 - x0 + 1) * (temp - t0) + t0\r
+ bt = float(x - x0) / float(x1 - x0 + 1) * (bedTemp - bt0) + bt0\r
+ dc.SetPen(tempPenBG)\r
+ dc.DrawLine(x, h, x, h - (t * h / 300))\r
+ dc.SetPen(bedTempPenBG)\r
+ dc.DrawLine(x, h, x, h - (bt * h / 300))\r
+ t0 = temp\r
+ bt0 = bedTemp\r
+ tSP0 = tempSP\r
+ btSP0 = bedTempSP\r
+ x0 = x1 + 1\r
+\r
+ #Draw the grid\r
for x in xrange(w, 0, -30):\r
dc.SetPen(bgLinePen)\r
dc.DrawLine(x, 0, x, h)\r
dc.DrawLine(0, 0, w, 0)\r
dc.DrawLine(0, 0, 0, h)\r
\r
+ x0 = 0\r
+ t0 = 0\r
+ bt0 = 0\r
+ tSP0 = 0\r
+ btSP0 = 0\r
for temp, tempSP, bedTemp, bedTempSP, t in self.points:\r
x1 = int(w - (now - t))\r
for x in xrange(x0, x1 + 1):\r
bt = float(x - x0) / float(x1 - x0 + 1) * (bedTemp - bt0) + bt0\r
tSP = float(x - x0) / float(x1 - x0 + 1) * (tempSP - tSP0) + tSP0\r
btSP = float(x - x0) / float(x1 - x0 + 1) * (bedTempSP - btSP0) + btSP0\r
- dc.SetPen(tempPenBG)\r
- dc.DrawLine(x, h, x, h - (t * h / 300))\r
- dc.SetPen(bedTempPenBG)\r
- dc.DrawLine(x, h, x, h - (bt * h / 300))\r
dc.SetPen(tempSPPen)\r
dc.DrawPoint(x, h - (tSP * h / 300))\r
dc.SetPen(bedTempSPPen)\r
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:
if callbackObject == None:
callbackObject = MachineComPrintCallback()
+ self._port = port
+ self._baudrate = baudrate
self._callback = callbackObject
self._state = self.STATE_NONE
self._serial = None
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()
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:
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
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:
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:
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.