2 from __future__ import absolute_import
\r
11 from gui import firmwareInstall
\r
12 from gui import toolbarUtil
\r
13 from gui import printWindow
\r
14 from util import machineCom
\r
15 from util import profile
\r
16 from util.resources import getPathForImage
\r
18 class InfoBox(wx.Panel):
\r
19 def __init__(self, parent):
\r
20 super(InfoBox, self).__init__(parent)
\r
21 self.SetBackgroundColour('#FFFF80')
\r
23 self.sizer = wx.GridBagSizer(5, 5)
\r
24 self.SetSizer(self.sizer)
\r
26 self.attentionBitmap = wx.Bitmap(getPathForImage('attention.png'))
\r
27 self.errorBitmap = wx.Bitmap(getPathForImage('error.png'))
\r
28 self.readyBitmap = wx.Bitmap(getPathForImage('ready.png'))
\r
30 wx.Bitmap(getPathForImage('busy-0.png')),
\r
31 wx.Bitmap(getPathForImage('busy-1.png')),
\r
32 wx.Bitmap(getPathForImage('busy-2.png')),
\r
33 wx.Bitmap(getPathForImage('busy-3.png'))
\r
36 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
\r
37 self.text = wx.StaticText(self, -1, '')
\r
38 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
\r
39 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
\r
40 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
\r
41 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
\r
42 self.sizer.AddGrowableCol(1)
\r
44 self.extraInfoButton.Show(False)
\r
46 self.extraInfoUrl = ''
\r
47 self.busyState = None
\r
48 self.timer = wx.Timer(self)
\r
49 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
\r
50 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
\r
51 self.timer.Start(100)
\r
53 def SetInfo(self, info):
\r
54 self.SetBackgroundColour('#FFFF80')
\r
55 self.text.SetLabel(info)
\r
56 self.extraInfoButton.Show(False)
\r
59 def SetError(self, info, extraInfoUrl):
\r
60 self.extraInfoUrl = extraInfoUrl
\r
61 self.SetBackgroundColour('#FF8080')
\r
62 self.text.SetLabel(info)
\r
63 self.extraInfoButton.Show(True)
\r
65 self.SetErrorIndicator()
\r
68 def SetAttention(self, info):
\r
69 self.SetBackgroundColour('#FFFF80')
\r
70 self.text.SetLabel(info)
\r
71 self.extraInfoButton.Show(False)
\r
72 self.SetAttentionIndicator()
\r
75 def SetBusyIndicator(self):
\r
77 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
79 def doExtraInfo(self, e):
\r
80 webbrowser.open(self.extraInfoUrl)
\r
82 def doBusyUpdate(self, e):
\r
83 if self.busyState == None:
\r
86 if self.busyState >= len(self.busyBitmap):
\r
88 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
90 def SetReadyIndicator(self):
\r
91 self.busyState = None
\r
92 self.bitmap.SetBitmap(self.readyBitmap)
\r
94 def SetErrorIndicator(self):
\r
95 self.busyState = None
\r
96 self.bitmap.SetBitmap(self.errorBitmap)
\r
98 def SetAttentionIndicator(self):
\r
99 self.busyState = None
\r
100 self.bitmap.SetBitmap(self.attentionBitmap)
\r
103 class InfoPage(wx.wizard.WizardPageSimple):
\r
104 def __init__(self, parent, title):
\r
105 wx.wizard.WizardPageSimple.__init__(self, parent)
\r
107 sizer = wx.GridBagSizer(5, 5)
\r
109 self.SetSizer(sizer)
\r
111 title = wx.StaticText(self, -1, title)
\r
112 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
\r
113 sizer.Add(title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
\r
114 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
\r
115 sizer.AddGrowableCol(1)
\r
119 def AddText(self, info):
\r
120 text = wx.StaticText(self, -1, info)
\r
121 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
\r
125 def AddSeperator(self):
\r
126 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
\r
129 def AddHiddenSeperator(self):
\r
132 def AddInfoBox(self):
\r
133 infoBox = InfoBox(self)
\r
134 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
\r
138 def AddRadioButton(self, label, style=0):
\r
139 radio = wx.RadioButton(self, -1, label, style=style)
\r
140 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
\r
144 def AddCheckbox(self, label, checked=False):
\r
145 check = wx.CheckBox(self, -1)
\r
146 text = wx.StaticText(self, -1, label)
\r
147 check.SetValue(checked)
\r
148 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
\r
149 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
\r
153 def AddButton(self, label):
\r
154 button = wx.Button(self, -1, label)
\r
155 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
\r
159 def AddDualButton(self, label1, label2):
\r
160 button1 = wx.Button(self, -1, label1)
\r
161 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
\r
162 button2 = wx.Button(self, -1, label2)
\r
163 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
\r
165 return button1, button2
\r
167 def AddTextCtrl(self, value):
\r
168 ret = wx.TextCtrl(self, -1, value)
\r
169 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
\r
173 def AddLabelTextCtrl(self, info, value):
\r
174 text = wx.StaticText(self, -1, info)
\r
175 ret = wx.TextCtrl(self, -1, value)
\r
176 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
\r
177 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
\r
181 def AddTextCtrlButton(self, value, buttonText):
\r
182 text = wx.TextCtrl(self, -1, value)
\r
183 button = wx.Button(self, -1, buttonText)
\r
184 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
\r
185 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
\r
187 return text, button
\r
189 def AddBitmap(self, bitmap):
\r
190 bitmap = wx.StaticBitmap(self, -1, bitmap)
\r
191 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
\r
195 def AddCheckmark(self, label, bitmap):
\r
196 check = wx.StaticBitmap(self, -1, bitmap)
\r
197 text = wx.StaticText(self, -1, label)
\r
198 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
\r
199 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
\r
203 def AllowNext(self):
\r
206 def StoreData(self):
\r
210 class FirstInfoPage(InfoPage):
\r
211 def __init__(self, parent):
\r
212 super(FirstInfoPage, self).__init__(parent, "First time run wizard")
\r
213 self.AddText('Welcome, and thanks for trying Cura!')
\r
214 self.AddSeperator()
\r
215 self.AddText('This wizard will help you with the following steps:')
\r
216 self.AddText('* Configure Cura for your machine')
\r
217 self.AddText('* Upgrade your firmware')
\r
218 self.AddText('* Check if your machine is working safely')
\r
220 #self.AddText('* Calibrate your machine')
\r
221 #self.AddText('* Do your first print')
\r
224 class RepRapInfoPage(InfoPage):
\r
225 def __init__(self, parent):
\r
226 super(RepRapInfoPage, self).__init__(parent, "RepRap information")
\r
228 'RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
\r
229 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
\r
230 self.AddSeperator()
\r
231 self.AddText('You will have to manually install Marlin or Sprinter firmware.')
\r
232 self.AddSeperator()
\r
233 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')
\r
234 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')
\r
235 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')
\r
236 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')
\r
237 self.heatedBed = self.AddCheckbox('Heated bed')
\r
239 def StoreData(self):
\r
240 profile.putPreference('machine_width', self.machineWidth.GetValue())
\r
241 profile.putPreference('machine_depth', self.machineDepth.GetValue())
\r
242 profile.putPreference('machine_height', self.machineHeight.GetValue())
\r
243 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
\r
244 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
\r
245 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
\r
248 class MachineSelectPage(InfoPage):
\r
249 def __init__(self, parent):
\r
250 super(MachineSelectPage, self).__init__(parent, "Select your machine")
\r
251 self.AddText('What kind of machine do you have:')
\r
253 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)
\r
254 self.UltimakerRadio.SetValue(True)
\r
255 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
\r
256 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")
\r
257 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
\r
259 def OnUltimakerSelect(self, e):
\r
260 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
\r
262 def OnOtherSelect(self, e):
\r
263 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)
\r
265 def StoreData(self):
\r
266 if self.UltimakerRadio.GetValue():
\r
267 profile.putPreference('machine_width', '205')
\r
268 profile.putPreference('machine_depth', '205')
\r
269 profile.putPreference('machine_height', '200')
\r
270 profile.putPreference('machine_type', 'ultimaker')
\r
271 profile.putProfileSetting('nozzle_size', '0.4')
\r
273 profile.putPreference('machine_width', '80')
\r
274 profile.putPreference('machine_depth', '80')
\r
275 profile.putPreference('machine_height', '60')
\r
276 profile.putPreference('machine_type', 'reprap')
\r
277 profile.putPreference('startMode', 'Normal')
\r
278 profile.putProfileSetting('nozzle_size', '0.5')
\r
279 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
\r
282 class SelectParts(InfoPage):
\r
283 def __init__(self, parent):
\r
284 super(SelectParts, self).__init__(parent, "Select upgraded parts you have")
\r
285 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
286 self.AddSeperator()
\r
287 self.springExtruder = self.AddCheckbox('Extruder drive upgrade')
\r
288 self.heatedBed = self.AddCheckbox('Heated printer bed (self build)')
\r
289 self.dualExtrusion = self.AddCheckbox('Dual extrusion (experimental)')
\r
290 self.AddSeperator()
\r
291 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
292 self.AddText('This upgrade can be bought from the Ultimaker webshop shop\nor found on thingiverse as thing:26094')
\r
293 self.springExtruder.SetValue(True)
\r
295 def StoreData(self):
\r
296 profile.putPreference('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
\r
297 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
\r
298 if self.dualExtrusion.GetValue():
\r
299 profile.putPreference('extruder_amount', '2')
\r
300 if getPreference('ultimaker_extruder_upgrade') == 'True':
\r
301 putProfileSetting('retraction_enable', 'True')
\r
304 class FirmwareUpgradePage(InfoPage):
\r
305 def __init__(self, parent):
\r
306 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
\r
308 '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
309 self.AddHiddenSeperator()
\r
311 'The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
\r
312 self.AddHiddenSeperator()
\r
314 '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
315 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
\r
316 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
\r
317 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
318 self.AddHiddenSeperator()
\r
319 self.AddText('Do not upgrade to this firmware if:')
\r
320 self.AddText('* You have an older machine based on ATMega1280')
\r
321 self.AddText('* Have other changes in the firmware')
\r
322 button = self.AddButton('Goto this page for a custom firmware')
\r
323 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
\r
325 def AllowNext(self):
\r
328 def OnUpgradeClick(self, e):
\r
329 if firmwareInstall.InstallFirmware():
\r
330 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
332 def OnSkipClick(self, e):
\r
333 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
335 def OnUrlClick(self, e):
\r
336 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
\r
339 class UltimakerCheckupPage(InfoPage):
\r
340 def __init__(self, parent):
\r
341 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
\r
343 self.checkBitmap = wx.Bitmap(getPathForImage('checkmark.png'))
\r
344 self.crossBitmap = wx.Bitmap(getPathForImage('cross.png'))
\r
345 self.unknownBitmap = wx.Bitmap(getPathForImage('question.png'))
\r
346 self.endStopNoneBitmap = wx.Bitmap(getPathForImage('endstop_none.png'))
\r
347 self.endStopXMinBitmap = wx.Bitmap(getPathForImage('endstop_xmin.png'))
\r
348 self.endStopXMaxBitmap = wx.Bitmap(getPathForImage('endstop_xmax.png'))
\r
349 self.endStopYMinBitmap = wx.Bitmap(getPathForImage('endstop_ymin.png'))
\r
350 self.endStopYMaxBitmap = wx.Bitmap(getPathForImage('endstop_ymax.png'))
\r
351 self.endStopZMinBitmap = wx.Bitmap(getPathForImage('endstop_zmin.png'))
\r
352 self.endStopZMaxBitmap = wx.Bitmap(getPathForImage('endstop_zmax.png'))
\r
355 '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
356 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
\r
357 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
\r
358 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
359 self.AddSeperator()
\r
360 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
\r
361 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
\r
362 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
\r
363 self.AddSeperator()
\r
364 self.infoBox = self.AddInfoBox()
\r
365 self.machineState = self.AddText('')
\r
366 self.temperatureLabel = self.AddText('')
\r
367 self.errorLogButton = self.AddButton('Show error log')
\r
368 self.errorLogButton.Show(False)
\r
369 self.AddSeperator()
\r
370 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
\r
372 self.xMinStop = False
\r
373 self.xMaxStop = False
\r
374 self.yMinStop = False
\r
375 self.yMaxStop = False
\r
376 self.zMinStop = False
\r
377 self.zMaxStop = False
\r
379 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
\r
382 if self.comm != None:
\r
385 def AllowNext(self):
\r
386 self.endstopBitmap.Show(False)
\r
389 def OnSkipClick(self, e):
\r
390 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
392 def OnCheckClick(self, e=None):
\r
393 self.errorLogButton.Show(False)
\r
394 if self.comm != None:
\r
398 wx.CallAfter(self.OnCheckClick)
\r
400 self.infoBox.SetInfo('Connecting to machine.')
\r
401 self.infoBox.SetBusyIndicator()
\r
402 self.commState.SetBitmap(self.unknownBitmap)
\r
403 self.tempState.SetBitmap(self.unknownBitmap)
\r
404 self.stopState.SetBitmap(self.unknownBitmap)
\r
405 self.checkupState = 0
\r
406 self.comm = machineCom.MachineCom(callbackObject=self)
\r
408 def OnErrorLog(self, e):
\r
409 printWindow.LogWindow('\n'.join(self.comm.getLog()))
\r
411 def mcLog(self, message):
\r
414 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
\r
415 if not self.comm.isOperational():
\r
417 if self.checkupState == 0:
\r
418 self.tempCheckTimeout = 20
\r
420 self.checkupState = 1
\r
421 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
\r
422 self.comm.sendCommand('M104 S0')
\r
423 self.comm.sendCommand('M104 S0')
\r
425 self.startTemp = temp
\r
426 self.checkupState = 2
\r
427 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
428 self.comm.sendCommand('M104 S200')
\r
429 self.comm.sendCommand('M104 S200')
\r
430 elif self.checkupState == 1:
\r
432 self.startTemp = temp
\r
433 self.checkupState = 2
\r
434 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
435 self.comm.sendCommand('M104 S200')
\r
436 self.comm.sendCommand('M104 S200')
\r
437 elif self.checkupState == 2:
\r
438 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
\r
439 if temp > self.startTemp + 40:
\r
440 self.checkupState = 3
\r
441 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
\r
442 wx.CallAfter(self.endstopBitmap.Show, True)
\r
443 wx.CallAfter(self.Layout)
\r
444 self.comm.sendCommand('M104 S0')
\r
445 self.comm.sendCommand('M104 S0')
\r
446 self.comm.sendCommand('M119')
\r
447 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
\r
449 self.tempCheckTimeout -= 1
\r
450 if self.tempCheckTimeout < 1:
\r
451 self.checkupState = -1
\r
452 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
\r
453 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura/Temperature_measurement_problems')
\r
454 self.comm.sendCommand('M104 S0')
\r
455 self.comm.sendCommand('M104 S0')
\r
456 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp))
\r
458 def mcStateChange(self, state):
\r
459 if self.comm == None:
\r
461 if self.comm.isOperational():
\r
462 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
\r
463 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
464 elif self.comm.isError():
\r
465 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
\r
466 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura/Connection_problems')
\r
467 wx.CallAfter(self.endstopBitmap.Show, False)
\r
468 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
\r
469 wx.CallAfter(self.errorLogButton.Show, True)
\r
470 wx.CallAfter(self.Layout)
\r
472 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
474 def mcMessage(self, message):
\r
475 if self.checkupState >= 3 and self.checkupState < 10 and 'x_min' in message:
\r
476 for data in message.split(' '):
\r
478 tag, value = data.split(':', 2)
\r
480 self.xMinStop = (value == 'H')
\r
482 self.xMaxStop = (value == 'H')
\r
484 self.yMinStop = (value == 'H')
\r
486 self.yMaxStop = (value == 'H')
\r
488 self.zMinStop = (value == 'H')
\r
490 self.zMaxStop = (value == 'H')
\r
491 self.comm.sendCommand('M119')
\r
493 if self.checkupState == 3:
\r
494 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
495 self.checkupState = 4
\r
496 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
\r
497 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
\r
498 elif self.checkupState == 4:
\r
499 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
500 self.checkupState = 5
\r
501 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
\r
502 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
\r
503 elif self.checkupState == 5:
\r
504 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
505 self.checkupState = 6
\r
506 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
\r
507 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
\r
508 elif self.checkupState == 6:
\r
509 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
510 self.checkupState = 7
\r
511 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
\r
512 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
\r
513 elif self.checkupState == 7:
\r
514 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
515 self.checkupState = 8
\r
516 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
\r
517 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
\r
518 elif self.checkupState == 8:
\r
519 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
\r
520 self.checkupState = 9
\r
521 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
\r
522 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
\r
523 elif self.checkupState == 9:
\r
524 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
\r
525 self.checkupState = 10
\r
527 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
\r
528 wx.CallAfter(self.infoBox.SetReadyIndicator)
\r
529 wx.CallAfter(self.endstopBitmap.Show, False)
\r
530 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
\r
531 wx.CallAfter(self.OnSkipClick, None)
\r
533 def mcProgress(self, lineNr):
\r
536 def mcZChange(self, newZ):
\r
540 class UltimakerCalibrationPage(InfoPage):
\r
541 def __init__(self, parent):
\r
542 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
\r
544 self.AddText("Your Ultimaker requires some calibration.")
\r
545 self.AddText("This calibration is needed for a proper extrusion amount.")
\r
546 self.AddSeperator()
\r
547 self.AddText("The following values are needed:")
\r
548 self.AddText("* Diameter of filament")
\r
549 self.AddText("* Number of steps per mm of filament extrusion")
\r
550 self.AddSeperator()
\r
551 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
\r
552 self.AddSeperator()
\r
553 self.AddText("First we need the diameter of your filament:")
\r
554 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
\r
556 "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
557 self.AddText("Note: This value can be changed later at any time.")
\r
559 def StoreData(self):
\r
560 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
\r
563 class UltimakerCalibrateStepsPerEPage(InfoPage):
\r
564 def __init__(self, parent):
\r
565 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
\r
567 if profile.getPreference('steps_per_e') == '0':
\r
568 profile.putPreference('steps_per_e', '865.888')
\r
570 self.AddText("Calibrating the Steps Per E requires some manual actions.")
\r
571 self.AddText("First remove any filament from your machine.")
\r
572 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
\r
573 self.AddText("We'll push the filament 100mm")
\r
574 self.extrudeButton = self.AddButton("Extrude 100mm filament")
\r
575 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
\r
576 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
\r
577 self.AddText("This results in the following steps per E:")
\r
578 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
\r
579 self.AddText("You can repeat these steps to get better calibration.")
\r
580 self.AddSeperator()
\r
582 "If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
\r
583 self.heatButton = self.AddButton("Heatup for filament removal")
\r
585 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
\r
586 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
\r
587 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
\r
589 def OnSaveLengthClick(self, e):
\r
590 currentEValue = float(self.stepsPerEInput.GetValue())
\r
591 realExtrudeLength = float(self.lengthInput.GetValue())
\r
592 newEValue = currentEValue * 100 / realExtrudeLength
\r
593 self.stepsPerEInput.SetValue(str(newEValue))
\r
594 self.lengthInput.SetValue("100")
\r
596 def OnExtrudeClick(self, e):
\r
597 threading.Thread(target=self.OnExtrudeRun).start()
\r
599 def OnExtrudeRun(self):
\r
600 self.heatButton.Enable(False)
\r
601 self.extrudeButton.Enable(False)
\r
602 currentEValue = float(self.stepsPerEInput.GetValue())
\r
603 self.comm = machineCom.MachineCom()
\r
604 if not self.comm.isOpen():
\r
606 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
\r
607 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
608 self.heatButton.Enable(True)
\r
609 self.extrudeButton.Enable(True)
\r
612 line = self.comm.readline()
\r
615 if 'start' in line:
\r
617 #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
620 self.sendGCommand('M302') #Disable cold extrusion protection
\r
621 self.sendGCommand("M92 E%f" % (currentEValue))
\r
622 self.sendGCommand("G92 E0")
\r
623 self.sendGCommand("G1 E100 F600")
\r
626 self.extrudeButton.Enable()
\r
627 self.heatButton.Enable()
\r
629 def OnHeatClick(self, e):
\r
630 threading.Thread(target=self.OnHeatRun).start()
\r
632 def OnHeatRun(self):
\r
633 self.heatButton.Enable(False)
\r
634 self.extrudeButton.Enable(False)
\r
635 self.comm = machineCom.MachineCom()
\r
636 if not self.comm.isOpen():
\r
638 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
\r
639 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
640 self.heatButton.Enable(True)
\r
641 self.extrudeButton.Enable(True)
\r
644 line = self.comm.readline()
\r
646 self.heatButton.Enable(True)
\r
647 self.extrudeButton.Enable(True)
\r
649 if 'start' in line:
\r
651 #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
654 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
\r
656 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
\r
657 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
\r
658 self.sendGCommand('M104 S0')
\r
661 self.heatButton.Enable(True)
\r
662 self.extrudeButton.Enable(True)
\r
664 def sendGCommand(self, cmd):
\r
665 self.comm.sendCommand(cmd) #Disable cold extrusion protection
\r
667 line = self.comm.readline()
\r
670 if line.startswith('ok'):
\r
673 def StoreData(self):
\r
674 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
\r
677 class configWizard(wx.wizard.Wizard):
\r
678 def __init__(self):
\r
679 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
\r
681 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
\r
682 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
\r
684 self.firstInfoPage = FirstInfoPage(self)
\r
685 self.machineSelectPage = MachineSelectPage(self)
\r
686 self.ultimakerSelectParts = SelectParts(self)
\r
687 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
\r
688 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
\r
689 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
\r
690 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
\r
691 self.repRapInfoPage = RepRapInfoPage(self)
\r
693 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
\r
694 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
\r
695 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
\r
696 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
\r
697 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
\r
698 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
\r
700 self.FitToPage(self.firstInfoPage)
\r
701 self.GetPageAreaSizer().Add(self.firstInfoPage)
\r
703 self.RunWizard(self.firstInfoPage)
\r
706 def OnPageChanging(self, e):
\r
707 e.GetPage().StoreData()
\r
709 def OnPageChanged(self, e):
\r
710 if e.GetPage().AllowNext():
\r
711 self.FindWindowById(wx.ID_FORWARD).Enable()
\r
713 self.FindWindowById(wx.ID_FORWARD).Disable()
\r
714 self.FindWindowById(wx.ID_BACKWARD).Disable()
\r