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
18 from Cura.util import version
21 class InfoBox(wx.Panel):
22 def __init__(self, parent):
23 super(InfoBox, self).__init__(parent)
24 self.SetBackgroundColour('#FFFF80')
26 self.sizer = wx.GridBagSizer(5, 5)
27 self.SetSizer(self.sizer)
29 self.attentionBitmap = wx.Bitmap(resources.getPathForImage('attention.png'))
30 self.errorBitmap = wx.Bitmap(resources.getPathForImage('error.png'))
31 self.readyBitmap = wx.Bitmap(resources.getPathForImage('ready.png'))
33 wx.Bitmap(resources.getPathForImage('busy-0.png')),
34 wx.Bitmap(resources.getPathForImage('busy-1.png')),
35 wx.Bitmap(resources.getPathForImage('busy-2.png')),
36 wx.Bitmap(resources.getPathForImage('busy-3.png'))
39 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
40 self.text = wx.StaticText(self, -1, '')
41 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
42 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
43 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
44 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
45 self.sizer.AddGrowableCol(1)
47 self.extraInfoButton.Show(False)
49 self.extraInfoUrl = ''
51 self.timer = wx.Timer(self)
52 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
53 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
56 def SetInfo(self, info):
57 self.SetBackgroundColour('#FFFF80')
58 self.text.SetLabel(info)
59 self.extraInfoButton.Show(False)
62 def SetError(self, info, extraInfoUrl):
63 self.extraInfoUrl = extraInfoUrl
64 self.SetBackgroundColour('#FF8080')
65 self.text.SetLabel(info)
67 self.extraInfoButton.Show(True)
69 self.SetErrorIndicator()
72 def SetAttention(self, info):
73 self.SetBackgroundColour('#FFFF80')
74 self.text.SetLabel(info)
75 self.extraInfoButton.Show(False)
76 self.SetAttentionIndicator()
80 def SetBusy(self, info):
82 self.SetBusyIndicator()
84 def SetBusyIndicator(self):
86 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
88 def doExtraInfo(self, e):
89 webbrowser.open(self.extraInfoUrl)
91 def doBusyUpdate(self, e):
92 if self.busyState is None:
95 if self.busyState >= len(self.busyBitmap):
97 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
99 def SetReadyIndicator(self):
100 self.busyState = None
101 self.bitmap.SetBitmap(self.readyBitmap)
103 def SetErrorIndicator(self):
104 self.busyState = None
105 self.bitmap.SetBitmap(self.errorBitmap)
107 def SetAttentionIndicator(self):
108 self.busyState = None
109 self.bitmap.SetBitmap(self.attentionBitmap)
111 class ImageButton(wx.Panel):
112 DefaultOverlay = wx.Bitmap(resources.getPathForImage('ImageButton_Overlay.png'))
115 __last_group__ = None
116 def __init__(self, parent, label, bitmap, extra_label=None, overlay=DefaultOverlay, style=None):
117 super(ImageButton, self).__init__(parent)
119 if style is ImageButton.IB_GROUP:
120 ImageButton.__last_group__ = self
121 ImageButton.__groups__[self] = [self]
124 if ImageButton.__last_group__:
125 ImageButton.__groups__[ImageButton.__last_group__].append(self)
126 self.group = ImageButton.__last_group__
129 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self), wx.VERTICAL)
130 self.SetSizer(self.sizer)
132 self.original_overlay = overlay
133 self.overlay = self.createOverlay(bitmap, overlay)
134 self.text = wx.StaticText(self, -1, label)
135 self.bmp = wx.StaticBitmap(self, -1, self.bitmap)
137 self.extra_text = wx.StaticText(self, -1, extra_label)
139 self.extra_text = None
140 self.selected = False
143 self.sizer.Add(self.text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
144 self.sizer.Add(self.bmp, 1, flag=wx.ALL|wx.ALIGN_CENTER|wx.EXPAND, border=5)
146 self.sizer.Add(self.extra_text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
147 self.bmp.Bind(wx.EVT_LEFT_UP, self.OnLeftClick)
151 ImageButton.__groups__[self.group].remove(self)
152 if self == self.group:
153 for ib in ImageButton.__groups__[self.group]:
155 del ImageButton.__groups__[self.group]
156 if ImageButton.__last_group__ == self:
157 ImageButton.__last_group__ = None
159 def TriggerGroupCallbacks(self):
161 for ib in ImageButton.__groups__[self.group]:
162 if ib.GetValue() and ib.callback:
166 if self.GetValue() and self.callback:
169 def OnLeftClick(self, e):
175 def SetValue(self, value):
176 old_value = self.selected
177 self.selected = bool(value)
178 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
179 if self.selected and self.group:
180 for ib in ImageButton.__groups__[self.group]:
185 if self.callback and not old_value and self.selected:
188 def SetLabel(self, label):
189 self.text.SetLabel(label)
192 def SetExtraLabel(self, label):
194 self.extra_text.SetLabel(label)
196 self.extra_text = wx.StaticText(self, -1, label)
197 self.sizer.Add(self.extra_text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
200 def SetBitmap(self, bitmap):
202 self.overlay = self.createOverlay(bitmap, self.original_overlay)
203 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
206 def SetOverlay(self, overlay):
207 self.original_overlay = overlay
208 self.overlay = self.createOverlay(self.bitmap, self.original_overlay)
209 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
212 def OnSelected(self, callback):
213 self.callback = callback
215 def createOverlay(self, bitmap, overlay):
216 result = bitmap.GetSubBitmap(wx.Rect(0, 0, *bitmap.Size))
217 (width, height) = bitmap.GetSize()
218 overlay_image = wx.ImageFromBitmap(overlay)
219 overlay_image = overlay_image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
220 overlay_scaled = wx.BitmapFromImage(overlay_image)
222 dc.SelectObject(result)
223 dc.DrawBitmap(overlay_scaled, 0, 0)
224 dc.SelectObject(wx.NullBitmap)
228 class InfoPage(wx.wizard.WizardPageSimple):
229 def __init__(self, parent, title):
230 wx.wizard.WizardPageSimple.__init__(self, parent)
232 parent.GetPageAreaSizer().Add(self)
233 sizer = wx.GridBagSizer(5, 5)
237 self.title = wx.StaticText(self, -1, title)
238 font = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)
239 self.title.SetFont(font)
240 # HACK ALERT: For some reason, the StaticText keeps its same size as if
241 # the font was not modified, this causes the text to wrap and to
242 # get out of bounds of the widgets area and hide other widgets.
243 # The only way I found for the widget to get its right size was to calculate
244 # the new font's extent and set the min size on the widget
245 self.title.SetMinSize(self.GetTextExtent(font, title))
246 sizer.Add(self.title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
247 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
248 sizer.AddGrowableCol(1)
252 def GetTextExtent(self, font, text):
255 w,h = dc.GetTextExtent(text)
258 def AddText(self, info):
259 text = wx.StaticText(self, -1, info)
260 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
264 def AddSeperator(self):
265 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
268 def AddHiddenSeperator(self):
271 def AddInfoBox(self):
272 infoBox = InfoBox(self)
273 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
277 def AddRadioButton(self, label, style=0):
278 radio = wx.RadioButton(self, -1, label, style=style)
279 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
283 def AddCheckbox(self, label, checked=False):
284 check = wx.CheckBox(self, -1)
285 text = wx.StaticText(self, -1, label)
286 check.SetValue(checked)
287 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
288 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
292 def AddButton(self, label):
293 button = wx.Button(self, -1, label)
294 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
298 def AddDualButton(self, label1, label2):
299 button1 = wx.Button(self, -1, label1)
300 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
301 button2 = wx.Button(self, -1, label2)
302 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
304 return button1, button2
306 def AddTextCtrl(self, value):
307 ret = wx.TextCtrl(self, -1, value)
308 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
312 def AddLabelTextCtrl(self, info, value):
313 text = wx.StaticText(self, -1, info)
314 ret = wx.TextCtrl(self, -1, value)
315 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
316 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
320 def AddTextCtrlButton(self, value, buttonText):
321 text = wx.TextCtrl(self, -1, value)
322 button = wx.Button(self, -1, buttonText)
323 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
324 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
328 def AddBitmap(self, bitmap):
329 bitmap = wx.StaticBitmap(self, -1, bitmap)
330 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
335 panel = wx.Panel(self, -1)
336 sizer = wx.GridBagSizer(2, 2)
337 panel.SetSizer(sizer)
338 self.GetSizer().Add(panel, pos=(self.rowNr, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND)
342 def AddCheckmark(self, label, bitmap):
343 check = wx.StaticBitmap(self, -1, bitmap)
344 text = wx.StaticText(self, -1, label)
345 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
346 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
350 def AddCombo(self, label, options):
351 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
352 text = wx.StaticText(self, -1, label)
353 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER)
354 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
358 def AddImageButton(self, panel, x, y, label, filename, image_size=None,
359 extra_label=None, overlay=ImageButton.DefaultOverlay, style=None):
360 ib = ImageButton(panel, label, self.GetBitmap(filename, image_size), extra_label, overlay, style)
361 panel.GetSizer().Add(ib, pos=(x, y), flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
364 def GetBitmap(self, filename, image_size):
365 if image_size == None:
366 return wx.Bitmap(resources.getPathForImage(filename))
368 image = wx.Image(resources.getPathForImage(filename))
369 image_scaled = image.Scale(image_size[0], image_size[1], wx.IMAGE_QUALITY_HIGH)
370 return wx.BitmapFromImage(image_scaled)
381 class PrintrbotPage(InfoPage):
382 def __init__(self, parent):
383 self._printer_info = [
384 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
385 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
386 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
387 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
388 (":" + _("Older models"),),
389 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
390 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
391 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
392 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
393 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
394 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
395 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
396 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
397 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
398 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
399 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
400 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
401 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
404 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
405 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
406 self.AddText(_("Select which Printrbot machine you have:"))
408 for printer in self._printer_info:
409 if printer[0].startswith(":"):
411 self.AddText(printer[0][1:])
413 item = self.AddRadioButton(printer[0])
414 item.data = printer[1:]
415 self._items.append(item)
418 profile.putMachineSetting('machine_name', 'Printrbot ???')
419 for item in self._items:
422 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
423 profile.putMachineSetting('machine_width', data[0])
424 profile.putMachineSetting('machine_depth', data[1])
425 profile.putMachineSetting('machine_height', data[2])
426 profile.putProfileSetting('nozzle_size', data[3])
427 profile.putProfileSetting('filament_diameter', data[4])
428 profile.putProfileSetting('print_temperature', data[5])
429 profile.putProfileSetting('print_speed', data[6])
430 profile.putProfileSetting('travel_speed', data[7])
431 profile.putProfileSetting('retraction_speed', data[8])
432 profile.putProfileSetting('retraction_amount', data[9])
433 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
434 profile.putMachineSetting('has_heated_bed', 'False')
435 profile.putMachineSetting('machine_center_is_zero', 'False')
436 profile.putMachineSetting('extruder_head_size_min_x', '0')
437 profile.putMachineSetting('extruder_head_size_min_y', '0')
438 profile.putMachineSetting('extruder_head_size_max_x', '0')
439 profile.putMachineSetting('extruder_head_size_max_y', '0')
440 profile.putMachineSetting('extruder_head_size_height', '0')
442 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
443 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
444 ;Print time: {print_time}
445 ;Filament used: {filament_amount}m {filament_weight}g
446 ;Filament cost: {filament_cost}
447 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
448 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
450 G90 ;absolute positioning
451 M82 ;set extruder to absolute mode
452 M107 ;start with the fan off
453 G28 X0 Y0 ;move X/Y to min endstops
454 G28 Z0 ;move Z to min endstops
455 G29 ;Run the auto bed leveling
456 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
457 G92 E0 ;zero the extruded length
458 G1 F200 E3 ;extrude 3mm of feed stock
459 G92 E0 ;zero the extruded length again
461 ;Put printing message on LCD screen
465 class OtherMachineSelectPage(InfoPage):
466 def __init__(self, parent):
467 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
468 self.AddText(_("The following pre-defined machine profiles are available"))
469 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."))
471 machines = resources.getDefaultMachineProfiles()
473 for filename in machines:
474 name = os.path.splitext(os.path.basename(filename))[0]
475 item = self.AddRadioButton(name)
476 item.filename = filename
477 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
478 self.options.append(item)
480 item = self.AddRadioButton(_('Custom...'))
482 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
484 def OnProfileSelect(self, e):
485 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
487 def OnOtherSelect(self, e):
488 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
491 for option in self.options:
492 if option.GetValue():
493 profile.loadProfile(option.filename)
494 profile.loadMachineSettings(option.filename)
496 class OtherMachineInfoPage(InfoPage):
497 def __init__(self, parent):
498 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
499 self.AddText(_("Cura is now ready to be used!"))
501 class CustomRepRapInfoPage(InfoPage):
502 def __init__(self, parent):
503 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
504 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
505 self.AddText(_("Be sure to review the default profile before running it on your machine."))
506 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
508 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
510 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
511 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
512 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
513 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
514 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
515 self.heatedBed = self.AddCheckbox(_("Heated bed"))
516 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
519 profile.putMachineSetting('machine_name', self.machineName.GetValue())
520 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
521 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
522 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
523 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
524 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
525 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
526 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
527 profile.putMachineSetting('extruder_head_size_min_x', '0')
528 profile.putMachineSetting('extruder_head_size_min_y', '0')
529 profile.putMachineSetting('extruder_head_size_max_x', '0')
530 profile.putMachineSetting('extruder_head_size_max_y', '0')
531 profile.putMachineSetting('extruder_head_size_height', '0')
532 profile.checkAndUpdateMachineName()
534 class MachineSelectPage(InfoPage):
535 def __init__(self, parent):
536 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
537 self.AddText(_("What kind of machine do you have:"))
539 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
540 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
541 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
542 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
543 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
544 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
545 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
546 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
547 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
548 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
549 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
550 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
551 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
552 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
554 def OnUltimaker2Select(self, e):
555 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
557 def OnUltimakerSelect(self, e):
558 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
560 def OnUltimakerOPSelect(self, e):
561 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
563 def OnPrintrbotSelect(self, e):
564 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
566 def OnOtherSelect(self, e):
567 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
570 profile.putProfileSetting('retraction_enable', 'True')
571 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
572 if self.Ultimaker2Radio.GetValue():
573 profile.putMachineSetting('machine_width', '230')
574 profile.putMachineSetting('machine_depth', '225')
575 profile.putMachineSetting('machine_height', '205')
576 profile.putMachineSetting('machine_name', 'ultimaker2')
577 profile.putMachineSetting('machine_type', 'ultimaker2')
578 profile.putMachineSetting('has_heated_bed', 'True')
579 if self.Ultimaker2GoRadio.GetValue():
580 profile.putMachineSetting('machine_width', '120')
581 profile.putMachineSetting('machine_depth', '120')
582 profile.putMachineSetting('machine_height', '115')
583 profile.putMachineSetting('machine_name', 'ultimaker2go')
584 profile.putMachineSetting('machine_type', 'ultimaker2go')
585 profile.putMachineSetting('has_heated_bed', 'False')
586 if self.Ultimaker2ExtRadio.GetValue():
587 profile.putMachineSetting('machine_width', '230')
588 profile.putMachineSetting('machine_depth', '225')
589 profile.putMachineSetting('machine_height', '315')
590 profile.putMachineSetting('machine_name', 'ultimaker2extended')
591 profile.putMachineSetting('machine_type', 'ultimaker2extended')
592 profile.putMachineSetting('has_heated_bed', 'False')
593 profile.putMachineSetting('machine_center_is_zero', 'False')
594 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
595 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
596 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
597 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
598 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
599 profile.putMachineSetting('extruder_head_size_height', '48.0')
600 profile.putProfileSetting('nozzle_size', '0.4')
601 profile.putProfileSetting('fan_full_height', '5.0')
602 profile.putMachineSetting('extruder_offset_x1', '18.0')
603 profile.putMachineSetting('extruder_offset_y1', '0.0')
604 elif self.UltimakerRadio.GetValue():
605 profile.putMachineSetting('machine_width', '205')
606 profile.putMachineSetting('machine_depth', '205')
607 profile.putMachineSetting('machine_height', '200')
608 profile.putMachineSetting('machine_name', 'ultimaker original')
609 profile.putMachineSetting('machine_type', 'ultimaker')
610 profile.putMachineSetting('machine_center_is_zero', 'False')
611 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
612 profile.putProfileSetting('nozzle_size', '0.4')
613 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
614 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
615 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
616 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
617 profile.putMachineSetting('extruder_head_size_height', '55.0')
618 elif self.UltimakerOPRadio.GetValue():
619 profile.putMachineSetting('machine_width', '205')
620 profile.putMachineSetting('machine_depth', '205')
621 profile.putMachineSetting('machine_height', '200')
622 profile.putMachineSetting('machine_name', 'ultimaker original+')
623 profile.putMachineSetting('machine_type', 'ultimaker_plus')
624 profile.putMachineSetting('machine_center_is_zero', 'False')
625 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
626 profile.putProfileSetting('nozzle_size', '0.4')
627 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
628 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
629 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
630 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
631 profile.putMachineSetting('extruder_head_size_height', '55.0')
632 profile.putMachineSetting('has_heated_bed', 'True')
633 profile.putMachineSetting('extruder_amount', '1')
634 profile.putProfileSetting('retraction_enable', 'True')
636 profile.putMachineSetting('machine_width', '80')
637 profile.putMachineSetting('machine_depth', '80')
638 profile.putMachineSetting('machine_height', '60')
639 profile.putMachineSetting('machine_name', 'reprap')
640 profile.putMachineSetting('machine_type', 'reprap')
641 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
642 profile.putPreference('startMode', 'Normal')
643 profile.putProfileSetting('nozzle_size', '0.5')
644 profile.checkAndUpdateMachineName()
645 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
647 class SelectParts(InfoPage):
648 def __init__(self, parent):
649 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
650 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."))
652 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
653 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
654 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
655 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
657 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."))
658 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
659 self.springExtruder.SetValue(True)
662 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
663 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
664 profile.putMachineSetting('has_heated_bed', 'True')
666 profile.putMachineSetting('has_heated_bed', 'False')
667 if self.dualExtrusion.GetValue():
668 profile.putMachineSetting('extruder_amount', '2')
669 profile.putMachineSetting('machine_depth', '195')
671 profile.putMachineSetting('extruder_amount', '1')
672 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
673 profile.putProfileSetting('retraction_enable', 'True')
675 profile.putProfileSetting('retraction_enable', 'False')
678 class UltimakerFirmwareUpgradePage(InfoPage):
679 def __init__(self, parent):
680 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
681 self.AddText(_("Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the stepper motors, regulates the temperature\nand ultimately makes your printer work."))
682 self.AddHiddenSeperator()
683 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
684 self.AddHiddenSeperator()
685 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."))
686 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
687 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
688 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
689 self.AddHiddenSeperator()
690 if profile.getMachineSetting('machine_type') == 'ultimaker':
691 self.AddText(_("Do not upgrade to this firmware if:"))
692 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
693 self.AddText(_("* Build your own heated bed"))
694 self.AddText(_("* Have other changes in the firmware"))
695 # button = self.AddButton('Goto this page for a custom firmware')
696 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
701 def OnUpgradeClick(self, e):
702 if firmwareInstall.InstallFirmware():
703 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
705 def OnSkipClick(self, e):
706 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
707 self.GetParent().ShowPage(self.GetNext())
709 def OnUrlClick(self, e):
710 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
712 class UltimakerCheckupPage(InfoPage):
713 def __init__(self, parent):
714 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
716 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
717 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
718 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
719 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
720 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
721 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
722 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
723 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
724 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
725 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
728 _("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."))
729 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
730 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
731 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
733 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
734 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
735 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
737 self.infoBox = self.AddInfoBox()
738 self.machineState = self.AddText("")
739 self.temperatureLabel = self.AddText("")
740 self.errorLogButton = self.AddButton(_("Show error log"))
741 self.errorLogButton.Show(False)
743 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
745 self.xMinStop = False
746 self.xMaxStop = False
747 self.yMinStop = False
748 self.yMaxStop = False
749 self.zMinStop = False
750 self.zMaxStop = False
752 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
755 if self.comm is not None:
759 self.endstopBitmap.Show(False)
762 def OnSkipClick(self, e):
763 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
764 self.GetParent().ShowPage(self.GetNext())
766 def OnCheckClick(self, e=None):
767 self.errorLogButton.Show(False)
768 if self.comm is not None:
772 wx.CallAfter(self.OnCheckClick)
774 self.infoBox.SetBusy(_("Connecting to machine."))
775 self.commState.SetBitmap(self.unknownBitmap)
776 self.tempState.SetBitmap(self.unknownBitmap)
777 self.stopState.SetBitmap(self.unknownBitmap)
778 self.checkupState = 0
779 self.checkExtruderNr = 0
780 self.comm = machineCom.MachineCom(callbackObject=self)
782 def OnErrorLog(self, e):
783 printWindow.LogWindow('\n'.join(self.comm.getLog()))
785 def mcLog(self, message):
788 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
789 if not self.comm.isOperational():
791 if self.checkupState == 0:
792 self.tempCheckTimeout = 20
793 if temp[self.checkExtruderNr] > 70:
794 self.checkupState = 1
795 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
796 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
797 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
799 self.startTemp = temp[self.checkExtruderNr]
800 self.checkupState = 2
801 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
802 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
803 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
804 elif self.checkupState == 1:
805 if temp[self.checkExtruderNr] < 60:
806 self.startTemp = temp[self.checkExtruderNr]
807 self.checkupState = 2
808 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
809 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
810 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
811 elif self.checkupState == 2:
812 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
813 if temp[self.checkExtruderNr] > self.startTemp + 40:
814 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
815 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
816 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
817 self.checkExtruderNr = 0
818 self.checkupState = 3
819 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
820 wx.CallAfter(self.endstopBitmap.Show, True)
821 wx.CallAfter(self.Layout)
822 self.comm.sendCommand('M119')
823 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
825 self.checkupState = 0
826 self.checkExtruderNr += 1
828 self.tempCheckTimeout -= 1
829 if self.tempCheckTimeout < 1:
830 self.checkupState = -1
831 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
832 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
833 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
834 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
835 elif self.checkupState >= 3 and self.checkupState < 10:
836 self.comm.sendCommand('M119')
837 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
839 def mcStateChange(self, state):
840 if self.comm is None:
842 if self.comm.isOperational():
843 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
844 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
845 elif self.comm.isError():
846 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
847 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
848 wx.CallAfter(self.endstopBitmap.Show, False)
849 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
850 wx.CallAfter(self.errorLogButton.Show, True)
851 wx.CallAfter(self.Layout)
853 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
855 def mcMessage(self, message):
856 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
857 for data in message.split(' '):
859 tag, value = data.split(':', 1)
861 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
863 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
865 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
867 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
869 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
871 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
873 tag, value = map(str.strip, message.split(':', 1))
875 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
877 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
879 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
881 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
883 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
885 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
886 if 'z_max' in message:
887 self.comm.sendCommand('M119')
889 if self.checkupState == 3:
890 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
891 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
892 self.checkupState = 5
893 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
894 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
896 self.checkupState = 4
897 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
898 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
899 elif self.checkupState == 4:
900 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
901 self.checkupState = 5
902 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
903 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
904 elif self.checkupState == 5:
905 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
906 self.checkupState = 6
907 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
908 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
909 elif self.checkupState == 6:
910 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
911 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
912 self.checkupState = 8
913 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
914 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
916 self.checkupState = 7
917 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
918 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
919 elif self.checkupState == 7:
920 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
921 self.checkupState = 8
922 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
923 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
924 elif self.checkupState == 8:
925 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
926 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
927 self.checkupState = 10
929 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
930 wx.CallAfter(self.infoBox.SetReadyIndicator)
931 wx.CallAfter(self.endstopBitmap.Show, False)
932 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
933 wx.CallAfter(self.OnSkipClick, None)
935 self.checkupState = 9
936 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
937 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
938 elif self.checkupState == 9:
939 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
940 self.checkupState = 10
942 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
943 wx.CallAfter(self.infoBox.SetReadyIndicator)
944 wx.CallAfter(self.endstopBitmap.Show, False)
945 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
946 wx.CallAfter(self.OnSkipClick, None)
948 def mcProgress(self, lineNr):
951 def mcZChange(self, newZ):
955 class UltimakerCalibrationPage(InfoPage):
956 def __init__(self, parent):
957 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
959 self.AddText("Your Ultimaker requires some calibration.")
960 self.AddText("This calibration is needed for a proper extrusion amount.")
962 self.AddText("The following values are needed:")
963 self.AddText("* Diameter of filament")
964 self.AddText("* Number of steps per mm of filament extrusion")
966 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
968 self.AddText("First we need the diameter of your filament:")
969 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
971 "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.")
972 self.AddText("Note: This value can be changed later at any time.")
975 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
978 class UltimakerCalibrateStepsPerEPage(InfoPage):
979 def __init__(self, parent):
980 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
982 #if profile.getMachineSetting('steps_per_e') == '0':
983 # profile.putMachineSetting('steps_per_e', '865.888')
985 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
986 self.AddText(_("First remove any filament from your machine."))
987 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
988 self.AddText(_("We'll push the filament 100mm"))
989 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
990 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
991 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
992 self.AddText(_("This results in the following steps per E:"))
993 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
994 self.AddText(_("You can repeat these steps to get better calibration."))
997 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
998 self.heatButton = self.AddButton(_("Heatup for filament removal"))
1000 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
1001 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
1002 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
1004 def OnSaveLengthClick(self, e):
1005 currentEValue = float(self.stepsPerEInput.GetValue())
1006 realExtrudeLength = float(self.lengthInput.GetValue())
1007 newEValue = currentEValue * 100 / realExtrudeLength
1008 self.stepsPerEInput.SetValue(str(newEValue))
1009 self.lengthInput.SetValue("100")
1011 def OnExtrudeClick(self, e):
1012 t = threading.Thread(target=self.OnExtrudeRun)
1016 def OnExtrudeRun(self):
1017 self.heatButton.Enable(False)
1018 self.extrudeButton.Enable(False)
1019 currentEValue = float(self.stepsPerEInput.GetValue())
1020 self.comm = machineCom.MachineCom()
1021 if not self.comm.isOpen():
1023 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1024 'Printer error', wx.OK | wx.ICON_INFORMATION)
1025 self.heatButton.Enable(True)
1026 self.extrudeButton.Enable(True)
1029 line = self.comm.readline()
1034 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1037 self.sendGCommand('M302') #Disable cold extrusion protection
1038 self.sendGCommand("M92 E%f" % (currentEValue))
1039 self.sendGCommand("G92 E0")
1040 self.sendGCommand("G1 E100 F600")
1043 self.extrudeButton.Enable()
1044 self.heatButton.Enable()
1046 def OnHeatClick(self, e):
1047 t = threading.Thread(target=self.OnHeatRun)
1051 def OnHeatRun(self):
1052 self.heatButton.Enable(False)
1053 self.extrudeButton.Enable(False)
1054 self.comm = machineCom.MachineCom()
1055 if not self.comm.isOpen():
1057 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1058 'Printer error', wx.OK | wx.ICON_INFORMATION)
1059 self.heatButton.Enable(True)
1060 self.extrudeButton.Enable(True)
1063 line = self.comm.readline()
1065 self.heatButton.Enable(True)
1066 self.extrudeButton.Enable(True)
1070 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1073 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
1075 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
1076 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
1077 self.sendGCommand('M104 S0')
1080 self.heatButton.Enable(True)
1081 self.extrudeButton.Enable(True)
1083 def sendGCommand(self, cmd):
1084 self.comm.sendCommand(cmd) #Disable cold extrusion protection
1086 line = self.comm.readline()
1089 if line.startswith('ok'):
1092 def StoreData(self):
1093 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1095 class Ultimaker2ReadyPage(InfoPage):
1096 def __init__(self, parent):
1097 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1098 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1099 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1102 class LulzbotMachineSelectPage(InfoPage):
1106 def __init__(self, parent):
1107 super(LulzbotMachineSelectPage, self).__init__(parent, _("Select your machine"))
1109 self.panel = self.AddPanel()
1111 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1112 self.LulzbotMini = self.AddImageButton(self.panel, 0, 0, _("LulzBot Mini"),
1113 'Lulzbot_mini.jpg', image_size, style=ImageButton.IB_GROUP)
1114 self.LulzbotMini.OnSelected(self.OnLulzbotMiniSelected)
1116 self.LulzbotTaz6 = self.AddImageButton(self.panel, 0, 1, _("LulzBot TAZ 6"),
1117 'Lulzbot_TAZ6.jpg', image_size)
1118 self.LulzbotTaz6.OnSelected(self.OnLulzbotTaz6Selected)
1120 self.LulzbotTaz = self.AddImageButton(self.panel, 1, 0, _("LulzBot TAZ 4 or 5"),
1121 'Lulzbot_TAZ5.jpg', image_size)
1122 self.LulzbotTaz.OnSelected(self.OnLulzbotTazSelected)
1124 self.OtherPrinters = self.AddImageButton(self.panel, 1, 1, _("Other Printers"),
1125 'Generic-3D-Printer.png', image_size)
1126 self.OtherPrinters.OnSelected(self.OnOthersSelected)
1127 self.LulzbotMini.SetValue(True)
1129 def OnPageShown(self):
1130 self.LulzbotMini.TriggerGroupCallbacks()
1132 def OnOthersSelected(self):
1133 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().machineSelectPage)
1135 def OnLulzbotMiniSelected(self):
1136 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotMiniToolheadPage)
1137 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotMiniToolheadPage,
1138 self.GetParent().lulzbotReadyPage)
1140 def OnLulzbotTaz6Selected(self):
1141 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz6ToolheadPage)
1143 def OnLulzbotTazSelected(self):
1144 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTazSelectPage)
1146 def AllowNext(self):
1149 def AllowBack(self):
1152 def StoreData(self):
1153 if self.LulzbotTaz.GetValue() or self.LulzbotMini.GetValue() or self.LulzbotTaz6.GetValue():
1154 if self.LulzbotTaz.GetValue():
1155 profile.putMachineSetting('machine_width', '290')
1156 profile.putMachineSetting('machine_depth', '275')
1157 profile.putMachineSetting('machine_height', '250')
1158 profile.putMachineSetting('serial_baud', '115200')
1159 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
1160 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
1161 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
1162 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
1163 profile.putMachineSetting('extruder_head_size_height', '0.0')
1164 elif self.LulzbotTaz6.GetValue():
1165 profile.putMachineSetting('machine_width', '280')
1166 profile.putMachineSetting('machine_depth', '280')
1167 profile.putMachineSetting('machine_height', '250')
1168 profile.putMachineSetting('serial_baud', '250000')
1169 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
1170 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
1171 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
1172 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
1173 profile.putMachineSetting('extruder_head_size_height', '0.0')
1175 # Nozzle diameter and machine type will be set in the toolhead selection page
1176 profile.putMachineSetting('machine_name', 'LulzBot Mini')
1177 profile.putMachineSetting('machine_width', '155')
1178 profile.putMachineSetting('machine_depth', '155')
1179 profile.putMachineSetting('machine_height', '158')
1180 profile.putMachineSetting('serial_baud', '115200')
1181 profile.putMachineSetting('extruder_head_size_min_x', '40')
1182 profile.putMachineSetting('extruder_head_size_max_x', '75')
1183 profile.putMachineSetting('extruder_head_size_min_y', '25')
1184 profile.putMachineSetting('extruder_head_size_max_y', '55')
1185 profile.putMachineSetting('extruder_head_size_height', '17')
1187 profile.putMachineSetting('machine_center_is_zero', 'False')
1188 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
1189 profile.putMachineSetting('has_heated_bed', 'True')
1190 profile.putProfileSetting('retraction_enable', 'True')
1191 profile.putPreference('startMode', 'Simple')
1192 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
1193 profile.checkAndUpdateMachineName()
1195 class LulzbotReadyPage(InfoPage):
1196 def __init__(self, parent):
1197 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1198 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1200 self.AddText(_('For more information about using Cura with your LulzBot'))
1201 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1203 self.AddText(_('Please contact support if you have problems operating'))
1204 self.AddText(_('your LulzBot 3D Printer www.LulzBot.com/support'))
1207 class LulzbotMiniToolheadSelectPage(InfoPage):
1208 def __init__(self, parent, allowBack = True):
1209 super(LulzbotMiniToolheadSelectPage, self).__init__(parent, _("LulzBot Mini Tool Head Selection"))
1211 self.allowBack = allowBack
1212 self.panel = self.AddPanel()
1213 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1214 self.standard = self.AddImageButton(self.panel, 0, 0, _('Standard LulzBot Mini'),
1215 'Lulzbot_mini.jpg', image_size,
1216 style=ImageButton.IB_GROUP)
1217 self.flexy = self.AddImageButton(self.panel, 0, 1, _('LulzBot Mini with Flexystruder'),
1218 'Lulzbot_Toolhead_Mini_Flexystruder.jpg', image_size)
1219 self.standard.SetValue(True)
1221 def AllowBack(self):
1222 return self.allowBack
1224 def StoreData(self):
1225 if self.standard.GetValue():
1226 profile.putProfileSetting('nozzle_size', '0.5')
1227 profile.putMachineSetting('extruder_amount', '1')
1228 profile.putMachineSetting('toolhead', 'Single Extruder v2')
1229 profile.putMachineSetting('toolhead_shortname', '')
1230 profile.putMachineSetting('machine_type', 'lulzbot_mini')
1232 profile.putProfileSetting('nozzle_size', '0.6')
1233 profile.putMachineSetting('extruder_amount', '1')
1234 profile.putMachineSetting('toolhead', 'Flexystruder v2')
1235 profile.putMachineSetting('toolhead_shortname', 'Flexystruder')
1236 profile.putMachineSetting('machine_type', 'lulzbot_mini_flexystruder')
1238 class LulzbotTaz6ToolheadSelectPage(InfoPage):
1239 def __init__(self, parent, allowBack = True):
1240 super(LulzbotTaz6ToolheadSelectPage, self).__init__(parent, _("LulzBot TAZ 6 Tool Head Selection"))
1242 self.panel = self.AddPanel()
1243 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1244 self.taz6 = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v2.1'),
1245 'Lulzbot_Toolhead_TAZ_Tilapia.jpg', image_size,
1246 style=ImageButton.IB_GROUP)
1247 self.taz6.OnSelected(self.OnTilapiaSelected)
1248 self.taz6.SetValue(True)
1250 def OnPageShown(self):
1251 self.taz6.TriggerGroupCallbacks()
1253 def OnTilapiaSelected(self):
1254 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
1256 def StoreData(self):
1257 profile.putProfileSetting('nozzle_size', '0.5')
1258 profile.putMachineSetting('extruder_amount', '1')
1259 profile.putMachineSetting('toolhead', 'Single Extruder v2.1')
1260 profile.putMachineSetting('toolhead_shortname', 'Single v2.1')
1261 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_6_Single_v2.1')
1262 profile.putMachineSetting('machine_name', 'LulzBot TAZ 6')
1264 class LulzbotTazSelectPage(InfoPage):
1265 def __init__(self, parent):
1266 super(LulzbotTazSelectPage, self).__init__(parent, _("LulzBot TAZ 4-5 Selection"))
1268 self.panel = self.AddPanel()
1269 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1270 self.taz5 = self.AddImageButton(self.panel, 0, 0, _('Stock TAZ 5 (PEI && v2)'),
1271 'Lulzbot_TAZ_5_Hex_and_PEI.jpg', image_size,
1272 style=ImageButton.IB_GROUP)
1273 self.taz5.OnSelected(self.OnTaz5Selected)
1274 self.taz4 = self.AddImageButton(self.panel, 0, 1, _('Stock TAZ 4 (PET && v1)'),
1275 'Lulzbot_TAZ_4_Buda_and_PET.jpg', image_size)
1276 self.taz4.OnSelected(self.OnTaz4Selected)
1277 self.modified = self.AddImageButton(self.panel, 1, 0, _('Modified LulzBot TAZ 4 or 5'),
1278 'Lulzbot_TAZ5.jpg', image_size)
1279 self.modified.OnSelected(self.OnModifiedSelected)
1280 self.taz5.SetValue(True)
1282 def OnPageShown(self):
1283 self.taz5.TriggerGroupCallbacks()
1285 def OnTaz5Selected(self):
1286 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1287 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage,
1288 self.GetParent().lulzbotReadyPage)
1290 def OnTaz4Selected(self):
1291 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
1293 def OnModifiedSelected(self):
1294 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTazBedSelectPage)
1295 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTazBedSelectPage,
1296 self.GetParent().lulzbotTazHotendPage)
1298 def StoreData(self):
1299 if self.taz5.GetValue():
1300 profile.putProfileSetting('nozzle_size', '0.5')
1301 profile.putMachineSetting('extruder_amount', '1')
1302 profile.putMachineSetting('toolhead', 'Single Extruder V2')
1303 profile.putMachineSetting('toolhead_shortname', '')
1304 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5_SingleV2')
1305 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
1306 elif self.taz4.GetValue():
1307 profile.putProfileSetting('nozzle_size', '0.35')
1308 profile.putMachineSetting('extruder_amount', '1')
1309 profile.putMachineSetting('toolhead', 'Single Extruder V1')
1310 profile.putMachineSetting('toolhead_shortname', '')
1311 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4_SingleV1')
1312 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
1314 class LulzbotTazBedSelectPage(InfoPage):
1315 def __init__(self, parent):
1316 super(LulzbotTazBedSelectPage, self).__init__(parent, _("Bed Surface"))
1318 self.panel = self.AddPanel()
1319 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1320 self.pei = self.AddImageButton(self.panel, 0, 0, _('PEI'),
1321 'Lulzbot_TAZ_PEI_Bed.jpg', image_size,
1322 style=ImageButton.IB_GROUP)
1323 self.pet = self.AddImageButton(self.panel, 0, 1, _('PET'),
1324 'Lulzbot_TAZ_PET_Bed.jpg', image_size)
1325 self.pei.SetValue(True)
1327 def StoreData(self):
1328 if self.pei.GetValue():
1329 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
1330 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
1332 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
1333 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
1335 class LulzbotTazToolheadSelectPage(InfoPage):
1336 def __init__(self, parent):
1337 super(LulzbotTazToolheadSelectPage, self).__init__(parent, _("LulzBot TAZ Tool Head Selection"))
1339 self.panel = self.AddPanel()
1340 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1341 self.single = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v1'),
1342 'Lulzbot_Toolhead_TAZ_Single_v1.jpg', image_size,
1343 style=ImageButton.IB_GROUP)
1344 self.flexy = self.AddImageButton(self.panel, 0, 1, _('Flexystruder v1'),
1345 'Lulzbot_Toolhead_TAZ_Flexystruder_v1.jpg', image_size)
1346 self.dually = self.AddImageButton(self.panel, 1, 0, _('Dual Extruder v1'),
1347 'Lulzbot_Toolhead_TAZ_Dual_Extruder_v1.jpg', image_size)
1348 self.flexydually = self.AddImageButton(self.panel, 1, 1, _('FlexyDually v1'),
1349 'Lulzbot_Toolhead_TAZ_FlexyDually_v1.jpg', image_size)
1351 self.single.SetValue(True)
1353 def SetVersion(self, version):
1354 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1355 self.single.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Single_v%d.jpg' % version, image_size))
1356 self.single.SetLabel(_('Single Extruder v%d' % version))
1357 self.flexy.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Flexystruder_v%d.jpg' % version, image_size))
1358 self.flexy.SetLabel(_('Flexystruder v%d' % version))
1359 self.dually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Dual_Extruder_v%d.jpg' % version, image_size))
1360 self.dually.SetLabel(_('Dual Extruder v%d' % version))
1361 self.flexydually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_FlexyDually_v%d.jpg' % version, image_size))
1362 self.flexydually.SetLabel(_('FlexyDually v%d' % version))
1363 self.version = version
1365 self.single.OnSelected(None)
1366 self.flexy.OnSelected(None)
1367 self.dually.OnSelected(None)
1368 self.flexydually.OnSelected(None)
1369 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1371 self.single.OnSelected(self.OnSingleV2)
1372 self.flexy.OnSelected(self.OnNonSingle)
1373 self.dually.OnSelected(self.OnNonSingle)
1374 self.flexydually.OnSelected(self.OnNonSingle)
1375 if self.single.GetValue():
1376 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1377 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotFirmwarePage)
1379 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1380 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotFirmwarePage, self.GetParent().lulzbotReadyPage)
1382 def OnSingleV2(self):
1383 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1384 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotFirmwarePage)
1386 def OnNonSingle(self):
1387 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1389 def StoreData(self):
1390 if profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1394 version = (taz_version, self.version)
1395 if self.single.GetValue():
1396 profile.putProfileSetting('nozzle_size', '0.5' if self.version == 2 else '0.35')
1397 profile.putMachineSetting('extruder_amount', '1')
1398 profile.putMachineSetting('toolhead', 'Single Extruder V%d' % self.version)
1399 profile.putMachineSetting('toolhead_shortname', '')
1400 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_SingleV%d' % version)
1401 elif self.flexy.GetValue():
1402 profile.putProfileSetting('nozzle_size', '0.6')
1403 profile.putMachineSetting('extruder_amount', '1')
1404 profile.putMachineSetting('toolhead', 'Flexystruder V%d' % self.version)
1405 profile.putMachineSetting('toolhead_shortname', 'Flexystruder v%d' % self.version)
1406 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_FlexystruderV%d' % version)
1407 elif self.dually.GetValue():
1408 profile.putProfileSetting('nozzle_size', '0.5')
1409 profile.putMachineSetting('extruder_amount', '2')
1410 profile.putMachineSetting('extruder_offset_x1', '0.0')
1411 profile.putMachineSetting('extruder_offset_y1', '-50.0' if self.version == 2 else '-52.00')
1412 profile.putMachineSetting('toolhead', 'Dual Extruder V%d' % self.version)
1413 profile.putMachineSetting('toolhead_shortname', 'Dual v%d' % self.version)
1414 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_DualV%d' % version)
1415 elif self.flexydually.GetValue():
1416 profile.putProfileSetting('nozzle_size', '0.6')
1417 profile.putMachineSetting('extruder_amount', '2')
1418 profile.putMachineSetting('extruder_offset_x1', '0.0')
1419 profile.putMachineSetting('extruder_offset_y1', '-50.0' if self.version == 2 else '-52.00')
1420 profile.putMachineSetting('toolhead', 'FlexyDually V%d' % self.version)
1421 profile.putMachineSetting('toolhead_shortname', 'FlexyDually v%d' % self.version)
1422 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_FlexyDuallyV%d' % version)
1424 class LulzbotHotendSelectPage(InfoPage):
1425 def __init__(self, parent, allowBack = True):
1426 super(LulzbotHotendSelectPage, self).__init__(parent, _("LulzBot Tool Head Hot end Selection"))
1428 self.allowBack = allowBack
1429 self.panel = self.AddPanel()
1430 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1431 self.v1 = self.AddImageButton(self.panel, 0, 0, _('v1 (Budaschnozzle)'),
1432 'Lulzbot_Toolhead_v1.jpg', image_size,
1433 style=ImageButton.IB_GROUP)
1434 self.v2 = self.AddImageButton(self.panel, 0, 1, _('v2 (LulzBot Hexagon)'),
1435 'Lulzbot_Toolhead_v2.jpg', image_size)
1436 self.v1.SetValue(True)
1438 def AllowBack(self):
1439 return self.allowBack
1441 def StoreData(self):
1442 self.GetParent().lulzbotTazToolheadPage.SetVersion(1 if self.v1.GetValue() else 2)
1444 class LulzbotTaz5NozzleSelectPage(InfoPage):
1445 url2='http://lulzbot.com/printer-identification'
1447 def __init__(self, parent):
1448 super(LulzbotTaz5NozzleSelectPage, self).__init__(parent, _("LulzBot TAZ Single v2 Nozzle Selection"))
1450 self.AddText(_('Please select your LulzBot Hexagon Hot End\'s nozzle diameter:'))
1451 self.Nozzle35Radio = self.AddRadioButton("0.35 mm", style=wx.RB_GROUP)
1452 self.Nozzle35Radio.SetValue(True)
1453 self.Nozzle50Radio = self.AddRadioButton("0.5 mm")
1454 self.AddText(_(' '))
1457 self.AddText(_('If you are not sure which nozzle diameter you have,'))
1458 self.AddText(_('please check this webpage: '))
1459 button = self.AddButton(LulzbotTaz5NozzleSelectPage.url2)
1460 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
1462 def OnUrlClick(self, e):
1463 webbrowser.open(LulzbotTaz5NozzleSelectPage.url2)
1465 def StoreData(self):
1466 if profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1470 if self.Nozzle35Radio.GetValue():
1471 profile.putProfileSetting('nozzle_size', '0.35')
1472 profile.putMachineSetting('toolhead', 'Single Extruder v2 (0.35mm nozzle)')
1473 profile.putMachineSetting('toolhead_shortname', '0.35 nozzle')
1474 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_035nozzle' % taz_version)
1477 profile.putProfileSetting('nozzle_size', '0.5')
1478 profile.putMachineSetting('toolhead', 'Single Extruder v2 (0.5mm nozzle)')
1479 profile.putMachineSetting('toolhead_shortname', '0.5 nozzle')
1480 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_05nozzle' % taz_version)
1482 class LulzbotFirmwareUpdatePage(InfoPage):
1483 def __init__(self, parent):
1484 super(LulzbotFirmwareUpdatePage, self).__init__(parent, _("LulzBot Firmware Update"))
1486 self.AddText(_("Your LulzBot printer\'s firmware will now be updated.\n" +
1487 "Note: this will overwrite your existing firmware."))
1489 self.AddText(_("Follow these steps to prevent writing firmware to the wrong device:\n" +
1490 " 1) Unplug all USB devices from your computer\n" +
1491 " 2) Plug your 3D Printer into the computer with a USB cable\n" +
1492 " 3) Turn on your 3D Printer\n" +
1493 " 4) Click \"Flash the firmware\""))
1494 self.AddHiddenSeperator()
1495 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Flash the firmware'), _('Skip upgrade'))
1496 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
1497 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
1499 def AllowNext(self):
1500 return version.isDevVersion()
1502 def OnUpgradeClick(self, e):
1503 if firmwareInstall.InstallFirmware():
1504 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
1505 self.GetParent().ShowPage(self.GetNext())
1507 def OnSkipClick(self, e):
1508 dlg = wx.MessageDialog(self,
1509 _("CAUTION: Updating firmware is necessary when changing the\n" \
1510 "tool head on your LulzBot desktop 3D Printer." \
1512 "Are you sure you want to skip the firmware update?"),
1513 _('Skip firmware update?'),
1514 wx.YES_NO | wx.ICON_EXCLAMATION)
1515 skip = dlg.ShowModal() == wx.ID_YES
1518 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
1519 self.GetParent().ShowPage(self.GetNext())
1521 class LulzbotChangeToolheadWizard(wx.wizard.Wizard):
1523 super(LulzbotChangeToolheadWizard, self).__init__(None, -1, _("Change LulzBot Tool Head Wizard"))
1525 self._nozzle_size = profile.getProfileSettingFloat('nozzle_size')
1526 self._machine_name = profile.getMachineSetting('machine_name')
1527 self._machine_type = profile.getMachineSetting('machine_type')
1528 self._extruder_amount = int(profile.getMachineSettingFloat('extruder_amount'))
1530 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1531 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1532 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1534 self.lulzbotReadyPage = LulzbotReadyPage(self)
1535 self.lulzbotFirmwarePage = LulzbotFirmwareUpdatePage(self)
1536 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self, False)
1537 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1538 self.lulzbotTaz6ToolheadPage = LulzbotTaz6ToolheadSelectPage(self, False)
1539 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self, False)
1540 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1541 self.lulzbotTazBedSelectPage = LulzbotTazBedSelectPage(self)
1542 self.lulzbotTazSelectPage = LulzbotTazSelectPage(self)
1544 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotReadyPage)
1545 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1547 if profile.getMachineSetting('machine_type').startswith('lulzbot_mini'):
1548 self.RunWizard(self.lulzbotMiniToolheadPage)
1549 elif profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_5') or \
1550 profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1551 self.RunWizard(self.lulzbotTazHotendPage)
1552 elif profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_6'):
1553 self.RunWizard(self.lulzbotTaz6ToolheadPage)
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()
1568 if hasattr(e.GetPage(), 'OnPageShown'):
1569 e.GetPage().OnPageShown()
1571 def OnCancel(self, e):
1572 profile.putProfileSetting('nozzle_size', self._nozzle_size)
1573 profile.putMachineSetting('machine_name', self._machine_name)
1574 profile.putMachineSetting('machine_type', self._machine_type)
1575 profile.putMachineSetting('extruder_amount', self._extruder_amount)
1577 class ConfigWizard(wx.wizard.Wizard):
1578 def __init__(self, addNew = False):
1579 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1581 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1583 profile.setActiveMachine(profile.getMachineCount())
1585 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1586 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1587 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1589 self.machineSelectPage = MachineSelectPage(self)
1590 self.ultimakerSelectParts = SelectParts(self)
1591 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1592 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1593 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1594 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1595 self.bedLevelPage = bedLevelWizardMain(self)
1596 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1597 self.printrbotSelectType = PrintrbotPage(self)
1598 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1599 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1600 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1602 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1603 self.lulzbotReadyPage = LulzbotReadyPage(self)
1604 self.lulzbotFirmwarePage = LulzbotFirmwareUpdatePage(self)
1605 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self)
1606 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1607 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self)
1608 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1609 self.lulzbotMachineSelectPage = LulzbotMachineSelectPage(self)
1610 self.lulzbotTazBedSelectPage = LulzbotTazBedSelectPage(self)
1611 self.lulzbotTazSelectPage = LulzbotTazSelectPage(self)
1612 self.lulzbotTaz6ToolheadPage = LulzbotTaz6ToolheadSelectPage(self)
1614 wx.wizard.WizardPageSimple.Chain(self.lulzbotMachineSelectPage, self.lulzbotMiniToolheadPage)
1615 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotReadyPage)
1616 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1617 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1618 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1619 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1620 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1621 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1622 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1624 self.RunWizard(self.lulzbotMachineSelectPage)
1627 def OnPageChanging(self, e):
1628 e.GetPage().StoreData()
1630 def OnPageChanged(self, e):
1631 if e.GetPage().AllowNext():
1632 self.FindWindowById(wx.ID_FORWARD).Enable()
1634 self.FindWindowById(wx.ID_FORWARD).Disable()
1635 if e.GetPage().AllowBack():
1636 self.FindWindowById(wx.ID_BACKWARD).Enable()
1638 self.FindWindowById(wx.ID_BACKWARD).Disable()
1639 if hasattr(e.GetPage(), 'OnPageShown'):
1640 e.GetPage().OnPageShown()
1642 def OnCancel(self, e):
1643 new_machine_index = int(profile.getPreferenceFloat('active_machine'))
1644 profile.setActiveMachine(self._old_machine_index)
1645 profile.removeMachine(new_machine_index)
1647 class bedLevelWizardMain(InfoPage):
1648 def __init__(self, parent):
1649 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1651 self.AddText(_('This wizard will help you in leveling your printer bed'))
1653 self.AddText(_('It will do the following steps'))
1654 self.AddText(_('* Move the printer head to each corner'))
1655 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1656 self.AddText(_('* Print a line around the bed to check if it is level'))
1659 self.connectButton = self.AddButton(_('Connect to printer'))
1662 self.infoBox = self.AddInfoBox()
1663 self.resumeButton = self.AddButton(_('Resume'))
1664 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1665 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1666 self.resumeButton.Enable(False)
1668 self.upButton.Enable(False)
1669 self.downButton.Enable(False)
1670 self.upButton2.Enable(False)
1671 self.downButton2.Enable(False)
1673 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1674 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1675 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1676 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1677 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1678 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1680 def OnConnect(self, e = None):
1681 if self.comm is not None:
1685 wx.CallAfter(self.OnConnect)
1687 self.connectButton.Enable(False)
1688 self.comm = machineCom.MachineCom(callbackObject=self)
1689 self.infoBox.SetBusy(_('Connecting to machine.'))
1690 self._wizardState = 0
1692 def OnBedUp(self, e):
1693 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1694 self.comm.sendCommand('G92 Z10')
1695 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1696 self.comm.sendCommand('M400')
1698 def OnBedDown(self, e):
1699 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1700 self.comm.sendCommand('G92 Z10')
1701 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1702 self.comm.sendCommand('M400')
1704 def OnBedUp2(self, e):
1705 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1706 self.comm.sendCommand('G92 Z10')
1707 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1708 self.comm.sendCommand('M400')
1710 def OnBedDown2(self, e):
1711 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1712 self.comm.sendCommand('G92 Z10')
1713 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1714 self.comm.sendCommand('M400')
1716 def AllowNext(self):
1717 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1718 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1721 def OnResume(self, e):
1722 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1723 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1724 if self._wizardState == -1:
1725 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1726 wx.CallAfter(self.upButton.Enable, False)
1727 wx.CallAfter(self.downButton.Enable, False)
1728 wx.CallAfter(self.upButton2.Enable, False)
1729 wx.CallAfter(self.downButton2.Enable, False)
1730 self.comm.sendCommand('M105')
1731 self.comm.sendCommand('G28')
1732 self._wizardState = 1
1733 elif self._wizardState == 2:
1734 if profile.getMachineSetting('has_heated_bed') == 'True':
1735 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1736 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1737 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1738 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1739 self.comm.sendCommand('M400')
1740 self._wizardState = 3
1742 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1743 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1744 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1745 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1746 self.comm.sendCommand('M400')
1747 self._wizardState = 3
1748 elif self._wizardState == 4:
1749 if profile.getMachineSetting('has_heated_bed') == 'True':
1750 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1751 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1752 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1753 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1754 self.comm.sendCommand('M400')
1755 self._wizardState = 7
1757 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1758 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1759 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1760 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1761 self.comm.sendCommand('M400')
1762 self._wizardState = 5
1763 elif self._wizardState == 6:
1764 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1765 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1766 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1767 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1768 self.comm.sendCommand('M400')
1769 self._wizardState = 7
1770 elif self._wizardState == 8:
1771 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1772 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1773 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1774 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1775 self._wizardState = 9
1776 elif self._wizardState == 10:
1777 self._wizardState = 11
1778 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1779 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1780 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1781 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1782 w = profile.getMachineSettingFloat('machine_width') - 10
1783 d = profile.getMachineSettingFloat('machine_depth')
1784 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1785 filamentArea = math.pi * filamentRadius * filamentRadius
1786 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1790 'G1 Z2 F%d' % (feedZ),
1792 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1793 'G1 Z0.3 F%d' % (feedZ)]
1795 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1797 for i in xrange(0, 3):
1798 dist = 5.0 + 0.4 * float(i)
1799 eValue += (d - 2.0*dist) * ePerMM
1800 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1801 eValue += (w - 2.0*dist) * ePerMM
1802 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1803 eValue += (d - 2.0*dist) * ePerMM
1804 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1805 eValue += (w - 2.0*dist) * ePerMM
1806 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1808 gcodeList.append('M400')
1809 self.comm.printGCode(gcodeList)
1810 self.resumeButton.Enable(False)
1812 def mcLog(self, message):
1813 print 'Log:', message
1815 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1816 if self._wizardState == 1:
1817 self._wizardState = 2
1818 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1819 wx.CallAfter(self.resumeButton.Enable, True)
1820 elif self._wizardState == 3:
1821 self._wizardState = 4
1822 if profile.getMachineSetting('has_heated_bed') == 'True':
1823 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1825 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1826 wx.CallAfter(self.resumeButton.Enable, True)
1827 elif self._wizardState == 5:
1828 self._wizardState = 6
1829 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1830 wx.CallAfter(self.resumeButton.Enable, True)
1831 elif self._wizardState == 7:
1832 self._wizardState = 8
1833 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1834 wx.CallAfter(self.resumeButton.Enable, True)
1835 elif self._wizardState == 9:
1836 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1837 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1839 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1840 wx.CallAfter(self.resumeButton.Enable, True)
1841 self._wizardState = 10
1843 def mcStateChange(self, state):
1844 if self.comm is None:
1846 if self.comm.isOperational():
1847 if self._wizardState == 0:
1848 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1849 wx.CallAfter(self.upButton.Enable, True)
1850 wx.CallAfter(self.downButton.Enable, True)
1851 wx.CallAfter(self.upButton2.Enable, True)
1852 wx.CallAfter(self.downButton2.Enable, True)
1853 wx.CallAfter(self.resumeButton.Enable, True)
1854 self._wizardState = -1
1855 elif self._wizardState == 11 and not self.comm.isPrinting():
1856 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1857 self.comm.sendCommand('G92 E0')
1858 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1859 self.comm.sendCommand('M104 S0')
1860 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1861 wx.CallAfter(self.infoBox.SetReadyIndicator)
1862 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1863 wx.CallAfter(self.connectButton.Enable, True)
1864 self._wizardState = 12
1865 elif self.comm.isError():
1866 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1868 def mcMessage(self, message):
1871 def mcProgress(self, lineNr):
1874 def mcZChange(self, newZ):
1877 class headOffsetCalibrationPage(InfoPage):
1878 def __init__(self, parent):
1879 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1881 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1884 self.connectButton = self.AddButton(_('Connect to printer'))
1887 self.infoBox = self.AddInfoBox()
1888 self.textEntry = self.AddTextCtrl('')
1889 self.textEntry.Enable(False)
1890 self.resumeButton = self.AddButton(_('Resume'))
1891 self.resumeButton.Enable(False)
1893 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1894 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1896 def AllowBack(self):
1899 def OnConnect(self, e = None):
1900 if self.comm is not None:
1904 wx.CallAfter(self.OnConnect)
1906 self.connectButton.Enable(False)
1907 self.comm = machineCom.MachineCom(callbackObject=self)
1908 self.infoBox.SetBusy(_('Connecting to machine.'))
1909 self._wizardState = 0
1911 def OnResume(self, e):
1912 if self._wizardState == 2:
1913 self._wizardState = 3
1914 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1916 w = profile.getMachineSettingFloat('machine_width')
1917 d = profile.getMachineSettingFloat('machine_depth')
1919 gcode = gcodeGenerator.gcodeGenerator()
1920 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1921 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1928 gcode.addMove(w/2, 5)
1929 gcode.addMove(z=0.2)
1931 gcode.addExtrude(w/2, d-5.0)
1933 gcode.addMove(5, d/2)
1935 gcode.addExtrude(w-5.0, d/2)
1936 gcode.addRetract(15)
1939 gcode.addMove(w/2, 5)
1941 gcode.addExtrude(w/2, d-5.0)
1943 gcode.addMove(5, d/2)
1945 gcode.addExtrude(w-5.0, d/2)
1946 gcode.addRetract(15)
1951 gcode.addCmd('M400')
1953 self.comm.printGCode(gcode.list())
1954 self.resumeButton.Enable(False)
1955 elif self._wizardState == 4:
1957 float(self.textEntry.GetValue())
1960 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1961 self._wizardState = 5
1962 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1963 self.textEntry.SetValue('0.0')
1964 self.textEntry.Enable(True)
1965 elif self._wizardState == 5:
1967 float(self.textEntry.GetValue())
1970 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1971 self._wizardState = 6
1972 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1973 self.textEntry.SetValue('')
1974 self.textEntry.Enable(False)
1975 self.resumeButton.Enable(False)
1977 x = profile.getMachineSettingFloat('extruder_offset_x1')
1978 y = profile.getMachineSettingFloat('extruder_offset_y1')
1979 gcode = gcodeGenerator.gcodeGenerator()
1980 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1981 gcode.setPrintSpeed(25)
1984 gcode.addMove(50, 40, 0.2)
1986 for n in xrange(0, 10):
1987 gcode.addExtrude(50 + n * 10, 150)
1988 gcode.addExtrude(50 + n * 10 + 5, 150)
1989 gcode.addExtrude(50 + n * 10 + 5, 40)
1990 gcode.addExtrude(50 + n * 10 + 10, 40)
1991 gcode.addMove(40, 50)
1992 for n in xrange(0, 10):
1993 gcode.addExtrude(150, 50 + n * 10)
1994 gcode.addExtrude(150, 50 + n * 10 + 5)
1995 gcode.addExtrude(40, 50 + n * 10 + 5)
1996 gcode.addExtrude(40, 50 + n * 10 + 10)
1997 gcode.addRetract(15)
2000 gcode.addMove(50 - x, 30 - y, 0.2)
2002 for n in xrange(0, 10):
2003 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
2004 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
2005 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
2006 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
2007 gcode.addMove(30 - x, 50 - y, 0.2)
2008 for n in xrange(0, 10):
2009 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
2010 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
2011 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
2012 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
2013 gcode.addRetract(15)
2015 gcode.addCmd('M400')
2016 gcode.addCmd('M104 T0 S0')
2017 gcode.addCmd('M104 T1 S0')
2018 self.comm.printGCode(gcode.list())
2019 elif self._wizardState == 7:
2021 n = int(self.textEntry.GetValue()) - 1
2024 x = profile.getMachineSettingFloat('extruder_offset_x1')
2026 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
2027 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
2028 self.textEntry.SetValue('10')
2029 self._wizardState = 8
2030 elif self._wizardState == 8:
2032 n = int(self.textEntry.GetValue()) - 1
2035 y = profile.getMachineSettingFloat('extruder_offset_y1')
2037 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
2038 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
2039 self.infoBox.SetReadyIndicator()
2040 self._wizardState = 8
2042 self.resumeButton.Enable(False)
2044 def mcLog(self, message):
2045 print 'Log:', message
2047 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
2048 if self._wizardState == 1:
2049 if temp[0] >= 210 and temp[1] >= 210:
2050 self._wizardState = 2
2051 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
2052 wx.CallAfter(self.resumeButton.Enable, True)
2053 wx.CallAfter(self.resumeButton.SetFocus)
2055 def mcStateChange(self, state):
2056 if self.comm is None:
2058 if self.comm.isOperational():
2059 if self._wizardState == 0:
2060 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
2061 self.comm.sendCommand('M105')
2062 self.comm.sendCommand('M104 S220 T0')
2063 self.comm.sendCommand('M104 S220 T1')
2064 self.comm.sendCommand('G28')
2065 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
2066 self._wizardState = 1
2067 if not self.comm.isPrinting():
2068 if self._wizardState == 3:
2069 self._wizardState = 4
2070 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
2071 wx.CallAfter(self.textEntry.SetValue, '0.0')
2072 wx.CallAfter(self.textEntry.Enable, True)
2073 wx.CallAfter(self.resumeButton.Enable, True)
2074 wx.CallAfter(self.resumeButton.SetFocus)
2075 elif self._wizardState == 6:
2076 self._wizardState = 7
2077 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
2078 wx.CallAfter(self.textEntry.SetValue, '10')
2079 wx.CallAfter(self.textEntry.Enable, True)
2080 wx.CallAfter(self.resumeButton.Enable, True)
2081 wx.CallAfter(self.resumeButton.SetFocus)
2083 elif self.comm.isError():
2084 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
2086 def mcMessage(self, message):
2089 def mcProgress(self, lineNr):
2092 def mcZChange(self, newZ):
2095 class bedLevelWizard(wx.wizard.Wizard):
2097 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
2099 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
2100 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
2102 self.mainPage = bedLevelWizardMain(self)
2103 self.headOffsetCalibration = None
2105 self.RunWizard(self.mainPage)
2108 def OnPageChanging(self, e):
2109 e.GetPage().StoreData()
2111 def OnPageChanged(self, e):
2112 if e.GetPage().AllowNext():
2113 self.FindWindowById(wx.ID_FORWARD).Enable()
2115 self.FindWindowById(wx.ID_FORWARD).Disable()
2116 if e.GetPage().AllowBack():
2117 self.FindWindowById(wx.ID_BACKWARD).Enable()
2119 self.FindWindowById(wx.ID_BACKWARD).Disable()
2121 class headOffsetWizard(wx.wizard.Wizard):
2123 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
2125 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
2126 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
2128 self.mainPage = headOffsetCalibrationPage(self)
2130 self.RunWizard(self.mainPage)
2133 def OnPageChanging(self, e):
2134 e.GetPage().StoreData()
2136 def OnPageChanged(self, e):
2137 if e.GetPage().AllowNext():
2138 self.FindWindowById(wx.ID_FORWARD).Enable()
2140 self.FindWindowById(wx.ID_FORWARD).Disable()
2141 if e.GetPage().AllowBack():
2142 self.FindWindowById(wx.ID_BACKWARD).Enable()
2144 self.FindWindowById(wx.ID_BACKWARD).Disable()