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.OnTaz5Select)
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 OnTaz5Select(self, e):
423 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().taz5NozzleSelectPage)
425 def OnOtherSelect(self, e):
426 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
429 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
433 profile.putProfileSetting('retraction_enable', 'True')
434 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
435 if self.Ultimaker2Radio.GetValue():
436 profile.putMachineSetting('machine_width', '230')
437 profile.putMachineSetting('machine_depth', '225')
438 profile.putMachineSetting('machine_height', '205')
439 profile.putMachineSetting('machine_name', 'ultimaker2')
440 profile.putMachineSetting('machine_type', 'ultimaker2')
441 profile.putMachineSetting('has_heated_bed', 'True')
442 if self.Ultimaker2GoRadio.GetValue():
443 profile.putMachineSetting('machine_width', '120')
444 profile.putMachineSetting('machine_depth', '120')
445 profile.putMachineSetting('machine_height', '115')
446 profile.putMachineSetting('machine_name', 'ultimaker2go')
447 profile.putMachineSetting('machine_type', 'ultimaker2go')
448 profile.putMachineSetting('has_heated_bed', 'False')
449 if self.Ultimaker2ExtRadio.GetValue():
450 profile.putMachineSetting('machine_width', '230')
451 profile.putMachineSetting('machine_depth', '225')
452 profile.putMachineSetting('machine_height', '315')
453 profile.putMachineSetting('machine_name', 'ultimaker2extended')
454 profile.putMachineSetting('machine_type', 'ultimaker2extended')
455 profile.putMachineSetting('has_heated_bed', 'False')
456 profile.putMachineSetting('machine_center_is_zero', 'False')
457 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
458 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
459 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
460 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
461 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
462 profile.putMachineSetting('extruder_head_size_height', '48.0')
463 profile.putProfileSetting('nozzle_size', '0.4')
464 profile.putProfileSetting('fan_full_height', '5.0')
465 profile.putMachineSetting('extruder_offset_x1', '18.0')
466 profile.putMachineSetting('extruder_offset_y1', '0.0')
467 elif self.UltimakerRadio.GetValue():
468 profile.putMachineSetting('machine_width', '205')
469 profile.putMachineSetting('machine_depth', '205')
470 profile.putMachineSetting('machine_height', '200')
471 profile.putMachineSetting('machine_name', 'ultimaker original')
472 profile.putMachineSetting('machine_type', 'ultimaker')
473 profile.putMachineSetting('machine_center_is_zero', 'False')
474 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
475 profile.putProfileSetting('nozzle_size', '0.4')
476 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
477 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
478 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
479 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
480 profile.putMachineSetting('extruder_head_size_height', '55.0')
481 elif self.UltimakerOPRadio.GetValue():
482 profile.putMachineSetting('machine_width', '205')
483 profile.putMachineSetting('machine_depth', '205')
484 profile.putMachineSetting('machine_height', '200')
485 profile.putMachineSetting('machine_name', 'ultimaker original+')
486 profile.putMachineSetting('machine_type', 'ultimaker_plus')
487 profile.putMachineSetting('machine_center_is_zero', 'False')
488 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
489 profile.putProfileSetting('nozzle_size', '0.4')
490 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
491 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
492 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
493 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
494 profile.putMachineSetting('extruder_head_size_height', '55.0')
495 profile.putMachineSetting('has_heated_bed', 'True')
496 profile.putMachineSetting('extruder_amount', '1')
497 profile.putProfileSetting('retraction_enable', 'True')
498 elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
499 if self.LulzbotTaz4Radio.GetValue():
500 profile.putMachineSetting('machine_width', '298')
501 profile.putMachineSetting('machine_depth', '275')
502 profile.putMachineSetting('machine_height', '250')
503 profile.putProfileSetting('nozzle_size', '0.35')
504 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
505 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
506 profile.putMachineSetting('serial_baud', '115200')
507 elif self.LulzbotTaz5Radio.GetValue():
508 profile.putMachineSetting('machine_width', '298')
509 profile.putMachineSetting('machine_depth', '275')
510 profile.putMachineSetting('machine_height', '250')
511 profile.putProfileSetting('nozzle_size', '0.35')
512 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
513 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
514 profile.putMachineSetting('serial_baud', '115200')
516 profile.putMachineSetting('machine_width', '155')
517 profile.putMachineSetting('machine_depth', '155')
518 profile.putMachineSetting('machine_height', '163')
519 profile.putProfileSetting('nozzle_size', '0.5')
520 profile.putMachineSetting('machine_name', 'LulzBot Mini')
521 profile.putMachineSetting('machine_type', 'lulzbot_mini')
522 profile.putMachineSetting('serial_baud', '115200')
523 profile.putMachineSetting('extruder_head_size_min_x', '40')
524 profile.putMachineSetting('extruder_head_size_max_x', '75')
525 profile.putMachineSetting('extruder_head_size_min_y', '25')
526 profile.putMachineSetting('extruder_head_size_max_y', '55')
527 profile.putMachineSetting('extruder_head_size_height', '17')
529 profile.putMachineSetting('machine_center_is_zero', 'False')
530 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
531 profile.putMachineSetting('has_heated_bed', 'True')
532 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
533 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
534 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
535 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
536 profile.putMachineSetting('extruder_head_size_height', '0.0')
537 profile.putPreference('startMode', 'Simple')
539 profile.putMachineSetting('machine_width', '80')
540 profile.putMachineSetting('machine_depth', '80')
541 profile.putMachineSetting('machine_height', '60')
542 profile.putMachineSetting('machine_name', 'reprap')
543 profile.putMachineSetting('machine_type', 'reprap')
544 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
545 profile.putPreference('startMode', 'Normal')
546 profile.putProfileSetting('nozzle_size', '0.5')
547 profile.checkAndUpdateMachineName()
548 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
550 class SelectParts(InfoPage):
551 def __init__(self, parent):
552 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
553 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."))
555 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
556 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
557 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
558 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
560 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."))
561 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
562 self.springExtruder.SetValue(True)
565 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
566 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
567 profile.putMachineSetting('has_heated_bed', 'True')
569 profile.putMachineSetting('has_heated_bed', 'False')
570 if self.dualExtrusion.GetValue():
571 profile.putMachineSetting('extruder_amount', '2')
572 profile.putMachineSetting('machine_depth', '195')
574 profile.putMachineSetting('extruder_amount', '1')
575 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
576 profile.putProfileSetting('retraction_enable', 'True')
578 profile.putProfileSetting('retraction_enable', 'False')
581 class UltimakerFirmwareUpgradePage(InfoPage):
582 def __init__(self, parent):
583 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
584 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."))
585 self.AddHiddenSeperator()
586 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
587 self.AddHiddenSeperator()
588 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."))
589 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
590 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
591 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
592 self.AddHiddenSeperator()
593 if profile.getMachineSetting('machine_type') == 'ultimaker':
594 self.AddText(_("Do not upgrade to this firmware if:"))
595 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
596 self.AddText(_("* Build your own heated bed"))
597 self.AddText(_("* Have other changes in the firmware"))
598 # button = self.AddButton('Goto this page for a custom firmware')
599 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
604 def OnUpgradeClick(self, e):
605 if firmwareInstall.InstallFirmware():
606 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
608 def OnSkipClick(self, e):
609 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
610 self.GetParent().ShowPage(self.GetNext())
612 def OnUrlClick(self, e):
613 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
615 class UltimakerCheckupPage(InfoPage):
616 def __init__(self, parent):
617 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
619 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
620 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
621 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
622 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
623 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
624 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
625 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
626 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
627 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
628 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
631 _("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."))
632 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
633 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
634 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
636 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
637 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
638 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
640 self.infoBox = self.AddInfoBox()
641 self.machineState = self.AddText("")
642 self.temperatureLabel = self.AddText("")
643 self.errorLogButton = self.AddButton(_("Show error log"))
644 self.errorLogButton.Show(False)
646 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
648 self.xMinStop = False
649 self.xMaxStop = False
650 self.yMinStop = False
651 self.yMaxStop = False
652 self.zMinStop = False
653 self.zMaxStop = False
655 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
658 if self.comm is not None:
662 self.endstopBitmap.Show(False)
665 def OnSkipClick(self, e):
666 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
667 self.GetParent().ShowPage(self.GetNext())
669 def OnCheckClick(self, e=None):
670 self.errorLogButton.Show(False)
671 if self.comm is not None:
675 wx.CallAfter(self.OnCheckClick)
677 self.infoBox.SetBusy(_("Connecting to machine."))
678 self.commState.SetBitmap(self.unknownBitmap)
679 self.tempState.SetBitmap(self.unknownBitmap)
680 self.stopState.SetBitmap(self.unknownBitmap)
681 self.checkupState = 0
682 self.checkExtruderNr = 0
683 self.comm = machineCom.MachineCom(callbackObject=self)
685 def OnErrorLog(self, e):
686 printWindow.LogWindow('\n'.join(self.comm.getLog()))
688 def mcLog(self, message):
691 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
692 if not self.comm.isOperational():
694 if self.checkupState == 0:
695 self.tempCheckTimeout = 20
696 if temp[self.checkExtruderNr] > 70:
697 self.checkupState = 1
698 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
699 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
700 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
702 self.startTemp = temp[self.checkExtruderNr]
703 self.checkupState = 2
704 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
705 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
706 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
707 elif self.checkupState == 1:
708 if temp[self.checkExtruderNr] < 60:
709 self.startTemp = temp[self.checkExtruderNr]
710 self.checkupState = 2
711 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
712 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
713 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
714 elif self.checkupState == 2:
715 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
716 if temp[self.checkExtruderNr] > self.startTemp + 40:
717 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
718 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
719 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
720 self.checkExtruderNr = 0
721 self.checkupState = 3
722 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
723 wx.CallAfter(self.endstopBitmap.Show, True)
724 wx.CallAfter(self.Layout)
725 self.comm.sendCommand('M119')
726 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
728 self.checkupState = 0
729 self.checkExtruderNr += 1
731 self.tempCheckTimeout -= 1
732 if self.tempCheckTimeout < 1:
733 self.checkupState = -1
734 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
735 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
736 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
737 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
738 elif self.checkupState >= 3 and self.checkupState < 10:
739 self.comm.sendCommand('M119')
740 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
742 def mcStateChange(self, state):
743 if self.comm is None:
745 if self.comm.isOperational():
746 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
747 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
748 elif self.comm.isError():
749 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
750 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
751 wx.CallAfter(self.endstopBitmap.Show, False)
752 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
753 wx.CallAfter(self.errorLogButton.Show, True)
754 wx.CallAfter(self.Layout)
756 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
758 def mcMessage(self, message):
759 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
760 for data in message.split(' '):
762 tag, value = data.split(':', 1)
764 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
766 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
768 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
770 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
772 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
774 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
776 tag, value = map(str.strip, message.split(':', 1))
778 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
780 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
782 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
784 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
786 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
788 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
789 if 'z_max' in message:
790 self.comm.sendCommand('M119')
792 if self.checkupState == 3:
793 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
794 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
795 self.checkupState = 5
796 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
797 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
799 self.checkupState = 4
800 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
801 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
802 elif self.checkupState == 4:
803 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
804 self.checkupState = 5
805 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
806 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
807 elif self.checkupState == 5:
808 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
809 self.checkupState = 6
810 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
811 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
812 elif self.checkupState == 6:
813 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
814 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
815 self.checkupState = 8
816 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
817 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
819 self.checkupState = 7
820 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
821 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
822 elif self.checkupState == 7:
823 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
824 self.checkupState = 8
825 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
826 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
827 elif self.checkupState == 8:
828 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
829 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
830 self.checkupState = 10
832 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
833 wx.CallAfter(self.infoBox.SetReadyIndicator)
834 wx.CallAfter(self.endstopBitmap.Show, False)
835 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
836 wx.CallAfter(self.OnSkipClick, None)
838 self.checkupState = 9
839 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
840 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
841 elif self.checkupState == 9:
842 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
843 self.checkupState = 10
845 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
846 wx.CallAfter(self.infoBox.SetReadyIndicator)
847 wx.CallAfter(self.endstopBitmap.Show, False)
848 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
849 wx.CallAfter(self.OnSkipClick, None)
851 def mcProgress(self, lineNr):
854 def mcZChange(self, newZ):
858 class UltimakerCalibrationPage(InfoPage):
859 def __init__(self, parent):
860 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
862 self.AddText("Your Ultimaker requires some calibration.")
863 self.AddText("This calibration is needed for a proper extrusion amount.")
865 self.AddText("The following values are needed:")
866 self.AddText("* Diameter of filament")
867 self.AddText("* Number of steps per mm of filament extrusion")
869 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
871 self.AddText("First we need the diameter of your filament:")
872 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
874 "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.")
875 self.AddText("Note: This value can be changed later at any time.")
878 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
881 class UltimakerCalibrateStepsPerEPage(InfoPage):
882 def __init__(self, parent):
883 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
885 #if profile.getMachineSetting('steps_per_e') == '0':
886 # profile.putMachineSetting('steps_per_e', '865.888')
888 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
889 self.AddText(_("First remove any filament from your machine."))
890 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
891 self.AddText(_("We'll push the filament 100mm"))
892 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
893 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
894 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
895 self.AddText(_("This results in the following steps per E:"))
896 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
897 self.AddText(_("You can repeat these steps to get better calibration."))
900 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
901 self.heatButton = self.AddButton(_("Heatup for filament removal"))
903 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
904 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
905 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
907 def OnSaveLengthClick(self, e):
908 currentEValue = float(self.stepsPerEInput.GetValue())
909 realExtrudeLength = float(self.lengthInput.GetValue())
910 newEValue = currentEValue * 100 / realExtrudeLength
911 self.stepsPerEInput.SetValue(str(newEValue))
912 self.lengthInput.SetValue("100")
914 def OnExtrudeClick(self, e):
915 t = threading.Thread(target=self.OnExtrudeRun)
919 def OnExtrudeRun(self):
920 self.heatButton.Enable(False)
921 self.extrudeButton.Enable(False)
922 currentEValue = float(self.stepsPerEInput.GetValue())
923 self.comm = machineCom.MachineCom()
924 if not self.comm.isOpen():
926 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
927 'Printer error', wx.OK | wx.ICON_INFORMATION)
928 self.heatButton.Enable(True)
929 self.extrudeButton.Enable(True)
932 line = self.comm.readline()
937 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
940 self.sendGCommand('M302') #Disable cold extrusion protection
941 self.sendGCommand("M92 E%f" % (currentEValue))
942 self.sendGCommand("G92 E0")
943 self.sendGCommand("G1 E100 F600")
946 self.extrudeButton.Enable()
947 self.heatButton.Enable()
949 def OnHeatClick(self, e):
950 t = threading.Thread(target=self.OnHeatRun)
955 self.heatButton.Enable(False)
956 self.extrudeButton.Enable(False)
957 self.comm = machineCom.MachineCom()
958 if not self.comm.isOpen():
960 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
961 'Printer error', wx.OK | wx.ICON_INFORMATION)
962 self.heatButton.Enable(True)
963 self.extrudeButton.Enable(True)
966 line = self.comm.readline()
968 self.heatButton.Enable(True)
969 self.extrudeButton.Enable(True)
973 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
976 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
978 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
979 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
980 self.sendGCommand('M104 S0')
983 self.heatButton.Enable(True)
984 self.extrudeButton.Enable(True)
986 def sendGCommand(self, cmd):
987 self.comm.sendCommand(cmd) #Disable cold extrusion protection
989 line = self.comm.readline()
992 if line.startswith('ok'):
996 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
998 class Ultimaker2ReadyPage(InfoPage):
999 def __init__(self, parent):
1000 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1001 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1002 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1005 class LulzbotReadyPage(InfoPage):
1006 def __init__(self, parent):
1007 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ4/Mini"))
1008 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1010 self.AddText(_('For more information about using Cura with your LulzBot'))
1011 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1014 class Taz5NozzleSelectPage(InfoPage):
1015 def __init__(self, parent):
1016 super(Taz5NozzleSelectPage, self).__init__(parent, _("LulzBot TAZ5"))
1017 self.AddText(_('Please select nozzle size:'))
1020 class ConfigWizard(wx.wizard.Wizard):
1021 def __init__(self, addNew = False):
1022 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1024 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1026 profile.setActiveMachine(profile.getMachineCount())
1028 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1029 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1030 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1032 self.machineSelectPage = MachineSelectPage(self)
1033 self.ultimakerSelectParts = SelectParts(self)
1034 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1035 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1036 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1037 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1038 self.bedLevelPage = bedLevelWizardMain(self)
1039 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1040 self.printrbotSelectType = PrintrbotPage(self)
1041 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1042 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1043 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1045 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1046 self.lulzbotReadyPage = LulzbotReadyPage(self)
1047 self.taz5NozzleSelectPage = Taz5NozzleSelectPage(self)
1049 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1050 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1051 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1052 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1053 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1054 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1055 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1056 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1058 self.FitToPage(self.machineSelectPage)
1059 self.GetPageAreaSizer().Add(self.machineSelectPage)
1061 self.RunWizard(self.machineSelectPage)
1064 def OnPageChanging(self, e):
1065 e.GetPage().StoreData()
1067 def OnPageChanged(self, e):
1068 if e.GetPage().AllowNext():
1069 self.FindWindowById(wx.ID_FORWARD).Enable()
1071 self.FindWindowById(wx.ID_FORWARD).Disable()
1072 if e.GetPage().AllowBack():
1073 self.FindWindowById(wx.ID_BACKWARD).Enable()
1075 self.FindWindowById(wx.ID_BACKWARD).Disable()
1077 def OnCancel(self, e):
1078 profile.setActiveMachine(self._old_machine_index)
1080 class bedLevelWizardMain(InfoPage):
1081 def __init__(self, parent):
1082 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1084 self.AddText(_('This wizard will help you in leveling your printer bed'))
1086 self.AddText(_('It will do the following steps'))
1087 self.AddText(_('* Move the printer head to each corner'))
1088 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1089 self.AddText(_('* Print a line around the bed to check if it is level'))
1092 self.connectButton = self.AddButton(_('Connect to printer'))
1095 self.infoBox = self.AddInfoBox()
1096 self.resumeButton = self.AddButton(_('Resume'))
1097 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1098 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1099 self.resumeButton.Enable(False)
1101 self.upButton.Enable(False)
1102 self.downButton.Enable(False)
1103 self.upButton2.Enable(False)
1104 self.downButton2.Enable(False)
1106 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1107 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1108 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1109 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1110 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1111 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1113 def OnConnect(self, e = None):
1114 if self.comm is not None:
1118 wx.CallAfter(self.OnConnect)
1120 self.connectButton.Enable(False)
1121 self.comm = machineCom.MachineCom(callbackObject=self)
1122 self.infoBox.SetBusy(_('Connecting to machine.'))
1123 self._wizardState = 0
1125 def OnBedUp(self, e):
1126 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1127 self.comm.sendCommand('G92 Z10')
1128 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1129 self.comm.sendCommand('M400')
1131 def OnBedDown(self, e):
1132 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1133 self.comm.sendCommand('G92 Z10')
1134 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1135 self.comm.sendCommand('M400')
1137 def OnBedUp2(self, e):
1138 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1139 self.comm.sendCommand('G92 Z10')
1140 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1141 self.comm.sendCommand('M400')
1143 def OnBedDown2(self, e):
1144 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1145 self.comm.sendCommand('G92 Z10')
1146 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1147 self.comm.sendCommand('M400')
1149 def AllowNext(self):
1150 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1151 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1154 def OnResume(self, e):
1155 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1156 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1157 if self._wizardState == -1:
1158 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1159 wx.CallAfter(self.upButton.Enable, False)
1160 wx.CallAfter(self.downButton.Enable, False)
1161 wx.CallAfter(self.upButton2.Enable, False)
1162 wx.CallAfter(self.downButton2.Enable, False)
1163 self.comm.sendCommand('M105')
1164 self.comm.sendCommand('G28')
1165 self._wizardState = 1
1166 elif self._wizardState == 2:
1167 if profile.getMachineSetting('has_heated_bed') == 'True':
1168 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1169 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1170 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1171 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1172 self.comm.sendCommand('M400')
1173 self._wizardState = 3
1175 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1176 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1177 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1178 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1179 self.comm.sendCommand('M400')
1180 self._wizardState = 3
1181 elif self._wizardState == 4:
1182 if profile.getMachineSetting('has_heated_bed') == 'True':
1183 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1184 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1185 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1186 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1187 self.comm.sendCommand('M400')
1188 self._wizardState = 7
1190 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1191 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1192 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1193 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1194 self.comm.sendCommand('M400')
1195 self._wizardState = 5
1196 elif self._wizardState == 6:
1197 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1198 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1199 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1200 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1201 self.comm.sendCommand('M400')
1202 self._wizardState = 7
1203 elif self._wizardState == 8:
1204 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1205 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1206 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1207 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1208 self._wizardState = 9
1209 elif self._wizardState == 10:
1210 self._wizardState = 11
1211 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1212 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1213 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1214 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1215 w = profile.getMachineSettingFloat('machine_width') - 10
1216 d = profile.getMachineSettingFloat('machine_depth')
1217 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1218 filamentArea = math.pi * filamentRadius * filamentRadius
1219 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1223 'G1 Z2 F%d' % (feedZ),
1225 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1226 'G1 Z0.3 F%d' % (feedZ)]
1228 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1230 for i in xrange(0, 3):
1231 dist = 5.0 + 0.4 * float(i)
1232 eValue += (d - 2.0*dist) * ePerMM
1233 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1234 eValue += (w - 2.0*dist) * ePerMM
1235 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1236 eValue += (d - 2.0*dist) * ePerMM
1237 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1238 eValue += (w - 2.0*dist) * ePerMM
1239 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1241 gcodeList.append('M400')
1242 self.comm.printGCode(gcodeList)
1243 self.resumeButton.Enable(False)
1245 def mcLog(self, message):
1246 print 'Log:', message
1248 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1249 if self._wizardState == 1:
1250 self._wizardState = 2
1251 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1252 wx.CallAfter(self.resumeButton.Enable, True)
1253 elif self._wizardState == 3:
1254 self._wizardState = 4
1255 if profile.getMachineSetting('has_heated_bed') == 'True':
1256 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1258 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1259 wx.CallAfter(self.resumeButton.Enable, True)
1260 elif self._wizardState == 5:
1261 self._wizardState = 6
1262 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1263 wx.CallAfter(self.resumeButton.Enable, True)
1264 elif self._wizardState == 7:
1265 self._wizardState = 8
1266 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1267 wx.CallAfter(self.resumeButton.Enable, True)
1268 elif self._wizardState == 9:
1269 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1270 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1272 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1273 wx.CallAfter(self.resumeButton.Enable, True)
1274 self._wizardState = 10
1276 def mcStateChange(self, state):
1277 if self.comm is None:
1279 if self.comm.isOperational():
1280 if self._wizardState == 0:
1281 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1282 wx.CallAfter(self.upButton.Enable, True)
1283 wx.CallAfter(self.downButton.Enable, True)
1284 wx.CallAfter(self.upButton2.Enable, True)
1285 wx.CallAfter(self.downButton2.Enable, True)
1286 wx.CallAfter(self.resumeButton.Enable, True)
1287 self._wizardState = -1
1288 elif self._wizardState == 11 and not self.comm.isPrinting():
1289 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1290 self.comm.sendCommand('G92 E0')
1291 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1292 self.comm.sendCommand('M104 S0')
1293 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1294 wx.CallAfter(self.infoBox.SetReadyIndicator)
1295 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1296 wx.CallAfter(self.connectButton.Enable, True)
1297 self._wizardState = 12
1298 elif self.comm.isError():
1299 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1301 def mcMessage(self, message):
1304 def mcProgress(self, lineNr):
1307 def mcZChange(self, newZ):
1310 class headOffsetCalibrationPage(InfoPage):
1311 def __init__(self, parent):
1312 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1314 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1317 self.connectButton = self.AddButton(_('Connect to printer'))
1320 self.infoBox = self.AddInfoBox()
1321 self.textEntry = self.AddTextCtrl('')
1322 self.textEntry.Enable(False)
1323 self.resumeButton = self.AddButton(_('Resume'))
1324 self.resumeButton.Enable(False)
1326 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1327 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1329 def AllowBack(self):
1332 def OnConnect(self, e = None):
1333 if self.comm is not None:
1337 wx.CallAfter(self.OnConnect)
1339 self.connectButton.Enable(False)
1340 self.comm = machineCom.MachineCom(callbackObject=self)
1341 self.infoBox.SetBusy(_('Connecting to machine.'))
1342 self._wizardState = 0
1344 def OnResume(self, e):
1345 if self._wizardState == 2:
1346 self._wizardState = 3
1347 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1349 w = profile.getMachineSettingFloat('machine_width')
1350 d = profile.getMachineSettingFloat('machine_depth')
1352 gcode = gcodeGenerator.gcodeGenerator()
1353 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1354 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1361 gcode.addMove(w/2, 5)
1362 gcode.addMove(z=0.2)
1364 gcode.addExtrude(w/2, d-5.0)
1366 gcode.addMove(5, d/2)
1368 gcode.addExtrude(w-5.0, d/2)
1369 gcode.addRetract(15)
1372 gcode.addMove(w/2, 5)
1374 gcode.addExtrude(w/2, d-5.0)
1376 gcode.addMove(5, d/2)
1378 gcode.addExtrude(w-5.0, d/2)
1379 gcode.addRetract(15)
1384 gcode.addCmd('M400')
1386 self.comm.printGCode(gcode.list())
1387 self.resumeButton.Enable(False)
1388 elif self._wizardState == 4:
1390 float(self.textEntry.GetValue())
1393 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1394 self._wizardState = 5
1395 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1396 self.textEntry.SetValue('0.0')
1397 self.textEntry.Enable(True)
1398 elif self._wizardState == 5:
1400 float(self.textEntry.GetValue())
1403 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1404 self._wizardState = 6
1405 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1406 self.textEntry.SetValue('')
1407 self.textEntry.Enable(False)
1408 self.resumeButton.Enable(False)
1410 x = profile.getMachineSettingFloat('extruder_offset_x1')
1411 y = profile.getMachineSettingFloat('extruder_offset_y1')
1412 gcode = gcodeGenerator.gcodeGenerator()
1413 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1414 gcode.setPrintSpeed(25)
1417 gcode.addMove(50, 40, 0.2)
1419 for n in xrange(0, 10):
1420 gcode.addExtrude(50 + n * 10, 150)
1421 gcode.addExtrude(50 + n * 10 + 5, 150)
1422 gcode.addExtrude(50 + n * 10 + 5, 40)
1423 gcode.addExtrude(50 + n * 10 + 10, 40)
1424 gcode.addMove(40, 50)
1425 for n in xrange(0, 10):
1426 gcode.addExtrude(150, 50 + n * 10)
1427 gcode.addExtrude(150, 50 + n * 10 + 5)
1428 gcode.addExtrude(40, 50 + n * 10 + 5)
1429 gcode.addExtrude(40, 50 + n * 10 + 10)
1430 gcode.addRetract(15)
1433 gcode.addMove(50 - x, 30 - y, 0.2)
1435 for n in xrange(0, 10):
1436 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1437 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1438 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1439 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1440 gcode.addMove(30 - x, 50 - y, 0.2)
1441 for n in xrange(0, 10):
1442 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1443 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1444 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1445 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1446 gcode.addRetract(15)
1448 gcode.addCmd('M400')
1449 gcode.addCmd('M104 T0 S0')
1450 gcode.addCmd('M104 T1 S0')
1451 self.comm.printGCode(gcode.list())
1452 elif self._wizardState == 7:
1454 n = int(self.textEntry.GetValue()) - 1
1457 x = profile.getMachineSettingFloat('extruder_offset_x1')
1459 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1460 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1461 self.textEntry.SetValue('10')
1462 self._wizardState = 8
1463 elif self._wizardState == 8:
1465 n = int(self.textEntry.GetValue()) - 1
1468 y = profile.getMachineSettingFloat('extruder_offset_y1')
1470 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1471 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1472 self.infoBox.SetReadyIndicator()
1473 self._wizardState = 8
1475 self.resumeButton.Enable(False)
1477 def mcLog(self, message):
1478 print 'Log:', message
1480 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1481 if self._wizardState == 1:
1482 if temp[0] >= 210 and temp[1] >= 210:
1483 self._wizardState = 2
1484 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1485 wx.CallAfter(self.resumeButton.Enable, True)
1486 wx.CallAfter(self.resumeButton.SetFocus)
1488 def mcStateChange(self, state):
1489 if self.comm is None:
1491 if self.comm.isOperational():
1492 if self._wizardState == 0:
1493 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1494 self.comm.sendCommand('M105')
1495 self.comm.sendCommand('M104 S220 T0')
1496 self.comm.sendCommand('M104 S220 T1')
1497 self.comm.sendCommand('G28')
1498 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1499 self._wizardState = 1
1500 if not self.comm.isPrinting():
1501 if self._wizardState == 3:
1502 self._wizardState = 4
1503 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1504 wx.CallAfter(self.textEntry.SetValue, '0.0')
1505 wx.CallAfter(self.textEntry.Enable, True)
1506 wx.CallAfter(self.resumeButton.Enable, True)
1507 wx.CallAfter(self.resumeButton.SetFocus)
1508 elif self._wizardState == 6:
1509 self._wizardState = 7
1510 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1511 wx.CallAfter(self.textEntry.SetValue, '10')
1512 wx.CallAfter(self.textEntry.Enable, True)
1513 wx.CallAfter(self.resumeButton.Enable, True)
1514 wx.CallAfter(self.resumeButton.SetFocus)
1516 elif self.comm.isError():
1517 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1519 def mcMessage(self, message):
1522 def mcProgress(self, lineNr):
1525 def mcZChange(self, newZ):
1528 class bedLevelWizard(wx.wizard.Wizard):
1530 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1532 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1533 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1535 self.mainPage = bedLevelWizardMain(self)
1536 self.headOffsetCalibration = None
1538 self.FitToPage(self.mainPage)
1539 self.GetPageAreaSizer().Add(self.mainPage)
1541 self.RunWizard(self.mainPage)
1544 def OnPageChanging(self, e):
1545 e.GetPage().StoreData()
1547 def OnPageChanged(self, e):
1548 if e.GetPage().AllowNext():
1549 self.FindWindowById(wx.ID_FORWARD).Enable()
1551 self.FindWindowById(wx.ID_FORWARD).Disable()
1552 if e.GetPage().AllowBack():
1553 self.FindWindowById(wx.ID_BACKWARD).Enable()
1555 self.FindWindowById(wx.ID_BACKWARD).Disable()
1557 class headOffsetWizard(wx.wizard.Wizard):
1559 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1561 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1562 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1564 self.mainPage = headOffsetCalibrationPage(self)
1566 self.FitToPage(self.mainPage)
1567 self.GetPageAreaSizer().Add(self.mainPage)
1569 self.RunWizard(self.mainPage)
1572 def OnPageChanging(self, e):
1573 e.GetPage().StoreData()
1575 def OnPageChanged(self, e):
1576 if e.GetPage().AllowNext():
1577 self.FindWindowById(wx.ID_FORWARD).Enable()
1579 self.FindWindowById(wx.ID_FORWARD).Disable()
1580 if e.GetPage().AllowBack():
1581 self.FindWindowById(wx.ID_BACKWARD).Enable()
1583 self.FindWindowById(wx.ID_BACKWARD).Disable()