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)
227 class PrintrbotPage(InfoPage):
228 def __init__(self, parent):
229 self._printer_info = [
230 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
231 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
232 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
233 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
234 (":" + _("Older models"),),
235 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
236 ("Simple Maker's Edition v1", 100, 100, 100, 0.5, 1.75, 208, 40, 70, 30, 1, False),
237 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.5, 1.75, 208, 40, 70, 30, 1, False),
238 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.5, 1.75, 208, 40, 70, 30, 1, False),
239 ("Simple Maker's Edition v4 (Model 1405)", 100, 100, 100, 0.5, 1.75, 208, 40, 70, 30, 1, False),
240 ("Jr v1", 150, 100, 80, 0.5, 1.75, 208, 40, 70, 30, 1, False),
241 ("Jr v2", 150, 150, 150, 0.5, 1.75, 208, 40, 70, 30, 1, False),
242 ("LC v2", 150, 150, 150, 0.5, 1.75, 208, 40, 70, 30, 1, False),
243 ("Plus v2", 200, 200, 200, 0.5, 1.75, 208, 40, 70, 30, 1, False),
244 ("Plus v2.1", 200, 200, 200, 0.5, 1.75, 208, 40, 70, 30, 1, False),
245 ("Plus v2.2 (Model 1404/140422)", 250, 250, 250, 0.5, 1.75, 208, 40, 70, 30, 1, False),
246 ("Plus v2.3 (Model 140501)", 250, 250, 250, 0.5, 1.75, 208, 40, 70, 30, 1, False),
247 ("Plus v2.4 (Model 140507)", 250, 250, 250, 0.5, 1.75, 208, 40, 70, 30, 1, False),
248 ("Go v2 Large", 609, 305, 305, 0.5, 1.75, 208, 35, 70, 30, 1, False),
251 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
252 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
253 self.AddText(_("Select which Printrbot machine you have:"))
255 for printer in self._printer_info:
256 if printer[0].startswith(":"):
258 self.AddText(printer[0][1:])
260 item = self.AddRadioButton(printer[0])
261 item.data = printer[1:]
262 self._items.append(item)
265 profile.putMachineSetting('machine_name', 'Printrbot ???')
266 for item in self._items:
269 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
270 profile.putMachineSetting('machine_width', data[0])
271 profile.putMachineSetting('machine_depth', data[1])
272 profile.putMachineSetting('machine_height', data[2])
273 profile.putProfileSetting('nozzle_size', data[3])
274 profile.putProfileSetting('filament_diameter', data[4])
275 profile.putProfileSetting('print_temperature', data[5])
276 profile.putProfileSetting('print_speed', data[6])
277 profile.putProfileSetting('travel_speed', data[7])
278 profile.putProfileSetting('retraction_speed', data[8])
279 profile.putProfileSetting('retraction_amount', data[9])
280 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
281 profile.putMachineSetting('has_heated_bed', 'False')
282 profile.putMachineSetting('machine_center_is_zero', 'False')
283 profile.putMachineSetting('extruder_head_size_min_x', '0')
284 profile.putMachineSetting('extruder_head_size_min_y', '0')
285 profile.putMachineSetting('extruder_head_size_max_x', '0')
286 profile.putMachineSetting('extruder_head_size_max_y', '0')
287 profile.putMachineSetting('extruder_head_size_height', '0')
289 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
290 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
291 ;Print time: {print_time}
292 ;Filament used: {filament_amount}m {filament_weight}g
293 ;Filament cost: {filament_cost}
294 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
295 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
297 G90 ;absolute positioning
298 M82 ;set extruder to absolute mode
299 M107 ;start with the fan off
301 G28 X0 Y0 ;move X/Y to min endstops
302 G28 Z0 ;move Z to min endstops
303 G29 ;Run the auto bed leveling
305 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
307 G92 E0 ;zero the extruded length
308 G1 F200 E3 ;extrude 3mm of feed stock
309 G92 E0 ;zero the extruded length again
311 ;Put printing message on LCD screen
315 class OtherMachineSelectPage(InfoPage):
316 def __init__(self, parent):
317 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
318 self.AddText(_("The following pre-defined machine profiles are available"))
319 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."))
321 machines = resources.getDefaultMachineProfiles()
323 for filename in machines:
324 name = os.path.splitext(os.path.basename(filename))[0]
325 item = self.AddRadioButton(name)
326 item.filename = filename
327 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
328 self.options.append(item)
330 item = self.AddRadioButton(_('Custom...'))
332 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
334 def OnProfileSelect(self, e):
335 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
337 def OnOtherSelect(self, e):
338 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
341 for option in self.options:
342 if option.GetValue():
343 profile.loadProfile(option.filename)
344 profile.loadMachineSettings(option.filename)
346 class OtherMachineInfoPage(InfoPage):
347 def __init__(self, parent):
348 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
349 self.AddText(_("Cura is now ready to be used!"))
351 class CustomRepRapInfoPage(InfoPage):
352 def __init__(self, parent):
353 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
354 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
355 self.AddText(_("Be sure to review the default profile before running it on your machine."))
356 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
358 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
360 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
361 self.machineWidth = self.AddLabelTextCtrl(_("Machine width (mm)"), "80")
362 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth (mm)"), "80")
363 self.machineHeight = self.AddLabelTextCtrl(_("Machine height (mm)"), "55")
364 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
365 self.heatedBed = self.AddCheckbox(_("Heated bed"))
366 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
369 profile.putMachineSetting('machine_name', self.machineName.GetValue())
370 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
371 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
372 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
373 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
374 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
375 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
376 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
377 profile.putMachineSetting('extruder_head_size_min_x', '0')
378 profile.putMachineSetting('extruder_head_size_min_y', '0')
379 profile.putMachineSetting('extruder_head_size_max_x', '0')
380 profile.putMachineSetting('extruder_head_size_max_y', '0')
381 profile.putMachineSetting('extruder_head_size_height', '0')
382 profile.checkAndUpdateMachineName()
384 class MachineSelectPage(InfoPage):
385 def __init__(self, parent):
386 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
387 self.AddText(_("What kind of machine do you have:"))
389 self.LulzbotMiniRadio = self.AddRadioButton("LulzBot Mini", style=wx.RB_GROUP)
390 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
391 self.LulzbotMiniRadio.SetValue(True)
392 self.LulzbotTaz5Radio = self.AddRadioButton("LulzBot TAZ 5")
393 self.LulzbotTaz5Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
394 self.LulzbotTaz4Radio = self.AddRadioButton("LulzBot TAZ 4")
395 self.LulzbotTaz4Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
396 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
397 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
398 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
399 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
400 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
401 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
402 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
403 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
404 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
405 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
406 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
407 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
408 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
409 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
411 def OnUltimaker2Select(self, e):
412 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
414 def OnUltimakerSelect(self, e):
415 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
417 def OnUltimakerOPSelect(self, e):
418 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
420 def OnPrintrbotSelect(self, e):
421 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
423 def OnLulzbotSelect(self, e):
424 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
426 def OnOtherSelect(self, e):
427 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
430 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
434 profile.putProfileSetting('retraction_enable', 'True')
435 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
436 if self.Ultimaker2Radio.GetValue():
437 profile.putMachineSetting('machine_width', '230')
438 profile.putMachineSetting('machine_depth', '225')
439 profile.putMachineSetting('machine_height', '205')
440 profile.putMachineSetting('machine_name', 'ultimaker2')
441 profile.putMachineSetting('machine_type', 'ultimaker2')
442 profile.putMachineSetting('has_heated_bed', 'True')
443 if self.Ultimaker2GoRadio.GetValue():
444 profile.putMachineSetting('machine_width', '120')
445 profile.putMachineSetting('machine_depth', '120')
446 profile.putMachineSetting('machine_height', '115')
447 profile.putMachineSetting('machine_name', 'ultimaker2go')
448 profile.putMachineSetting('machine_type', 'ultimaker2go')
449 profile.putMachineSetting('has_heated_bed', 'False')
450 if self.Ultimaker2ExtRadio.GetValue():
451 profile.putMachineSetting('machine_width', '230')
452 profile.putMachineSetting('machine_depth', '225')
453 profile.putMachineSetting('machine_height', '305')
454 profile.putMachineSetting('machine_name', 'ultimaker2extended')
455 profile.putMachineSetting('machine_type', 'ultimaker2extended')
456 profile.putMachineSetting('has_heated_bed', 'False')
457 profile.putMachineSetting('machine_center_is_zero', 'False')
458 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
459 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
460 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
461 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
462 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
463 profile.putMachineSetting('extruder_head_size_height', '48.0')
464 profile.putProfileSetting('nozzle_size', '0.4')
465 profile.putProfileSetting('fan_full_height', '5.0')
466 profile.putMachineSetting('extruder_offset_x1', '18.0')
467 profile.putMachineSetting('extruder_offset_y1', '0.0')
468 elif self.UltimakerRadio.GetValue():
469 profile.putMachineSetting('machine_width', '205')
470 profile.putMachineSetting('machine_depth', '205')
471 profile.putMachineSetting('machine_height', '200')
472 profile.putMachineSetting('machine_name', 'ultimaker original')
473 profile.putMachineSetting('machine_type', 'ultimaker')
474 profile.putMachineSetting('machine_center_is_zero', 'False')
475 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
476 profile.putProfileSetting('nozzle_size', '0.4')
477 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
478 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
479 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
480 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
481 profile.putMachineSetting('extruder_head_size_height', '55.0')
482 elif self.UltimakerOPRadio.GetValue():
483 profile.putMachineSetting('machine_width', '205')
484 profile.putMachineSetting('machine_depth', '205')
485 profile.putMachineSetting('machine_height', '200')
486 profile.putMachineSetting('machine_name', 'ultimaker original+')
487 profile.putMachineSetting('machine_type', 'ultimaker_plus')
488 profile.putMachineSetting('machine_center_is_zero', 'False')
489 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
490 profile.putProfileSetting('nozzle_size', '0.4')
491 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
492 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
493 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
494 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
495 profile.putMachineSetting('extruder_head_size_height', '55.0')
496 profile.putMachineSetting('has_heated_bed', 'True')
497 profile.putMachineSetting('extruder_amount', '1')
498 profile.putProfileSetting('retraction_enable', 'True')
499 elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
500 if self.LulzbotTaz4Radio.GetValue():
501 profile.putMachineSetting('machine_width', '298')
502 profile.putMachineSetting('machine_depth', '275')
503 profile.putMachineSetting('machine_height', '250')
504 profile.putProfileSetting('nozzle_size', '0.35')
505 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
506 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
507 profile.putMachineSetting('serial_baud', '115200')
508 elif self.LulzbotTaz5Radio.GetValue():
509 profile.putMachineSetting('machine_width', '298')
510 profile.putMachineSetting('machine_depth', '275')
511 profile.putMachineSetting('machine_height', '250')
512 profile.putProfileSetting('nozzle_size', '0.35')
513 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
514 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
515 profile.putMachineSetting('serial_baud', '115200')
517 profile.putMachineSetting('machine_width', '155')
518 profile.putMachineSetting('machine_depth', '155')
519 profile.putMachineSetting('machine_height', '163')
520 profile.putProfileSetting('nozzle_size', '0.5')
521 profile.putMachineSetting('machine_name', 'LulzBot Mini')
522 profile.putMachineSetting('machine_type', 'lulzbot_mini')
523 profile.putMachineSetting('serial_baud', '115200')
524 profile.putMachineSetting('machine_center_is_zero', 'False')
525 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
526 profile.putMachineSetting('has_heated_bed', 'True')
527 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
528 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
529 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
530 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
531 profile.putMachineSetting('extruder_head_size_height', '0.0')
532 profile.putPreference('startMode', 'Simple')
534 profile.putMachineSetting('machine_width', '80')
535 profile.putMachineSetting('machine_depth', '80')
536 profile.putMachineSetting('machine_height', '60')
537 profile.putMachineSetting('machine_name', 'reprap')
538 profile.putMachineSetting('machine_type', 'reprap')
539 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
540 profile.putPreference('startMode', 'Normal')
541 profile.putProfileSetting('nozzle_size', '0.5')
542 profile.checkAndUpdateMachineName()
543 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
545 class SelectParts(InfoPage):
546 def __init__(self, parent):
547 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
548 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."))
550 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
551 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
552 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
553 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
555 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."))
556 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
557 self.springExtruder.SetValue(True)
560 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
561 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
562 profile.putMachineSetting('has_heated_bed', 'True')
564 profile.putMachineSetting('has_heated_bed', 'False')
565 if self.dualExtrusion.GetValue():
566 profile.putMachineSetting('extruder_amount', '2')
567 profile.putMachineSetting('machine_depth', '195')
569 profile.putMachineSetting('extruder_amount', '1')
570 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
571 profile.putProfileSetting('retraction_enable', 'True')
573 profile.putProfileSetting('retraction_enable', 'False')
576 class UltimakerFirmwareUpgradePage(InfoPage):
577 def __init__(self, parent):
578 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
579 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."))
580 self.AddHiddenSeperator()
581 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
582 self.AddHiddenSeperator()
583 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."))
584 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
585 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
586 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
587 self.AddHiddenSeperator()
588 if profile.getMachineSetting('machine_type') == 'ultimaker':
589 self.AddText(_("Do not upgrade to this firmware if:"))
590 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
591 self.AddText(_("* Build your own heated bed"))
592 self.AddText(_("* Have other changes in the firmware"))
593 # button = self.AddButton('Goto this page for a custom firmware')
594 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
599 def OnUpgradeClick(self, e):
600 if firmwareInstall.InstallFirmware():
601 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
603 def OnSkipClick(self, e):
604 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
605 self.GetParent().ShowPage(self.GetNext())
607 def OnUrlClick(self, e):
608 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
610 class UltimakerCheckupPage(InfoPage):
611 def __init__(self, parent):
612 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
614 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
615 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
616 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
617 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
618 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
619 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
620 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
621 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
622 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
623 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
626 _("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."))
627 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
628 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
629 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
631 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
632 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
633 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
635 self.infoBox = self.AddInfoBox()
636 self.machineState = self.AddText("")
637 self.temperatureLabel = self.AddText("")
638 self.errorLogButton = self.AddButton(_("Show error log"))
639 self.errorLogButton.Show(False)
641 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
643 self.xMinStop = False
644 self.xMaxStop = False
645 self.yMinStop = False
646 self.yMaxStop = False
647 self.zMinStop = False
648 self.zMaxStop = False
650 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
653 if self.comm is not None:
657 self.endstopBitmap.Show(False)
660 def OnSkipClick(self, e):
661 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
662 self.GetParent().ShowPage(self.GetNext())
664 def OnCheckClick(self, e=None):
665 self.errorLogButton.Show(False)
666 if self.comm is not None:
670 wx.CallAfter(self.OnCheckClick)
672 self.infoBox.SetBusy(_("Connecting to machine."))
673 self.commState.SetBitmap(self.unknownBitmap)
674 self.tempState.SetBitmap(self.unknownBitmap)
675 self.stopState.SetBitmap(self.unknownBitmap)
676 self.checkupState = 0
677 self.checkExtruderNr = 0
678 self.comm = machineCom.MachineCom(callbackObject=self)
680 def OnErrorLog(self, e):
681 printWindow.LogWindow('\n'.join(self.comm.getLog()))
683 def mcLog(self, message):
686 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
687 if not self.comm.isOperational():
689 if self.checkupState == 0:
690 self.tempCheckTimeout = 20
691 if temp[self.checkExtruderNr] > 70:
692 self.checkupState = 1
693 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
694 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
695 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
697 self.startTemp = temp[self.checkExtruderNr]
698 self.checkupState = 2
699 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
700 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
701 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
702 elif self.checkupState == 1:
703 if temp[self.checkExtruderNr] < 60:
704 self.startTemp = temp[self.checkExtruderNr]
705 self.checkupState = 2
706 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
707 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
708 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
709 elif self.checkupState == 2:
710 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
711 if temp[self.checkExtruderNr] > self.startTemp + 40:
712 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
713 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
714 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
715 self.checkExtruderNr = 0
716 self.checkupState = 3
717 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
718 wx.CallAfter(self.endstopBitmap.Show, True)
719 wx.CallAfter(self.Layout)
720 self.comm.sendCommand('M119')
721 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
723 self.checkupState = 0
724 self.checkExtruderNr += 1
726 self.tempCheckTimeout -= 1
727 if self.tempCheckTimeout < 1:
728 self.checkupState = -1
729 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
730 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
731 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
732 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
733 elif self.checkupState >= 3 and self.checkupState < 10:
734 self.comm.sendCommand('M119')
735 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
737 def mcStateChange(self, state):
738 if self.comm is None:
740 if self.comm.isOperational():
741 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
742 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
743 elif self.comm.isError():
744 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
745 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
746 wx.CallAfter(self.endstopBitmap.Show, False)
747 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
748 wx.CallAfter(self.errorLogButton.Show, True)
749 wx.CallAfter(self.Layout)
751 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
753 def mcMessage(self, message):
754 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
755 for data in message.split(' '):
757 tag, value = data.split(':', 1)
759 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
761 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
763 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
765 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
767 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
769 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
771 tag, value = map(str.strip, message.split(':', 1))
773 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
775 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
777 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
779 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
781 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
783 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
784 if 'z_max' in message:
785 self.comm.sendCommand('M119')
787 if self.checkupState == 3:
788 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
789 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
790 self.checkupState = 5
791 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
792 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
794 self.checkupState = 4
795 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
796 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
797 elif self.checkupState == 4:
798 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
799 self.checkupState = 5
800 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
801 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
802 elif self.checkupState == 5:
803 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
804 self.checkupState = 6
805 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
806 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
807 elif self.checkupState == 6:
808 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
809 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
810 self.checkupState = 8
811 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
812 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
814 self.checkupState = 7
815 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
816 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
817 elif self.checkupState == 7:
818 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
819 self.checkupState = 8
820 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
821 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
822 elif self.checkupState == 8:
823 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
824 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
825 self.checkupState = 10
827 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
828 wx.CallAfter(self.infoBox.SetReadyIndicator)
829 wx.CallAfter(self.endstopBitmap.Show, False)
830 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
831 wx.CallAfter(self.OnSkipClick, None)
833 self.checkupState = 9
834 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
835 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
836 elif self.checkupState == 9:
837 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
838 self.checkupState = 10
840 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
841 wx.CallAfter(self.infoBox.SetReadyIndicator)
842 wx.CallAfter(self.endstopBitmap.Show, False)
843 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
844 wx.CallAfter(self.OnSkipClick, None)
846 def mcProgress(self, lineNr):
849 def mcZChange(self, newZ):
853 class UltimakerCalibrationPage(InfoPage):
854 def __init__(self, parent):
855 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
857 self.AddText("Your Ultimaker requires some calibration.")
858 self.AddText("This calibration is needed for a proper extrusion amount.")
860 self.AddText("The following values are needed:")
861 self.AddText("* Diameter of filament")
862 self.AddText("* Number of steps per mm of filament extrusion")
864 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
866 self.AddText("First we need the diameter of your filament:")
867 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
869 "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.")
870 self.AddText("Note: This value can be changed later at any time.")
873 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
876 class UltimakerCalibrateStepsPerEPage(InfoPage):
877 def __init__(self, parent):
878 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
880 #if profile.getMachineSetting('steps_per_e') == '0':
881 # profile.putMachineSetting('steps_per_e', '865.888')
883 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
884 self.AddText(_("First remove any filament from your machine."))
885 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
886 self.AddText(_("We'll push the filament 100mm"))
887 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
888 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
889 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
890 self.AddText(_("This results in the following steps per E:"))
891 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
892 self.AddText(_("You can repeat these steps to get better calibration."))
895 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
896 self.heatButton = self.AddButton(_("Heatup for filament removal"))
898 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
899 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
900 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
902 def OnSaveLengthClick(self, e):
903 currentEValue = float(self.stepsPerEInput.GetValue())
904 realExtrudeLength = float(self.lengthInput.GetValue())
905 newEValue = currentEValue * 100 / realExtrudeLength
906 self.stepsPerEInput.SetValue(str(newEValue))
907 self.lengthInput.SetValue("100")
909 def OnExtrudeClick(self, e):
910 t = threading.Thread(target=self.OnExtrudeRun)
914 def OnExtrudeRun(self):
915 self.heatButton.Enable(False)
916 self.extrudeButton.Enable(False)
917 currentEValue = float(self.stepsPerEInput.GetValue())
918 self.comm = machineCom.MachineCom()
919 if not self.comm.isOpen():
921 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
922 'Printer error', wx.OK | wx.ICON_INFORMATION)
923 self.heatButton.Enable(True)
924 self.extrudeButton.Enable(True)
927 line = self.comm.readline()
932 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
935 self.sendGCommand('M302') #Disable cold extrusion protection
936 self.sendGCommand("M92 E%f" % (currentEValue))
937 self.sendGCommand("G92 E0")
938 self.sendGCommand("G1 E100 F600")
941 self.extrudeButton.Enable()
942 self.heatButton.Enable()
944 def OnHeatClick(self, e):
945 t = threading.Thread(target=self.OnHeatRun)
950 self.heatButton.Enable(False)
951 self.extrudeButton.Enable(False)
952 self.comm = machineCom.MachineCom()
953 if not self.comm.isOpen():
955 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
956 'Printer error', wx.OK | wx.ICON_INFORMATION)
957 self.heatButton.Enable(True)
958 self.extrudeButton.Enable(True)
961 line = self.comm.readline()
963 self.heatButton.Enable(True)
964 self.extrudeButton.Enable(True)
968 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
971 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
973 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
974 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
975 self.sendGCommand('M104 S0')
978 self.heatButton.Enable(True)
979 self.extrudeButton.Enable(True)
981 def sendGCommand(self, cmd):
982 self.comm.sendCommand(cmd) #Disable cold extrusion protection
984 line = self.comm.readline()
987 if line.startswith('ok'):
991 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
993 class Ultimaker2ReadyPage(InfoPage):
994 def __init__(self, parent):
995 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
996 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
997 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1000 class LulzbotReadyPage(InfoPage):
1001 def __init__(self, parent):
1002 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1003 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1005 self.AddText(_('For more information about using Cura with your LulzBot'))
1006 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1009 class ConfigWizard(wx.wizard.Wizard):
1010 def __init__(self, addNew = False):
1011 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1013 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1015 profile.setActiveMachine(profile.getMachineCount())
1017 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1018 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1019 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1021 self.machineSelectPage = MachineSelectPage(self)
1022 self.ultimakerSelectParts = SelectParts(self)
1023 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1024 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1025 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1026 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1027 self.bedLevelPage = bedLevelWizardMain(self)
1028 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1029 self.printrbotSelectType = PrintrbotPage(self)
1030 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1031 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1032 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1034 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1035 self.lulzbotReadyPage = LulzbotReadyPage(self)
1037 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1038 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1039 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1040 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1041 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1042 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1043 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1044 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1046 self.FitToPage(self.machineSelectPage)
1047 self.GetPageAreaSizer().Add(self.machineSelectPage)
1049 self.RunWizard(self.machineSelectPage)
1052 def OnPageChanging(self, e):
1053 e.GetPage().StoreData()
1055 def OnPageChanged(self, e):
1056 if e.GetPage().AllowNext():
1057 self.FindWindowById(wx.ID_FORWARD).Enable()
1059 self.FindWindowById(wx.ID_FORWARD).Disable()
1060 if e.GetPage().AllowBack():
1061 self.FindWindowById(wx.ID_BACKWARD).Enable()
1063 self.FindWindowById(wx.ID_BACKWARD).Disable()
1065 def OnCancel(self, e):
1066 profile.setActiveMachine(self._old_machine_index)
1068 class bedLevelWizardMain(InfoPage):
1069 def __init__(self, parent):
1070 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1072 self.AddText(_('This wizard will help you in leveling your printer bed'))
1074 self.AddText(_('It will do the following steps'))
1075 self.AddText(_('* Move the printer head to each corner'))
1076 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1077 self.AddText(_('* Print a line around the bed to check if it is level'))
1080 self.connectButton = self.AddButton(_('Connect to printer'))
1083 self.infoBox = self.AddInfoBox()
1084 self.resumeButton = self.AddButton(_('Resume'))
1085 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1086 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1087 self.resumeButton.Enable(False)
1089 self.upButton.Enable(False)
1090 self.downButton.Enable(False)
1091 self.upButton2.Enable(False)
1092 self.downButton2.Enable(False)
1094 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1095 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1096 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1097 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1098 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1099 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1101 def OnConnect(self, e = None):
1102 if self.comm is not None:
1106 wx.CallAfter(self.OnConnect)
1108 self.connectButton.Enable(False)
1109 self.comm = machineCom.MachineCom(callbackObject=self)
1110 self.infoBox.SetBusy(_('Connecting to machine.'))
1111 self._wizardState = 0
1113 def OnBedUp(self, e):
1114 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1115 self.comm.sendCommand('G92 Z10')
1116 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1117 self.comm.sendCommand('M400')
1119 def OnBedDown(self, e):
1120 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1121 self.comm.sendCommand('G92 Z10')
1122 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1123 self.comm.sendCommand('M400')
1125 def OnBedUp2(self, e):
1126 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1127 self.comm.sendCommand('G92 Z10')
1128 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1129 self.comm.sendCommand('M400')
1131 def OnBedDown2(self, e):
1132 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1133 self.comm.sendCommand('G92 Z10')
1134 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1135 self.comm.sendCommand('M400')
1137 def AllowNext(self):
1138 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1139 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1142 def OnResume(self, e):
1143 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1144 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1145 if self._wizardState == -1:
1146 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1147 wx.CallAfter(self.upButton.Enable, False)
1148 wx.CallAfter(self.downButton.Enable, False)
1149 wx.CallAfter(self.upButton2.Enable, False)
1150 wx.CallAfter(self.downButton2.Enable, False)
1151 self.comm.sendCommand('M105')
1152 self.comm.sendCommand('G28')
1153 self._wizardState = 1
1154 elif self._wizardState == 2:
1155 if profile.getMachineSetting('has_heated_bed') == 'True':
1156 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1157 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1158 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1159 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1160 self.comm.sendCommand('M400')
1161 self._wizardState = 3
1163 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1164 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1165 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1166 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1167 self.comm.sendCommand('M400')
1168 self._wizardState = 3
1169 elif self._wizardState == 4:
1170 if profile.getMachineSetting('has_heated_bed') == 'True':
1171 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1172 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1173 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1174 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1175 self.comm.sendCommand('M400')
1176 self._wizardState = 7
1178 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1179 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1180 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1181 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1182 self.comm.sendCommand('M400')
1183 self._wizardState = 5
1184 elif self._wizardState == 6:
1185 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1186 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1187 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1188 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1189 self.comm.sendCommand('M400')
1190 self._wizardState = 7
1191 elif self._wizardState == 8:
1192 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1193 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1194 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1195 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1196 self._wizardState = 9
1197 elif self._wizardState == 10:
1198 self._wizardState = 11
1199 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1200 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1201 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1202 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1203 w = profile.getMachineSettingFloat('machine_width') - 10
1204 d = profile.getMachineSettingFloat('machine_depth')
1205 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1206 filamentArea = math.pi * filamentRadius * filamentRadius
1207 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1211 'G1 Z2 F%d' % (feedZ),
1213 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1214 'G1 Z0.3 F%d' % (feedZ)]
1216 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1218 for i in xrange(0, 3):
1219 dist = 5.0 + 0.4 * float(i)
1220 eValue += (d - 2.0*dist) * ePerMM
1221 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1222 eValue += (w - 2.0*dist) * ePerMM
1223 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1224 eValue += (d - 2.0*dist) * ePerMM
1225 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1226 eValue += (w - 2.0*dist) * ePerMM
1227 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1229 gcodeList.append('M400')
1230 self.comm.printGCode(gcodeList)
1231 self.resumeButton.Enable(False)
1233 def mcLog(self, message):
1234 print 'Log:', message
1236 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1237 if self._wizardState == 1:
1238 self._wizardState = 2
1239 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1240 wx.CallAfter(self.resumeButton.Enable, True)
1241 elif self._wizardState == 3:
1242 self._wizardState = 4
1243 if profile.getMachineSetting('has_heated_bed') == 'True':
1244 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1246 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1247 wx.CallAfter(self.resumeButton.Enable, True)
1248 elif self._wizardState == 5:
1249 self._wizardState = 6
1250 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1251 wx.CallAfter(self.resumeButton.Enable, True)
1252 elif self._wizardState == 7:
1253 self._wizardState = 8
1254 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1255 wx.CallAfter(self.resumeButton.Enable, True)
1256 elif self._wizardState == 9:
1257 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1258 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1260 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1261 wx.CallAfter(self.resumeButton.Enable, True)
1262 self._wizardState = 10
1264 def mcStateChange(self, state):
1265 if self.comm is None:
1267 if self.comm.isOperational():
1268 if self._wizardState == 0:
1269 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1270 wx.CallAfter(self.upButton.Enable, True)
1271 wx.CallAfter(self.downButton.Enable, True)
1272 wx.CallAfter(self.upButton2.Enable, True)
1273 wx.CallAfter(self.downButton2.Enable, True)
1274 wx.CallAfter(self.resumeButton.Enable, True)
1275 self._wizardState = -1
1276 elif self._wizardState == 11 and not self.comm.isPrinting():
1277 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1278 self.comm.sendCommand('G92 E0')
1279 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1280 self.comm.sendCommand('M104 S0')
1281 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1282 wx.CallAfter(self.infoBox.SetReadyIndicator)
1283 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1284 wx.CallAfter(self.connectButton.Enable, True)
1285 self._wizardState = 12
1286 elif self.comm.isError():
1287 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1289 def mcMessage(self, message):
1292 def mcProgress(self, lineNr):
1295 def mcZChange(self, newZ):
1298 class headOffsetCalibrationPage(InfoPage):
1299 def __init__(self, parent):
1300 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1302 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1305 self.connectButton = self.AddButton(_('Connect to printer'))
1308 self.infoBox = self.AddInfoBox()
1309 self.textEntry = self.AddTextCtrl('')
1310 self.textEntry.Enable(False)
1311 self.resumeButton = self.AddButton(_('Resume'))
1312 self.resumeButton.Enable(False)
1314 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1315 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1317 def AllowBack(self):
1320 def OnConnect(self, e = None):
1321 if self.comm is not None:
1325 wx.CallAfter(self.OnConnect)
1327 self.connectButton.Enable(False)
1328 self.comm = machineCom.MachineCom(callbackObject=self)
1329 self.infoBox.SetBusy(_('Connecting to machine.'))
1330 self._wizardState = 0
1332 def OnResume(self, e):
1333 if self._wizardState == 2:
1334 self._wizardState = 3
1335 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1337 w = profile.getMachineSettingFloat('machine_width')
1338 d = profile.getMachineSettingFloat('machine_depth')
1340 gcode = gcodeGenerator.gcodeGenerator()
1341 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1342 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1349 gcode.addMove(w/2, 5)
1350 gcode.addMove(z=0.2)
1352 gcode.addExtrude(w/2, d-5.0)
1354 gcode.addMove(5, d/2)
1356 gcode.addExtrude(w-5.0, d/2)
1357 gcode.addRetract(15)
1360 gcode.addMove(w/2, 5)
1362 gcode.addExtrude(w/2, d-5.0)
1364 gcode.addMove(5, d/2)
1366 gcode.addExtrude(w-5.0, d/2)
1367 gcode.addRetract(15)
1372 gcode.addCmd('M400')
1374 self.comm.printGCode(gcode.list())
1375 self.resumeButton.Enable(False)
1376 elif self._wizardState == 4:
1378 float(self.textEntry.GetValue())
1381 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1382 self._wizardState = 5
1383 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1384 self.textEntry.SetValue('0.0')
1385 self.textEntry.Enable(True)
1386 elif self._wizardState == 5:
1388 float(self.textEntry.GetValue())
1391 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1392 self._wizardState = 6
1393 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1394 self.textEntry.SetValue('')
1395 self.textEntry.Enable(False)
1396 self.resumeButton.Enable(False)
1398 x = profile.getMachineSettingFloat('extruder_offset_x1')
1399 y = profile.getMachineSettingFloat('extruder_offset_y1')
1400 gcode = gcodeGenerator.gcodeGenerator()
1401 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1402 gcode.setPrintSpeed(25)
1405 gcode.addMove(50, 40, 0.2)
1407 for n in xrange(0, 10):
1408 gcode.addExtrude(50 + n * 10, 150)
1409 gcode.addExtrude(50 + n * 10 + 5, 150)
1410 gcode.addExtrude(50 + n * 10 + 5, 40)
1411 gcode.addExtrude(50 + n * 10 + 10, 40)
1412 gcode.addMove(40, 50)
1413 for n in xrange(0, 10):
1414 gcode.addExtrude(150, 50 + n * 10)
1415 gcode.addExtrude(150, 50 + n * 10 + 5)
1416 gcode.addExtrude(40, 50 + n * 10 + 5)
1417 gcode.addExtrude(40, 50 + n * 10 + 10)
1418 gcode.addRetract(15)
1421 gcode.addMove(50 - x, 30 - y, 0.2)
1423 for n in xrange(0, 10):
1424 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1425 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1426 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1427 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1428 gcode.addMove(30 - x, 50 - y, 0.2)
1429 for n in xrange(0, 10):
1430 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1431 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1432 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1433 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1434 gcode.addRetract(15)
1436 gcode.addCmd('M400')
1437 gcode.addCmd('M104 T0 S0')
1438 gcode.addCmd('M104 T1 S0')
1439 self.comm.printGCode(gcode.list())
1440 elif self._wizardState == 7:
1442 n = int(self.textEntry.GetValue()) - 1
1445 x = profile.getMachineSettingFloat('extruder_offset_x1')
1447 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1448 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1449 self.textEntry.SetValue('10')
1450 self._wizardState = 8
1451 elif self._wizardState == 8:
1453 n = int(self.textEntry.GetValue()) - 1
1456 y = profile.getMachineSettingFloat('extruder_offset_y1')
1458 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1459 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1460 self.infoBox.SetReadyIndicator()
1461 self._wizardState = 8
1463 self.resumeButton.Enable(False)
1465 def mcLog(self, message):
1466 print 'Log:', message
1468 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1469 if self._wizardState == 1:
1470 if temp[0] >= 210 and temp[1] >= 210:
1471 self._wizardState = 2
1472 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1473 wx.CallAfter(self.resumeButton.Enable, True)
1474 wx.CallAfter(self.resumeButton.SetFocus)
1476 def mcStateChange(self, state):
1477 if self.comm is None:
1479 if self.comm.isOperational():
1480 if self._wizardState == 0:
1481 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1482 self.comm.sendCommand('M105')
1483 self.comm.sendCommand('M104 S220 T0')
1484 self.comm.sendCommand('M104 S220 T1')
1485 self.comm.sendCommand('G28')
1486 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1487 self._wizardState = 1
1488 if not self.comm.isPrinting():
1489 if self._wizardState == 3:
1490 self._wizardState = 4
1491 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1492 wx.CallAfter(self.textEntry.SetValue, '0.0')
1493 wx.CallAfter(self.textEntry.Enable, True)
1494 wx.CallAfter(self.resumeButton.Enable, True)
1495 wx.CallAfter(self.resumeButton.SetFocus)
1496 elif self._wizardState == 6:
1497 self._wizardState = 7
1498 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1499 wx.CallAfter(self.textEntry.SetValue, '10')
1500 wx.CallAfter(self.textEntry.Enable, True)
1501 wx.CallAfter(self.resumeButton.Enable, True)
1502 wx.CallAfter(self.resumeButton.SetFocus)
1504 elif self.comm.isError():
1505 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1507 def mcMessage(self, message):
1510 def mcProgress(self, lineNr):
1513 def mcZChange(self, newZ):
1516 class bedLevelWizard(wx.wizard.Wizard):
1518 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1520 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1521 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1523 self.mainPage = bedLevelWizardMain(self)
1524 self.headOffsetCalibration = None
1526 self.FitToPage(self.mainPage)
1527 self.GetPageAreaSizer().Add(self.mainPage)
1529 self.RunWizard(self.mainPage)
1532 def OnPageChanging(self, e):
1533 e.GetPage().StoreData()
1535 def OnPageChanged(self, e):
1536 if e.GetPage().AllowNext():
1537 self.FindWindowById(wx.ID_FORWARD).Enable()
1539 self.FindWindowById(wx.ID_FORWARD).Disable()
1540 if e.GetPage().AllowBack():
1541 self.FindWindowById(wx.ID_BACKWARD).Enable()
1543 self.FindWindowById(wx.ID_BACKWARD).Disable()
1545 class headOffsetWizard(wx.wizard.Wizard):
1547 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1549 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1550 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1552 self.mainPage = headOffsetCalibrationPage(self)
1554 self.FitToPage(self.mainPage)
1555 self.GetPageAreaSizer().Add(self.mainPage)
1557 self.RunWizard(self.mainPage)
1560 def OnPageChanging(self, e):
1561 e.GetPage().StoreData()
1563 def OnPageChanged(self, e):
1564 if e.GetPage().AllowNext():
1565 self.FindWindowById(wx.ID_FORWARD).Enable()
1567 self.FindWindowById(wx.ID_FORWARD).Disable()
1568 if e.GetPage().AllowBack():
1569 self.FindWindowById(wx.ID_BACKWARD).Enable()
1571 self.FindWindowById(wx.ID_BACKWARD).Disable()