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.4, 1.75, 208, 40, 70, 30, 1, False),
237 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
238 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
239 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
240 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
241 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
242 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
243 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
244 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
245 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
246 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
247 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
250 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
251 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
252 self.AddText(_("Select which Printrbot machine you have:"))
254 for printer in self._printer_info:
255 if printer[0].startswith(":"):
257 self.AddText(printer[0][1:])
259 item = self.AddRadioButton(printer[0])
260 item.data = printer[1:]
261 self._items.append(item)
264 profile.putMachineSetting('machine_name', 'Printrbot ???')
265 for item in self._items:
268 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
269 profile.putMachineSetting('machine_width', data[0])
270 profile.putMachineSetting('machine_depth', data[1])
271 profile.putMachineSetting('machine_height', data[2])
272 profile.putProfileSetting('nozzle_size', data[3])
273 profile.putProfileSetting('filament_diameter', data[4])
274 profile.putProfileSetting('print_temperature', data[5])
275 profile.putProfileSetting('print_speed', data[6])
276 profile.putProfileSetting('travel_speed', data[7])
277 profile.putProfileSetting('retraction_speed', data[8])
278 profile.putProfileSetting('retraction_amount', data[9])
279 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
280 profile.putMachineSetting('has_heated_bed', 'False')
281 profile.putMachineSetting('machine_center_is_zero', 'False')
282 profile.putMachineSetting('extruder_head_size_min_x', '0')
283 profile.putMachineSetting('extruder_head_size_min_y', '0')
284 profile.putMachineSetting('extruder_head_size_max_x', '0')
285 profile.putMachineSetting('extruder_head_size_max_y', '0')
286 profile.putMachineSetting('extruder_head_size_height', '0')
288 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
289 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
290 ;Print time: {print_time}
291 ;Filament used: {filament_amount}m {filament_weight}g
292 ;Filament cost: {filament_cost}
293 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
294 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
296 G90 ;absolute positioning
297 M82 ;set extruder to absolute mode
298 M107 ;start with the fan off
299 G28 X0 Y0 ;move X/Y to min endstops
300 G28 Z0 ;move Z to min endstops
301 G29 ;Run the auto bed leveling
302 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
303 G92 E0 ;zero the extruded length
304 G1 F200 E3 ;extrude 3mm of feed stock
305 G92 E0 ;zero the extruded length again
307 ;Put printing message on LCD screen
311 class OtherMachineSelectPage(InfoPage):
312 def __init__(self, parent):
313 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
314 self.AddText(_("The following pre-defined machine profiles are available"))
315 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."))
317 machines = resources.getDefaultMachineProfiles()
319 for filename in machines:
320 name = os.path.splitext(os.path.basename(filename))[0]
321 item = self.AddRadioButton(name)
322 item.filename = filename
323 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
324 self.options.append(item)
326 item = self.AddRadioButton(_('Custom...'))
328 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
330 def OnProfileSelect(self, e):
331 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
333 def OnOtherSelect(self, e):
334 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
337 for option in self.options:
338 if option.GetValue():
339 profile.loadProfile(option.filename)
340 profile.loadMachineSettings(option.filename)
342 class OtherMachineInfoPage(InfoPage):
343 def __init__(self, parent):
344 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
345 self.AddText(_("Cura is now ready to be used!"))
347 class CustomRepRapInfoPage(InfoPage):
348 def __init__(self, parent):
349 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
350 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
351 self.AddText(_("Be sure to review the default profile before running it on your machine."))
352 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
354 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
356 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
357 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
358 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
359 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
360 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
361 self.heatedBed = self.AddCheckbox(_("Heated bed"))
362 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
365 profile.putMachineSetting('machine_name', self.machineName.GetValue())
366 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
367 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
368 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
369 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
370 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
371 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
372 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
373 profile.putMachineSetting('extruder_head_size_min_x', '0')
374 profile.putMachineSetting('extruder_head_size_min_y', '0')
375 profile.putMachineSetting('extruder_head_size_max_x', '0')
376 profile.putMachineSetting('extruder_head_size_max_y', '0')
377 profile.putMachineSetting('extruder_head_size_height', '0')
378 profile.checkAndUpdateMachineName()
380 class MachineSelectPage(InfoPage):
381 def __init__(self, parent):
382 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
383 self.AddText(_("What kind of machine do you have:"))
385 self.LulzbotMiniRadio = self.AddRadioButton("LulzBot Mini", style=wx.RB_GROUP)
386 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
387 self.LulzbotMiniRadio.SetValue(True)
388 self.LulzbotTaz5Radio = self.AddRadioButton("LulzBot TAZ 5")
389 self.LulzbotTaz5Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
390 self.LulzbotTaz4Radio = self.AddRadioButton("LulzBot TAZ 4")
391 self.LulzbotTaz4Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
392 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
393 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
394 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
395 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
396 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
397 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
398 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
399 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
400 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
401 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
402 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
403 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
404 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
405 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
407 def OnUltimaker2Select(self, e):
408 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
410 def OnUltimakerSelect(self, e):
411 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
413 def OnUltimakerOPSelect(self, e):
414 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
416 def OnPrintrbotSelect(self, e):
417 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
419 def OnLulzbotSelect(self, e):
420 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
422 def OnOtherSelect(self, e):
423 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
426 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
430 profile.putProfileSetting('retraction_enable', 'True')
431 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
432 if self.Ultimaker2Radio.GetValue():
433 profile.putMachineSetting('machine_width', '230')
434 profile.putMachineSetting('machine_depth', '225')
435 profile.putMachineSetting('machine_height', '205')
436 profile.putMachineSetting('machine_name', 'ultimaker2')
437 profile.putMachineSetting('machine_type', 'ultimaker2')
438 profile.putMachineSetting('has_heated_bed', 'True')
439 if self.Ultimaker2GoRadio.GetValue():
440 profile.putMachineSetting('machine_width', '120')
441 profile.putMachineSetting('machine_depth', '120')
442 profile.putMachineSetting('machine_height', '115')
443 profile.putMachineSetting('machine_name', 'ultimaker2go')
444 profile.putMachineSetting('machine_type', 'ultimaker2go')
445 profile.putMachineSetting('has_heated_bed', 'False')
446 if self.Ultimaker2ExtRadio.GetValue():
447 profile.putMachineSetting('machine_width', '230')
448 profile.putMachineSetting('machine_depth', '225')
449 profile.putMachineSetting('machine_height', '315')
450 profile.putMachineSetting('machine_name', 'ultimaker2extended')
451 profile.putMachineSetting('machine_type', 'ultimaker2extended')
452 profile.putMachineSetting('has_heated_bed', 'False')
453 profile.putMachineSetting('machine_center_is_zero', 'False')
454 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
455 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
456 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
457 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
458 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
459 profile.putMachineSetting('extruder_head_size_height', '48.0')
460 profile.putProfileSetting('nozzle_size', '0.4')
461 profile.putProfileSetting('fan_full_height', '5.0')
462 profile.putMachineSetting('extruder_offset_x1', '18.0')
463 profile.putMachineSetting('extruder_offset_y1', '0.0')
464 elif self.UltimakerRadio.GetValue():
465 profile.putMachineSetting('machine_width', '205')
466 profile.putMachineSetting('machine_depth', '205')
467 profile.putMachineSetting('machine_height', '200')
468 profile.putMachineSetting('machine_name', 'ultimaker original')
469 profile.putMachineSetting('machine_type', 'ultimaker')
470 profile.putMachineSetting('machine_center_is_zero', 'False')
471 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
472 profile.putProfileSetting('nozzle_size', '0.4')
473 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
474 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
475 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
476 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
477 profile.putMachineSetting('extruder_head_size_height', '55.0')
478 elif self.UltimakerOPRadio.GetValue():
479 profile.putMachineSetting('machine_width', '205')
480 profile.putMachineSetting('machine_depth', '205')
481 profile.putMachineSetting('machine_height', '200')
482 profile.putMachineSetting('machine_name', 'ultimaker original+')
483 profile.putMachineSetting('machine_type', 'ultimaker_plus')
484 profile.putMachineSetting('machine_center_is_zero', 'False')
485 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
486 profile.putProfileSetting('nozzle_size', '0.4')
487 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
488 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
489 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
490 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
491 profile.putMachineSetting('extruder_head_size_height', '55.0')
492 profile.putMachineSetting('has_heated_bed', 'True')
493 profile.putMachineSetting('extruder_amount', '1')
494 profile.putProfileSetting('retraction_enable', 'True')
495 elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
496 if self.LulzbotTaz4Radio.GetValue():
497 profile.putMachineSetting('machine_width', '298')
498 profile.putMachineSetting('machine_depth', '275')
499 profile.putMachineSetting('machine_height', '250')
500 profile.putProfileSetting('nozzle_size', '0.35')
501 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
502 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
503 profile.putMachineSetting('serial_baud', '115200')
504 elif self.LulzbotTaz5Radio.GetValue():
505 profile.putMachineSetting('machine_width', '298')
506 profile.putMachineSetting('machine_depth', '275')
507 profile.putMachineSetting('machine_height', '250')
508 profile.putProfileSetting('nozzle_size', '0.35')
509 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
510 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
511 profile.putMachineSetting('serial_baud', '115200')
513 profile.putMachineSetting('machine_width', '155')
514 profile.putMachineSetting('machine_depth', '155')
515 profile.putMachineSetting('machine_height', '163')
516 profile.putProfileSetting('nozzle_size', '0.5')
517 profile.putMachineSetting('machine_name', 'LulzBot Mini')
518 profile.putMachineSetting('machine_type', 'lulzbot_mini')
519 profile.putMachineSetting('serial_baud', '115200')
520 profile.putMachineSetting('machine_center_is_zero', 'False')
521 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
522 profile.putMachineSetting('has_heated_bed', 'True')
523 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
524 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
525 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
526 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
527 profile.putMachineSetting('extruder_head_size_height', '0.0')
528 profile.putPreference('startMode', 'Simple')
530 profile.putMachineSetting('machine_width', '80')
531 profile.putMachineSetting('machine_depth', '80')
532 profile.putMachineSetting('machine_height', '60')
533 profile.putMachineSetting('machine_name', 'reprap')
534 profile.putMachineSetting('machine_type', 'reprap')
535 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
536 profile.putPreference('startMode', 'Normal')
537 profile.putProfileSetting('nozzle_size', '0.5')
538 profile.checkAndUpdateMachineName()
539 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
541 class SelectParts(InfoPage):
542 def __init__(self, parent):
543 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
544 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."))
546 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
547 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
548 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
549 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
551 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."))
552 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
553 self.springExtruder.SetValue(True)
556 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
557 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
558 profile.putMachineSetting('has_heated_bed', 'True')
560 profile.putMachineSetting('has_heated_bed', 'False')
561 if self.dualExtrusion.GetValue():
562 profile.putMachineSetting('extruder_amount', '2')
563 profile.putMachineSetting('machine_depth', '195')
565 profile.putMachineSetting('extruder_amount', '1')
566 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
567 profile.putProfileSetting('retraction_enable', 'True')
569 profile.putProfileSetting('retraction_enable', 'False')
572 class UltimakerFirmwareUpgradePage(InfoPage):
573 def __init__(self, parent):
574 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
575 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."))
576 self.AddHiddenSeperator()
577 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
578 self.AddHiddenSeperator()
579 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."))
580 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
581 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
582 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
583 self.AddHiddenSeperator()
584 if profile.getMachineSetting('machine_type') == 'ultimaker':
585 self.AddText(_("Do not upgrade to this firmware if:"))
586 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
587 self.AddText(_("* Build your own heated bed"))
588 self.AddText(_("* Have other changes in the firmware"))
589 # button = self.AddButton('Goto this page for a custom firmware')
590 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
595 def OnUpgradeClick(self, e):
596 if firmwareInstall.InstallFirmware():
597 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
599 def OnSkipClick(self, e):
600 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
601 self.GetParent().ShowPage(self.GetNext())
603 def OnUrlClick(self, e):
604 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
606 class UltimakerCheckupPage(InfoPage):
607 def __init__(self, parent):
608 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
610 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
611 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
612 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
613 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
614 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
615 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
616 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
617 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
618 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
619 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
622 _("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."))
623 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
624 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
625 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
627 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
628 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
629 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
631 self.infoBox = self.AddInfoBox()
632 self.machineState = self.AddText("")
633 self.temperatureLabel = self.AddText("")
634 self.errorLogButton = self.AddButton(_("Show error log"))
635 self.errorLogButton.Show(False)
637 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
639 self.xMinStop = False
640 self.xMaxStop = False
641 self.yMinStop = False
642 self.yMaxStop = False
643 self.zMinStop = False
644 self.zMaxStop = False
646 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
649 if self.comm is not None:
653 self.endstopBitmap.Show(False)
656 def OnSkipClick(self, e):
657 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
658 self.GetParent().ShowPage(self.GetNext())
660 def OnCheckClick(self, e=None):
661 self.errorLogButton.Show(False)
662 if self.comm is not None:
666 wx.CallAfter(self.OnCheckClick)
668 self.infoBox.SetBusy(_("Connecting to machine."))
669 self.commState.SetBitmap(self.unknownBitmap)
670 self.tempState.SetBitmap(self.unknownBitmap)
671 self.stopState.SetBitmap(self.unknownBitmap)
672 self.checkupState = 0
673 self.checkExtruderNr = 0
674 self.comm = machineCom.MachineCom(callbackObject=self)
676 def OnErrorLog(self, e):
677 printWindow.LogWindow('\n'.join(self.comm.getLog()))
679 def mcLog(self, message):
682 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
683 if not self.comm.isOperational():
685 if self.checkupState == 0:
686 self.tempCheckTimeout = 20
687 if temp[self.checkExtruderNr] > 70:
688 self.checkupState = 1
689 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
690 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
691 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
693 self.startTemp = temp[self.checkExtruderNr]
694 self.checkupState = 2
695 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
696 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
697 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
698 elif self.checkupState == 1:
699 if temp[self.checkExtruderNr] < 60:
700 self.startTemp = temp[self.checkExtruderNr]
701 self.checkupState = 2
702 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
703 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
704 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
705 elif self.checkupState == 2:
706 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
707 if temp[self.checkExtruderNr] > self.startTemp + 40:
708 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
709 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
710 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
711 self.checkExtruderNr = 0
712 self.checkupState = 3
713 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
714 wx.CallAfter(self.endstopBitmap.Show, True)
715 wx.CallAfter(self.Layout)
716 self.comm.sendCommand('M119')
717 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
719 self.checkupState = 0
720 self.checkExtruderNr += 1
722 self.tempCheckTimeout -= 1
723 if self.tempCheckTimeout < 1:
724 self.checkupState = -1
725 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
726 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
727 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
728 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
729 elif self.checkupState >= 3 and self.checkupState < 10:
730 self.comm.sendCommand('M119')
731 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
733 def mcStateChange(self, state):
734 if self.comm is None:
736 if self.comm.isOperational():
737 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
738 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
739 elif self.comm.isError():
740 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
741 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
742 wx.CallAfter(self.endstopBitmap.Show, False)
743 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
744 wx.CallAfter(self.errorLogButton.Show, True)
745 wx.CallAfter(self.Layout)
747 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
749 def mcMessage(self, message):
750 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
751 for data in message.split(' '):
753 tag, value = data.split(':', 1)
755 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
757 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
759 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
761 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
763 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
765 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
767 tag, value = map(str.strip, message.split(':', 1))
769 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
771 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
773 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
775 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
777 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
779 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
780 if 'z_max' in message:
781 self.comm.sendCommand('M119')
783 if self.checkupState == 3:
784 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
785 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
786 self.checkupState = 5
787 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
788 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
790 self.checkupState = 4
791 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
792 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
793 elif self.checkupState == 4:
794 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
795 self.checkupState = 5
796 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
797 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
798 elif self.checkupState == 5:
799 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
800 self.checkupState = 6
801 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
802 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
803 elif self.checkupState == 6:
804 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
805 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
806 self.checkupState = 8
807 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
808 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
810 self.checkupState = 7
811 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
812 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
813 elif self.checkupState == 7:
814 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
815 self.checkupState = 8
816 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
817 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
818 elif self.checkupState == 8:
819 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
820 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
821 self.checkupState = 10
823 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
824 wx.CallAfter(self.infoBox.SetReadyIndicator)
825 wx.CallAfter(self.endstopBitmap.Show, False)
826 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
827 wx.CallAfter(self.OnSkipClick, None)
829 self.checkupState = 9
830 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
831 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
832 elif self.checkupState == 9:
833 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
834 self.checkupState = 10
836 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
837 wx.CallAfter(self.infoBox.SetReadyIndicator)
838 wx.CallAfter(self.endstopBitmap.Show, False)
839 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
840 wx.CallAfter(self.OnSkipClick, None)
842 def mcProgress(self, lineNr):
845 def mcZChange(self, newZ):
849 class UltimakerCalibrationPage(InfoPage):
850 def __init__(self, parent):
851 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
853 self.AddText("Your Ultimaker requires some calibration.")
854 self.AddText("This calibration is needed for a proper extrusion amount.")
856 self.AddText("The following values are needed:")
857 self.AddText("* Diameter of filament")
858 self.AddText("* Number of steps per mm of filament extrusion")
860 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
862 self.AddText("First we need the diameter of your filament:")
863 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
865 "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.")
866 self.AddText("Note: This value can be changed later at any time.")
869 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
872 class UltimakerCalibrateStepsPerEPage(InfoPage):
873 def __init__(self, parent):
874 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
876 #if profile.getMachineSetting('steps_per_e') == '0':
877 # profile.putMachineSetting('steps_per_e', '865.888')
879 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
880 self.AddText(_("First remove any filament from your machine."))
881 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
882 self.AddText(_("We'll push the filament 100mm"))
883 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
884 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
885 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
886 self.AddText(_("This results in the following steps per E:"))
887 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
888 self.AddText(_("You can repeat these steps to get better calibration."))
891 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
892 self.heatButton = self.AddButton(_("Heatup for filament removal"))
894 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
895 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
896 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
898 def OnSaveLengthClick(self, e):
899 currentEValue = float(self.stepsPerEInput.GetValue())
900 realExtrudeLength = float(self.lengthInput.GetValue())
901 newEValue = currentEValue * 100 / realExtrudeLength
902 self.stepsPerEInput.SetValue(str(newEValue))
903 self.lengthInput.SetValue("100")
905 def OnExtrudeClick(self, e):
906 t = threading.Thread(target=self.OnExtrudeRun)
910 def OnExtrudeRun(self):
911 self.heatButton.Enable(False)
912 self.extrudeButton.Enable(False)
913 currentEValue = float(self.stepsPerEInput.GetValue())
914 self.comm = machineCom.MachineCom()
915 if not self.comm.isOpen():
917 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
918 'Printer error', wx.OK | wx.ICON_INFORMATION)
919 self.heatButton.Enable(True)
920 self.extrudeButton.Enable(True)
923 line = self.comm.readline()
928 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
931 self.sendGCommand('M302') #Disable cold extrusion protection
932 self.sendGCommand("M92 E%f" % (currentEValue))
933 self.sendGCommand("G92 E0")
934 self.sendGCommand("G1 E100 F600")
937 self.extrudeButton.Enable()
938 self.heatButton.Enable()
940 def OnHeatClick(self, e):
941 t = threading.Thread(target=self.OnHeatRun)
946 self.heatButton.Enable(False)
947 self.extrudeButton.Enable(False)
948 self.comm = machineCom.MachineCom()
949 if not self.comm.isOpen():
951 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
952 'Printer error', wx.OK | wx.ICON_INFORMATION)
953 self.heatButton.Enable(True)
954 self.extrudeButton.Enable(True)
957 line = self.comm.readline()
959 self.heatButton.Enable(True)
960 self.extrudeButton.Enable(True)
964 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
967 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
969 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
970 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
971 self.sendGCommand('M104 S0')
974 self.heatButton.Enable(True)
975 self.extrudeButton.Enable(True)
977 def sendGCommand(self, cmd):
978 self.comm.sendCommand(cmd) #Disable cold extrusion protection
980 line = self.comm.readline()
983 if line.startswith('ok'):
987 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
989 class Ultimaker2ReadyPage(InfoPage):
990 def __init__(self, parent):
991 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
992 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
993 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
996 class LulzbotReadyPage(InfoPage):
997 def __init__(self, parent):
998 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
999 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1001 self.AddText(_('For more information about using Cura with your LulzBot'))
1002 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1005 class ConfigWizard(wx.wizard.Wizard):
1006 def __init__(self, addNew = False):
1007 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1009 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1011 profile.setActiveMachine(profile.getMachineCount())
1013 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1014 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1015 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1017 self.machineSelectPage = MachineSelectPage(self)
1018 self.ultimakerSelectParts = SelectParts(self)
1019 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1020 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1021 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1022 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1023 self.bedLevelPage = bedLevelWizardMain(self)
1024 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1025 self.printrbotSelectType = PrintrbotPage(self)
1026 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1027 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1028 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1030 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1031 self.lulzbotReadyPage = LulzbotReadyPage(self)
1033 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1034 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1035 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1036 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1037 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1038 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1039 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1040 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1042 self.FitToPage(self.machineSelectPage)
1043 self.GetPageAreaSizer().Add(self.machineSelectPage)
1045 self.RunWizard(self.machineSelectPage)
1048 def OnPageChanging(self, e):
1049 e.GetPage().StoreData()
1051 def OnPageChanged(self, e):
1052 if e.GetPage().AllowNext():
1053 self.FindWindowById(wx.ID_FORWARD).Enable()
1055 self.FindWindowById(wx.ID_FORWARD).Disable()
1056 if e.GetPage().AllowBack():
1057 self.FindWindowById(wx.ID_BACKWARD).Enable()
1059 self.FindWindowById(wx.ID_BACKWARD).Disable()
1061 def OnCancel(self, e):
1062 profile.setActiveMachine(self._old_machine_index)
1064 class bedLevelWizardMain(InfoPage):
1065 def __init__(self, parent):
1066 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1068 self.AddText(_('This wizard will help you in leveling your printer bed'))
1070 self.AddText(_('It will do the following steps'))
1071 self.AddText(_('* Move the printer head to each corner'))
1072 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1073 self.AddText(_('* Print a line around the bed to check if it is level'))
1076 self.connectButton = self.AddButton(_('Connect to printer'))
1079 self.infoBox = self.AddInfoBox()
1080 self.resumeButton = self.AddButton(_('Resume'))
1081 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1082 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1083 self.resumeButton.Enable(False)
1085 self.upButton.Enable(False)
1086 self.downButton.Enable(False)
1087 self.upButton2.Enable(False)
1088 self.downButton2.Enable(False)
1090 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1091 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1092 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1093 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1094 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1095 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1097 def OnConnect(self, e = None):
1098 if self.comm is not None:
1102 wx.CallAfter(self.OnConnect)
1104 self.connectButton.Enable(False)
1105 self.comm = machineCom.MachineCom(callbackObject=self)
1106 self.infoBox.SetBusy(_('Connecting to machine.'))
1107 self._wizardState = 0
1109 def OnBedUp(self, e):
1110 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1111 self.comm.sendCommand('G92 Z10')
1112 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1113 self.comm.sendCommand('M400')
1115 def OnBedDown(self, e):
1116 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1117 self.comm.sendCommand('G92 Z10')
1118 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1119 self.comm.sendCommand('M400')
1121 def OnBedUp2(self, e):
1122 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1123 self.comm.sendCommand('G92 Z10')
1124 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1125 self.comm.sendCommand('M400')
1127 def OnBedDown2(self, e):
1128 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1129 self.comm.sendCommand('G92 Z10')
1130 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1131 self.comm.sendCommand('M400')
1133 def AllowNext(self):
1134 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1135 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1138 def OnResume(self, e):
1139 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1140 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1141 if self._wizardState == -1:
1142 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1143 wx.CallAfter(self.upButton.Enable, False)
1144 wx.CallAfter(self.downButton.Enable, False)
1145 wx.CallAfter(self.upButton2.Enable, False)
1146 wx.CallAfter(self.downButton2.Enable, False)
1147 self.comm.sendCommand('M105')
1148 self.comm.sendCommand('G28')
1149 self._wizardState = 1
1150 elif self._wizardState == 2:
1151 if profile.getMachineSetting('has_heated_bed') == 'True':
1152 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1153 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1154 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1155 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1156 self.comm.sendCommand('M400')
1157 self._wizardState = 3
1159 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1160 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1161 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1162 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1163 self.comm.sendCommand('M400')
1164 self._wizardState = 3
1165 elif self._wizardState == 4:
1166 if profile.getMachineSetting('has_heated_bed') == 'True':
1167 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1168 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1169 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1170 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1171 self.comm.sendCommand('M400')
1172 self._wizardState = 7
1174 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1175 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1176 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1177 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1178 self.comm.sendCommand('M400')
1179 self._wizardState = 5
1180 elif self._wizardState == 6:
1181 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1182 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1183 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1184 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1185 self.comm.sendCommand('M400')
1186 self._wizardState = 7
1187 elif self._wizardState == 8:
1188 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1189 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1190 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1191 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1192 self._wizardState = 9
1193 elif self._wizardState == 10:
1194 self._wizardState = 11
1195 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1196 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1197 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1198 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1199 w = profile.getMachineSettingFloat('machine_width') - 10
1200 d = profile.getMachineSettingFloat('machine_depth')
1201 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1202 filamentArea = math.pi * filamentRadius * filamentRadius
1203 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1207 'G1 Z2 F%d' % (feedZ),
1209 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1210 'G1 Z0.3 F%d' % (feedZ)]
1212 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1214 for i in xrange(0, 3):
1215 dist = 5.0 + 0.4 * float(i)
1216 eValue += (d - 2.0*dist) * ePerMM
1217 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1218 eValue += (w - 2.0*dist) * ePerMM
1219 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1220 eValue += (d - 2.0*dist) * ePerMM
1221 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1222 eValue += (w - 2.0*dist) * ePerMM
1223 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1225 gcodeList.append('M400')
1226 self.comm.printGCode(gcodeList)
1227 self.resumeButton.Enable(False)
1229 def mcLog(self, message):
1230 print 'Log:', message
1232 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1233 if self._wizardState == 1:
1234 self._wizardState = 2
1235 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1236 wx.CallAfter(self.resumeButton.Enable, True)
1237 elif self._wizardState == 3:
1238 self._wizardState = 4
1239 if profile.getMachineSetting('has_heated_bed') == 'True':
1240 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1242 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1243 wx.CallAfter(self.resumeButton.Enable, True)
1244 elif self._wizardState == 5:
1245 self._wizardState = 6
1246 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1247 wx.CallAfter(self.resumeButton.Enable, True)
1248 elif self._wizardState == 7:
1249 self._wizardState = 8
1250 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1251 wx.CallAfter(self.resumeButton.Enable, True)
1252 elif self._wizardState == 9:
1253 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1254 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1256 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1257 wx.CallAfter(self.resumeButton.Enable, True)
1258 self._wizardState = 10
1260 def mcStateChange(self, state):
1261 if self.comm is None:
1263 if self.comm.isOperational():
1264 if self._wizardState == 0:
1265 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1266 wx.CallAfter(self.upButton.Enable, True)
1267 wx.CallAfter(self.downButton.Enable, True)
1268 wx.CallAfter(self.upButton2.Enable, True)
1269 wx.CallAfter(self.downButton2.Enable, True)
1270 wx.CallAfter(self.resumeButton.Enable, True)
1271 self._wizardState = -1
1272 elif self._wizardState == 11 and not self.comm.isPrinting():
1273 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1274 self.comm.sendCommand('G92 E0')
1275 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1276 self.comm.sendCommand('M104 S0')
1277 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1278 wx.CallAfter(self.infoBox.SetReadyIndicator)
1279 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1280 wx.CallAfter(self.connectButton.Enable, True)
1281 self._wizardState = 12
1282 elif self.comm.isError():
1283 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1285 def mcMessage(self, message):
1288 def mcProgress(self, lineNr):
1291 def mcZChange(self, newZ):
1294 class headOffsetCalibrationPage(InfoPage):
1295 def __init__(self, parent):
1296 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1298 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1301 self.connectButton = self.AddButton(_('Connect to printer'))
1304 self.infoBox = self.AddInfoBox()
1305 self.textEntry = self.AddTextCtrl('')
1306 self.textEntry.Enable(False)
1307 self.resumeButton = self.AddButton(_('Resume'))
1308 self.resumeButton.Enable(False)
1310 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1311 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1313 def AllowBack(self):
1316 def OnConnect(self, e = None):
1317 if self.comm is not None:
1321 wx.CallAfter(self.OnConnect)
1323 self.connectButton.Enable(False)
1324 self.comm = machineCom.MachineCom(callbackObject=self)
1325 self.infoBox.SetBusy(_('Connecting to machine.'))
1326 self._wizardState = 0
1328 def OnResume(self, e):
1329 if self._wizardState == 2:
1330 self._wizardState = 3
1331 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1333 w = profile.getMachineSettingFloat('machine_width')
1334 d = profile.getMachineSettingFloat('machine_depth')
1336 gcode = gcodeGenerator.gcodeGenerator()
1337 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1338 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1345 gcode.addMove(w/2, 5)
1346 gcode.addMove(z=0.2)
1348 gcode.addExtrude(w/2, d-5.0)
1350 gcode.addMove(5, d/2)
1352 gcode.addExtrude(w-5.0, d/2)
1353 gcode.addRetract(15)
1356 gcode.addMove(w/2, 5)
1358 gcode.addExtrude(w/2, d-5.0)
1360 gcode.addMove(5, d/2)
1362 gcode.addExtrude(w-5.0, d/2)
1363 gcode.addRetract(15)
1368 gcode.addCmd('M400')
1370 self.comm.printGCode(gcode.list())
1371 self.resumeButton.Enable(False)
1372 elif self._wizardState == 4:
1374 float(self.textEntry.GetValue())
1377 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1378 self._wizardState = 5
1379 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1380 self.textEntry.SetValue('0.0')
1381 self.textEntry.Enable(True)
1382 elif self._wizardState == 5:
1384 float(self.textEntry.GetValue())
1387 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1388 self._wizardState = 6
1389 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1390 self.textEntry.SetValue('')
1391 self.textEntry.Enable(False)
1392 self.resumeButton.Enable(False)
1394 x = profile.getMachineSettingFloat('extruder_offset_x1')
1395 y = profile.getMachineSettingFloat('extruder_offset_y1')
1396 gcode = gcodeGenerator.gcodeGenerator()
1397 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1398 gcode.setPrintSpeed(25)
1401 gcode.addMove(50, 40, 0.2)
1403 for n in xrange(0, 10):
1404 gcode.addExtrude(50 + n * 10, 150)
1405 gcode.addExtrude(50 + n * 10 + 5, 150)
1406 gcode.addExtrude(50 + n * 10 + 5, 40)
1407 gcode.addExtrude(50 + n * 10 + 10, 40)
1408 gcode.addMove(40, 50)
1409 for n in xrange(0, 10):
1410 gcode.addExtrude(150, 50 + n * 10)
1411 gcode.addExtrude(150, 50 + n * 10 + 5)
1412 gcode.addExtrude(40, 50 + n * 10 + 5)
1413 gcode.addExtrude(40, 50 + n * 10 + 10)
1414 gcode.addRetract(15)
1417 gcode.addMove(50 - x, 30 - y, 0.2)
1419 for n in xrange(0, 10):
1420 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1421 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1422 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1423 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1424 gcode.addMove(30 - x, 50 - y, 0.2)
1425 for n in xrange(0, 10):
1426 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1427 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1428 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1429 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1430 gcode.addRetract(15)
1432 gcode.addCmd('M400')
1433 gcode.addCmd('M104 T0 S0')
1434 gcode.addCmd('M104 T1 S0')
1435 self.comm.printGCode(gcode.list())
1436 elif self._wizardState == 7:
1438 n = int(self.textEntry.GetValue()) - 1
1441 x = profile.getMachineSettingFloat('extruder_offset_x1')
1443 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1444 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1445 self.textEntry.SetValue('10')
1446 self._wizardState = 8
1447 elif self._wizardState == 8:
1449 n = int(self.textEntry.GetValue()) - 1
1452 y = profile.getMachineSettingFloat('extruder_offset_y1')
1454 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1455 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1456 self.infoBox.SetReadyIndicator()
1457 self._wizardState = 8
1459 self.resumeButton.Enable(False)
1461 def mcLog(self, message):
1462 print 'Log:', message
1464 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1465 if self._wizardState == 1:
1466 if temp[0] >= 210 and temp[1] >= 210:
1467 self._wizardState = 2
1468 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1469 wx.CallAfter(self.resumeButton.Enable, True)
1470 wx.CallAfter(self.resumeButton.SetFocus)
1472 def mcStateChange(self, state):
1473 if self.comm is None:
1475 if self.comm.isOperational():
1476 if self._wizardState == 0:
1477 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1478 self.comm.sendCommand('M105')
1479 self.comm.sendCommand('M104 S220 T0')
1480 self.comm.sendCommand('M104 S220 T1')
1481 self.comm.sendCommand('G28')
1482 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1483 self._wizardState = 1
1484 if not self.comm.isPrinting():
1485 if self._wizardState == 3:
1486 self._wizardState = 4
1487 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1488 wx.CallAfter(self.textEntry.SetValue, '0.0')
1489 wx.CallAfter(self.textEntry.Enable, True)
1490 wx.CallAfter(self.resumeButton.Enable, True)
1491 wx.CallAfter(self.resumeButton.SetFocus)
1492 elif self._wizardState == 6:
1493 self._wizardState = 7
1494 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1495 wx.CallAfter(self.textEntry.SetValue, '10')
1496 wx.CallAfter(self.textEntry.Enable, True)
1497 wx.CallAfter(self.resumeButton.Enable, True)
1498 wx.CallAfter(self.resumeButton.SetFocus)
1500 elif self.comm.isError():
1501 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1503 def mcMessage(self, message):
1506 def mcProgress(self, lineNr):
1509 def mcZChange(self, newZ):
1512 class bedLevelWizard(wx.wizard.Wizard):
1514 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1516 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1517 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1519 self.mainPage = bedLevelWizardMain(self)
1520 self.headOffsetCalibration = None
1522 self.FitToPage(self.mainPage)
1523 self.GetPageAreaSizer().Add(self.mainPage)
1525 self.RunWizard(self.mainPage)
1528 def OnPageChanging(self, e):
1529 e.GetPage().StoreData()
1531 def OnPageChanged(self, e):
1532 if e.GetPage().AllowNext():
1533 self.FindWindowById(wx.ID_FORWARD).Enable()
1535 self.FindWindowById(wx.ID_FORWARD).Disable()
1536 if e.GetPage().AllowBack():
1537 self.FindWindowById(wx.ID_BACKWARD).Enable()
1539 self.FindWindowById(wx.ID_BACKWARD).Disable()
1541 class headOffsetWizard(wx.wizard.Wizard):
1543 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1545 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1546 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1548 self.mainPage = headOffsetCalibrationPage(self)
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()