1 __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 import resources
20 class InfoBox(wx.Panel):
21 def __init__(self, parent):
22 super(InfoBox, self).__init__(parent)
23 self.SetBackgroundColour('#FFFF80')
25 self.sizer = wx.GridBagSizer(5, 5)
26 self.SetSizer(self.sizer)
28 self.attentionBitmap = wx.Bitmap(resources.getPathForImage('attention.png'))
29 self.errorBitmap = wx.Bitmap(resources.getPathForImage('error.png'))
30 self.readyBitmap = wx.Bitmap(resources.getPathForImage('ready.png'))
32 wx.Bitmap(resources.getPathForImage('busy-0.png')),
33 wx.Bitmap(resources.getPathForImage('busy-1.png')),
34 wx.Bitmap(resources.getPathForImage('busy-2.png')),
35 wx.Bitmap(resources.getPathForImage('busy-3.png'))
38 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
39 self.text = wx.StaticText(self, -1, '')
40 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
41 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
42 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
43 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
44 self.sizer.AddGrowableCol(1)
46 self.extraInfoButton.Show(False)
48 self.extraInfoUrl = ''
50 self.timer = wx.Timer(self)
51 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
52 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
55 def SetInfo(self, info):
56 self.SetBackgroundColour('#FFFF80')
57 self.text.SetLabel(info)
58 self.extraInfoButton.Show(False)
61 def SetError(self, info, extraInfoUrl):
62 self.extraInfoUrl = extraInfoUrl
63 self.SetBackgroundColour('#FF8080')
64 self.text.SetLabel(info)
65 self.extraInfoButton.Show(True)
67 self.SetErrorIndicator()
70 def SetAttention(self, info):
71 self.SetBackgroundColour('#FFFF80')
72 self.text.SetLabel(info)
73 self.extraInfoButton.Show(False)
74 self.SetAttentionIndicator()
78 def SetBusy(self, info):
80 self.SetBusyIndicator()
82 def SetBusyIndicator(self):
84 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
86 def doExtraInfo(self, e):
87 webbrowser.open(self.extraInfoUrl)
89 def doBusyUpdate(self, e):
90 if self.busyState is None:
93 if self.busyState >= len(self.busyBitmap):
95 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
97 def SetReadyIndicator(self):
99 self.bitmap.SetBitmap(self.readyBitmap)
101 def SetErrorIndicator(self):
102 self.busyState = None
103 self.bitmap.SetBitmap(self.errorBitmap)
105 def SetAttentionIndicator(self):
106 self.busyState = None
107 self.bitmap.SetBitmap(self.attentionBitmap)
110 class InfoPage(wx.wizard.WizardPageSimple):
111 def __init__(self, parent, title):
112 wx.wizard.WizardPageSimple.__init__(self, parent)
114 sizer = wx.GridBagSizer(5, 5)
118 title = wx.StaticText(self, -1, title)
119 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
120 sizer.Add(title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
121 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
122 sizer.AddGrowableCol(1)
126 def AddText(self, info):
127 text = wx.StaticText(self, -1, info)
128 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
132 def AddSeperator(self):
133 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
136 def AddHiddenSeperator(self):
139 def AddInfoBox(self):
140 infoBox = InfoBox(self)
141 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
145 def AddRadioButton(self, label, style=0):
146 radio = wx.RadioButton(self, -1, label, style=style)
147 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
151 def AddCheckbox(self, label, checked=False):
152 check = wx.CheckBox(self, -1)
153 text = wx.StaticText(self, -1, label)
154 check.SetValue(checked)
155 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
156 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
160 def AddButton(self, label):
161 button = wx.Button(self, -1, label)
162 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
166 def AddDualButton(self, label1, label2):
167 button1 = wx.Button(self, -1, label1)
168 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
169 button2 = wx.Button(self, -1, label2)
170 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
172 return button1, button2
174 def AddTextCtrl(self, value):
175 ret = wx.TextCtrl(self, -1, value)
176 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
180 def AddLabelTextCtrl(self, info, value):
181 text = wx.StaticText(self, -1, info)
182 ret = wx.TextCtrl(self, -1, value)
183 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
184 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
188 def AddTextCtrlButton(self, value, buttonText):
189 text = wx.TextCtrl(self, -1, value)
190 button = wx.Button(self, -1, buttonText)
191 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
192 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
196 def AddBitmap(self, bitmap):
197 bitmap = wx.StaticBitmap(self, -1, bitmap)
198 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
202 def AddCheckmark(self, label, bitmap):
203 check = wx.StaticBitmap(self, -1, bitmap)
204 text = wx.StaticText(self, -1, label)
205 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
206 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
210 def AddCombo(self, label, options):
211 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
212 text = wx.StaticText(self, -1, label)
213 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
214 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
228 class FirstInfoPage(InfoPage):
229 def __init__(self, parent, addNew):
231 super(FirstInfoPage, self).__init__(parent, _("Add new machine wizard"))
233 super(FirstInfoPage, self).__init__(parent, _("First time run wizard"))
234 self.AddText(_("Welcome, and thanks for trying Cura!"))
236 self.AddText(_("This wizard will help you in setting up Cura for your machine."))
239 self._language_option = self.AddCombo(_("Select your language:"), map(lambda o: o[1], resources.getLanguageOptions()))
241 self._language_option = None
242 # self.AddText(_("This wizard will help you with the following steps:"))
243 # self.AddText(_("* Configure Cura for your machine"))
244 # self.AddText(_("* Optionally upgrade your firmware"))
245 # self.AddText(_("* Optionally check if your machine is working safely"))
246 # self.AddText(_("* Optionally level your printer bed"))
248 #self.AddText('* Calibrate your machine')
249 #self.AddText('* Do your first print')
255 if self._language_option is not None:
256 profile.putPreference('language', self._language_option.GetValue())
257 resources.setupLocalization(self._language_option.GetValue())
259 class PrintrbotPage(InfoPage):
260 def __init__(self, parent):
261 self._printer_info = [
262 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
263 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
264 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
265 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
266 (":" + _("Older models"),),
267 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
268 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
269 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
270 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
271 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
272 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
273 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
274 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
275 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
276 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
277 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
278 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
279 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
282 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
283 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
284 self.AddText(_("Select which Printrbot machine you have:"))
286 for printer in self._printer_info:
287 if printer[0].startswith(":"):
289 self.AddText(printer[0][1:])
291 item = self.AddRadioButton(printer[0])
292 item.data = printer[1:]
293 self._items.append(item)
296 profile.putMachineSetting('machine_name', 'Printrbot ???')
297 for item in self._items:
300 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
301 profile.putMachineSetting('machine_width', data[0])
302 profile.putMachineSetting('machine_depth', data[1])
303 profile.putMachineSetting('machine_height', data[2])
304 profile.putProfileSetting('nozzle_size', data[3])
305 profile.putProfileSetting('filament_diameter', data[4])
306 profile.putProfileSetting('print_temperature', data[5])
307 profile.putProfileSetting('print_speed', data[6])
308 profile.putProfileSetting('travel_speed', data[7])
309 profile.putProfileSetting('retraction_speed', data[8])
310 profile.putProfileSetting('retraction_amount', data[9])
311 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
312 profile.putMachineSetting('has_heated_bed', 'False')
313 profile.putMachineSetting('machine_center_is_zero', 'False')
314 profile.putMachineSetting('extruder_head_size_min_x', '0')
315 profile.putMachineSetting('extruder_head_size_min_y', '0')
316 profile.putMachineSetting('extruder_head_size_max_x', '0')
317 profile.putMachineSetting('extruder_head_size_max_y', '0')
318 profile.putMachineSetting('extruder_head_size_height', '0')
320 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
321 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
322 ;Print time: {print_time}
323 ;Filament used: {filament_amount}m {filament_weight}g
324 ;Filament cost: {filament_cost}
325 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
326 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
328 G90 ;absolute positioning
329 M82 ;set extruder to absolute mode
330 M107 ;start with the fan off
331 G28 X0 Y0 ;move X/Y to min endstops
332 G28 Z0 ;move Z to min endstops
333 G29 ;Run the auto bed leveling
334 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
335 G92 E0 ;zero the extruded length
336 G1 F200 E3 ;extrude 3mm of feed stock
337 G92 E0 ;zero the extruded length again
339 ;Put printing message on LCD screen
343 class OtherMachineSelectPage(InfoPage):
344 def __init__(self, parent):
345 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
346 self.AddText(_("The following pre-defined machine profiles are available"))
347 self.AddText(_("Note that these profiles are not guaranteed to give good results,\nor work at all. Extra tweaks might be required.\nIf you find issues with the predefined profiles,\nor want an extra profile.\nPlease report it at the github issue tracker."))
349 machines = resources.getDefaultMachineProfiles()
351 for filename in machines:
352 name = os.path.splitext(os.path.basename(filename))[0]
353 item = self.AddRadioButton(name)
354 item.filename = filename
355 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
356 self.options.append(item)
358 item = self.AddRadioButton(_('Custom...'))
360 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
362 def OnProfileSelect(self, e):
363 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
365 def OnOtherSelect(self, e):
366 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
369 for option in self.options:
370 if option.GetValue():
371 profile.loadProfile(option.filename)
372 profile.loadMachineSettings(option.filename)
374 class OtherMachineInfoPage(InfoPage):
375 def __init__(self, parent):
376 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
377 self.AddText(_("Cura is now ready to be used!"))
379 class CustomRepRapInfoPage(InfoPage):
380 def __init__(self, parent):
381 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
382 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
383 self.AddText(_("Be sure to review the default profile before running it on your machine."))
384 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
386 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
388 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
389 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
390 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
391 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
392 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
393 self.heatedBed = self.AddCheckbox(_("Heated bed"))
394 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
397 profile.putMachineSetting('machine_name', self.machineName.GetValue())
398 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
399 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
400 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
401 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
402 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
403 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
404 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
405 profile.putMachineSetting('extruder_head_size_min_x', '0')
406 profile.putMachineSetting('extruder_head_size_min_y', '0')
407 profile.putMachineSetting('extruder_head_size_max_x', '0')
408 profile.putMachineSetting('extruder_head_size_max_y', '0')
409 profile.putMachineSetting('extruder_head_size_height', '0')
410 profile.checkAndUpdateMachineName()
412 class MachineSelectPage(InfoPage):
413 def __init__(self, parent):
414 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
415 self.AddText(_("What kind of machine do you have:"))
417 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2", style=wx.RB_GROUP)
418 self.Ultimaker2Radio.SetValue(True)
419 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
420 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
421 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
422 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
423 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
424 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
425 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
426 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
427 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
428 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
429 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
430 self.LulzbotTazRadio = self.AddRadioButton("Lulzbot TAZ")
431 self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
432 self.LulzbotMiniRadio = self.AddRadioButton("Lulzbot Mini")
433 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
434 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
435 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
437 self.AddText(_("The collection of anonymous usage information helps with the continued improvement of Cura."))
438 self.AddText(_("This does NOT submit your models online nor gathers any privacy related information."))
439 self.SubmitUserStats = self.AddCheckbox(_("Submit anonymous usage information:"))
440 self.AddText(_("For full details see: http://wiki.ultimaker.com/Cura:stats"))
441 self.SubmitUserStats.SetValue(True)
443 def OnUltimaker2Select(self, e):
444 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
446 def OnUltimakerSelect(self, e):
447 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
449 def OnUltimakerOPSelect(self, e):
450 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
452 def OnPrintrbotSelect(self, e):
453 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
455 def OnLulzbotSelect(self, e):
456 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
458 def OnOtherSelect(self, e):
459 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
462 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
466 profile.putProfileSetting('retraction_enable', 'True')
467 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
468 if self.Ultimaker2Radio.GetValue():
469 profile.putMachineSetting('machine_width', '230')
470 profile.putMachineSetting('machine_depth', '225')
471 profile.putMachineSetting('machine_height', '205')
472 profile.putMachineSetting('machine_name', 'ultimaker2')
473 profile.putMachineSetting('machine_type', 'ultimaker2')
474 profile.putMachineSetting('has_heated_bed', 'True')
475 if self.Ultimaker2GoRadio.GetValue():
476 profile.putMachineSetting('machine_width', '120')
477 profile.putMachineSetting('machine_depth', '120')
478 profile.putMachineSetting('machine_height', '115')
479 profile.putMachineSetting('machine_name', 'ultimaker2go')
480 profile.putMachineSetting('machine_type', 'ultimaker2go')
481 profile.putMachineSetting('has_heated_bed', 'False')
482 if self.Ultimaker2ExtRadio.GetValue():
483 profile.putMachineSetting('machine_width', '230')
484 profile.putMachineSetting('machine_depth', '225')
485 profile.putMachineSetting('machine_height', '315')
486 profile.putMachineSetting('machine_name', 'ultimaker2extended')
487 profile.putMachineSetting('machine_type', 'ultimaker2extended')
488 profile.putMachineSetting('has_heated_bed', 'False')
489 profile.putMachineSetting('machine_center_is_zero', 'False')
490 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
491 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
492 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
493 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
494 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
495 profile.putMachineSetting('extruder_head_size_height', '48.0')
496 profile.putProfileSetting('nozzle_size', '0.4')
497 profile.putProfileSetting('fan_full_height', '5.0')
498 profile.putMachineSetting('extruder_offset_x1', '18.0')
499 profile.putMachineSetting('extruder_offset_y1', '0.0')
500 elif self.UltimakerRadio.GetValue():
501 profile.putMachineSetting('machine_width', '205')
502 profile.putMachineSetting('machine_depth', '205')
503 profile.putMachineSetting('machine_height', '200')
504 profile.putMachineSetting('machine_name', 'ultimaker original')
505 profile.putMachineSetting('machine_type', 'ultimaker')
506 profile.putMachineSetting('machine_center_is_zero', 'False')
507 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
508 profile.putProfileSetting('nozzle_size', '0.4')
509 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
510 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
511 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
512 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
513 profile.putMachineSetting('extruder_head_size_height', '55.0')
514 elif self.UltimakerOPRadio.GetValue():
515 profile.putMachineSetting('machine_width', '205')
516 profile.putMachineSetting('machine_depth', '205')
517 profile.putMachineSetting('machine_height', '200')
518 profile.putMachineSetting('machine_name', 'ultimaker original+')
519 profile.putMachineSetting('machine_type', 'ultimaker_plus')
520 profile.putMachineSetting('machine_center_is_zero', 'False')
521 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
522 profile.putProfileSetting('nozzle_size', '0.4')
523 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
524 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
525 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
526 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
527 profile.putMachineSetting('extruder_head_size_height', '55.0')
528 profile.putMachineSetting('has_heated_bed', 'True')
529 profile.putMachineSetting('extruder_amount', '1')
530 profile.putProfileSetting('retraction_enable', 'True')
531 elif self.LulzbotTazRadio.GetValue() or self.LulzbotMiniRadio.GetValue():
532 if self.LulzbotTazRadio.GetValue():
533 profile.putMachineSetting('machine_width', '298')
534 profile.putMachineSetting('machine_depth', '275')
535 profile.putMachineSetting('machine_height', '250')
536 profile.putProfileSetting('nozzle_size', '0.35')
537 profile.putMachineSetting('machine_name', 'Lulzbot TAZ')
539 profile.putMachineSetting('machine_width', '160')
540 profile.putMachineSetting('machine_depth', '160')
541 profile.putMachineSetting('machine_height', '160')
542 profile.putProfileSetting('nozzle_size', '0.5')
543 profile.putMachineSetting('machine_name', 'Lulzbot Mini')
544 profile.putMachineSetting('machine_type', 'Aleph Objects')
545 profile.putMachineSetting('machine_center_is_zero', 'False')
546 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
547 profile.putMachineSetting('has_heated_bed', 'True')
548 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
549 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
550 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
551 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
552 profile.putMachineSetting('extruder_head_size_height', '0.0')
554 profile.putMachineSetting('machine_width', '80')
555 profile.putMachineSetting('machine_depth', '80')
556 profile.putMachineSetting('machine_height', '60')
557 profile.putMachineSetting('machine_name', 'reprap')
558 profile.putMachineSetting('machine_type', 'reprap')
559 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
560 profile.putPreference('startMode', 'Normal')
561 profile.putProfileSetting('nozzle_size', '0.5')
562 profile.checkAndUpdateMachineName()
563 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
564 if self.SubmitUserStats.GetValue():
565 profile.putPreference('submit_slice_information', 'True')
567 profile.putPreference('submit_slice_information', 'False')
570 class SelectParts(InfoPage):
571 def __init__(self, parent):
572 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
573 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."))
575 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
576 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
577 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
578 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
580 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."))
581 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
582 self.springExtruder.SetValue(True)
585 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
586 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
587 profile.putMachineSetting('has_heated_bed', 'True')
589 profile.putMachineSetting('has_heated_bed', 'False')
590 if self.dualExtrusion.GetValue():
591 profile.putMachineSetting('extruder_amount', '2')
592 profile.putMachineSetting('machine_depth', '195')
594 profile.putMachineSetting('extruder_amount', '1')
595 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
596 profile.putProfileSetting('retraction_enable', 'True')
598 profile.putProfileSetting('retraction_enable', 'False')
601 class UltimakerFirmwareUpgradePage(InfoPage):
602 def __init__(self, parent):
603 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
604 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."))
605 self.AddHiddenSeperator()
606 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
607 self.AddHiddenSeperator()
608 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."))
609 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
610 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
611 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
612 self.AddHiddenSeperator()
613 if profile.getMachineSetting('machine_type') == 'ultimaker':
614 self.AddText(_("Do not upgrade to this firmware if:"))
615 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
616 self.AddText(_("* Build your own heated bed"))
617 self.AddText(_("* Have other changes in the firmware"))
618 # button = self.AddButton('Goto this page for a custom firmware')
619 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
624 def OnUpgradeClick(self, e):
625 if firmwareInstall.InstallFirmware():
626 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
628 def OnSkipClick(self, e):
629 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
630 self.GetParent().ShowPage(self.GetNext())
632 def OnUrlClick(self, e):
633 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
635 class UltimakerCheckupPage(InfoPage):
636 def __init__(self, parent):
637 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
639 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
640 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
641 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
642 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
643 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
644 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
645 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
646 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
647 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
648 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
651 _("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."))
652 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
653 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
654 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
656 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
657 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
658 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
660 self.infoBox = self.AddInfoBox()
661 self.machineState = self.AddText("")
662 self.temperatureLabel = self.AddText("")
663 self.errorLogButton = self.AddButton(_("Show error log"))
664 self.errorLogButton.Show(False)
666 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
668 self.xMinStop = False
669 self.xMaxStop = False
670 self.yMinStop = False
671 self.yMaxStop = False
672 self.zMinStop = False
673 self.zMaxStop = False
675 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
678 if self.comm is not None:
682 self.endstopBitmap.Show(False)
685 def OnSkipClick(self, e):
686 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
687 self.GetParent().ShowPage(self.GetNext())
689 def OnCheckClick(self, e=None):
690 self.errorLogButton.Show(False)
691 if self.comm is not None:
695 wx.CallAfter(self.OnCheckClick)
697 self.infoBox.SetBusy(_("Connecting to machine."))
698 self.commState.SetBitmap(self.unknownBitmap)
699 self.tempState.SetBitmap(self.unknownBitmap)
700 self.stopState.SetBitmap(self.unknownBitmap)
701 self.checkupState = 0
702 self.checkExtruderNr = 0
703 self.comm = machineCom.MachineCom(callbackObject=self)
705 def OnErrorLog(self, e):
706 printWindow.LogWindow('\n'.join(self.comm.getLog()))
708 def mcLog(self, message):
711 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
712 if not self.comm.isOperational():
714 if self.checkupState == 0:
715 self.tempCheckTimeout = 20
716 if temp[self.checkExtruderNr] > 70:
717 self.checkupState = 1
718 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
719 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
720 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
722 self.startTemp = temp[self.checkExtruderNr]
723 self.checkupState = 2
724 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
725 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
726 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
727 elif self.checkupState == 1:
728 if temp[self.checkExtruderNr] < 60:
729 self.startTemp = temp[self.checkExtruderNr]
730 self.checkupState = 2
731 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
732 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
733 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
734 elif self.checkupState == 2:
735 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
736 if temp[self.checkExtruderNr] > self.startTemp + 40:
737 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
738 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
739 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
740 self.checkExtruderNr = 0
741 self.checkupState = 3
742 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
743 wx.CallAfter(self.endstopBitmap.Show, True)
744 wx.CallAfter(self.Layout)
745 self.comm.sendCommand('M119')
746 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
748 self.checkupState = 0
749 self.checkExtruderNr += 1
751 self.tempCheckTimeout -= 1
752 if self.tempCheckTimeout < 1:
753 self.checkupState = -1
754 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
755 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
756 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
757 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
758 elif self.checkupState >= 3 and self.checkupState < 10:
759 self.comm.sendCommand('M119')
760 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
762 def mcStateChange(self, state):
763 if self.comm is None:
765 if self.comm.isOperational():
766 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
767 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
768 elif self.comm.isError():
769 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
770 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
771 wx.CallAfter(self.endstopBitmap.Show, False)
772 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
773 wx.CallAfter(self.errorLogButton.Show, True)
774 wx.CallAfter(self.Layout)
776 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
778 def mcMessage(self, message):
779 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
780 for data in message.split(' '):
782 tag, value = data.split(':', 1)
784 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
786 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
788 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
790 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
792 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
794 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
796 tag, value = map(str.strip, message.split(':', 1))
798 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
800 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
802 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
804 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
806 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
808 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
809 if 'z_max' in message:
810 self.comm.sendCommand('M119')
812 if self.checkupState == 3:
813 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
814 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
815 self.checkupState = 5
816 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
817 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
819 self.checkupState = 4
820 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
821 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
822 elif self.checkupState == 4:
823 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
824 self.checkupState = 5
825 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
826 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
827 elif self.checkupState == 5:
828 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
829 self.checkupState = 6
830 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
831 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
832 elif self.checkupState == 6:
833 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
834 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
835 self.checkupState = 8
836 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
837 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
839 self.checkupState = 7
840 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
841 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
842 elif self.checkupState == 7:
843 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
844 self.checkupState = 8
845 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
846 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
847 elif self.checkupState == 8:
848 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
849 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
850 self.checkupState = 10
852 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
853 wx.CallAfter(self.infoBox.SetReadyIndicator)
854 wx.CallAfter(self.endstopBitmap.Show, False)
855 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
856 wx.CallAfter(self.OnSkipClick, None)
858 self.checkupState = 9
859 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
860 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
861 elif self.checkupState == 9:
862 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
863 self.checkupState = 10
865 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
866 wx.CallAfter(self.infoBox.SetReadyIndicator)
867 wx.CallAfter(self.endstopBitmap.Show, False)
868 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
869 wx.CallAfter(self.OnSkipClick, None)
871 def mcProgress(self, lineNr):
874 def mcZChange(self, newZ):
878 class UltimakerCalibrationPage(InfoPage):
879 def __init__(self, parent):
880 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
882 self.AddText("Your Ultimaker requires some calibration.")
883 self.AddText("This calibration is needed for a proper extrusion amount.")
885 self.AddText("The following values are needed:")
886 self.AddText("* Diameter of filament")
887 self.AddText("* Number of steps per mm of filament extrusion")
889 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
891 self.AddText("First we need the diameter of your filament:")
892 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
894 "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.")
895 self.AddText("Note: This value can be changed later at any time.")
898 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
901 class UltimakerCalibrateStepsPerEPage(InfoPage):
902 def __init__(self, parent):
903 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
905 #if profile.getMachineSetting('steps_per_e') == '0':
906 # profile.putMachineSetting('steps_per_e', '865.888')
908 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
909 self.AddText(_("First remove any filament from your machine."))
910 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
911 self.AddText(_("We'll push the filament 100mm"))
912 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
913 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
914 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
915 self.AddText(_("This results in the following steps per E:"))
916 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
917 self.AddText(_("You can repeat these steps to get better calibration."))
920 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
921 self.heatButton = self.AddButton(_("Heatup for filament removal"))
923 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
924 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
925 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
927 def OnSaveLengthClick(self, e):
928 currentEValue = float(self.stepsPerEInput.GetValue())
929 realExtrudeLength = float(self.lengthInput.GetValue())
930 newEValue = currentEValue * 100 / realExtrudeLength
931 self.stepsPerEInput.SetValue(str(newEValue))
932 self.lengthInput.SetValue("100")
934 def OnExtrudeClick(self, e):
935 t = threading.Thread(target=self.OnExtrudeRun)
939 def OnExtrudeRun(self):
940 self.heatButton.Enable(False)
941 self.extrudeButton.Enable(False)
942 currentEValue = float(self.stepsPerEInput.GetValue())
943 self.comm = machineCom.MachineCom()
944 if not self.comm.isOpen():
946 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
947 'Printer error', wx.OK | wx.ICON_INFORMATION)
948 self.heatButton.Enable(True)
949 self.extrudeButton.Enable(True)
952 line = self.comm.readline()
957 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
960 self.sendGCommand('M302') #Disable cold extrusion protection
961 self.sendGCommand("M92 E%f" % (currentEValue))
962 self.sendGCommand("G92 E0")
963 self.sendGCommand("G1 E100 F600")
966 self.extrudeButton.Enable()
967 self.heatButton.Enable()
969 def OnHeatClick(self, e):
970 t = threading.Thread(target=self.OnHeatRun)
975 self.heatButton.Enable(False)
976 self.extrudeButton.Enable(False)
977 self.comm = machineCom.MachineCom()
978 if not self.comm.isOpen():
980 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
981 'Printer error', wx.OK | wx.ICON_INFORMATION)
982 self.heatButton.Enable(True)
983 self.extrudeButton.Enable(True)
986 line = self.comm.readline()
988 self.heatButton.Enable(True)
989 self.extrudeButton.Enable(True)
993 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
996 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
998 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
999 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
1000 self.sendGCommand('M104 S0')
1003 self.heatButton.Enable(True)
1004 self.extrudeButton.Enable(True)
1006 def sendGCommand(self, cmd):
1007 self.comm.sendCommand(cmd) #Disable cold extrusion protection
1009 line = self.comm.readline()
1012 if line.startswith('ok'):
1015 def StoreData(self):
1016 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1018 class Ultimaker2ReadyPage(InfoPage):
1019 def __init__(self, parent):
1020 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1021 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1022 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1025 class LulzbotReadyPage(InfoPage):
1026 def __init__(self, parent):
1027 super(LulzbotReadyPage, self).__init__(parent, _("Lulzbot TAZ/Mini"))
1028 self.AddText(_('Cura is now ready to be used with your Lulzbot.'))
1031 class ConfigWizard(wx.wizard.Wizard):
1032 def __init__(self, addNew = False):
1033 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1035 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1037 profile.setActiveMachine(profile.getMachineCount())
1039 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1040 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1041 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1043 self.firstInfoPage = FirstInfoPage(self, addNew)
1044 self.machineSelectPage = MachineSelectPage(self)
1045 self.ultimakerSelectParts = SelectParts(self)
1046 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1047 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1048 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1049 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1050 self.bedLevelPage = bedLevelWizardMain(self)
1051 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1052 self.printrbotSelectType = PrintrbotPage(self)
1053 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1054 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1055 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1057 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1058 self.lulzbotReadyPage = LulzbotReadyPage(self)
1060 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
1061 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1062 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1063 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1064 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1065 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1066 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1067 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1068 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1070 self.FitToPage(self.firstInfoPage)
1071 self.GetPageAreaSizer().Add(self.firstInfoPage)
1073 self.RunWizard(self.firstInfoPage)
1076 def OnPageChanging(self, e):
1077 e.GetPage().StoreData()
1079 def OnPageChanged(self, e):
1080 if e.GetPage().AllowNext():
1081 self.FindWindowById(wx.ID_FORWARD).Enable()
1083 self.FindWindowById(wx.ID_FORWARD).Disable()
1084 if e.GetPage().AllowBack():
1085 self.FindWindowById(wx.ID_BACKWARD).Enable()
1087 self.FindWindowById(wx.ID_BACKWARD).Disable()
1089 def OnCancel(self, e):
1090 profile.setActiveMachine(self._old_machine_index)
1092 class bedLevelWizardMain(InfoPage):
1093 def __init__(self, parent):
1094 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1096 self.AddText(_('This wizard will help you in leveling your printer bed'))
1098 self.AddText(_('It will do the following steps'))
1099 self.AddText(_('* Move the printer head to each corner'))
1100 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1101 self.AddText(_('* Print a line around the bed to check if it is level'))
1104 self.connectButton = self.AddButton(_('Connect to printer'))
1107 self.infoBox = self.AddInfoBox()
1108 self.resumeButton = self.AddButton(_('Resume'))
1109 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1110 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1111 self.resumeButton.Enable(False)
1113 self.upButton.Enable(False)
1114 self.downButton.Enable(False)
1115 self.upButton2.Enable(False)
1116 self.downButton2.Enable(False)
1118 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1119 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1120 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1121 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1122 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1123 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1125 def OnConnect(self, e = None):
1126 if self.comm is not None:
1130 wx.CallAfter(self.OnConnect)
1132 self.connectButton.Enable(False)
1133 self.comm = machineCom.MachineCom(callbackObject=self)
1134 self.infoBox.SetBusy(_('Connecting to machine.'))
1135 self._wizardState = 0
1137 def OnBedUp(self, e):
1138 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1139 self.comm.sendCommand('G92 Z10')
1140 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1141 self.comm.sendCommand('M400')
1143 def OnBedDown(self, e):
1144 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1145 self.comm.sendCommand('G92 Z10')
1146 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1147 self.comm.sendCommand('M400')
1149 def OnBedUp2(self, e):
1150 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1151 self.comm.sendCommand('G92 Z10')
1152 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1153 self.comm.sendCommand('M400')
1155 def OnBedDown2(self, e):
1156 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1157 self.comm.sendCommand('G92 Z10')
1158 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1159 self.comm.sendCommand('M400')
1161 def AllowNext(self):
1162 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1163 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1166 def OnResume(self, e):
1167 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1168 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1169 if self._wizardState == -1:
1170 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1171 wx.CallAfter(self.upButton.Enable, False)
1172 wx.CallAfter(self.downButton.Enable, False)
1173 wx.CallAfter(self.upButton2.Enable, False)
1174 wx.CallAfter(self.downButton2.Enable, False)
1175 self.comm.sendCommand('M105')
1176 self.comm.sendCommand('G28')
1177 self._wizardState = 1
1178 elif self._wizardState == 2:
1179 if profile.getMachineSetting('has_heated_bed') == 'True':
1180 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1181 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1182 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1183 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1184 self.comm.sendCommand('M400')
1185 self._wizardState = 3
1187 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1188 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1189 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1190 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1191 self.comm.sendCommand('M400')
1192 self._wizardState = 3
1193 elif self._wizardState == 4:
1194 if profile.getMachineSetting('has_heated_bed') == 'True':
1195 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1196 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1197 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1198 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1199 self.comm.sendCommand('M400')
1200 self._wizardState = 7
1202 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1203 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1204 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1205 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1206 self.comm.sendCommand('M400')
1207 self._wizardState = 5
1208 elif self._wizardState == 6:
1209 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1210 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1211 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1212 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1213 self.comm.sendCommand('M400')
1214 self._wizardState = 7
1215 elif self._wizardState == 8:
1216 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1217 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1218 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1219 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1220 self._wizardState = 9
1221 elif self._wizardState == 10:
1222 self._wizardState = 11
1223 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1224 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1225 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1226 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1227 w = profile.getMachineSettingFloat('machine_width') - 10
1228 d = profile.getMachineSettingFloat('machine_depth')
1229 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1230 filamentArea = math.pi * filamentRadius * filamentRadius
1231 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1235 'G1 Z2 F%d' % (feedZ),
1237 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1238 'G1 Z0.3 F%d' % (feedZ)]
1240 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1242 for i in xrange(0, 3):
1243 dist = 5.0 + 0.4 * float(i)
1244 eValue += (d - 2.0*dist) * ePerMM
1245 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1246 eValue += (w - 2.0*dist) * ePerMM
1247 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1248 eValue += (d - 2.0*dist) * ePerMM
1249 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1250 eValue += (w - 2.0*dist) * ePerMM
1251 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1253 gcodeList.append('M400')
1254 self.comm.printGCode(gcodeList)
1255 self.resumeButton.Enable(False)
1257 def mcLog(self, message):
1258 print 'Log:', message
1260 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1261 if self._wizardState == 1:
1262 self._wizardState = 2
1263 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1264 wx.CallAfter(self.resumeButton.Enable, True)
1265 elif self._wizardState == 3:
1266 self._wizardState = 4
1267 if profile.getMachineSetting('has_heated_bed') == 'True':
1268 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1270 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1271 wx.CallAfter(self.resumeButton.Enable, True)
1272 elif self._wizardState == 5:
1273 self._wizardState = 6
1274 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1275 wx.CallAfter(self.resumeButton.Enable, True)
1276 elif self._wizardState == 7:
1277 self._wizardState = 8
1278 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1279 wx.CallAfter(self.resumeButton.Enable, True)
1280 elif self._wizardState == 9:
1281 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1282 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1284 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1285 wx.CallAfter(self.resumeButton.Enable, True)
1286 self._wizardState = 10
1288 def mcStateChange(self, state):
1289 if self.comm is None:
1291 if self.comm.isOperational():
1292 if self._wizardState == 0:
1293 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1294 wx.CallAfter(self.upButton.Enable, True)
1295 wx.CallAfter(self.downButton.Enable, True)
1296 wx.CallAfter(self.upButton2.Enable, True)
1297 wx.CallAfter(self.downButton2.Enable, True)
1298 wx.CallAfter(self.resumeButton.Enable, True)
1299 self._wizardState = -1
1300 elif self._wizardState == 11 and not self.comm.isPrinting():
1301 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1302 self.comm.sendCommand('G92 E0')
1303 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1304 self.comm.sendCommand('M104 S0')
1305 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1306 wx.CallAfter(self.infoBox.SetReadyIndicator)
1307 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1308 wx.CallAfter(self.connectButton.Enable, True)
1309 self._wizardState = 12
1310 elif self.comm.isError():
1311 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1313 def mcMessage(self, message):
1316 def mcProgress(self, lineNr):
1319 def mcZChange(self, newZ):
1322 class headOffsetCalibrationPage(InfoPage):
1323 def __init__(self, parent):
1324 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
1326 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1329 self.connectButton = self.AddButton(_('Connect to printer'))
1332 self.infoBox = self.AddInfoBox()
1333 self.textEntry = self.AddTextCtrl('')
1334 self.textEntry.Enable(False)
1335 self.resumeButton = self.AddButton(_('Resume'))
1336 self.resumeButton.Enable(False)
1338 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1339 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1341 def AllowBack(self):
1344 def OnConnect(self, e = None):
1345 if self.comm is not None:
1349 wx.CallAfter(self.OnConnect)
1351 self.connectButton.Enable(False)
1352 self.comm = machineCom.MachineCom(callbackObject=self)
1353 self.infoBox.SetBusy(_('Connecting to machine.'))
1354 self._wizardState = 0
1356 def OnResume(self, e):
1357 if self._wizardState == 2:
1358 self._wizardState = 3
1359 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1361 w = profile.getMachineSettingFloat('machine_width')
1362 d = profile.getMachineSettingFloat('machine_depth')
1364 gcode = gcodeGenerator.gcodeGenerator()
1365 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1366 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1373 gcode.addMove(w/2, 5)
1374 gcode.addMove(z=0.2)
1376 gcode.addExtrude(w/2, d-5.0)
1378 gcode.addMove(5, d/2)
1380 gcode.addExtrude(w-5.0, d/2)
1381 gcode.addRetract(15)
1384 gcode.addMove(w/2, 5)
1386 gcode.addExtrude(w/2, d-5.0)
1388 gcode.addMove(5, d/2)
1390 gcode.addExtrude(w-5.0, d/2)
1391 gcode.addRetract(15)
1396 gcode.addCmd('M400')
1398 self.comm.printGCode(gcode.list())
1399 self.resumeButton.Enable(False)
1400 elif self._wizardState == 4:
1402 float(self.textEntry.GetValue())
1405 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1406 self._wizardState = 5
1407 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1408 self.textEntry.SetValue('0.0')
1409 self.textEntry.Enable(True)
1410 elif self._wizardState == 5:
1412 float(self.textEntry.GetValue())
1415 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1416 self._wizardState = 6
1417 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1418 self.textEntry.SetValue('')
1419 self.textEntry.Enable(False)
1420 self.resumeButton.Enable(False)
1422 x = profile.getMachineSettingFloat('extruder_offset_x1')
1423 y = profile.getMachineSettingFloat('extruder_offset_y1')
1424 gcode = gcodeGenerator.gcodeGenerator()
1425 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1426 gcode.setPrintSpeed(25)
1429 gcode.addMove(50, 40, 0.2)
1431 for n in xrange(0, 10):
1432 gcode.addExtrude(50 + n * 10, 150)
1433 gcode.addExtrude(50 + n * 10 + 5, 150)
1434 gcode.addExtrude(50 + n * 10 + 5, 40)
1435 gcode.addExtrude(50 + n * 10 + 10, 40)
1436 gcode.addMove(40, 50)
1437 for n in xrange(0, 10):
1438 gcode.addExtrude(150, 50 + n * 10)
1439 gcode.addExtrude(150, 50 + n * 10 + 5)
1440 gcode.addExtrude(40, 50 + n * 10 + 5)
1441 gcode.addExtrude(40, 50 + n * 10 + 10)
1442 gcode.addRetract(15)
1445 gcode.addMove(50 - x, 30 - y, 0.2)
1447 for n in xrange(0, 10):
1448 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1449 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1450 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1451 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1452 gcode.addMove(30 - x, 50 - y, 0.2)
1453 for n in xrange(0, 10):
1454 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1455 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1456 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1457 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1458 gcode.addRetract(15)
1460 gcode.addCmd('M400')
1461 gcode.addCmd('M104 T0 S0')
1462 gcode.addCmd('M104 T1 S0')
1463 self.comm.printGCode(gcode.list())
1464 elif self._wizardState == 7:
1466 n = int(self.textEntry.GetValue()) - 1
1469 x = profile.getMachineSettingFloat('extruder_offset_x1')
1471 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1472 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1473 self.textEntry.SetValue('10')
1474 self._wizardState = 8
1475 elif self._wizardState == 8:
1477 n = int(self.textEntry.GetValue()) - 1
1480 y = profile.getMachineSettingFloat('extruder_offset_y1')
1482 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1483 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1484 self.infoBox.SetReadyIndicator()
1485 self._wizardState = 8
1487 self.resumeButton.Enable(False)
1489 def mcLog(self, message):
1490 print 'Log:', message
1492 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1493 if self._wizardState == 1:
1494 if temp[0] >= 210 and temp[1] >= 210:
1495 self._wizardState = 2
1496 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1497 wx.CallAfter(self.resumeButton.Enable, True)
1498 wx.CallAfter(self.resumeButton.SetFocus)
1500 def mcStateChange(self, state):
1501 if self.comm is None:
1503 if self.comm.isOperational():
1504 if self._wizardState == 0:
1505 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1506 self.comm.sendCommand('M105')
1507 self.comm.sendCommand('M104 S220 T0')
1508 self.comm.sendCommand('M104 S220 T1')
1509 self.comm.sendCommand('G28')
1510 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1511 self._wizardState = 1
1512 if not self.comm.isPrinting():
1513 if self._wizardState == 3:
1514 self._wizardState = 4
1515 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1516 wx.CallAfter(self.textEntry.SetValue, '0.0')
1517 wx.CallAfter(self.textEntry.Enable, True)
1518 wx.CallAfter(self.resumeButton.Enable, True)
1519 wx.CallAfter(self.resumeButton.SetFocus)
1520 elif self._wizardState == 6:
1521 self._wizardState = 7
1522 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1523 wx.CallAfter(self.textEntry.SetValue, '10')
1524 wx.CallAfter(self.textEntry.Enable, True)
1525 wx.CallAfter(self.resumeButton.Enable, True)
1526 wx.CallAfter(self.resumeButton.SetFocus)
1528 elif self.comm.isError():
1529 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1531 def mcMessage(self, message):
1534 def mcProgress(self, lineNr):
1537 def mcZChange(self, newZ):
1540 class bedLevelWizard(wx.wizard.Wizard):
1542 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1544 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1545 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1547 self.mainPage = bedLevelWizardMain(self)
1548 self.headOffsetCalibration = None
1550 self.FitToPage(self.mainPage)
1551 self.GetPageAreaSizer().Add(self.mainPage)
1553 self.RunWizard(self.mainPage)
1556 def OnPageChanging(self, e):
1557 e.GetPage().StoreData()
1559 def OnPageChanged(self, e):
1560 if e.GetPage().AllowNext():
1561 self.FindWindowById(wx.ID_FORWARD).Enable()
1563 self.FindWindowById(wx.ID_FORWARD).Disable()
1564 if e.GetPage().AllowBack():
1565 self.FindWindowById(wx.ID_BACKWARD).Enable()
1567 self.FindWindowById(wx.ID_BACKWARD).Disable()
1569 class headOffsetWizard(wx.wizard.Wizard):
1571 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1573 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1574 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1576 self.mainPage = headOffsetCalibrationPage(self)
1578 self.FitToPage(self.mainPage)
1579 self.GetPageAreaSizer().Add(self.mainPage)
1581 self.RunWizard(self.mainPage)
1584 def OnPageChanging(self, e):
1585 e.GetPage().StoreData()
1587 def OnPageChanged(self, e):
1588 if e.GetPage().AllowNext():
1589 self.FindWindowById(wx.ID_FORWARD).Enable()
1591 self.FindWindowById(wx.ID_FORWARD).Disable()
1592 if e.GetPage().AllowBack():
1593 self.FindWindowById(wx.ID_BACKWARD).Enable()
1595 self.FindWindowById(wx.ID_BACKWARD).Disable()