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 SelectParts(InfoPage):
\r
266 def __init__(self, parent):
\r
267 super(SelectParts, self).__init__(parent, "Select upgraded parts you have")
\r
268 self.AddText('To assist you in having better default settings for your Ultimaker\nCura would like to know which upgrades you have in your machine.')
\r
269 self.AddSeperator()
\r
270 self.springExtruder = self.AddCheckbox('Extruder drive upgrade')
\r
271 self.heatedBed = self.AddCheckbox('Heated printer bed (self build)')
\r
272 self.dualExtrusion = self.AddCheckbox('Dual extrusion (experimental)')
\r
273 self.AddSeperator()
\r
274 self.AddText('If you have an Ultimaker bought after october 2012 you will have the\nExtruder drive upgrade. If you do not have this upgrade,\nit is highly recommended to improve reliablity.')
\r
275 self.AddText('This upgrade can be bought from the Ultimaker webshop shop\nor found on thingiverse as thing:26094')
\r
276 self.springExtruder.SetValue(True)
\r
278 def StoreData(self):
\r
279 profile.putPreference('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
\r
280 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
\r
281 if self.dualExtrusion.GetValue():
\r
282 profile.putPreference('extruder_amount', '2')
\r
283 if getPreference('ultimaker_extruder_upgrade') == 'True':
\r
284 putProfileSetting('retraction_enable', 'True')
\r
286 class FirmwareUpgradePage(InfoPage):
\r
287 def __init__(self, parent):
\r
288 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
\r
289 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
290 self.AddHiddenSeperator()
\r
291 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
\r
292 self.AddHiddenSeperator()
\r
293 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
294 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
\r
295 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
\r
296 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
297 self.AddHiddenSeperator()
\r
298 self.AddText('Do not upgrade to this firmware if:')
\r
299 self.AddText('* You have an older machine based on ATMega1280')
\r
300 self.AddText('* Have other changes in the firmware')
\r
301 button = self.AddButton('Goto this page for a custom firmware')
\r
302 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
\r
304 def AllowNext(self):
\r
307 def OnUpgradeClick(self, e):
\r
308 if firmwareInstall.InstallFirmware():
\r
309 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
311 def OnSkipClick(self, e):
\r
312 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
314 def OnUrlClick(self, e):
\r
315 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
\r
317 class UltimakerCheckupPage(InfoPage):
\r
318 def __init__(self, parent):
\r
319 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
\r
321 self.checkBitmap = toolbarUtil.getBitmapImage('checkmark.png')
\r
322 self.crossBitmap = toolbarUtil.getBitmapImage('cross.png')
\r
323 self.unknownBitmap = toolbarUtil.getBitmapImage('question.png')
\r
324 self.endStopNoneBitmap = toolbarUtil.getBitmapImage('endstop_none.png')
\r
325 self.endStopXMinBitmap = toolbarUtil.getBitmapImage('endstop_xmin.png')
\r
326 self.endStopXMaxBitmap = toolbarUtil.getBitmapImage('endstop_xmax.png')
\r
327 self.endStopYMinBitmap = toolbarUtil.getBitmapImage('endstop_ymin.png')
\r
328 self.endStopYMaxBitmap = toolbarUtil.getBitmapImage('endstop_ymax.png')
\r
329 self.endStopZMinBitmap = toolbarUtil.getBitmapImage('endstop_zmin.png')
\r
330 self.endStopZMaxBitmap = toolbarUtil.getBitmapImage('endstop_zmax.png')
\r
332 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
333 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
\r
334 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
\r
335 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
336 self.AddSeperator()
\r
337 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
\r
338 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
\r
339 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
\r
340 self.AddSeperator()
\r
341 self.infoBox = self.AddInfoBox()
\r
342 self.machineState = self.AddText('')
\r
343 self.temperatureLabel = self.AddText('')
\r
344 self.errorLogButton = self.AddButton('Show error log')
\r
345 self.errorLogButton.Show(False)
\r
346 self.AddSeperator()
\r
347 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
\r
349 self.xMinStop = False
\r
350 self.xMaxStop = False
\r
351 self.yMinStop = False
\r
352 self.yMaxStop = False
\r
353 self.zMinStop = False
\r
354 self.zMaxStop = False
\r
356 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
\r
359 if self.comm != None:
\r
362 def AllowNext(self):
\r
363 self.endstopBitmap.Show(False)
\r
366 def OnSkipClick(self, e):
\r
367 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
369 def OnCheckClick(self, e = None):
\r
370 self.errorLogButton.Show(False)
\r
371 if self.comm != None:
\r
375 wx.CallAfter(self.OnCheckClick)
\r
377 self.infoBox.SetInfo('Connecting to machine.')
\r
378 self.infoBox.SetBusyIndicator()
\r
379 self.commState.SetBitmap(self.unknownBitmap)
\r
380 self.tempState.SetBitmap(self.unknownBitmap)
\r
381 self.stopState.SetBitmap(self.unknownBitmap)
\r
382 self.checkupState = 0
\r
383 self.comm = machineCom.MachineCom(callbackObject=self)
\r
385 def OnErrorLog(self, e):
\r
386 printWindow.LogWindow('\n'.join(self.comm.getLog()))
\r
388 def mcLog(self, message):
\r
391 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
\r
392 if not self.comm.isOperational():
\r
394 if self.checkupState == 0:
\r
395 self.tempCheckTimeout = 20
\r
397 self.checkupState = 1
\r
398 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
\r
399 self.comm.sendCommand('M104 S0')
\r
400 self.comm.sendCommand('M104 S0')
\r
402 self.startTemp = temp
\r
403 self.checkupState = 2
\r
404 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
405 self.comm.sendCommand('M104 S200')
\r
406 self.comm.sendCommand('M104 S200')
\r
407 elif self.checkupState == 1:
\r
409 self.startTemp = temp
\r
410 self.checkupState = 2
\r
411 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
412 self.comm.sendCommand('M104 S200')
\r
413 self.comm.sendCommand('M104 S200')
\r
414 elif self.checkupState == 2:
\r
415 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
\r
416 if temp > self.startTemp + 40:
\r
417 self.checkupState = 3
\r
418 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
\r
419 wx.CallAfter(self.endstopBitmap.Show, True)
\r
420 wx.CallAfter(self.Layout)
\r
421 self.comm.sendCommand('M104 S0')
\r
422 self.comm.sendCommand('M104 S0')
\r
423 self.comm.sendCommand('M119')
\r
424 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
\r
426 self.tempCheckTimeout -= 1
\r
427 if self.tempCheckTimeout < 1:
\r
428 self.checkupState = -1
\r
429 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
\r
430 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura/Temperature_measurement_problems')
\r
431 self.comm.sendCommand('M104 S0')
\r
432 self.comm.sendCommand('M104 S0')
\r
433 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp))
\r
435 def mcStateChange(self, state):
\r
436 if self.comm == None:
\r
438 if self.comm.isOperational():
\r
439 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
\r
440 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
441 elif self.comm.isError():
\r
442 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
\r
443 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura/Connection_problems')
\r
444 wx.CallAfter(self.endstopBitmap.Show, False)
\r
445 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
\r
446 wx.CallAfter(self.errorLogButton.Show, True)
\r
447 wx.CallAfter(self.Layout)
\r
449 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
451 def mcMessage(self, message):
\r
452 if self.checkupState >= 3 and self.checkupState < 10 and 'x_min' in message:
\r
453 for data in message.split(' '):
\r
455 tag, value = data.split(':', 2)
\r
457 self.xMinStop = (value == 'H')
\r
459 self.xMaxStop = (value == 'H')
\r
461 self.yMinStop = (value == 'H')
\r
463 self.yMaxStop = (value == 'H')
\r
465 self.zMinStop = (value == 'H')
\r
467 self.zMaxStop = (value == 'H')
\r
468 self.comm.sendCommand('M119')
\r
470 if self.checkupState == 3:
\r
471 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
472 self.checkupState = 4
\r
473 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
\r
474 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
\r
475 elif self.checkupState == 4:
\r
476 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
477 self.checkupState = 5
\r
478 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
\r
479 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
\r
480 elif self.checkupState == 5:
\r
481 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
482 self.checkupState = 6
\r
483 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
\r
484 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
\r
485 elif self.checkupState == 6:
\r
486 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
487 self.checkupState = 7
\r
488 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
\r
489 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
\r
490 elif self.checkupState == 7:
\r
491 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
492 self.checkupState = 8
\r
493 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
\r
494 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
\r
495 elif self.checkupState == 8:
\r
496 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
\r
497 self.checkupState = 9
\r
498 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
\r
499 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
\r
500 elif self.checkupState == 9:
\r
501 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
\r
502 self.checkupState = 10
\r
504 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
\r
505 wx.CallAfter(self.infoBox.SetReadyIndicator)
\r
506 wx.CallAfter(self.endstopBitmap.Show, False)
\r
507 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
\r
508 wx.CallAfter(self.OnSkipClick, None)
\r
510 def mcProgress(self, lineNr):
\r
513 def mcZChange(self, newZ):
\r
516 class UltimakerCalibrationPage(InfoPage):
\r
517 def __init__(self, parent):
\r
518 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
\r
520 self.AddText("Your Ultimaker requires some calibration.")
\r
521 self.AddText("This calibration is needed for a proper extrusion amount.")
\r
522 self.AddSeperator()
\r
523 self.AddText("The following values are needed:")
\r
524 self.AddText("* Diameter of filament")
\r
525 self.AddText("* Number of steps per mm of filament extrusion")
\r
526 self.AddSeperator()
\r
527 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
\r
528 self.AddSeperator()
\r
529 self.AddText("First we need the diameter of your filament:")
\r
530 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
\r
531 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
532 self.AddText("Note: This value can be changed later at any time.")
\r
534 def StoreData(self):
\r
535 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
\r
537 class UltimakerCalibrateStepsPerEPage(InfoPage):
\r
538 def __init__(self, parent):
\r
539 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
\r
541 if profile.getPreference('steps_per_e') == '0':
\r
542 profile.putPreference('steps_per_e', '865.888')
\r
544 self.AddText("Calibrating the Steps Per E requires some manual actions.")
\r
545 self.AddText("First remove any filament from your machine.")
\r
546 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
\r
547 self.AddText("We'll push the filament 100mm")
\r
548 self.extrudeButton = self.AddButton("Extrude 100mm filament")
\r
549 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
\r
550 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
\r
551 self.AddText("This results in the following steps per E:")
\r
552 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
\r
553 self.AddText("You can repeat these steps to get better calibration.")
\r
554 self.AddSeperator()
\r
555 self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
\r
556 self.heatButton = self.AddButton("Heatup for filament removal")
\r
558 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
\r
559 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
\r
560 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
\r
562 def OnSaveLengthClick(self, e):
\r
563 currentEValue = float(self.stepsPerEInput.GetValue())
\r
564 realExtrudeLength = float(self.lengthInput.GetValue())
\r
565 newEValue = currentEValue * 100 / realExtrudeLength
\r
566 self.stepsPerEInput.SetValue(str(newEValue))
\r
567 self.lengthInput.SetValue("100")
\r
569 def OnExtrudeClick(self, e):
\r
570 threading.Thread(target=self.OnExtrudeRun).start()
\r
572 def OnExtrudeRun(self):
\r
573 self.heatButton.Enable(False)
\r
574 self.extrudeButton.Enable(False)
\r
575 currentEValue = float(self.stepsPerEInput.GetValue())
\r
576 self.comm = machineCom.MachineCom()
\r
577 if not self.comm.isOpen():
\r
578 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
579 self.heatButton.Enable(True)
\r
580 self.extrudeButton.Enable(True)
\r
583 line = self.comm.readline()
\r
586 if 'start' in line:
\r
588 #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
591 self.sendGCommand('M302') #Disable cold extrusion protection
\r
592 self.sendGCommand("M92 E%f" % (currentEValue))
\r
593 self.sendGCommand("G92 E0")
\r
594 self.sendGCommand("G1 E100 F600")
\r
597 self.extrudeButton.Enable()
\r
598 self.heatButton.Enable()
\r
600 def OnHeatClick(self, e):
\r
601 threading.Thread(target=self.OnHeatRun).start()
\r
603 def OnHeatRun(self):
\r
604 self.heatButton.Enable(False)
\r
605 self.extrudeButton.Enable(False)
\r
606 self.comm = machineCom.MachineCom()
\r
607 if not self.comm.isOpen():
\r
608 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
609 self.heatButton.Enable(True)
\r
610 self.extrudeButton.Enable(True)
\r
613 line = self.comm.readline()
\r
615 self.heatButton.Enable(True)
\r
616 self.extrudeButton.Enable(True)
\r
618 if 'start' in line:
\r
620 #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
623 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
\r
624 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
625 self.sendGCommand('M104 S0')
\r
628 self.heatButton.Enable(True)
\r
629 self.extrudeButton.Enable(True)
\r
631 def sendGCommand(self, cmd):
\r
632 self.comm.sendCommand(cmd) #Disable cold extrusion protection
\r
634 line = self.comm.readline()
\r
637 if line.startswith('ok'):
\r
640 def StoreData(self):
\r
641 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
\r
643 class configWizard(wx.wizard.Wizard):
\r
644 def __init__(self):
\r
645 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
\r
647 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
\r
648 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
\r
650 self.firstInfoPage = FirstInfoPage(self)
\r
651 self.machineSelectPage = MachineSelectPage(self)
\r
652 self.ultimakerSelectParts = SelectParts(self)
\r
653 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
\r
654 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
\r
655 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
\r
656 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
\r
657 self.repRapInfoPage = RepRapInfoPage(self)
\r
659 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
\r
660 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
\r
661 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
\r
662 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
\r
663 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
\r
664 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
\r
666 self.FitToPage(self.firstInfoPage)
\r
667 self.GetPageAreaSizer().Add(self.firstInfoPage)
\r
669 self.RunWizard(self.firstInfoPage)
\r
672 def OnPageChanging(self, e):
\r
673 e.GetPage().StoreData()
\r
675 def OnPageChanged(self, e):
\r
676 if e.GetPage().AllowNext():
\r
677 self.FindWindowById(wx.ID_FORWARD).Enable()
\r
679 self.FindWindowById(wx.ID_FORWARD).Disable()
\r
680 self.FindWindowById(wx.ID_BACKWARD).Disable()
\r