1 from __future__ import absolute_import
\r
4 import wx, os, platform, types, webbrowser, threading, time, re
\r
7 from gui import firmwareInstall
\r
8 from gui import toolbarUtil
\r
9 from gui import printWindow
\r
10 from util import machineCom
\r
11 from util import profile
\r
13 class InfoBox(wx.Panel):
\r
14 def __init__(self, parent):
\r
15 super(InfoBox, self).__init__(parent)
\r
16 self.SetBackgroundColour('#FFFF80')
\r
18 self.sizer = wx.GridBagSizer(5, 5)
\r
19 self.SetSizer(self.sizer)
\r
21 self.attentionBitmap = toolbarUtil.getBitmapImage('attention.png')
\r
22 self.errorBitmap = toolbarUtil.getBitmapImage('error.png')
\r
23 self.readyBitmap = toolbarUtil.getBitmapImage('ready.png')
\r
24 self.busyBitmap = [toolbarUtil.getBitmapImage('busy-0.png'), toolbarUtil.getBitmapImage('busy-1.png'), toolbarUtil.getBitmapImage('busy-2.png'), toolbarUtil.getBitmapImage('busy-3.png')]
\r
26 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
\r
27 self.text = wx.StaticText(self, -1, '')
\r
28 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
\r
29 self.sizer.Add(self.bitmap, pos=(0,0), flag=wx.ALL, border=5)
\r
30 self.sizer.Add(self.text, pos=(0,1), flag=wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER_VERTICAL, border=5)
\r
31 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
\r
32 self.sizer.AddGrowableCol(1)
\r
34 self.extraInfoButton.Show(False)
\r
36 self.extraInfoUrl = ''
\r
37 self.busyState = None
\r
38 self.timer = wx.Timer(self)
\r
39 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
\r
40 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
\r
41 self.timer.Start(100)
\r
43 def SetInfo(self, info):
\r
44 self.SetBackgroundColour('#FFFF80')
\r
45 self.text.SetLabel(info)
\r
46 self.extraInfoButton.Show(False)
\r
49 def SetError(self, info, extraInfoUrl):
\r
50 self.extraInfoUrl = extraInfoUrl
\r
51 self.SetBackgroundColour('#FF8080')
\r
52 self.text.SetLabel(info)
\r
53 self.extraInfoButton.Show(True)
\r
55 self.SetErrorIndicator()
\r
58 def SetAttention(self, info):
\r
59 self.SetBackgroundColour('#FFFF80')
\r
60 self.text.SetLabel(info)
\r
61 self.extraInfoButton.Show(False)
\r
62 self.SetAttentionIndicator()
\r
65 def SetBusyIndicator(self):
\r
67 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
69 def doBusyUpdate(self, e):
\r
70 if self.busyState == None:
\r
73 if self.busyState >= len(self.busyBitmap):
\r
75 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
77 def doExtraInfo(self, e):
\r
78 webbrowser.open(self.extraInfoUrl)
\r
80 def SetReadyIndicator(self):
\r
81 self.busyState = None
\r
82 self.bitmap.SetBitmap(self.readyBitmap)
\r
84 def SetErrorIndicator(self):
\r
85 self.busyState = None
\r
86 self.bitmap.SetBitmap(self.errorBitmap)
\r
88 def SetAttentionIndicator(self):
\r
89 self.busyState = None
\r
90 self.bitmap.SetBitmap(self.attentionBitmap)
\r
92 class InfoPage(wx.wizard.WizardPageSimple):
\r
93 def __init__(self, parent, title):
\r
94 wx.wizard.WizardPageSimple.__init__(self, parent)
\r
96 sizer = wx.GridBagSizer(5, 5)
\r
98 self.SetSizer(sizer)
\r
100 title = wx.StaticText(self, -1, title)
\r
101 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
\r
102 sizer.Add(title, pos=(0, 0), span=(1,2), flag=wx.ALIGN_CENTRE|wx.ALL)
\r
103 sizer.Add(wx.StaticLine(self, -1), pos=(1,0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
104 sizer.AddGrowableCol(1)
\r
108 def AddText(self,info):
\r
109 text = wx.StaticText(self, -1, info)
\r
110 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)
\r
114 def AddSeperator(self):
\r
115 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
118 def AddHiddenSeperator(self):
\r
121 def AddInfoBox(self):
\r
122 infoBox = InfoBox(self)
\r
123 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT|wx.EXPAND)
\r
127 def AddRadioButton(self, label, style = 0):
\r
128 radio = wx.RadioButton(self, -1, label, style=style)
\r
129 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
133 def AddCheckbox(self, label, checked = False):
\r
134 check = wx.CheckBox(self, -1)
\r
135 text = wx.StaticText(self, -1, label)
\r
136 check.SetValue(checked)
\r
137 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT|wx.RIGHT)
\r
138 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1,2), flag=wx.ALL)
\r
142 def AddButton(self, label):
\r
143 button = wx.Button(self, -1, label)
\r
144 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
148 def AddDualButton(self, label1, label2):
\r
149 button1 = wx.Button(self, -1, label1)
\r
150 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
\r
151 button2 = wx.Button(self, -1, label2)
\r
152 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
\r
154 return button1, button2
\r
156 def AddTextCtrl(self, value):
\r
157 ret = wx.TextCtrl(self, -1, value)
\r
158 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
162 def AddLabelTextCtrl(self, info, value):
\r
163 text = wx.StaticText(self, -1, info)
\r
164 ret = wx.TextCtrl(self, -1, value)
\r
165 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
166 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
170 def AddTextCtrlButton(self, value, buttonText):
\r
171 text = wx.TextCtrl(self, -1, value)
\r
172 button = wx.Button(self, -1, buttonText)
\r
173 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
174 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
176 return text, button
\r
178 def AddBitmap(self, bitmap):
\r
179 bitmap = wx.StaticBitmap(self, -1, bitmap)
\r
180 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)
\r
184 def AddCheckmark(self, label, bitmap):
\r
185 check = wx.StaticBitmap(self, -1, bitmap)
\r
186 text = wx.StaticText(self, -1, label)
\r
187 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT|wx.RIGHT)
\r
188 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1,1), flag=wx.ALL)
\r
192 def AllowNext(self):
\r
195 def StoreData(self):
\r
198 class FirstInfoPage(InfoPage):
\r
199 def __init__(self, parent):
\r
200 super(FirstInfoPage, self).__init__(parent, "First time run wizard")
\r
201 self.AddText('Welcome, and thanks for trying Cura!')
\r
202 self.AddSeperator()
\r
203 self.AddText('This wizard will help you with the following steps:')
\r
204 self.AddText('* Configure Cura for your machine')
\r
205 self.AddText('* Upgrade your firmware')
\r
206 self.AddText('* Check if your machine is working safely')
\r
207 #self.AddText('* Calibrate your machine')
\r
208 #self.AddText('* Do your first print')
\r
210 class RepRapInfoPage(InfoPage):
\r
211 def __init__(self, parent):
\r
212 super(RepRapInfoPage, self).__init__(parent, "RepRap information")
\r
213 self.AddText('RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
\r
214 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
\r
215 self.AddSeperator()
\r
216 self.AddText('You will have to manually install Marlin or Sprinter firmware.')
\r
217 self.AddSeperator()
\r
218 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')
\r
219 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')
\r
220 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')
\r
221 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')
\r
222 self.heatedBed = self.AddCheckbox('Heated bed')
\r
224 def StoreData(self):
\r
225 profile.putPreference('machine_width', self.machineWidth.GetValue())
\r
226 profile.putPreference('machine_depth', self.machineDepth.GetValue())
\r
227 profile.putPreference('machine_height', self.machineHeight.GetValue())
\r
228 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
\r
229 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
\r
230 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
\r
232 class MachineSelectPage(InfoPage):
\r
233 def __init__(self, parent):
\r
234 super(MachineSelectPage, self).__init__(parent, "Select your machine")
\r
235 self.AddText('What kind of machine do you have:')
\r
237 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)
\r
238 self.UltimakerRadio.SetValue(True)
\r
239 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
\r
240 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")
\r
241 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
\r
243 def OnUltimakerSelect(self, e):
\r
244 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
\r
246 def OnOtherSelect(self, e):
\r
247 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)
\r
249 def StoreData(self):
\r
250 if self.UltimakerRadio.GetValue():
\r
251 profile.putPreference('machine_width', '205')
\r
252 profile.putPreference('machine_depth', '205')
\r
253 profile.putPreference('machine_height', '200')
\r
254 profile.putPreference('machine_type', 'ultimaker')
\r
255 profile.putProfileSetting('nozzle_size', '0.4')
\r
257 profile.putPreference('machine_width', '80')
\r
258 profile.putPreference('machine_depth', '80')
\r
259 profile.putPreference('machine_height', '60')
\r
260 profile.putPreference('machine_type', 'reprap')
\r
261 profile.putPreference('startMode', 'Normal')
\r
262 profile.putProfileSetting('nozzle_size', '0.5')
\r
263 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
\r
265 class FirmwareUpgradePage(InfoPage):
\r
266 def __init__(self, parent):
\r
267 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
\r
268 self.AddText('Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the step motors, regulates the temperature\nand ultimately makes your printer work.')
\r
269 self.AddHiddenSeperator()
\r
270 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
\r
271 self.AddHiddenSeperator()
\r
272 self.AddText('Cura requires these new features and thus\nyour firmware will most likely need to be upgraded.\nYou will get the chance to do so now.')
\r
273 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
\r
274 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
\r
275 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
276 self.AddHiddenSeperator()
\r
277 self.AddText('Do not upgrade to this firmware if:')
\r
278 self.AddText('* You have an older machine based on ATMega1280')
\r
279 self.AddText('* Have other changes in the firmware')
\r
280 button = self.AddButton('Goto this page for a custom firmware')
\r
281 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
\r
283 def AllowNext(self):
\r
286 def OnUpgradeClick(self, e):
\r
287 if firmwareInstall.InstallFirmware():
\r
288 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
290 def OnSkipClick(self, e):
\r
291 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
293 def OnUrlClick(self, e):
\r
294 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
\r
296 class UltimakerCheckupPage(InfoPage):
\r
297 def __init__(self, parent):
\r
298 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
\r
300 self.checkBitmap = toolbarUtil.getBitmapImage('checkmark.png')
\r
301 self.crossBitmap = toolbarUtil.getBitmapImage('cross.png')
\r
302 self.unknownBitmap = toolbarUtil.getBitmapImage('question.png')
\r
303 self.endStopNoneBitmap = toolbarUtil.getBitmapImage('endstop_none.png')
\r
304 self.endStopXMinBitmap = toolbarUtil.getBitmapImage('endstop_xmin.png')
\r
305 self.endStopXMaxBitmap = toolbarUtil.getBitmapImage('endstop_xmax.png')
\r
306 self.endStopYMinBitmap = toolbarUtil.getBitmapImage('endstop_ymin.png')
\r
307 self.endStopYMaxBitmap = toolbarUtil.getBitmapImage('endstop_ymax.png')
\r
308 self.endStopZMinBitmap = toolbarUtil.getBitmapImage('endstop_zmin.png')
\r
309 self.endStopZMaxBitmap = toolbarUtil.getBitmapImage('endstop_zmax.png')
\r
311 self.AddText('It is a good idea to do a few sanity checks now on your Ultimaker.\nYou can skip these if you know your machine is functional.')
\r
312 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
\r
313 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
\r
314 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
315 self.AddSeperator()
\r
316 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
\r
317 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
\r
318 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
\r
319 self.AddSeperator()
\r
320 self.infoBox = self.AddInfoBox()
\r
321 self.machineState = self.AddText('')
\r
322 self.temperatureLabel = self.AddText('')
\r
323 self.errorLogButton = self.AddButton('Show error log')
\r
324 self.errorLogButton.Show(False)
\r
325 self.AddSeperator()
\r
326 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
\r
328 self.xMinStop = False
\r
329 self.xMaxStop = False
\r
330 self.yMinStop = False
\r
331 self.yMaxStop = False
\r
332 self.zMinStop = False
\r
333 self.zMaxStop = False
\r
335 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
\r
338 if self.comm != None:
\r
341 def AllowNext(self):
\r
342 self.endstopBitmap.Show(False)
\r
345 def OnSkipClick(self, e):
\r
346 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
348 def OnCheckClick(self, e = None):
\r
349 self.errorLogButton.Show(False)
\r
350 if self.comm != None:
\r
354 wx.CallAfter(self.OnCheckClick)
\r
356 self.infoBox.SetInfo('Connecting to machine.')
\r
357 self.infoBox.SetBusyIndicator()
\r
358 self.commState.SetBitmap(self.unknownBitmap)
\r
359 self.tempState.SetBitmap(self.unknownBitmap)
\r
360 self.stopState.SetBitmap(self.unknownBitmap)
\r
361 self.checkupState = 0
\r
362 self.comm = machineCom.MachineCom(callbackObject=self)
\r
364 def OnErrorLog(self, e):
\r
365 printWindow.LogWindow('\n'.join(self.comm.getLog()))
\r
367 def mcLog(self, message):
\r
370 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
\r
371 if not self.comm.isOperational():
\r
373 if self.checkupState == 0:
\r
374 self.tempCheckTimeout = 20
\r
376 self.checkupState = 1
\r
377 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
\r
378 self.comm.sendCommand('M104 S0')
\r
379 self.comm.sendCommand('M104 S0')
\r
381 self.startTemp = temp
\r
382 self.checkupState = 2
\r
383 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
384 self.comm.sendCommand('M104 S200')
\r
385 self.comm.sendCommand('M104 S200')
\r
386 elif self.checkupState == 1:
\r
388 self.startTemp = temp
\r
389 self.checkupState = 2
\r
390 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
391 self.comm.sendCommand('M104 S200')
\r
392 self.comm.sendCommand('M104 S200')
\r
393 elif self.checkupState == 2:
\r
394 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
\r
395 if temp > self.startTemp + 40:
\r
396 self.checkupState = 3
\r
397 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
\r
398 wx.CallAfter(self.endstopBitmap.Show, True)
\r
399 wx.CallAfter(self.Layout)
\r
400 self.comm.sendCommand('M104 S0')
\r
401 self.comm.sendCommand('M104 S0')
\r
402 self.comm.sendCommand('M119')
\r
403 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
\r
405 self.tempCheckTimeout -= 1
\r
406 if self.tempCheckTimeout < 1:
\r
407 self.checkupState = -1
\r
408 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
\r
409 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura/Temperature_measurement_problems')
\r
410 self.comm.sendCommand('M104 S0')
\r
411 self.comm.sendCommand('M104 S0')
\r
412 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp))
\r
414 def mcStateChange(self, state):
\r
415 if self.comm == None:
\r
417 if self.comm.isOperational():
\r
418 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
\r
419 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
420 elif self.comm.isError():
\r
421 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
\r
422 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura/Connection_problems')
\r
423 wx.CallAfter(self.endstopBitmap.Show, False)
\r
424 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
\r
425 wx.CallAfter(self.errorLogButton.Show, True)
\r
426 wx.CallAfter(self.Layout)
\r
428 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
430 def mcMessage(self, message):
\r
431 if self.checkupState >= 3 and self.checkupState < 10 and 'x_min' in message:
\r
432 for data in message.split(' '):
\r
434 tag, value = data.split(':', 2)
\r
436 self.xMinStop = (value == 'H')
\r
438 self.xMaxStop = (value == 'H')
\r
440 self.yMinStop = (value == 'H')
\r
442 self.yMaxStop = (value == 'H')
\r
444 self.zMinStop = (value == 'H')
\r
446 self.zMaxStop = (value == 'H')
\r
447 self.comm.sendCommand('M119')
\r
449 if self.checkupState == 3:
\r
450 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
451 self.checkupState = 4
\r
452 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
\r
453 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
\r
454 elif self.checkupState == 4:
\r
455 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
456 self.checkupState = 5
\r
457 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
\r
458 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
\r
459 elif self.checkupState == 5:
\r
460 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
461 self.checkupState = 6
\r
462 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
\r
463 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
\r
464 elif self.checkupState == 6:
\r
465 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
466 self.checkupState = 7
\r
467 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
\r
468 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
\r
469 elif self.checkupState == 7:
\r
470 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
471 self.checkupState = 8
\r
472 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
\r
473 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
\r
474 elif self.checkupState == 8:
\r
475 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
\r
476 self.checkupState = 9
\r
477 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
\r
478 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
\r
479 elif self.checkupState == 9:
\r
480 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
\r
481 self.checkupState = 10
\r
483 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
\r
484 wx.CallAfter(self.infoBox.SetReadyIndicator)
\r
485 wx.CallAfter(self.endstopBitmap.Show, False)
\r
486 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
\r
487 wx.CallAfter(self.OnSkipClick, None)
\r
489 def mcProgress(self, lineNr):
\r
492 def mcZChange(self, newZ):
\r
495 class UltimakerCalibrationPage(InfoPage):
\r
496 def __init__(self, parent):
\r
497 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
\r
499 self.AddText("Your Ultimaker requires some calibration.")
\r
500 self.AddText("This calibration is needed for a proper extrusion amount.")
\r
501 self.AddSeperator()
\r
502 self.AddText("The following values are needed:")
\r
503 self.AddText("* Diameter of filament")
\r
504 self.AddText("* Number of steps per mm of filament extrusion")
\r
505 self.AddSeperator()
\r
506 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
\r
507 self.AddSeperator()
\r
508 self.AddText("First we need the diameter of your filament:")
\r
509 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
\r
510 self.AddText("If you do not own digital Calipers that can measure\nat least 2 digits then use 2.89mm.\nWhich is the average diameter of most filament.")
\r
511 self.AddText("Note: This value can be changed later at any time.")
\r
513 def StoreData(self):
\r
514 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
\r
516 class UltimakerCalibrateStepsPerEPage(InfoPage):
\r
517 def __init__(self, parent):
\r
518 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
\r
520 if profile.getPreference('steps_per_e') == '0':
\r
521 profile.putPreference('steps_per_e', '865.888')
\r
523 self.AddText("Calibrating the Steps Per E requires some manual actions.")
\r
524 self.AddText("First remove any filament from your machine.")
\r
525 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
\r
526 self.AddText("We'll push the filament 100mm")
\r
527 self.extrudeButton = self.AddButton("Extrude 100mm filament")
\r
528 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
\r
529 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
\r
530 self.AddText("This results in the following steps per E:")
\r
531 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
\r
532 self.AddText("You can repeat these steps to get better calibration.")
\r
533 self.AddSeperator()
\r
534 self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
\r
535 self.heatButton = self.AddButton("Heatup for filament removal")
\r
537 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
\r
538 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
\r
539 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
\r
541 def OnSaveLengthClick(self, e):
\r
542 currentEValue = float(self.stepsPerEInput.GetValue())
\r
543 realExtrudeLength = float(self.lengthInput.GetValue())
\r
544 newEValue = currentEValue * 100 / realExtrudeLength
\r
545 self.stepsPerEInput.SetValue(str(newEValue))
\r
546 self.lengthInput.SetValue("100")
\r
548 def OnExtrudeClick(self, e):
\r
549 threading.Thread(target=self.OnExtrudeRun).start()
\r
551 def OnExtrudeRun(self):
\r
552 self.heatButton.Enable(False)
\r
553 self.extrudeButton.Enable(False)
\r
554 currentEValue = float(self.stepsPerEInput.GetValue())
\r
555 self.comm = machineCom.MachineCom()
\r
556 if not self.comm.isOpen():
\r
557 wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
558 self.heatButton.Enable(True)
\r
559 self.extrudeButton.Enable(True)
\r
562 line = self.comm.readline()
\r
565 if 'start' in line:
\r
567 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
\r
570 self.sendGCommand('M302') #Disable cold extrusion protection
\r
571 self.sendGCommand("M92 E%f" % (currentEValue))
\r
572 self.sendGCommand("G92 E0")
\r
573 self.sendGCommand("G1 E100 F600")
\r
576 self.extrudeButton.Enable()
\r
577 self.heatButton.Enable()
\r
579 def OnHeatClick(self, e):
\r
580 threading.Thread(target=self.OnHeatRun).start()
\r
582 def OnHeatRun(self):
\r
583 self.heatButton.Enable(False)
\r
584 self.extrudeButton.Enable(False)
\r
585 self.comm = machineCom.MachineCom()
\r
586 if not self.comm.isOpen():
\r
587 wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
588 self.heatButton.Enable(True)
\r
589 self.extrudeButton.Enable(True)
\r
592 line = self.comm.readline()
\r
594 self.heatButton.Enable(True)
\r
595 self.extrudeButton.Enable(True)
\r
597 if 'start' in line:
\r
599 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
\r
602 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
\r
603 wx.MessageBox('Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)', 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
\r
604 self.sendGCommand('M104 S0')
\r
607 self.heatButton.Enable(True)
\r
608 self.extrudeButton.Enable(True)
\r
610 def sendGCommand(self, cmd):
\r
611 self.comm.sendCommand(cmd) #Disable cold extrusion protection
\r
613 line = self.comm.readline()
\r
616 if line.startswith('ok'):
\r
619 def StoreData(self):
\r
620 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
\r
622 class configWizard(wx.wizard.Wizard):
\r
623 def __init__(self):
\r
624 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
\r
626 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
\r
627 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
\r
629 self.firstInfoPage = FirstInfoPage(self)
\r
630 self.machineSelectPage = MachineSelectPage(self)
\r
631 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
\r
632 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
\r
633 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
\r
634 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
\r
635 self.repRapInfoPage = RepRapInfoPage(self)
\r
637 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
\r
638 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerFirmwareUpgradePage)
\r
639 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
\r
640 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
\r
641 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
\r
643 self.FitToPage(self.firstInfoPage)
\r
644 self.GetPageAreaSizer().Add(self.firstInfoPage)
\r
646 self.RunWizard(self.firstInfoPage)
\r
649 def OnPageChanging(self, e):
\r
650 e.GetPage().StoreData()
\r
652 def OnPageChanged(self, e):
\r
653 if e.GetPage().AllowNext():
\r
654 self.FindWindowById(wx.ID_FORWARD).Enable()
\r
656 self.FindWindowById(wx.ID_FORWARD).Disable()
\r
657 self.FindWindowById(wx.ID_BACKWARD).Disable()
\r