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")
340 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.')
341 self.AddHiddenSeperator()
342 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
343 self.AddHiddenSeperator()
344 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.')
345 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
346 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
347 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
348 self.AddHiddenSeperator()
349 self.AddText('Do not upgrade to this firmware if:')
350 self.AddText('* You have an older machine based on ATMega1280')
351 self.AddText('* Have other changes in the firmware')
352 # button = self.AddButton('Goto this page for a custom firmware')
353 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
358 def OnUpgradeClick(self, e):
359 if firmwareInstall.InstallFirmware():
360 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
362 def OnSkipClick(self, e):
363 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
364 self.GetParent().ShowPage(self.GetNext())
366 def OnUrlClick(self, e):
367 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
370 class UltimakerCheckupPage(InfoPage):
371 def __init__(self, parent):
372 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
374 self.checkBitmap = wx.Bitmap(getPathForImage('checkmark.png'))
375 self.crossBitmap = wx.Bitmap(getPathForImage('cross.png'))
376 self.unknownBitmap = wx.Bitmap(getPathForImage('question.png'))
377 self.endStopNoneBitmap = wx.Bitmap(getPathForImage('endstop_none.png'))
378 self.endStopXMinBitmap = wx.Bitmap(getPathForImage('endstop_xmin.png'))
379 self.endStopXMaxBitmap = wx.Bitmap(getPathForImage('endstop_xmax.png'))
380 self.endStopYMinBitmap = wx.Bitmap(getPathForImage('endstop_ymin.png'))
381 self.endStopYMaxBitmap = wx.Bitmap(getPathForImage('endstop_ymax.png'))
382 self.endStopZMinBitmap = wx.Bitmap(getPathForImage('endstop_zmin.png'))
383 self.endStopZMaxBitmap = wx.Bitmap(getPathForImage('endstop_zmax.png'))
386 '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.')
387 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
388 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
389 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
391 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
392 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
393 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
395 self.infoBox = self.AddInfoBox()
396 self.machineState = self.AddText('')
397 self.temperatureLabel = self.AddText('')
398 self.errorLogButton = self.AddButton('Show error log')
399 self.errorLogButton.Show(False)
401 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
403 self.xMinStop = False
404 self.xMaxStop = False
405 self.yMinStop = False
406 self.yMaxStop = False
407 self.zMinStop = False
408 self.zMaxStop = False
410 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
413 if self.comm is not None:
417 self.endstopBitmap.Show(False)
420 def OnSkipClick(self, e):
421 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
422 self.GetParent().ShowPage(self.GetNext())
424 def OnCheckClick(self, e=None):
425 self.errorLogButton.Show(False)
426 if self.comm is not None:
430 wx.CallAfter(self.OnCheckClick)
432 self.infoBox.SetBusy('Connecting to machine.')
433 self.commState.SetBitmap(self.unknownBitmap)
434 self.tempState.SetBitmap(self.unknownBitmap)
435 self.stopState.SetBitmap(self.unknownBitmap)
436 self.checkupState = 0
437 self.checkExtruderNr = 0
438 self.comm = machineCom.MachineCom(callbackObject=self)
440 def OnErrorLog(self, e):
441 printWindow.LogWindow('\n'.join(self.comm.getLog()))
443 def mcLog(self, message):
446 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
447 if not self.comm.isOperational():
449 if self.checkupState == 0:
450 self.tempCheckTimeout = 20
451 if temp[self.checkExtruderNr] > 70:
452 self.checkupState = 1
453 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
454 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
455 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
457 self.startTemp = temp[self.checkExtruderNr]
458 self.checkupState = 2
459 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
460 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
461 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
462 elif self.checkupState == 1:
464 self.startTemp = temp[self.checkExtruderNr]
465 self.checkupState = 2
466 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
467 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
468 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
469 elif self.checkupState == 2:
470 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
471 if temp[self.checkExtruderNr] > self.startTemp + 40:
472 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
473 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
474 if self.checkExtruderNr < int(profile.getPreference('extruder_amount')):
475 self.checkExtruderNr = 0
476 self.checkupState = 3
477 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
478 wx.CallAfter(self.endstopBitmap.Show, True)
479 wx.CallAfter(self.Layout)
480 self.comm.sendCommand('M119')
481 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
483 self.checkupState = 0
484 self.checkExtruderNr += 1
486 self.tempCheckTimeout -= 1
487 if self.tempCheckTimeout < 1:
488 self.checkupState = -1
489 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
490 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
491 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
492 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
493 elif self.checkupState >= 3 and self.checkupState < 10:
494 self.comm.sendCommand('M119')
495 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp[self.checkExtruderNr]))
497 def mcStateChange(self, state):
498 if self.comm is None:
500 if self.comm.isOperational():
501 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
502 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
503 elif self.comm.isError():
504 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
505 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
506 wx.CallAfter(self.endstopBitmap.Show, False)
507 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
508 wx.CallAfter(self.errorLogButton.Show, True)
509 wx.CallAfter(self.Layout)
511 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
513 def mcMessage(self, message):
514 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
515 for data in message.split(' '):
517 tag, value = data.split(':', 1)
519 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
521 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
523 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
525 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
527 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
529 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
531 tag, value = map(str.strip, message.split(':', 1))
533 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
535 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
537 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
539 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
541 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
543 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
544 if 'z_max' in message:
545 self.comm.sendCommand('M119')
547 if self.checkupState == 3:
548 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
549 self.checkupState = 4
550 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
551 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
552 elif self.checkupState == 4:
553 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
554 self.checkupState = 5
555 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
556 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
557 elif self.checkupState == 5:
558 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
559 self.checkupState = 6
560 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
561 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
562 elif self.checkupState == 6:
563 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
564 self.checkupState = 7
565 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
566 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
567 elif self.checkupState == 7:
568 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
569 self.checkupState = 8
570 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
571 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
572 elif self.checkupState == 8:
573 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
574 self.checkupState = 9
575 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
576 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
577 elif self.checkupState == 9:
578 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
579 self.checkupState = 10
581 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
582 wx.CallAfter(self.infoBox.SetReadyIndicator)
583 wx.CallAfter(self.endstopBitmap.Show, False)
584 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
585 wx.CallAfter(self.OnSkipClick, None)
587 def mcProgress(self, lineNr):
590 def mcZChange(self, newZ):
594 class UltimakerCalibrationPage(InfoPage):
595 def __init__(self, parent):
596 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
598 self.AddText("Your Ultimaker requires some calibration.")
599 self.AddText("This calibration is needed for a proper extrusion amount.")
601 self.AddText("The following values are needed:")
602 self.AddText("* Diameter of filament")
603 self.AddText("* Number of steps per mm of filament extrusion")
605 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
607 self.AddText("First we need the diameter of your filament:")
608 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
610 "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.")
611 self.AddText("Note: This value can be changed later at any time.")
614 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
617 class UltimakerCalibrateStepsPerEPage(InfoPage):
618 def __init__(self, parent):
619 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
621 #if profile.getPreference('steps_per_e') == '0':
622 # profile.putPreference('steps_per_e', '865.888')
624 self.AddText("Calibrating the Steps Per E requires some manual actions.")
625 self.AddText("First remove any filament from your machine.")
626 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
627 self.AddText("We'll push the filament 100mm")
628 self.extrudeButton = self.AddButton("Extrude 100mm filament")
629 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
630 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
631 self.AddText("This results in the following steps per E:")
632 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
633 self.AddText("You can repeat these steps to get better calibration.")
636 "If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
637 self.heatButton = self.AddButton("Heatup for filament removal")
639 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
640 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
641 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
643 def OnSaveLengthClick(self, e):
644 currentEValue = float(self.stepsPerEInput.GetValue())
645 realExtrudeLength = float(self.lengthInput.GetValue())
646 newEValue = currentEValue * 100 / realExtrudeLength
647 self.stepsPerEInput.SetValue(str(newEValue))
648 self.lengthInput.SetValue("100")
650 def OnExtrudeClick(self, e):
651 threading.Thread(target=self.OnExtrudeRun).start()
653 def OnExtrudeRun(self):
654 self.heatButton.Enable(False)
655 self.extrudeButton.Enable(False)
656 currentEValue = float(self.stepsPerEInput.GetValue())
657 self.comm = machineCom.MachineCom()
658 if not self.comm.isOpen():
660 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
661 'Printer error', wx.OK | wx.ICON_INFORMATION)
662 self.heatButton.Enable(True)
663 self.extrudeButton.Enable(True)
666 line = self.comm.readline()
671 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
674 self.sendGCommand('M302') #Disable cold extrusion protection
675 self.sendGCommand("M92 E%f" % (currentEValue))
676 self.sendGCommand("G92 E0")
677 self.sendGCommand("G1 E100 F600")
680 self.extrudeButton.Enable()
681 self.heatButton.Enable()
683 def OnHeatClick(self, e):
684 threading.Thread(target=self.OnHeatRun).start()
687 self.heatButton.Enable(False)
688 self.extrudeButton.Enable(False)
689 self.comm = machineCom.MachineCom()
690 if not self.comm.isOpen():
692 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
693 'Printer error', wx.OK | wx.ICON_INFORMATION)
694 self.heatButton.Enable(True)
695 self.extrudeButton.Enable(True)
698 line = self.comm.readline()
700 self.heatButton.Enable(True)
701 self.extrudeButton.Enable(True)
705 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
708 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
710 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
711 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
712 self.sendGCommand('M104 S0')
715 self.heatButton.Enable(True)
716 self.extrudeButton.Enable(True)
718 def sendGCommand(self, cmd):
719 self.comm.sendCommand(cmd) #Disable cold extrusion protection
721 line = self.comm.readline()
724 if line.startswith('ok'):
728 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
731 class configWizard(wx.wizard.Wizard):
733 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
735 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
736 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
738 self.firstInfoPage = FirstInfoPage(self)
739 self.machineSelectPage = MachineSelectPage(self)
740 self.ultimakerSelectParts = SelectParts(self)
741 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
742 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
743 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
744 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
745 self.bedLevelPage = bedLevelWizardMain(self)
746 self.headOffsetCalibration = headOffsetCalibrationPage(self)
747 self.repRapInfoPage = RepRapInfoPage(self)
749 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
750 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
751 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
752 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
753 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
754 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
756 self.FitToPage(self.firstInfoPage)
757 self.GetPageAreaSizer().Add(self.firstInfoPage)
759 self.RunWizard(self.firstInfoPage)
762 def OnPageChanging(self, e):
763 e.GetPage().StoreData()
765 def OnPageChanged(self, e):
766 if e.GetPage().AllowNext():
767 self.FindWindowById(wx.ID_FORWARD).Enable()
769 self.FindWindowById(wx.ID_FORWARD).Disable()
770 self.FindWindowById(wx.ID_BACKWARD).Disable()
772 class bedLevelWizardMain(InfoPage):
773 def __init__(self, parent):
774 super(bedLevelWizardMain, self).__init__(parent, "Bed leveling wizard")
776 self.AddText('This wizard will help you in leveling your printer bed')
778 self.AddText('It will do the following steps')
779 self.AddText('* Move the printer head to each corner')
780 self.AddText(' and let you adjust the height of the bed to the nozzle')
781 self.AddText('* Print a line around the bed to check if it is level')
784 self.connectButton = self.AddButton('Connect to printer')
787 self.infoBox = self.AddInfoBox()
788 self.resumeButton = self.AddButton('Resume')
789 self.resumeButton.Enable(False)
791 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
792 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
794 def OnConnect(self, e = None):
795 if self.comm is not None:
799 wx.CallAfter(self.OnConnect)
801 self.connectButton.Enable(False)
802 self.comm = machineCom.MachineCom(callbackObject=self)
803 self.infoBox.SetBusy('Connecting to machine.')
804 self._wizardState = 0
807 if self.GetParent().headOffsetCalibration is not None and int(profile.getPreference('extruder_amount')) > 1:
808 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
811 def OnResume(self, e):
812 feedZ = profile.getProfileSettingFloat('print_speed') * 60
813 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
814 if self._wizardState == 2:
815 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...')
816 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
817 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getPreferenceFloat('machine_depth'), feedTravel))
818 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
819 self.comm.sendCommand('M400')
820 self._wizardState = 3
821 elif self._wizardState == 4:
822 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...')
823 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
824 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width') - 5.0, profile.getPreferenceFloat('machine_depth') - 25, feedTravel))
825 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
826 self.comm.sendCommand('M400')
827 self._wizardState = 5
828 elif self._wizardState == 6:
829 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
830 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
831 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getPreferenceFloat('machine_width') - 5.0, 20, feedTravel))
832 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
833 self.comm.sendCommand('M400')
834 self._wizardState = 7
835 elif self._wizardState == 8:
836 wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...')
837 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
838 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
839 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
840 self._wizardState = 9
841 elif self._wizardState == 10:
842 self._wizardState = 11
843 wx.CallAfter(self.infoBox.SetInfo, 'Printing a square on the printer bed at 0.3mm height.')
844 feedZ = profile.getProfileSettingFloat('print_speed') * 60
845 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
846 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
847 w = profile.getPreferenceFloat('machine_width')
848 d = profile.getPreferenceFloat('machine_depth')
849 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
850 filamentArea = math.pi * filamentRadius * filamentRadius
851 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
855 'G1 Z2 F%d' % (feedZ),
857 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
858 'G1 Z0.3 F%d' % (feedZ)]
860 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
862 for i in xrange(0, 3):
863 dist = 5.0 + 0.4 * float(i)
864 eValue += (d - 2.0*dist) * ePerMM
865 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
866 eValue += (w - 2.0*dist) * ePerMM
867 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
868 eValue += (d - 2.0*dist) * ePerMM
869 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
870 eValue += (w - 2.0*dist) * ePerMM
871 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
873 gcodeList.append('M400')
874 self.comm.printGCode(gcodeList)
875 self.resumeButton.Enable(False)
877 def mcLog(self, message):
878 print 'Log:', message
880 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
881 if self._wizardState == 1:
882 self._wizardState = 2
883 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.')
884 wx.CallAfter(self.resumeButton.Enable, True)
885 elif self._wizardState == 3:
886 self._wizardState = 4
887 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.')
888 wx.CallAfter(self.resumeButton.Enable, True)
889 elif self._wizardState == 5:
890 self._wizardState = 6
891 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.')
892 wx.CallAfter(self.resumeButton.Enable, True)
893 elif self._wizardState == 7:
894 self._wizardState = 8
895 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.')
896 wx.CallAfter(self.resumeButton.Enable, True)
897 elif self._wizardState == 9:
898 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
899 wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature')))
901 wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.')
902 wx.CallAfter(self.resumeButton.Enable, True)
903 self._wizardState = 10
905 def mcStateChange(self, state):
906 if self.comm is None:
908 if self.comm.isOperational():
909 if self._wizardState == 0:
910 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer...')
911 self.comm.sendCommand('M105')
912 self.comm.sendCommand('G28')
913 self._wizardState = 1
914 elif self._wizardState == 11 and not self.comm.isPrinting():
915 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
916 self.comm.sendCommand('G92 E0')
917 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
918 self.comm.sendCommand('M104 S0')
919 wx.CallAfter(self.infoBox.SetInfo, 'Calibration finished.\nThe squares on the bed should slightly touch each other.')
920 wx.CallAfter(self.infoBox.SetReadyIndicator)
921 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
922 wx.CallAfter(self.connectButton.Enable, True)
923 self._wizardState = 12
924 elif self.comm.isError():
925 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
927 def mcMessage(self, message):
930 def mcProgress(self, lineNr):
933 def mcZChange(self, newZ):
936 class headOffsetCalibrationPage(InfoPage):
937 def __init__(self, parent):
938 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
940 self.AddText('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine')
943 self.connectButton = self.AddButton('Connect to printer')
946 self.infoBox = self.AddInfoBox()
947 self.textEntry = self.AddTextCtrl('')
948 self.textEntry.Enable(False)
949 self.resumeButton = self.AddButton('Resume')
950 self.resumeButton.Enable(False)
952 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
953 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
955 def OnConnect(self, e = None):
956 if self.comm is not None:
960 wx.CallAfter(self.OnConnect)
962 self.connectButton.Enable(False)
963 self.comm = machineCom.MachineCom(callbackObject=self)
964 self.infoBox.SetBusy('Connecting to machine.')
965 self._wizardState = 0
967 def OnResume(self, e):
968 if self._wizardState == 2:
969 self._wizardState = 3
970 wx.CallAfter(self.infoBox.SetBusy, 'Printing initial calibration cross')
972 w = profile.getPreferenceFloat('machine_width')
973 d = profile.getPreferenceFloat('machine_depth')
975 gcode = gcodeGenerator.gcodeGenerator()
976 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
977 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
984 gcode.addMove(w/2, 5)
987 gcode.addExtrude(w/2, d-5.0)
989 gcode.addMove(5, d/2)
991 gcode.addExtrude(w-5.0, d/2)
995 gcode.addMove(w/2, 5)
997 gcode.addExtrude(w/2, d-5.0)
999 gcode.addMove(5, d/2)
1001 gcode.addExtrude(w-5.0, d/2)
1002 gcode.addRetract(15)
1007 gcode.addCmd('M400')
1009 self.comm.printGCode(gcode.list())
1010 self.resumeButton.Enable(False)
1011 elif self._wizardState == 4:
1013 float(self.textEntry.GetValue())
1016 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1017 self._wizardState = 5
1018 self.infoBox.SetAttention('Please measure the distance between the horizontal lines in millimeters.')
1019 self.textEntry.SetValue('0.0')
1020 self.textEntry.Enable(True)
1021 elif self._wizardState == 5:
1023 float(self.textEntry.GetValue())
1026 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1027 self._wizardState = 6
1028 self.infoBox.SetBusy('Printing the fine calibration lines.')
1029 self.textEntry.SetValue('')
1030 self.textEntry.Enable(False)
1031 self.resumeButton.Enable(False)
1033 x = profile.getPreferenceFloat('extruder_offset_x1')
1034 y = profile.getPreferenceFloat('extruder_offset_y1')
1035 gcode = gcodeGenerator.gcodeGenerator()
1036 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1037 gcode.setPrintSpeed(25)
1040 gcode.addMove(50, 40, 0.2)
1042 for n in xrange(0, 10):
1043 gcode.addExtrude(50 + n * 10, 150)
1044 gcode.addExtrude(50 + n * 10 + 5, 150)
1045 gcode.addExtrude(50 + n * 10 + 5, 40)
1046 gcode.addExtrude(50 + n * 10 + 10, 40)
1047 gcode.addMove(40, 50)
1048 for n in xrange(0, 10):
1049 gcode.addExtrude(150, 50 + n * 10)
1050 gcode.addExtrude(150, 50 + n * 10 + 5)
1051 gcode.addExtrude(40, 50 + n * 10 + 5)
1052 gcode.addExtrude(40, 50 + n * 10 + 10)
1053 gcode.addRetract(15)
1056 gcode.addMove(50 - x, 30 - y, 0.2)
1058 for n in xrange(0, 10):
1059 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1060 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1061 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1062 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1063 gcode.addMove(30 - x, 50 - y, 0.2)
1064 for n in xrange(0, 10):
1065 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1066 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1067 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1068 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1069 gcode.addRetract(15)
1071 gcode.addCmd('M400')
1072 gcode.addCmd('M104 T0 S0')
1073 gcode.addCmd('M104 T1 S0')
1074 self.comm.printGCode(gcode.list())
1075 elif self._wizardState == 7:
1077 n = int(self.textEntry.GetValue()) - 1
1080 x = profile.getPreferenceFloat('extruder_offset_x1')
1082 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1083 self.infoBox.SetAttention('Which horizontal line number lays perfect on top of each other? Front most line is zero.')
1084 self.textEntry.SetValue('10')
1085 self._wizardState = 8
1086 elif self._wizardState == 8:
1088 n = int(self.textEntry.GetValue()) - 1
1091 y = profile.getPreferenceFloat('extruder_offset_y1')
1093 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1094 self.infoBox.SetInfo('Calibration finished. Offsets are: %s %s' % (profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1')))
1095 self.infoBox.SetReadyIndicator()
1096 self._wizardState = 8
1098 self.resumeButton.Enable(False)
1100 def mcLog(self, message):
1101 print 'Log:', message
1103 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1104 if self._wizardState == 1:
1105 if temp[0] >= 210 and temp[1] >= 210:
1106 self._wizardState = 2
1107 wx.CallAfter(self.infoBox.SetAttention, 'Please load both extruders with PLA.')
1108 wx.CallAfter(self.resumeButton.Enable, True)
1109 wx.CallAfter(self.resumeButton.SetFocus)
1111 def mcStateChange(self, state):
1112 if self.comm is None:
1114 if self.comm.isOperational():
1115 if self._wizardState == 0:
1116 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.')
1117 self.comm.sendCommand('M105')
1118 self.comm.sendCommand('M104 S220 T0')
1119 self.comm.sendCommand('M104 S220 T1')
1120 self.comm.sendCommand('G28')
1121 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1122 self._wizardState = 1
1123 if not self.comm.isPrinting():
1124 if self._wizardState == 3:
1125 self._wizardState = 4
1126 wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.')
1127 wx.CallAfter(self.textEntry.SetValue, '0.0')
1128 wx.CallAfter(self.textEntry.Enable, True)
1129 wx.CallAfter(self.resumeButton.Enable, True)
1130 wx.CallAfter(self.resumeButton.SetFocus)
1131 elif self._wizardState == 6:
1132 self._wizardState = 7
1133 wx.CallAfter(self.infoBox.SetAttention, 'Which vertical line number lays perfect on top of each other? Leftmost line is zero.')
1134 wx.CallAfter(self.textEntry.SetValue, '10')
1135 wx.CallAfter(self.textEntry.Enable, True)
1136 wx.CallAfter(self.resumeButton.Enable, True)
1137 wx.CallAfter(self.resumeButton.SetFocus)
1139 elif self.comm.isError():
1140 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1142 def mcMessage(self, message):
1145 def mcProgress(self, lineNr):
1148 def mcZChange(self, newZ):
1151 class bedLevelWizard(wx.wizard.Wizard):
1153 super(bedLevelWizard, self).__init__(None, -1, "Bed leveling wizard")
1155 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1156 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1158 self.mainPage = bedLevelWizardMain(self)
1159 self.headOffsetCalibration = None
1161 self.FitToPage(self.mainPage)
1162 self.GetPageAreaSizer().Add(self.mainPage)
1164 self.RunWizard(self.mainPage)
1167 def OnPageChanging(self, e):
1168 e.GetPage().StoreData()
1170 def OnPageChanged(self, e):
1171 if e.GetPage().AllowNext():
1172 self.FindWindowById(wx.ID_FORWARD).Enable()
1174 self.FindWindowById(wx.ID_FORWARD).Disable()
1175 self.FindWindowById(wx.ID_BACKWARD).Disable()
1177 class headOffsetWizard(wx.wizard.Wizard):
1179 super(headOffsetWizard, self).__init__(None, -1, "Head offset wizard")
1181 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1182 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1184 self.mainPage = headOffsetCalibrationPage(self)
1186 self.FitToPage(self.mainPage)
1187 self.GetPageAreaSizer().Add(self.mainPage)
1189 self.RunWizard(self.mainPage)
1192 def OnPageChanging(self, e):
1193 e.GetPage().StoreData()
1195 def OnPageChanged(self, e):
1196 if e.GetPage().AllowNext():
1197 self.FindWindowById(wx.ID_FORWARD).Enable()
1199 self.FindWindowById(wx.ID_FORWARD).Disable()
1200 self.FindWindowById(wx.ID_BACKWARD).Disable()