1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
12 from Cura.gui import firmwareInstall
13 from Cura.gui import printWindow
14 from Cura.util import machineCom
15 from Cura.util import profile
16 from Cura.util import gcodeGenerator
17 from Cura.util.resources import getPathForImage
19 class InfoBox(wx.Panel):
20 def __init__(self, parent):
21 super(InfoBox, self).__init__(parent)
22 self.SetBackgroundColour('#FFFF80')
24 self.sizer = wx.GridBagSizer(5, 5)
25 self.SetSizer(self.sizer)
27 self.attentionBitmap = wx.Bitmap(getPathForImage('attention.png'))
28 self.errorBitmap = wx.Bitmap(getPathForImage('error.png'))
29 self.readyBitmap = wx.Bitmap(getPathForImage('ready.png'))
31 wx.Bitmap(getPathForImage('busy-0.png')),
32 wx.Bitmap(getPathForImage('busy-1.png')),
33 wx.Bitmap(getPathForImage('busy-2.png')),
34 wx.Bitmap(getPathForImage('busy-3.png'))
37 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
38 self.text = wx.StaticText(self, -1, '')
39 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
40 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
41 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
42 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
43 self.sizer.AddGrowableCol(1)
45 self.extraInfoButton.Show(False)
47 self.extraInfoUrl = ''
49 self.timer = wx.Timer(self)
50 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
51 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
54 def SetInfo(self, info):
55 self.SetBackgroundColour('#FFFF80')
56 self.text.SetLabel(info)
57 self.extraInfoButton.Show(False)
60 def SetError(self, info, extraInfoUrl):
61 self.extraInfoUrl = extraInfoUrl
62 self.SetBackgroundColour('#FF8080')
63 self.text.SetLabel(info)
64 self.extraInfoButton.Show(True)
66 self.SetErrorIndicator()
69 def SetAttention(self, info):
70 self.SetBackgroundColour('#FFFF80')
71 self.text.SetLabel(info)
72 self.extraInfoButton.Show(False)
73 self.SetAttentionIndicator()
77 def SetBusy(self, info):
79 self.SetBusyIndicator()
81 def SetBusyIndicator(self):
83 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
85 def doExtraInfo(self, e):
86 webbrowser.open(self.extraInfoUrl)
88 def doBusyUpdate(self, e):
89 if self.busyState is None:
92 if self.busyState >= len(self.busyBitmap):
94 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
96 def SetReadyIndicator(self):
98 self.bitmap.SetBitmap(self.readyBitmap)
100 def SetErrorIndicator(self):
101 self.busyState = None
102 self.bitmap.SetBitmap(self.errorBitmap)
104 def SetAttentionIndicator(self):
105 self.busyState = None
106 self.bitmap.SetBitmap(self.attentionBitmap)
109 class InfoPage(wx.wizard.WizardPageSimple):
110 def __init__(self, parent, title):
111 wx.wizard.WizardPageSimple.__init__(self, parent)
113 sizer = wx.GridBagSizer(5, 5)
117 title = wx.StaticText(self, -1, title)
118 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
119 sizer.Add(title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
120 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
121 sizer.AddGrowableCol(1)
125 def AddText(self, info):
126 text = wx.StaticText(self, -1, info)
127 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
131 def AddSeperator(self):
132 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
135 def AddHiddenSeperator(self):
138 def AddInfoBox(self):
139 infoBox = InfoBox(self)
140 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
144 def AddRadioButton(self, label, style=0):
145 radio = wx.RadioButton(self, -1, label, style=style)
146 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
150 def AddCheckbox(self, label, checked=False):
151 check = wx.CheckBox(self, -1)
152 text = wx.StaticText(self, -1, label)
153 check.SetValue(checked)
154 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
155 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
159 def AddButton(self, label):
160 button = wx.Button(self, -1, label)
161 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
165 def AddDualButton(self, label1, label2):
166 button1 = wx.Button(self, -1, label1)
167 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
168 button2 = wx.Button(self, -1, label2)
169 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
171 return button1, button2
173 def AddTextCtrl(self, value):
174 ret = wx.TextCtrl(self, -1, value)
175 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
179 def AddLabelTextCtrl(self, info, value):
180 text = wx.StaticText(self, -1, info)
181 ret = wx.TextCtrl(self, -1, value)
182 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
183 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
187 def AddTextCtrlButton(self, value, buttonText):
188 text = wx.TextCtrl(self, -1, value)
189 button = wx.Button(self, -1, buttonText)
190 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
191 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
195 def AddBitmap(self, bitmap):
196 bitmap = wx.StaticBitmap(self, -1, bitmap)
197 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
201 def AddCheckmark(self, label, bitmap):
202 check = wx.StaticBitmap(self, -1, bitmap)
203 text = wx.StaticText(self, -1, label)
204 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
205 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
216 class FirstInfoPage(InfoPage):
217 def __init__(self, parent):
218 super(FirstInfoPage, self).__init__(parent, "First time run wizard")
219 self.AddText('Welcome, and thanks for trying Cura!')
221 self.AddText('This wizard will help you with the following steps:')
222 self.AddText('* Configure Cura for your machine')
223 self.AddText('* Upgrade your firmware')
224 self.AddText('* Check if your machine is working safely')
225 self.AddText('* Level your printer bed')
227 #self.AddText('* Calibrate your machine')
228 #self.AddText('* Do your first print')
231 class RepRapInfoPage(InfoPage):
232 def __init__(self, parent):
233 super(RepRapInfoPage, self).__init__(parent, "RepRap information")
235 'RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
236 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
238 self.AddText('You will have to manually install Marlin or Sprinter firmware.')
240 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')
241 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')
242 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')
243 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')
244 self.heatedBed = self.AddCheckbox('Heated bed')
245 self.HomeAtCenter = self.AddCheckbox('Bed center is 0,0,0 (RoStock)')
248 profile.putPreference('machine_width', self.machineWidth.GetValue())
249 profile.putPreference('machine_depth', self.machineDepth.GetValue())
250 profile.putPreference('machine_height', self.machineHeight.GetValue())
251 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
252 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
253 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
254 profile.putPreference('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
255 profile.putPreference('extruder_head_size_min_x', '0')
256 profile.putPreference('extruder_head_size_min_y', '0')
257 profile.putPreference('extruder_head_size_max_x', '0')
258 profile.putPreference('extruder_head_size_max_y', '0')
259 profile.putPreference('extruder_head_size_height', '0')
262 class MachineSelectPage(InfoPage):
263 def __init__(self, parent):
264 super(MachineSelectPage, self).__init__(parent, "Select your machine")
265 self.AddText('What kind of machine do you have:')
267 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)
268 self.UltimakerRadio.SetValue(True)
269 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
270 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")
271 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
273 self.AddText('The collection of anonymous usage information helps with the continued improvement of Cura.')
274 self.AddText('This does NOT submit your models online nor gathers any privacy related information.')
275 self.SubmitUserStats = self.AddCheckbox('Submit anonymous usage information:')
276 self.AddText('For full details see: http://wiki.ultimaker.com/Cura:stats')
277 self.SubmitUserStats.SetValue(True)
279 def OnUltimakerSelect(self, e):
280 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
282 def OnOtherSelect(self, e):
283 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)
286 if self.UltimakerRadio.GetValue():
287 profile.putPreference('machine_width', '205')
288 profile.putPreference('machine_depth', '205')
289 profile.putPreference('machine_height', '200')
290 profile.putPreference('machine_type', 'ultimaker')
291 profile.putPreference('machine_center_is_zero', 'False')
292 profile.putProfileSetting('nozzle_size', '0.4')
293 profile.putPreference('extruder_head_size_min_x', '75.0')
294 profile.putPreference('extruder_head_size_min_y', '18.0')
295 profile.putPreference('extruder_head_size_max_x', '18.0')
296 profile.putPreference('extruder_head_size_max_y', '35.0')
297 profile.putPreference('extruder_head_size_height', '60.0')
299 profile.putPreference('machine_width', '80')
300 profile.putPreference('machine_depth', '80')
301 profile.putPreference('machine_height', '60')
302 profile.putPreference('machine_type', 'reprap')
303 profile.putPreference('startMode', 'Normal')
304 profile.putProfileSetting('nozzle_size', '0.5')
305 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
306 if self.SubmitUserStats.GetValue():
307 profile.putPreference('submit_slice_information', 'True')
309 profile.putPreference('submit_slice_information', 'False')
311 class SelectParts(InfoPage):
312 def __init__(self, parent):
313 super(SelectParts, self).__init__(parent, "Select upgraded parts you have")
314 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.')
316 self.springExtruder = self.AddCheckbox('Extruder drive upgrade')
317 self.heatedBed = self.AddCheckbox('Heated printer bed (self built)')
318 self.dualExtrusion = self.AddCheckbox('Dual extrusion (experimental)')
320 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 reliability.')
321 self.AddText('This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094')
322 self.springExtruder.SetValue(True)
325 profile.putPreference('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
326 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
327 if self.dualExtrusion.GetValue():
328 profile.putPreference('extruder_amount', '2')
330 profile.putPreference('extruder_amount', '1')
331 if profile.getPreference('ultimaker_extruder_upgrade') == 'True':
332 profile.putProfileSetting('retraction_enable', 'True')
334 profile.putProfileSetting('retraction_enable', 'False')
337 class FirmwareUpgradePage(InfoPage):
338 def __init__(self, parent):
339 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
341 '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.')
342 self.AddHiddenSeperator()
344 'The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
345 self.AddHiddenSeperator()
347 '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.')
348 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
349 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
350 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
351 self.AddHiddenSeperator()
352 self.AddText('Do not upgrade to this firmware if:')
353 self.AddText('* You have an older machine based on ATMega1280')
354 self.AddText('* Have other changes in the firmware')
355 # button = self.AddButton('Goto this page for a custom firmware')
356 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
361 def OnUpgradeClick(self, e):
362 if firmwareInstall.InstallFirmware():
363 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
365 def OnSkipClick(self, e):
366 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
367 self.GetParent().ShowPage(self.GetNext())
369 def OnUrlClick(self, e):
370 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
373 class UltimakerCheckupPage(InfoPage):
374 def __init__(self, parent):
375 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
377 self.checkBitmap = wx.Bitmap(getPathForImage('checkmark.png'))
378 self.crossBitmap = wx.Bitmap(getPathForImage('cross.png'))
379 self.unknownBitmap = wx.Bitmap(getPathForImage('question.png'))
380 self.endStopNoneBitmap = wx.Bitmap(getPathForImage('endstop_none.png'))
381 self.endStopXMinBitmap = wx.Bitmap(getPathForImage('endstop_xmin.png'))
382 self.endStopXMaxBitmap = wx.Bitmap(getPathForImage('endstop_xmax.png'))
383 self.endStopYMinBitmap = wx.Bitmap(getPathForImage('endstop_ymin.png'))
384 self.endStopYMaxBitmap = wx.Bitmap(getPathForImage('endstop_ymax.png'))
385 self.endStopZMinBitmap = wx.Bitmap(getPathForImage('endstop_zmin.png'))
386 self.endStopZMaxBitmap = wx.Bitmap(getPathForImage('endstop_zmax.png'))
389 '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.')
390 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
391 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
392 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
394 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
395 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
396 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
398 self.infoBox = self.AddInfoBox()
399 self.machineState = self.AddText('')
400 self.temperatureLabel = self.AddText('')
401 self.errorLogButton = self.AddButton('Show error log')
402 self.errorLogButton.Show(False)
404 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
406 self.xMinStop = False
407 self.xMaxStop = False
408 self.yMinStop = False
409 self.yMaxStop = False
410 self.zMinStop = False
411 self.zMaxStop = False
413 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
416 if self.comm is not None:
420 self.endstopBitmap.Show(False)
423 def OnSkipClick(self, e):
424 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
425 self.GetParent().ShowPage(self.GetNext())
427 def OnCheckClick(self, e=None):
428 self.errorLogButton.Show(False)
429 if self.comm is not None:
433 wx.CallAfter(self.OnCheckClick)
435 self.infoBox.SetBusy('Connecting to machine.')
436 self.commState.SetBitmap(self.unknownBitmap)
437 self.tempState.SetBitmap(self.unknownBitmap)
438 self.stopState.SetBitmap(self.unknownBitmap)
439 self.checkupState = 0
440 self.checkExtruderNr = 0
441 self.comm = machineCom.MachineCom(callbackObject=self)
443 def OnErrorLog(self, e):
444 printWindow.LogWindow('\n'.join(self.comm.getLog()))
446 def mcLog(self, message):
449 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
450 if not self.comm.isOperational():
452 if self.checkupState == 0:
453 self.tempCheckTimeout = 20
454 if temp[self.checkExtruderNr] > 70:
455 self.checkupState = 1
456 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
457 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
458 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
460 self.startTemp = temp[self.checkExtruderNr]
461 self.checkupState = 2
462 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
463 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
464 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
465 elif self.checkupState == 1:
467 self.startTemp = temp[self.checkExtruderNr]
468 self.checkupState = 2
469 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
470 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
471 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
472 elif self.checkupState == 2:
473 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
474 if temp[self.checkExtruderNr] > self.startTemp + 40:
475 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
476 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
477 if self.checkExtruderNr < int(profile.getPreference('extruder_amount')):
478 self.checkExtruderNr = 0
479 self.checkupState = 3
480 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
481 wx.CallAfter(self.endstopBitmap.Show, True)
482 wx.CallAfter(self.Layout)
483 self.comm.sendCommand('M119')
484 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
486 self.checkupState = 0
487 self.checkExtruderNr += 1
489 self.tempCheckTimeout -= 1
490 if self.tempCheckTimeout < 1:
491 self.checkupState = -1
492 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
493 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
494 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
495 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
496 elif self.checkupState >= 3 and self.checkupState < 10:
497 self.comm.sendCommand('M119')
498 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp[self.checkExtruderNr]))
500 def mcStateChange(self, state):
501 if self.comm is None:
503 if self.comm.isOperational():
504 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
505 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
506 elif self.comm.isError():
507 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
508 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
509 wx.CallAfter(self.endstopBitmap.Show, False)
510 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
511 wx.CallAfter(self.errorLogButton.Show, True)
512 wx.CallAfter(self.Layout)
514 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
516 def mcMessage(self, message):
517 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
518 for data in message.split(' '):
520 tag, value = data.split(':', 1)
522 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
524 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
526 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
528 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
530 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
532 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
534 tag, value = map(str.strip, message.split(':', 1))
536 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
538 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
540 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
542 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
544 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
546 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
547 if 'z_max' in message:
548 self.comm.sendCommand('M119')
550 if self.checkupState == 3:
551 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
552 self.checkupState = 4
553 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
554 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
555 elif self.checkupState == 4:
556 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
557 self.checkupState = 5
558 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
559 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
560 elif self.checkupState == 5:
561 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
562 self.checkupState = 6
563 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
564 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
565 elif self.checkupState == 6:
566 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
567 self.checkupState = 7
568 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
569 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
570 elif self.checkupState == 7:
571 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
572 self.checkupState = 8
573 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
574 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
575 elif self.checkupState == 8:
576 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
577 self.checkupState = 9
578 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
579 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
580 elif self.checkupState == 9:
581 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
582 self.checkupState = 10
584 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
585 wx.CallAfter(self.infoBox.SetReadyIndicator)
586 wx.CallAfter(self.endstopBitmap.Show, False)
587 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
588 wx.CallAfter(self.OnSkipClick, None)
590 def mcProgress(self, lineNr):
593 def mcZChange(self, newZ):
597 class UltimakerCalibrationPage(InfoPage):
598 def __init__(self, parent):
599 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
601 self.AddText("Your Ultimaker requires some calibration.")
602 self.AddText("This calibration is needed for a proper extrusion amount.")
604 self.AddText("The following values are needed:")
605 self.AddText("* Diameter of filament")
606 self.AddText("* Number of steps per mm of filament extrusion")
608 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
610 self.AddText("First we need the diameter of your filament:")
611 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
613 "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.")
614 self.AddText("Note: This value can be changed later at any time.")
617 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
620 class UltimakerCalibrateStepsPerEPage(InfoPage):
621 def __init__(self, parent):
622 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
624 #if profile.getPreference('steps_per_e') == '0':
625 # profile.putPreference('steps_per_e', '865.888')
627 self.AddText("Calibrating the Steps Per E requires some manual actions.")
628 self.AddText("First remove any filament from your machine.")
629 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
630 self.AddText("We'll push the filament 100mm")
631 self.extrudeButton = self.AddButton("Extrude 100mm filament")
632 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
633 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
634 self.AddText("This results in the following steps per E:")
635 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
636 self.AddText("You can repeat these steps to get better calibration.")
639 "If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
640 self.heatButton = self.AddButton("Heatup for filament removal")
642 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
643 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
644 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
646 def OnSaveLengthClick(self, e):
647 currentEValue = float(self.stepsPerEInput.GetValue())
648 realExtrudeLength = float(self.lengthInput.GetValue())
649 newEValue = currentEValue * 100 / realExtrudeLength
650 self.stepsPerEInput.SetValue(str(newEValue))
651 self.lengthInput.SetValue("100")
653 def OnExtrudeClick(self, e):
654 threading.Thread(target=self.OnExtrudeRun).start()
656 def OnExtrudeRun(self):
657 self.heatButton.Enable(False)
658 self.extrudeButton.Enable(False)
659 currentEValue = float(self.stepsPerEInput.GetValue())
660 self.comm = machineCom.MachineCom()
661 if not self.comm.isOpen():
663 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
664 'Printer error', wx.OK | wx.ICON_INFORMATION)
665 self.heatButton.Enable(True)
666 self.extrudeButton.Enable(True)
669 line = self.comm.readline()
674 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
677 self.sendGCommand('M302') #Disable cold extrusion protection
678 self.sendGCommand("M92 E%f" % (currentEValue))
679 self.sendGCommand("G92 E0")
680 self.sendGCommand("G1 E100 F600")
683 self.extrudeButton.Enable()
684 self.heatButton.Enable()
686 def OnHeatClick(self, e):
687 threading.Thread(target=self.OnHeatRun).start()
690 self.heatButton.Enable(False)
691 self.extrudeButton.Enable(False)
692 self.comm = machineCom.MachineCom()
693 if not self.comm.isOpen():
695 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
696 'Printer error', wx.OK | wx.ICON_INFORMATION)
697 self.heatButton.Enable(True)
698 self.extrudeButton.Enable(True)
701 line = self.comm.readline()
703 self.heatButton.Enable(True)
704 self.extrudeButton.Enable(True)
708 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
711 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
713 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
714 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
715 self.sendGCommand('M104 S0')
718 self.heatButton.Enable(True)
719 self.extrudeButton.Enable(True)
721 def sendGCommand(self, cmd):
722 self.comm.sendCommand(cmd) #Disable cold extrusion protection
724 line = self.comm.readline()
727 if line.startswith('ok'):
731 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
734 class configWizard(wx.wizard.Wizard):
736 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
738 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
739 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
741 self.firstInfoPage = FirstInfoPage(self)
742 self.machineSelectPage = MachineSelectPage(self)
743 self.ultimakerSelectParts = SelectParts(self)
744 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
745 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
746 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
747 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
748 self.bedLevelPage = bedLevelWizardMain(self)
749 self.headOffsetCalibration = headOffsetCalibrationPage(self)
750 self.repRapInfoPage = RepRapInfoPage(self)
752 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
753 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
754 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
755 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
756 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
757 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
759 self.FitToPage(self.firstInfoPage)
760 self.GetPageAreaSizer().Add(self.firstInfoPage)
762 self.RunWizard(self.firstInfoPage)
765 def OnPageChanging(self, e):
766 e.GetPage().StoreData()
768 def OnPageChanged(self, e):
769 if e.GetPage().AllowNext():
770 self.FindWindowById(wx.ID_FORWARD).Enable()
772 self.FindWindowById(wx.ID_FORWARD).Disable()
773 self.FindWindowById(wx.ID_BACKWARD).Disable()
775 class bedLevelWizardMain(InfoPage):
776 def __init__(self, parent):
777 super(bedLevelWizardMain, self).__init__(parent, "Bed leveling wizard")
779 self.AddText('This wizard will help you in leveling your printer bed')
781 self.AddText('It will do the following steps')
782 self.AddText('* Move the printer head to each corner')
783 self.AddText(' and let you adjust the height of the bed to the nozzle')
784 self.AddText('* Print a line around the bed to check if it is level')
787 self.connectButton = self.AddButton('Connect to printer')
790 self.infoBox = self.AddInfoBox()
791 self.resumeButton = self.AddButton('Resume')
792 self.resumeButton.Enable(False)
794 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
795 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
797 def OnConnect(self, e = None):
798 if self.comm is not None:
802 wx.CallAfter(self.OnConnect)
804 self.connectButton.Enable(False)
805 self.comm = machineCom.MachineCom(callbackObject=self)
806 self.infoBox.SetBusy('Connecting to machine.')
807 self._wizardState = 0
810 if self.GetParent().headOffsetCalibration is not None and int(profile.getPreference('extruder_amount')) > 1:
811 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
814 def OnResume(self, e):
815 feedZ = profile.getProfileSettingFloat('print_speed') * 60
816 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
817 if self._wizardState == 2:
818 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...')
819 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
820 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getPreferenceFloat('machine_depth'), feedTravel))
821 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
822 self.comm.sendCommand('M400')
823 self._wizardState = 3
824 elif self._wizardState == 4:
825 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...')
826 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
827 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width') - 5.0, profile.getPreferenceFloat('machine_depth') - 25, feedTravel))
828 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
829 self.comm.sendCommand('M400')
830 self._wizardState = 5
831 elif self._wizardState == 6:
832 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
833 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
834 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width') - 5.0, 20, feedTravel))
835 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
836 self.comm.sendCommand('M400')
837 self._wizardState = 7
838 elif self._wizardState == 8:
839 wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...')
840 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
841 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
842 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
843 self._wizardState = 9
844 elif self._wizardState == 10:
845 self._wizardState = 11
846 wx.CallAfter(self.infoBox.SetInfo, 'Printing a square on the printer bed at 0.3mm height.')
847 feedZ = profile.getProfileSettingFloat('print_speed') * 60
848 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
849 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
850 w = profile.getPreferenceFloat('machine_width')
851 d = profile.getPreferenceFloat('machine_depth')
852 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
853 filamentArea = math.pi * filamentRadius * filamentRadius
854 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
858 'G1 Z2 F%d' % (feedZ),
860 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
861 'G1 Z0.3 F%d' % (feedZ)]
863 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
865 for i in xrange(0, 3):
866 dist = 5.0 + 0.4 * float(i)
867 eValue += (d - 2.0*dist) * ePerMM
868 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
869 eValue += (w - 2.0*dist) * ePerMM
870 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
871 eValue += (d - 2.0*dist) * ePerMM
872 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
873 eValue += (w - 2.0*dist) * ePerMM
874 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
876 gcodeList.append('M400')
877 self.comm.printGCode(gcodeList)
878 self.resumeButton.Enable(False)
880 def mcLog(self, message):
881 print 'Log:', message
883 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
884 if self._wizardState == 1:
885 self._wizardState = 2
886 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.')
887 wx.CallAfter(self.resumeButton.Enable, True)
888 elif self._wizardState == 3:
889 self._wizardState = 4
890 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.')
891 wx.CallAfter(self.resumeButton.Enable, True)
892 elif self._wizardState == 5:
893 self._wizardState = 6
894 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.')
895 wx.CallAfter(self.resumeButton.Enable, True)
896 elif self._wizardState == 7:
897 self._wizardState = 8
898 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.')
899 wx.CallAfter(self.resumeButton.Enable, True)
900 elif self._wizardState == 9:
901 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
902 wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature')))
904 wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.')
905 wx.CallAfter(self.resumeButton.Enable, True)
906 self._wizardState = 10
908 def mcStateChange(self, state):
909 if self.comm is None:
911 if self.comm.isOperational():
912 if self._wizardState == 0:
913 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer...')
914 self.comm.sendCommand('M105')
915 self.comm.sendCommand('G28')
916 self._wizardState = 1
917 elif self._wizardState == 11 and not self.comm.isPrinting():
918 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
919 self.comm.sendCommand('G92 E0')
920 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
921 self.comm.sendCommand('M104 S0')
922 wx.CallAfter(self.infoBox.SetInfo, 'Calibration finished.\nThe squares on the bed should slightly touch each other.')
923 wx.CallAfter(self.infoBox.SetReadyIndicator)
924 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
925 wx.CallAfter(self.connectButton.Enable, True)
926 self._wizardState = 12
927 elif self.comm.isError():
928 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
930 def mcMessage(self, message):
933 def mcProgress(self, lineNr):
936 def mcZChange(self, newZ):
939 class headOffsetCalibrationPage(InfoPage):
940 def __init__(self, parent):
941 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
943 self.AddText('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine')
946 self.connectButton = self.AddButton('Connect to printer')
949 self.infoBox = self.AddInfoBox()
950 self.textEntry = self.AddTextCtrl('')
951 self.textEntry.Enable(False)
952 self.resumeButton = self.AddButton('Resume')
953 self.resumeButton.Enable(False)
955 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
956 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
958 def OnConnect(self, e = None):
959 if self.comm is not None:
963 wx.CallAfter(self.OnConnect)
965 self.connectButton.Enable(False)
966 self.comm = machineCom.MachineCom(callbackObject=self)
967 self.infoBox.SetBusy('Connecting to machine.')
968 self._wizardState = 0
970 def OnResume(self, e):
971 if self._wizardState == 2:
972 self._wizardState = 3
973 wx.CallAfter(self.infoBox.SetBusy, 'Printing initial calibration cross')
975 w = profile.getPreferenceFloat('machine_width')
976 d = profile.getPreferenceFloat('machine_depth')
978 gcode = gcodeGenerator.gcodeGenerator()
979 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
980 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
987 gcode.addMove(w/2, 5)
990 gcode.addExtrude(w/2, d-5.0)
992 gcode.addMove(5, d/2)
994 gcode.addExtrude(w-5.0, d/2)
998 gcode.addMove(w/2, 5)
1000 gcode.addExtrude(w/2, d-5.0)
1002 gcode.addMove(5, d/2)
1004 gcode.addExtrude(w-5.0, d/2)
1005 gcode.addRetract(15)
1010 gcode.addCmd('M400')
1012 self.comm.printGCode(gcode.list())
1013 self.resumeButton.Enable(False)
1014 elif self._wizardState == 4:
1016 float(self.textEntry.GetValue())
1019 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1020 self._wizardState = 5
1021 self.infoBox.SetAttention('Please measure the distance between the horizontal lines in millimeters.')
1022 self.textEntry.SetValue('0.0')
1023 self.textEntry.Enable(True)
1024 elif self._wizardState == 5:
1026 float(self.textEntry.GetValue())
1029 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1030 self._wizardState = 6
1031 self.infoBox.SetBusy('Printing the fine calibration lines.')
1032 self.textEntry.SetValue('')
1033 self.textEntry.Enable(False)
1034 self.resumeButton.Enable(False)
1036 x = profile.getPreferenceFloat('extruder_offset_x1')
1037 y = profile.getPreferenceFloat('extruder_offset_y1')
1038 gcode = gcodeGenerator.gcodeGenerator()
1039 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1040 gcode.setPrintSpeed(25)
1043 gcode.addMove(50, 40, 0.2)
1045 for n in xrange(0, 10):
1046 gcode.addExtrude(50 + n * 10, 150)
1047 gcode.addExtrude(50 + n * 10 + 5, 150)
1048 gcode.addExtrude(50 + n * 10 + 5, 40)
1049 gcode.addExtrude(50 + n * 10 + 10, 40)
1050 gcode.addMove(40, 50)
1051 for n in xrange(0, 10):
1052 gcode.addExtrude(150, 50 + n * 10)
1053 gcode.addExtrude(150, 50 + n * 10 + 5)
1054 gcode.addExtrude(40, 50 + n * 10 + 5)
1055 gcode.addExtrude(40, 50 + n * 10 + 10)
1056 gcode.addRetract(15)
1059 gcode.addMove(50 - x, 30 - y, 0.2)
1061 for n in xrange(0, 10):
1062 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1063 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1064 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1065 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1066 gcode.addMove(30 - x, 50 - y, 0.2)
1067 for n in xrange(0, 10):
1068 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1069 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1070 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1071 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1072 gcode.addRetract(15)
1074 gcode.addCmd('M400')
1075 gcode.addCmd('M104 T0 S0')
1076 gcode.addCmd('M104 T1 S0')
1077 self.comm.printGCode(gcode.list())
1078 elif self._wizardState == 7:
1080 n = int(self.textEntry.GetValue()) - 1
1083 x = profile.getPreferenceFloat('extruder_offset_x1')
1085 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1086 self.infoBox.SetAttention('Which horizontal line number lays perfect on top of each other? Front most line is zero.')
1087 self.textEntry.SetValue('10')
1088 self._wizardState = 8
1089 elif self._wizardState == 8:
1091 n = int(self.textEntry.GetValue()) - 1
1094 y = profile.getPreferenceFloat('extruder_offset_y1')
1096 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1097 self.infoBox.SetInfo('Calibration finished. Offsets are: %s %s' % (profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1')))
1098 self.infoBox.SetReadyIndicator()
1099 self._wizardState = 8
1101 self.resumeButton.Enable(False)
1103 def mcLog(self, message):
1104 print 'Log:', message
1106 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1107 if self._wizardState == 1:
1108 if temp[0] >= 210 and temp[1] >= 210:
1109 self._wizardState = 2
1110 wx.CallAfter(self.infoBox.SetAttention, 'Please load both extruders with PLA.')
1111 wx.CallAfter(self.resumeButton.Enable, True)
1112 wx.CallAfter(self.resumeButton.SetFocus)
1114 def mcStateChange(self, state):
1115 if self.comm is None:
1117 if self.comm.isOperational():
1118 if self._wizardState == 0:
1119 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.')
1120 self.comm.sendCommand('M105')
1121 self.comm.sendCommand('M104 S220 T0')
1122 self.comm.sendCommand('M104 S220 T1')
1123 self.comm.sendCommand('G28')
1124 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1125 self._wizardState = 1
1126 if not self.comm.isPrinting():
1127 if self._wizardState == 3:
1128 self._wizardState = 4
1129 wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.')
1130 wx.CallAfter(self.textEntry.SetValue, '0.0')
1131 wx.CallAfter(self.textEntry.Enable, True)
1132 wx.CallAfter(self.resumeButton.Enable, True)
1133 wx.CallAfter(self.resumeButton.SetFocus)
1134 elif self._wizardState == 6:
1135 self._wizardState = 7
1136 wx.CallAfter(self.infoBox.SetAttention, 'Which vertical line number lays perfect on top of each other? Leftmost line is zero.')
1137 wx.CallAfter(self.textEntry.SetValue, '10')
1138 wx.CallAfter(self.textEntry.Enable, True)
1139 wx.CallAfter(self.resumeButton.Enable, True)
1140 wx.CallAfter(self.resumeButton.SetFocus)
1142 elif self.comm.isError():
1143 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1145 def mcMessage(self, message):
1148 def mcProgress(self, lineNr):
1151 def mcZChange(self, newZ):
1154 class bedLevelWizard(wx.wizard.Wizard):
1156 super(bedLevelWizard, self).__init__(None, -1, "Bed leveling wizard")
1158 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1159 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1161 self.mainPage = bedLevelWizardMain(self)
1162 self.headOffsetCalibration = None
1164 self.FitToPage(self.mainPage)
1165 self.GetPageAreaSizer().Add(self.mainPage)
1167 self.RunWizard(self.mainPage)
1170 def OnPageChanging(self, e):
1171 e.GetPage().StoreData()
1173 def OnPageChanged(self, e):
1174 if e.GetPage().AllowNext():
1175 self.FindWindowById(wx.ID_FORWARD).Enable()
1177 self.FindWindowById(wx.ID_FORWARD).Disable()
1178 self.FindWindowById(wx.ID_BACKWARD).Disable()
1180 class headOffsetWizard(wx.wizard.Wizard):
1182 super(headOffsetWizard, self).__init__(None, -1, "Head offset wizard")
1184 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1185 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1187 self.mainPage = headOffsetCalibrationPage(self)
1189 self.FitToPage(self.mainPage)
1190 self.GetPageAreaSizer().Add(self.mainPage)
1192 self.RunWizard(self.mainPage)
1195 def OnPageChanging(self, e):
1196 e.GetPage().StoreData()
1198 def OnPageChanged(self, e):
1199 if e.GetPage().AllowNext():
1200 self.FindWindowById(wx.ID_FORWARD).Enable()
1202 self.FindWindowById(wx.ID_FORWARD).Disable()
1203 self.FindWindowById(wx.ID_BACKWARD).Disable()