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 OnLeftClick(self, e):
165 def SetValue(self, value):
166 old_value = self.selected
167 self.selected = bool(value)
168 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
169 if self.selected and self.group:
170 for ib in ImageButton.__groups__[self.group]:
175 if self.callback and not old_value and self.selected:
178 def SetLabel(self, label):
179 self.text.SetLabel(label)
182 def SetExtraLabel(self, label):
184 self.extra_text.SetLabel(label)
186 self.extra_text = wx.StaticText(self, -1, label)
187 self.sizer.Add(self.extra_text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
190 def SetBitmap(self, bitmap):
192 self.overlay = self.createOverlay(bitmap, self.original_overlay)
193 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
196 def SetOverlay(self, overlay):
197 self.original_overlay = overlay
198 self.overlay = self.createOverlay(self.bitmap, self.original_overlay)
199 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
202 def OnSelected(self, callback):
203 self.callback = callback
205 def createOverlay(self, bitmap, overlay):
206 result = bitmap.GetSubBitmap(wx.Rect(0, 0, *bitmap.Size))
207 (width, height) = bitmap.GetSize()
208 overlay_image = wx.ImageFromBitmap(overlay)
209 overlay_image = overlay_image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
210 overlay_scaled = wx.BitmapFromImage(overlay_image)
212 dc.SelectObject(result)
213 dc.DrawBitmap(overlay_scaled, 0, 0)
214 dc.SelectObject(wx.NullBitmap)
218 class InfoPage(wx.wizard.WizardPageSimple):
219 def __init__(self, parent, title):
220 wx.wizard.WizardPageSimple.__init__(self, parent)
222 parent.GetPageAreaSizer().Add(self)
223 sizer = wx.GridBagSizer(5, 5)
227 self.title = wx.StaticText(self, -1, title)
228 font = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)
229 self.title.SetFont(font)
230 # HACK ALERT: For some reason, the StaticText keeps its same size as if
231 # the font was not modified, this causes the text to wrap and to
232 # get out of bounds of the widgets area and hide other widgets.
233 # The only way I found for the widget to get its right size was to calculate
234 # the new font's extent and set the min size on the widget
235 self.title.SetMinSize(self.GetTextExtent(font, title))
236 sizer.Add(self.title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
237 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
238 sizer.AddGrowableCol(1)
242 def GetTextExtent(self, font, text):
245 w,h = dc.GetTextExtent(text)
248 def AddText(self, info):
249 text = wx.StaticText(self, -1, info)
250 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
254 def AddSeperator(self):
255 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
258 def AddHiddenSeperator(self):
261 def AddInfoBox(self):
262 infoBox = InfoBox(self)
263 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
267 def AddRadioButton(self, label, style=0):
268 radio = wx.RadioButton(self, -1, label, style=style)
269 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
273 def AddCheckbox(self, label, checked=False):
274 check = wx.CheckBox(self, -1)
275 text = wx.StaticText(self, -1, label)
276 check.SetValue(checked)
277 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
278 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
282 def AddButton(self, label):
283 button = wx.Button(self, -1, label)
284 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
288 def AddDualButton(self, label1, label2):
289 button1 = wx.Button(self, -1, label1)
290 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
291 button2 = wx.Button(self, -1, label2)
292 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
294 return button1, button2
296 def AddTextCtrl(self, value):
297 ret = wx.TextCtrl(self, -1, value)
298 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
302 def AddLabelTextCtrl(self, info, value):
303 text = wx.StaticText(self, -1, info)
304 ret = wx.TextCtrl(self, -1, value)
305 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
306 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
310 def AddTextCtrlButton(self, value, buttonText):
311 text = wx.TextCtrl(self, -1, value)
312 button = wx.Button(self, -1, buttonText)
313 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
314 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
318 def AddBitmap(self, bitmap):
319 bitmap = wx.StaticBitmap(self, -1, bitmap)
320 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
325 panel = wx.Panel(self, -1)
326 sizer = wx.GridBagSizer(2, 2)
327 panel.SetSizer(sizer)
328 self.GetSizer().Add(panel, pos=(self.rowNr, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND)
332 def AddCheckmark(self, label, bitmap):
333 check = wx.StaticBitmap(self, -1, bitmap)
334 text = wx.StaticText(self, -1, label)
335 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
336 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
340 def AddCombo(self, label, options):
341 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
342 text = wx.StaticText(self, -1, label)
343 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER)
344 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
348 def AddImageButton(self, panel, x, y, label, filename, image_size=None,
349 extra_label=None, overlay=ImageButton.DefaultOverlay, style=None):
350 ib = ImageButton(panel, label, self.GetBitmap(filename, image_size), extra_label, overlay, style)
351 panel.GetSizer().Add(ib, pos=(x, y), flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
354 def GetBitmap(self, filename, image_size):
355 if image_size == None:
356 return wx.Bitmap(resources.getPathForImage(filename))
358 image = wx.Image(resources.getPathForImage(filename))
359 image_scaled = image.Scale(image_size[0], image_size[1], wx.IMAGE_QUALITY_HIGH)
360 return wx.BitmapFromImage(image_scaled)
371 class PrintrbotPage(InfoPage):
372 def __init__(self, parent):
373 self._printer_info = [
374 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
375 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
376 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
377 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
378 (":" + _("Older models"),),
379 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
380 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
381 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
382 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
383 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
384 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
385 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
386 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
387 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
388 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
389 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
390 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
391 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
394 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
395 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
396 self.AddText(_("Select which Printrbot machine you have:"))
398 for printer in self._printer_info:
399 if printer[0].startswith(":"):
401 self.AddText(printer[0][1:])
403 item = self.AddRadioButton(printer[0])
404 item.data = printer[1:]
405 self._items.append(item)
408 profile.putMachineSetting('machine_name', 'Printrbot ???')
409 for item in self._items:
412 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
413 profile.putMachineSetting('machine_width', data[0])
414 profile.putMachineSetting('machine_depth', data[1])
415 profile.putMachineSetting('machine_height', data[2])
416 profile.putProfileSetting('nozzle_size', data[3])
417 profile.putProfileSetting('filament_diameter', data[4])
418 profile.putProfileSetting('print_temperature', data[5])
419 profile.putProfileSetting('print_speed', data[6])
420 profile.putProfileSetting('travel_speed', data[7])
421 profile.putProfileSetting('retraction_speed', data[8])
422 profile.putProfileSetting('retraction_amount', data[9])
423 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
424 profile.putMachineSetting('has_heated_bed', 'False')
425 profile.putMachineSetting('machine_center_is_zero', 'False')
426 profile.putMachineSetting('extruder_head_size_min_x', '0')
427 profile.putMachineSetting('extruder_head_size_min_y', '0')
428 profile.putMachineSetting('extruder_head_size_max_x', '0')
429 profile.putMachineSetting('extruder_head_size_max_y', '0')
430 profile.putMachineSetting('extruder_head_size_height', '0')
432 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
433 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
434 ;Print time: {print_time}
435 ;Filament used: {filament_amount}m {filament_weight}g
436 ;Filament cost: {filament_cost}
437 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
438 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
440 G90 ;absolute positioning
441 M82 ;set extruder to absolute mode
442 M107 ;start with the fan off
443 G28 X0 Y0 ;move X/Y to min endstops
444 G28 Z0 ;move Z to min endstops
445 G29 ;Run the auto bed leveling
446 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
447 G92 E0 ;zero the extruded length
448 G1 F200 E3 ;extrude 3mm of feed stock
449 G92 E0 ;zero the extruded length again
451 ;Put printing message on LCD screen
455 class OtherMachineSelectPage(InfoPage):
456 def __init__(self, parent):
457 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
458 self.AddText(_("The following pre-defined machine profiles are available"))
459 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."))
461 machines = resources.getDefaultMachineProfiles()
463 for filename in machines:
464 name = os.path.splitext(os.path.basename(filename))[0]
465 item = self.AddRadioButton(name)
466 item.filename = filename
467 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
468 self.options.append(item)
470 item = self.AddRadioButton(_('Custom...'))
472 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
474 def OnProfileSelect(self, e):
475 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
477 def OnOtherSelect(self, e):
478 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
481 for option in self.options:
482 if option.GetValue():
483 profile.loadProfile(option.filename)
484 profile.loadMachineSettings(option.filename)
486 class OtherMachineInfoPage(InfoPage):
487 def __init__(self, parent):
488 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
489 self.AddText(_("Cura is now ready to be used!"))
491 class CustomRepRapInfoPage(InfoPage):
492 def __init__(self, parent):
493 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
494 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
495 self.AddText(_("Be sure to review the default profile before running it on your machine."))
496 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
498 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
500 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
501 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
502 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
503 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
504 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
505 self.heatedBed = self.AddCheckbox(_("Heated bed"))
506 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
509 profile.putMachineSetting('machine_name', self.machineName.GetValue())
510 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
511 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
512 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
513 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
514 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
515 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
516 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
517 profile.putMachineSetting('extruder_head_size_min_x', '0')
518 profile.putMachineSetting('extruder_head_size_min_y', '0')
519 profile.putMachineSetting('extruder_head_size_max_x', '0')
520 profile.putMachineSetting('extruder_head_size_max_y', '0')
521 profile.putMachineSetting('extruder_head_size_height', '0')
522 profile.checkAndUpdateMachineName()
524 class MachineSelectPage(InfoPage):
525 def __init__(self, parent):
526 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
527 self.AddText(_("What kind of machine do you have:"))
529 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
530 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
531 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
532 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
533 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
534 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
535 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
536 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
537 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
538 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
539 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
540 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
541 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
542 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
544 def OnUltimaker2Select(self, e):
545 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
547 def OnUltimakerSelect(self, e):
548 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
550 def OnUltimakerOPSelect(self, e):
551 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
553 def OnPrintrbotSelect(self, e):
554 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
556 def OnOtherSelect(self, e):
557 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
560 profile.putProfileSetting('retraction_enable', 'True')
561 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
562 if self.Ultimaker2Radio.GetValue():
563 profile.putMachineSetting('machine_width', '230')
564 profile.putMachineSetting('machine_depth', '225')
565 profile.putMachineSetting('machine_height', '205')
566 profile.putMachineSetting('machine_name', 'ultimaker2')
567 profile.putMachineSetting('machine_type', 'ultimaker2')
568 profile.putMachineSetting('has_heated_bed', 'True')
569 if self.Ultimaker2GoRadio.GetValue():
570 profile.putMachineSetting('machine_width', '120')
571 profile.putMachineSetting('machine_depth', '120')
572 profile.putMachineSetting('machine_height', '115')
573 profile.putMachineSetting('machine_name', 'ultimaker2go')
574 profile.putMachineSetting('machine_type', 'ultimaker2go')
575 profile.putMachineSetting('has_heated_bed', 'False')
576 if self.Ultimaker2ExtRadio.GetValue():
577 profile.putMachineSetting('machine_width', '230')
578 profile.putMachineSetting('machine_depth', '225')
579 profile.putMachineSetting('machine_height', '315')
580 profile.putMachineSetting('machine_name', 'ultimaker2extended')
581 profile.putMachineSetting('machine_type', 'ultimaker2extended')
582 profile.putMachineSetting('has_heated_bed', 'False')
583 profile.putMachineSetting('machine_center_is_zero', 'False')
584 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
585 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
586 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
587 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
588 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
589 profile.putMachineSetting('extruder_head_size_height', '48.0')
590 profile.putProfileSetting('nozzle_size', '0.4')
591 profile.putProfileSetting('fan_full_height', '5.0')
592 profile.putMachineSetting('extruder_offset_x1', '18.0')
593 profile.putMachineSetting('extruder_offset_y1', '0.0')
594 elif self.UltimakerRadio.GetValue():
595 profile.putMachineSetting('machine_width', '205')
596 profile.putMachineSetting('machine_depth', '205')
597 profile.putMachineSetting('machine_height', '200')
598 profile.putMachineSetting('machine_name', 'ultimaker original')
599 profile.putMachineSetting('machine_type', 'ultimaker')
600 profile.putMachineSetting('machine_center_is_zero', 'False')
601 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
602 profile.putProfileSetting('nozzle_size', '0.4')
603 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
604 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
605 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
606 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
607 profile.putMachineSetting('extruder_head_size_height', '55.0')
608 elif self.UltimakerOPRadio.GetValue():
609 profile.putMachineSetting('machine_width', '205')
610 profile.putMachineSetting('machine_depth', '205')
611 profile.putMachineSetting('machine_height', '200')
612 profile.putMachineSetting('machine_name', 'ultimaker original+')
613 profile.putMachineSetting('machine_type', 'ultimaker_plus')
614 profile.putMachineSetting('machine_center_is_zero', 'False')
615 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
616 profile.putProfileSetting('nozzle_size', '0.4')
617 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
618 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
619 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
620 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
621 profile.putMachineSetting('extruder_head_size_height', '55.0')
622 profile.putMachineSetting('has_heated_bed', 'True')
623 profile.putMachineSetting('extruder_amount', '1')
624 profile.putProfileSetting('retraction_enable', 'True')
626 profile.putMachineSetting('machine_width', '80')
627 profile.putMachineSetting('machine_depth', '80')
628 profile.putMachineSetting('machine_height', '60')
629 profile.putMachineSetting('machine_name', 'reprap')
630 profile.putMachineSetting('machine_type', 'reprap')
631 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
632 profile.putPreference('startMode', 'Normal')
633 profile.putProfileSetting('nozzle_size', '0.5')
634 profile.checkAndUpdateMachineName()
635 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
637 class SelectParts(InfoPage):
638 def __init__(self, parent):
639 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
640 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."))
642 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
643 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
644 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
645 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
647 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."))
648 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
649 self.springExtruder.SetValue(True)
652 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
653 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
654 profile.putMachineSetting('has_heated_bed', 'True')
656 profile.putMachineSetting('has_heated_bed', 'False')
657 if self.dualExtrusion.GetValue():
658 profile.putMachineSetting('extruder_amount', '2')
659 profile.putMachineSetting('machine_depth', '195')
661 profile.putMachineSetting('extruder_amount', '1')
662 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
663 profile.putProfileSetting('retraction_enable', 'True')
665 profile.putProfileSetting('retraction_enable', 'False')
668 class UltimakerFirmwareUpgradePage(InfoPage):
669 def __init__(self, parent):
670 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
671 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."))
672 self.AddHiddenSeperator()
673 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
674 self.AddHiddenSeperator()
675 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."))
676 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
677 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
678 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
679 self.AddHiddenSeperator()
680 if profile.getMachineSetting('machine_type') == 'ultimaker':
681 self.AddText(_("Do not upgrade to this firmware if:"))
682 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
683 self.AddText(_("* Build your own heated bed"))
684 self.AddText(_("* Have other changes in the firmware"))
685 # button = self.AddButton('Goto this page for a custom firmware')
686 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
691 def OnUpgradeClick(self, e):
692 if firmwareInstall.InstallFirmware():
693 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
695 def OnSkipClick(self, e):
696 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
697 self.GetParent().ShowPage(self.GetNext())
699 def OnUrlClick(self, e):
700 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
702 class UltimakerCheckupPage(InfoPage):
703 def __init__(self, parent):
704 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
706 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
707 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
708 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
709 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
710 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
711 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
712 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
713 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
714 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
715 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
718 _("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."))
719 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
720 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
721 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
723 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
724 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
725 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
727 self.infoBox = self.AddInfoBox()
728 self.machineState = self.AddText("")
729 self.temperatureLabel = self.AddText("")
730 self.errorLogButton = self.AddButton(_("Show error log"))
731 self.errorLogButton.Show(False)
733 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
735 self.xMinStop = False
736 self.xMaxStop = False
737 self.yMinStop = False
738 self.yMaxStop = False
739 self.zMinStop = False
740 self.zMaxStop = False
742 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
745 if self.comm is not None:
749 self.endstopBitmap.Show(False)
752 def OnSkipClick(self, e):
753 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
754 self.GetParent().ShowPage(self.GetNext())
756 def OnCheckClick(self, e=None):
757 self.errorLogButton.Show(False)
758 if self.comm is not None:
762 wx.CallAfter(self.OnCheckClick)
764 self.infoBox.SetBusy(_("Connecting to machine."))
765 self.commState.SetBitmap(self.unknownBitmap)
766 self.tempState.SetBitmap(self.unknownBitmap)
767 self.stopState.SetBitmap(self.unknownBitmap)
768 self.checkupState = 0
769 self.checkExtruderNr = 0
770 self.comm = machineCom.MachineCom(callbackObject=self)
772 def OnErrorLog(self, e):
773 printWindow.LogWindow('\n'.join(self.comm.getLog()))
775 def mcLog(self, message):
778 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
779 if not self.comm.isOperational():
781 if self.checkupState == 0:
782 self.tempCheckTimeout = 20
783 if temp[self.checkExtruderNr] > 70:
784 self.checkupState = 1
785 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
786 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
787 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
789 self.startTemp = temp[self.checkExtruderNr]
790 self.checkupState = 2
791 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
792 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
793 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
794 elif self.checkupState == 1:
795 if temp[self.checkExtruderNr] < 60:
796 self.startTemp = temp[self.checkExtruderNr]
797 self.checkupState = 2
798 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
799 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
800 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
801 elif self.checkupState == 2:
802 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
803 if temp[self.checkExtruderNr] > self.startTemp + 40:
804 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
805 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
806 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
807 self.checkExtruderNr = 0
808 self.checkupState = 3
809 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
810 wx.CallAfter(self.endstopBitmap.Show, True)
811 wx.CallAfter(self.Layout)
812 self.comm.sendCommand('M119')
813 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
815 self.checkupState = 0
816 self.checkExtruderNr += 1
818 self.tempCheckTimeout -= 1
819 if self.tempCheckTimeout < 1:
820 self.checkupState = -1
821 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
822 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
823 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
824 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
825 elif self.checkupState >= 3 and self.checkupState < 10:
826 self.comm.sendCommand('M119')
827 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
829 def mcStateChange(self, state):
830 if self.comm is None:
832 if self.comm.isOperational():
833 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
834 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
835 elif self.comm.isError():
836 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
837 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
838 wx.CallAfter(self.endstopBitmap.Show, False)
839 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
840 wx.CallAfter(self.errorLogButton.Show, True)
841 wx.CallAfter(self.Layout)
843 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
845 def mcMessage(self, message):
846 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
847 for data in message.split(' '):
849 tag, value = data.split(':', 1)
851 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
853 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
855 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
857 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
859 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
861 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
863 tag, value = map(str.strip, message.split(':', 1))
865 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
867 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
869 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
871 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
873 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
875 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
876 if 'z_max' in message:
877 self.comm.sendCommand('M119')
879 if self.checkupState == 3:
880 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
881 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
882 self.checkupState = 5
883 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
884 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
886 self.checkupState = 4
887 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
888 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
889 elif self.checkupState == 4:
890 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
891 self.checkupState = 5
892 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
893 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
894 elif self.checkupState == 5:
895 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
896 self.checkupState = 6
897 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
898 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
899 elif self.checkupState == 6:
900 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
901 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
902 self.checkupState = 8
903 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
904 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
906 self.checkupState = 7
907 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
908 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
909 elif self.checkupState == 7:
910 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
911 self.checkupState = 8
912 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
913 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
914 elif self.checkupState == 8:
915 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
916 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
917 self.checkupState = 10
919 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
920 wx.CallAfter(self.infoBox.SetReadyIndicator)
921 wx.CallAfter(self.endstopBitmap.Show, False)
922 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
923 wx.CallAfter(self.OnSkipClick, None)
925 self.checkupState = 9
926 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
927 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
928 elif self.checkupState == 9:
929 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
930 self.checkupState = 10
932 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
933 wx.CallAfter(self.infoBox.SetReadyIndicator)
934 wx.CallAfter(self.endstopBitmap.Show, False)
935 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
936 wx.CallAfter(self.OnSkipClick, None)
938 def mcProgress(self, lineNr):
941 def mcZChange(self, newZ):
945 class UltimakerCalibrationPage(InfoPage):
946 def __init__(self, parent):
947 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
949 self.AddText("Your Ultimaker requires some calibration.")
950 self.AddText("This calibration is needed for a proper extrusion amount.")
952 self.AddText("The following values are needed:")
953 self.AddText("* Diameter of filament")
954 self.AddText("* Number of steps per mm of filament extrusion")
956 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
958 self.AddText("First we need the diameter of your filament:")
959 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
961 "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.")
962 self.AddText("Note: This value can be changed later at any time.")
965 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
968 class UltimakerCalibrateStepsPerEPage(InfoPage):
969 def __init__(self, parent):
970 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
972 #if profile.getMachineSetting('steps_per_e') == '0':
973 # profile.putMachineSetting('steps_per_e', '865.888')
975 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
976 self.AddText(_("First remove any filament from your machine."))
977 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
978 self.AddText(_("We'll push the filament 100mm"))
979 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
980 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
981 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
982 self.AddText(_("This results in the following steps per E:"))
983 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
984 self.AddText(_("You can repeat these steps to get better calibration."))
987 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
988 self.heatButton = self.AddButton(_("Heatup for filament removal"))
990 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
991 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
992 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
994 def OnSaveLengthClick(self, e):
995 currentEValue = float(self.stepsPerEInput.GetValue())
996 realExtrudeLength = float(self.lengthInput.GetValue())
997 newEValue = currentEValue * 100 / realExtrudeLength
998 self.stepsPerEInput.SetValue(str(newEValue))
999 self.lengthInput.SetValue("100")
1001 def OnExtrudeClick(self, e):
1002 t = threading.Thread(target=self.OnExtrudeRun)
1006 def OnExtrudeRun(self):
1007 self.heatButton.Enable(False)
1008 self.extrudeButton.Enable(False)
1009 currentEValue = float(self.stepsPerEInput.GetValue())
1010 self.comm = machineCom.MachineCom()
1011 if not self.comm.isOpen():
1013 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1014 'Printer error', wx.OK | wx.ICON_INFORMATION)
1015 self.heatButton.Enable(True)
1016 self.extrudeButton.Enable(True)
1019 line = self.comm.readline()
1024 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1027 self.sendGCommand('M302') #Disable cold extrusion protection
1028 self.sendGCommand("M92 E%f" % (currentEValue))
1029 self.sendGCommand("G92 E0")
1030 self.sendGCommand("G1 E100 F600")
1033 self.extrudeButton.Enable()
1034 self.heatButton.Enable()
1036 def OnHeatClick(self, e):
1037 t = threading.Thread(target=self.OnHeatRun)
1041 def OnHeatRun(self):
1042 self.heatButton.Enable(False)
1043 self.extrudeButton.Enable(False)
1044 self.comm = machineCom.MachineCom()
1045 if not self.comm.isOpen():
1047 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1048 'Printer error', wx.OK | wx.ICON_INFORMATION)
1049 self.heatButton.Enable(True)
1050 self.extrudeButton.Enable(True)
1053 line = self.comm.readline()
1055 self.heatButton.Enable(True)
1056 self.extrudeButton.Enable(True)
1060 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1063 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
1065 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
1066 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
1067 self.sendGCommand('M104 S0')
1070 self.heatButton.Enable(True)
1071 self.extrudeButton.Enable(True)
1073 def sendGCommand(self, cmd):
1074 self.comm.sendCommand(cmd) #Disable cold extrusion protection
1076 line = self.comm.readline()
1079 if line.startswith('ok'):
1082 def StoreData(self):
1083 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1085 class Ultimaker2ReadyPage(InfoPage):
1086 def __init__(self, parent):
1087 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1088 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1089 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1092 class LulzbotMachineSelectPage(InfoPage):
1096 def __init__(self, parent):
1097 super(LulzbotMachineSelectPage, self).__init__(parent, _("Select your machine"))
1098 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1099 self.AddText(_("Select your printer :"))
1101 self.panel = self.AddPanel()
1103 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1104 self.LulzbotMini = self.AddImageButton(self.panel, 0, 0, _("LulzBot Mini"),
1105 'Lulzbot_mini.jpg', image_size, style=ImageButton.IB_GROUP)
1106 self.LulzbotMini.OnSelected(self.OnLulzbotMiniSelected)
1107 self.LulzbotMini.SetValue(True)
1108 self.LulzbotTaz5 = self.AddImageButton(self.panel, 0, 1, _("LulzBot TAZ 5"),
1109 'Lulzbot_TAZ5.jpg', image_size)
1110 self.LulzbotTaz5.OnSelected(self.OnLulzbotTazSelected)
1111 self.LulzbotTaz4 = self.AddImageButton(self.panel, 1, 0, _("LulzBot TAZ 4"),
1112 'Lulzbot_TAZ4.jpg', image_size)
1113 self.LulzbotTaz4.OnSelected(self.OnLulzbotTazSelected)
1114 self.OtherPrinters = self.AddImageButton(self.panel, 1, 1, _("Other Printers"),
1115 'Generic-3D-Printer.png', image_size)
1116 self.OtherPrinters.OnSelected(self.OnOthersSelected)
1118 def OnOthersSelected(self):
1119 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().machineSelectPage)
1121 def OnLulzbotMiniSelected(self):
1122 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotMiniToolheadPage)
1123 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotMiniToolheadPage,
1124 self.GetParent().lulzbotFirmwarePage)
1126 def OnLulzbotTazSelected(self):
1127 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTazHotendPage)
1129 def AllowNext(self):
1132 def AllowBack(self):
1135 def StoreData(self):
1136 if self.LulzbotTaz4.GetValue() or self.LulzbotTaz5.GetValue() or self.LulzbotMini.GetValue():
1137 if self.LulzbotTaz4.GetValue():
1138 # Nozzle diameter will be set in the toolhead selection page
1139 # We set the machine_type here so later pages can differenciate between TAZ 4 and 5
1140 profile.putMachineSetting('machine_width', '290')
1141 profile.putMachineSetting('machine_depth', '275')
1142 profile.putMachineSetting('machine_height', '250')
1143 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
1144 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
1145 profile.putMachineSetting('serial_baud', '115200')
1146 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
1147 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
1148 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
1149 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
1150 profile.putMachineSetting('extruder_head_size_height', '0.0')
1151 elif self.LulzbotTaz5.GetValue():
1152 # Nozzle diameter will be set in the toolhead selection page
1153 # We set the machine_type here so later pages can differenciate between TAZ 4 and 5
1154 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
1155 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
1156 profile.putMachineSetting('machine_width', '290')
1157 profile.putMachineSetting('machine_depth', '275')
1158 profile.putMachineSetting('machine_height', '250')
1159 profile.putMachineSetting('serial_baud', '115200')
1160 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
1161 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
1162 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
1163 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
1164 profile.putMachineSetting('extruder_head_size_height', '0.0')
1166 # Nozzle diameter and machine type will be set in the toolhead selection page
1167 profile.putMachineSetting('machine_name', 'LulzBot Mini')
1168 profile.putMachineSetting('machine_width', '155')
1169 profile.putMachineSetting('machine_depth', '155')
1170 profile.putMachineSetting('machine_height', '163')
1171 profile.putMachineSetting('serial_baud', '115200')
1172 profile.putMachineSetting('extruder_head_size_min_x', '40')
1173 profile.putMachineSetting('extruder_head_size_max_x', '75')
1174 profile.putMachineSetting('extruder_head_size_min_y', '25')
1175 profile.putMachineSetting('extruder_head_size_max_y', '55')
1176 profile.putMachineSetting('extruder_head_size_height', '17')
1178 profile.putMachineSetting('machine_center_is_zero', 'False')
1179 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
1180 profile.putMachineSetting('has_heated_bed', 'True')
1181 profile.putProfileSetting('retraction_enable', 'True')
1182 profile.putPreference('startMode', 'Simple')
1183 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
1184 profile.checkAndUpdateMachineName()
1186 class LulzbotReadyPage(InfoPage):
1187 def __init__(self, parent):
1188 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1189 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1190 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1192 self.AddText(_('For more information about using Cura with your LulzBot'))
1193 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1196 class LulzbotToolheadSelectPage(InfoPage):
1197 def __init__(self, parent, title):
1198 super(LulzbotToolheadSelectPage, self).__init__(parent, title)
1199 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1200 self.AddText(_('Picking the correct Tool Head is important.'))
1201 txt = self.AddText(_('WARNING: Printing with the incorrect firmware can damage your LulzBot printer!'))
1202 txt.SetForegroundColour(wx.RED)
1205 class LulzbotMiniToolheadSelectPage(LulzbotToolheadSelectPage):
1206 def __init__(self, parent, allowBack = True):
1207 super(LulzbotMiniToolheadSelectPage, self).__init__(parent, _("LulzBot Mini Tool Head Selection"))
1209 self.allowBack = allowBack
1210 self.panel = self.AddPanel()
1211 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1212 self.standard = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v2'),
1213 'Lulzbot_Toolhead_Mini_Standard.jpg', image_size,
1214 style=ImageButton.IB_GROUP)
1215 self.flexy = self.AddImageButton(self.panel, 0, 1, _('Flexystruder v2'),
1216 'Lulzbot_Toolhead_Mini_Flexystruder.jpg', image_size)
1217 self.standard.SetValue(True)
1219 def AllowBack(self):
1220 return self.allowBack
1222 def StoreData(self):
1223 if self.standard.GetValue():
1224 profile.putProfileSetting('nozzle_size', '0.5')
1225 profile.putMachineSetting('extruder_amount', '1')
1226 profile.putMachineSetting('toolhead', 'Single Extruder V2')
1227 profile.putMachineSetting('toolhead_shortname', '')
1228 profile.putMachineSetting('machine_type', 'lulzbot_mini')
1230 profile.putProfileSetting('nozzle_size', '0.6')
1231 profile.putMachineSetting('extruder_amount', '1')
1232 profile.putMachineSetting('toolhead', 'Flexystruder V2')
1233 profile.putMachineSetting('toolhead_shortname', 'Flexystruder')
1234 profile.putMachineSetting('machine_type', 'lulzbot_mini_flexystruder')
1237 class LulzbotTazToolheadSelectPage(LulzbotToolheadSelectPage):
1238 def __init__(self, parent):
1239 super(LulzbotTazToolheadSelectPage, self).__init__(parent, _("LulzBot TAZ Tool Head Selection"))
1241 self.panel = self.AddPanel()
1242 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1243 self.single = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v1'),
1244 'Lulzbot_Toolhead_TAZ_Single_v1.jpg', image_size,
1245 style=ImageButton.IB_GROUP)
1246 self.flexy = self.AddImageButton(self.panel, 0, 1, _('Flexystruder v1'),
1247 'Lulzbot_Toolhead_TAZ_Flexystruder_v1.jpg', image_size)
1248 self.dually = self.AddImageButton(self.panel, 1, 0, _('Dual Extruder v1'),
1249 'Lulzbot_Toolhead_TAZ_Dual_Extruder_v1.jpg', image_size)
1250 self.flexydually = self.AddImageButton(self.panel, 1, 1, _('FlexyDually v1'),
1251 'Lulzbot_Toolhead_TAZ_FlexyDually_v1.jpg', image_size)
1253 self.single.SetValue(True)
1255 def SetVersion(self, version):
1256 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1257 self.single.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Single_v%d.jpg' % version, image_size))
1258 self.single.SetLabel(_('Single Extruder v%d' % version))
1259 self.flexy.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Flexystruder_v%d.jpg' % version, image_size))
1260 self.flexy.SetLabel(_('Flexystruder v%d' % version))
1261 self.dually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Dual_Extruder_v%d.jpg' % version, image_size))
1262 self.dually.SetLabel(_('Dual Extruder v%d' % version))
1263 self.flexydually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_FlexyDually_v%d.jpg' % version, image_size))
1264 self.flexydually.SetLabel(_('FlexyDually v%d' % version))
1265 self.version = version
1267 self.single.OnSelected(None)
1268 self.flexy.OnSelected(None)
1269 self.dually.OnSelected(None)
1270 self.flexydually.OnSelected(None)
1271 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1273 self.single.OnSelected(self.OnSingleV2)
1274 self.flexy.OnSelected(self.OnNonSingle)
1275 self.dually.OnSelected(self.OnNonSingle)
1276 self.flexydually.OnSelected(self.OnNonSingle)
1277 if self.single.GetValue():
1278 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1279 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotFirmwarePage)
1281 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1283 def OnSingleV2(self):
1284 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1285 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotFirmwarePage)
1287 def OnNonSingle(self):
1288 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1290 def StoreData(self):
1291 if profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1295 version = (taz_version, self.version)
1296 if self.single.GetValue():
1297 profile.putProfileSetting('nozzle_size', '0.5' if self.version == 2 else '0.35')
1298 profile.putMachineSetting('extruder_amount', '1')
1299 profile.putMachineSetting('toolhead', 'Single Extruder V%d' % self.version)
1300 profile.putMachineSetting('toolhead_shortname', '')
1301 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_SingleV%d' % version)
1302 elif self.flexy.GetValue():
1303 profile.putProfileSetting('nozzle_size', '0.6')
1304 profile.putMachineSetting('extruder_amount', '1')
1305 profile.putMachineSetting('toolhead', 'Flexystruder V%d' % self.version)
1306 profile.putMachineSetting('toolhead_shortname', 'Flexystruder v%d' % self.version)
1307 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_FlexystruderV%d' % version)
1308 elif self.dually.GetValue():
1309 profile.putProfileSetting('nozzle_size', '0.5')
1310 profile.putMachineSetting('extruder_amount', '2')
1311 profile.putMachineSetting('extruder_offset_x1', '0.0')
1312 profile.putMachineSetting('extruder_offset_y1', '-50.0' if self.version == 2 else '-52.00')
1313 profile.putMachineSetting('toolhead', 'Dual Extruder V%d' % self.version)
1314 profile.putMachineSetting('toolhead_shortname', 'Dual v%d' % self.version)
1315 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_DualV%d' % version)
1316 elif self.flexydually.GetValue():
1317 profile.putProfileSetting('nozzle_size', '0.6')
1318 profile.putMachineSetting('extruder_amount', '2')
1319 profile.putMachineSetting('extruder_offset_x1', '0.0')
1320 profile.putMachineSetting('extruder_offset_y1', '-50.0' if self.version == 2 else '-52.00')
1321 profile.putMachineSetting('toolhead', 'FlexyDually V%d' % self.version)
1322 profile.putMachineSetting('toolhead_shortname', 'FlexyDually v%d' % self.version)
1323 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_FlexyDuallyV%d' % version)
1326 class LulzbotHotendSelectPage(LulzbotToolheadSelectPage):
1327 def __init__(self, parent, allowBack = True):
1328 super(LulzbotHotendSelectPage, self).__init__(parent, _("LulzBot Tool Head Hotend Selection"))
1330 self.allowBack = allowBack
1331 self.panel = self.AddPanel()
1332 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1333 self.v1 = self.AddImageButton(self.panel, 0, 0, _('v1 (Budaschnozzle)'),
1334 'Lulzbot_Toolhead_v1.jpg', image_size,
1335 style=ImageButton.IB_GROUP)
1336 self.v2 = self.AddImageButton(self.panel, 0, 1, _('v2 (Hexagon)'),
1337 'Lulzbot_Toolhead_v2.jpg', image_size)
1338 self.v1.SetValue(True)
1340 def AllowBack(self):
1341 return self.allowBack
1343 def StoreData(self):
1344 self.GetParent().lulzbotTazToolheadPage.SetVersion(1 if self.v1.GetValue() else 2)
1346 class LulzbotTaz5NozzleSelectPage(LulzbotToolheadSelectPage):
1347 url2='http://lulzbot.com/printer-identification'
1349 def __init__(self, parent):
1350 super(LulzbotTaz5NozzleSelectPage, self).__init__(parent, _("LulzBot TAZ Single V2 Nozzle Selection"))
1352 self.AddText(_('Please select your Hexagon hotend\'s nozzle diameter:'))
1353 self.Nozzle35Radio = self.AddRadioButton("0.35 mm", style=wx.RB_GROUP)
1354 self.Nozzle35Radio.SetValue(True)
1355 self.Nozzle50Radio = self.AddRadioButton("0.5 mm")
1356 self.AddText(_(' '))
1359 self.AddText(_('If you are not sure which nozzle diameter you have'))
1360 self.AddText(_('please check this webpage: '))
1361 button = self.AddButton(LulzbotTaz5NozzleSelectPage.url2)
1362 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
1364 def OnUrlClick(self, e):
1365 webbrowser.open(LulzbotTaz5NozzleSelectPage.url2)
1367 def StoreData(self):
1368 if profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1372 if self.Nozzle35Radio.GetValue():
1373 profile.putProfileSetting('nozzle_size', '0.35')
1374 profile.putMachineSetting('toolhead', 'Single Extruder V2 (0.35mm nozzle)')
1375 profile.putMachineSetting('toolhead_shortname', '0.35 nozzle')
1376 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_035nozzle' % taz_version)
1379 profile.putProfileSetting('nozzle_size', '0.5')
1380 profile.putMachineSetting('toolhead', 'Single Extruder V2 (0.5mm nozzle)')
1381 profile.putMachineSetting('toolhead_shortname', '0.5 nozzle')
1382 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_05nozzle' % taz_version)
1384 class LulzbotFirmwareUpdatePage(InfoPage):
1385 def __init__(self, parent):
1386 super(LulzbotFirmwareUpdatePage, self).__init__(parent, _("LulzBot Firmware Update"))
1388 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1390 self.AddText(_('Your LulzBot printer\'s firmware will now be updated.'))
1392 self.AddText(_("Firmware is the \"brain\" inside your 3D printer.\n" +
1393 "It controls motors/heaters, regulates temperature\n" +
1394 "and ultimately makes your printer work."))
1395 self.AddHiddenSeperator()
1396 self.AddText(_("When changing tool heads it is neccesary to update the firmware.\n" +
1397 "Please connect (with a USB cable) the printer you are currently configuring and power it on.\n" +
1398 "Disconnecting all other 3D printers helps reduce confusion."))
1399 self.AddHiddenSeperator()
1400 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Flash the firmware'), _('Skip upgrade'))
1401 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
1402 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
1404 def AllowNext(self):
1405 return version.isDevVersion()
1407 def OnUpgradeClick(self, e):
1408 if firmwareInstall.InstallFirmware():
1409 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
1410 self.GetParent().ShowPage(self.GetNext())
1412 def OnSkipClick(self, e):
1413 dlg = wx.MessageDialog(self,
1414 _("CAUTION: Updating your firmware is strongly recommended and " \
1415 "critical to protecting your LulzBot with the latest updates " \
1416 "and settings. Expert users note that this will overwrite " \
1417 " firmware changes or customization; you can skip this step " \
1418 "at your discretion.\n\n" +
1419 "Are you sure you want to skip the firmware upgrade?"),
1420 _('Skip firmware upgrade?'),
1421 wx.YES_NO | wx.ICON_EXCLAMATION)
1422 skip = dlg.ShowModal() == wx.ID_YES
1425 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
1426 self.GetParent().ShowPage(self.GetNext())
1428 class LulzbotChangeToolheadWizard(wx.wizard.Wizard):
1430 super(LulzbotChangeToolheadWizard, self).__init__(None, -1, _("Change Lulzbot Tool Head Wizard"))
1432 self._nozzle_size = profile.getProfileSettingFloat('nozzle_size')
1433 self._machine_name = profile.getMachineSetting('machine_name')
1434 self._machine_type = profile.getMachineSetting('machine_type')
1435 self._extruder_amount = int(profile.getMachineSettingFloat('extruder_amount'))
1437 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1438 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1439 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1441 self.lulzbotReadyPage = LulzbotReadyPage(self)
1442 self.lulzbotFirmwarePage = LulzbotFirmwareUpdatePage(self)
1443 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self, False)
1444 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1445 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self, False)
1446 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1448 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotFirmwarePage)
1449 wx.wizard.WizardPageSimple.Chain(self.lulzbotFirmwarePage, self.lulzbotReadyPage)
1450 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1452 if profile.getMachineSetting('machine_type').startswith('lulzbot_mini'):
1453 self.RunWizard(self.lulzbotMiniToolheadPage)
1455 self.RunWizard(self.lulzbotTazHotendPage)
1458 def OnPageChanging(self, e):
1459 e.GetPage().StoreData()
1461 def OnPageChanged(self, e):
1462 if e.GetPage().AllowNext():
1463 self.FindWindowById(wx.ID_FORWARD).Enable()
1465 self.FindWindowById(wx.ID_FORWARD).Disable()
1466 if e.GetPage().AllowBack():
1467 self.FindWindowById(wx.ID_BACKWARD).Enable()
1469 self.FindWindowById(wx.ID_BACKWARD).Disable()
1471 def OnCancel(self, e):
1472 profile.putProfileSetting('nozzle_size', self._nozzle_size)
1473 profile.putMachineSetting('machine_name', self._machine_name)
1474 profile.putMachineSetting('machine_type', self._machine_type)
1475 profile.putMachineSetting('extruder_amount', self._extruder_amount)
1477 class ConfigWizard(wx.wizard.Wizard):
1478 def __init__(self, addNew = False):
1479 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1481 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1483 profile.setActiveMachine(profile.getMachineCount())
1485 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1486 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1487 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1489 self.machineSelectPage = MachineSelectPage(self)
1490 self.ultimakerSelectParts = SelectParts(self)
1491 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1492 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1493 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1494 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1495 self.bedLevelPage = bedLevelWizardMain(self)
1496 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1497 self.printrbotSelectType = PrintrbotPage(self)
1498 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1499 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1500 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1502 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1503 self.lulzbotReadyPage = LulzbotReadyPage(self)
1504 self.lulzbotFirmwarePage = LulzbotFirmwareUpdatePage(self)
1505 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self)
1506 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1507 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self)
1508 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1509 self.lulzbotMachineSelectPage = LulzbotMachineSelectPage(self)
1511 wx.wizard.WizardPageSimple.Chain(self.lulzbotMachineSelectPage, self.lulzbotMiniToolheadPage)
1512 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotFirmwarePage)
1513 wx.wizard.WizardPageSimple.Chain(self.lulzbotFirmwarePage, self.lulzbotReadyPage)
1514 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1515 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1516 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1517 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1518 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1519 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1520 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1522 self.RunWizard(self.lulzbotMachineSelectPage)
1525 def OnPageChanging(self, e):
1526 e.GetPage().StoreData()
1528 def OnPageChanged(self, e):
1529 if e.GetPage().AllowNext():
1530 self.FindWindowById(wx.ID_FORWARD).Enable()
1532 self.FindWindowById(wx.ID_FORWARD).Disable()
1533 if e.GetPage().AllowBack():
1534 self.FindWindowById(wx.ID_BACKWARD).Enable()
1536 self.FindWindowById(wx.ID_BACKWARD).Disable()
1538 def OnCancel(self, e):
1539 new_machine_index = int(profile.getPreferenceFloat('active_machine'))
1540 profile.setActiveMachine(self._old_machine_index)
1541 profile.removeMachine(new_machine_index)
1543 class bedLevelWizardMain(InfoPage):
1544 def __init__(self, parent):
1545 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1547 self.AddText(_('This wizard will help you in leveling your printer bed'))
1549 self.AddText(_('It will do the following steps'))
1550 self.AddText(_('* Move the printer head to each corner'))
1551 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1552 self.AddText(_('* Print a line around the bed to check if it is level'))
1555 self.connectButton = self.AddButton(_('Connect to printer'))
1558 self.infoBox = self.AddInfoBox()
1559 self.resumeButton = self.AddButton(_('Resume'))
1560 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1561 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1562 self.resumeButton.Enable(False)
1564 self.upButton.Enable(False)
1565 self.downButton.Enable(False)
1566 self.upButton2.Enable(False)
1567 self.downButton2.Enable(False)
1569 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1570 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1571 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1572 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1573 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1574 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1576 def OnConnect(self, e = None):
1577 if self.comm is not None:
1581 wx.CallAfter(self.OnConnect)
1583 self.connectButton.Enable(False)
1584 self.comm = machineCom.MachineCom(callbackObject=self)
1585 self.infoBox.SetBusy(_('Connecting to machine.'))
1586 self._wizardState = 0
1588 def OnBedUp(self, e):
1589 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1590 self.comm.sendCommand('G92 Z10')
1591 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1592 self.comm.sendCommand('M400')
1594 def OnBedDown(self, e):
1595 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1596 self.comm.sendCommand('G92 Z10')
1597 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1598 self.comm.sendCommand('M400')
1600 def OnBedUp2(self, e):
1601 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1602 self.comm.sendCommand('G92 Z10')
1603 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1604 self.comm.sendCommand('M400')
1606 def OnBedDown2(self, e):
1607 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1608 self.comm.sendCommand('G92 Z10')
1609 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1610 self.comm.sendCommand('M400')
1612 def AllowNext(self):
1613 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1614 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1617 def OnResume(self, e):
1618 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1619 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1620 if self._wizardState == -1:
1621 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1622 wx.CallAfter(self.upButton.Enable, False)
1623 wx.CallAfter(self.downButton.Enable, False)
1624 wx.CallAfter(self.upButton2.Enable, False)
1625 wx.CallAfter(self.downButton2.Enable, False)
1626 self.comm.sendCommand('M105')
1627 self.comm.sendCommand('G28')
1628 self._wizardState = 1
1629 elif self._wizardState == 2:
1630 if profile.getMachineSetting('has_heated_bed') == 'True':
1631 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1632 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1633 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1634 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1635 self.comm.sendCommand('M400')
1636 self._wizardState = 3
1638 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1639 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1640 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1641 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1642 self.comm.sendCommand('M400')
1643 self._wizardState = 3
1644 elif self._wizardState == 4:
1645 if profile.getMachineSetting('has_heated_bed') == 'True':
1646 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1647 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1648 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1649 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1650 self.comm.sendCommand('M400')
1651 self._wizardState = 7
1653 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1654 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1655 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1656 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1657 self.comm.sendCommand('M400')
1658 self._wizardState = 5
1659 elif self._wizardState == 6:
1660 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1661 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1662 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1663 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1664 self.comm.sendCommand('M400')
1665 self._wizardState = 7
1666 elif self._wizardState == 8:
1667 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1668 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1669 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1670 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1671 self._wizardState = 9
1672 elif self._wizardState == 10:
1673 self._wizardState = 11
1674 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1675 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1676 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1677 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1678 w = profile.getMachineSettingFloat('machine_width') - 10
1679 d = profile.getMachineSettingFloat('machine_depth')
1680 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1681 filamentArea = math.pi * filamentRadius * filamentRadius
1682 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1686 'G1 Z2 F%d' % (feedZ),
1688 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1689 'G1 Z0.3 F%d' % (feedZ)]
1691 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1693 for i in xrange(0, 3):
1694 dist = 5.0 + 0.4 * float(i)
1695 eValue += (d - 2.0*dist) * ePerMM
1696 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1697 eValue += (w - 2.0*dist) * ePerMM
1698 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1699 eValue += (d - 2.0*dist) * ePerMM
1700 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1701 eValue += (w - 2.0*dist) * ePerMM
1702 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1704 gcodeList.append('M400')
1705 self.comm.printGCode(gcodeList)
1706 self.resumeButton.Enable(False)
1708 def mcLog(self, message):
1709 print 'Log:', message
1711 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1712 if self._wizardState == 1:
1713 self._wizardState = 2
1714 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1715 wx.CallAfter(self.resumeButton.Enable, True)
1716 elif self._wizardState == 3:
1717 self._wizardState = 4
1718 if profile.getMachineSetting('has_heated_bed') == 'True':
1719 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1721 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1722 wx.CallAfter(self.resumeButton.Enable, True)
1723 elif self._wizardState == 5:
1724 self._wizardState = 6
1725 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1726 wx.CallAfter(self.resumeButton.Enable, True)
1727 elif self._wizardState == 7:
1728 self._wizardState = 8
1729 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1730 wx.CallAfter(self.resumeButton.Enable, True)
1731 elif self._wizardState == 9:
1732 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1733 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1735 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1736 wx.CallAfter(self.resumeButton.Enable, True)
1737 self._wizardState = 10
1739 def mcStateChange(self, state):
1740 if self.comm is None:
1742 if self.comm.isOperational():
1743 if self._wizardState == 0:
1744 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1745 wx.CallAfter(self.upButton.Enable, True)
1746 wx.CallAfter(self.downButton.Enable, True)
1747 wx.CallAfter(self.upButton2.Enable, True)
1748 wx.CallAfter(self.downButton2.Enable, True)
1749 wx.CallAfter(self.resumeButton.Enable, True)
1750 self._wizardState = -1
1751 elif self._wizardState == 11 and not self.comm.isPrinting():
1752 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1753 self.comm.sendCommand('G92 E0')
1754 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1755 self.comm.sendCommand('M104 S0')
1756 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1757 wx.CallAfter(self.infoBox.SetReadyIndicator)
1758 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1759 wx.CallAfter(self.connectButton.Enable, True)
1760 self._wizardState = 12
1761 elif self.comm.isError():
1762 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1764 def mcMessage(self, message):
1767 def mcProgress(self, lineNr):
1770 def mcZChange(self, newZ):
1773 class headOffsetCalibrationPage(InfoPage):
1774 def __init__(self, parent):
1775 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1777 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1780 self.connectButton = self.AddButton(_('Connect to printer'))
1783 self.infoBox = self.AddInfoBox()
1784 self.textEntry = self.AddTextCtrl('')
1785 self.textEntry.Enable(False)
1786 self.resumeButton = self.AddButton(_('Resume'))
1787 self.resumeButton.Enable(False)
1789 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1790 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1792 def AllowBack(self):
1795 def OnConnect(self, e = None):
1796 if self.comm is not None:
1800 wx.CallAfter(self.OnConnect)
1802 self.connectButton.Enable(False)
1803 self.comm = machineCom.MachineCom(callbackObject=self)
1804 self.infoBox.SetBusy(_('Connecting to machine.'))
1805 self._wizardState = 0
1807 def OnResume(self, e):
1808 if self._wizardState == 2:
1809 self._wizardState = 3
1810 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1812 w = profile.getMachineSettingFloat('machine_width')
1813 d = profile.getMachineSettingFloat('machine_depth')
1815 gcode = gcodeGenerator.gcodeGenerator()
1816 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1817 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1824 gcode.addMove(w/2, 5)
1825 gcode.addMove(z=0.2)
1827 gcode.addExtrude(w/2, d-5.0)
1829 gcode.addMove(5, d/2)
1831 gcode.addExtrude(w-5.0, d/2)
1832 gcode.addRetract(15)
1835 gcode.addMove(w/2, 5)
1837 gcode.addExtrude(w/2, d-5.0)
1839 gcode.addMove(5, d/2)
1841 gcode.addExtrude(w-5.0, d/2)
1842 gcode.addRetract(15)
1847 gcode.addCmd('M400')
1849 self.comm.printGCode(gcode.list())
1850 self.resumeButton.Enable(False)
1851 elif self._wizardState == 4:
1853 float(self.textEntry.GetValue())
1856 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1857 self._wizardState = 5
1858 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1859 self.textEntry.SetValue('0.0')
1860 self.textEntry.Enable(True)
1861 elif self._wizardState == 5:
1863 float(self.textEntry.GetValue())
1866 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1867 self._wizardState = 6
1868 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1869 self.textEntry.SetValue('')
1870 self.textEntry.Enable(False)
1871 self.resumeButton.Enable(False)
1873 x = profile.getMachineSettingFloat('extruder_offset_x1')
1874 y = profile.getMachineSettingFloat('extruder_offset_y1')
1875 gcode = gcodeGenerator.gcodeGenerator()
1876 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1877 gcode.setPrintSpeed(25)
1880 gcode.addMove(50, 40, 0.2)
1882 for n in xrange(0, 10):
1883 gcode.addExtrude(50 + n * 10, 150)
1884 gcode.addExtrude(50 + n * 10 + 5, 150)
1885 gcode.addExtrude(50 + n * 10 + 5, 40)
1886 gcode.addExtrude(50 + n * 10 + 10, 40)
1887 gcode.addMove(40, 50)
1888 for n in xrange(0, 10):
1889 gcode.addExtrude(150, 50 + n * 10)
1890 gcode.addExtrude(150, 50 + n * 10 + 5)
1891 gcode.addExtrude(40, 50 + n * 10 + 5)
1892 gcode.addExtrude(40, 50 + n * 10 + 10)
1893 gcode.addRetract(15)
1896 gcode.addMove(50 - x, 30 - y, 0.2)
1898 for n in xrange(0, 10):
1899 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1900 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1901 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1902 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1903 gcode.addMove(30 - x, 50 - y, 0.2)
1904 for n in xrange(0, 10):
1905 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1906 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1907 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1908 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1909 gcode.addRetract(15)
1911 gcode.addCmd('M400')
1912 gcode.addCmd('M104 T0 S0')
1913 gcode.addCmd('M104 T1 S0')
1914 self.comm.printGCode(gcode.list())
1915 elif self._wizardState == 7:
1917 n = int(self.textEntry.GetValue()) - 1
1920 x = profile.getMachineSettingFloat('extruder_offset_x1')
1922 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1923 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1924 self.textEntry.SetValue('10')
1925 self._wizardState = 8
1926 elif self._wizardState == 8:
1928 n = int(self.textEntry.GetValue()) - 1
1931 y = profile.getMachineSettingFloat('extruder_offset_y1')
1933 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1934 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1935 self.infoBox.SetReadyIndicator()
1936 self._wizardState = 8
1938 self.resumeButton.Enable(False)
1940 def mcLog(self, message):
1941 print 'Log:', message
1943 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1944 if self._wizardState == 1:
1945 if temp[0] >= 210 and temp[1] >= 210:
1946 self._wizardState = 2
1947 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1948 wx.CallAfter(self.resumeButton.Enable, True)
1949 wx.CallAfter(self.resumeButton.SetFocus)
1951 def mcStateChange(self, state):
1952 if self.comm is None:
1954 if self.comm.isOperational():
1955 if self._wizardState == 0:
1956 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1957 self.comm.sendCommand('M105')
1958 self.comm.sendCommand('M104 S220 T0')
1959 self.comm.sendCommand('M104 S220 T1')
1960 self.comm.sendCommand('G28')
1961 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1962 self._wizardState = 1
1963 if not self.comm.isPrinting():
1964 if self._wizardState == 3:
1965 self._wizardState = 4
1966 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1967 wx.CallAfter(self.textEntry.SetValue, '0.0')
1968 wx.CallAfter(self.textEntry.Enable, True)
1969 wx.CallAfter(self.resumeButton.Enable, True)
1970 wx.CallAfter(self.resumeButton.SetFocus)
1971 elif self._wizardState == 6:
1972 self._wizardState = 7
1973 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1974 wx.CallAfter(self.textEntry.SetValue, '10')
1975 wx.CallAfter(self.textEntry.Enable, True)
1976 wx.CallAfter(self.resumeButton.Enable, True)
1977 wx.CallAfter(self.resumeButton.SetFocus)
1979 elif self.comm.isError():
1980 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1982 def mcMessage(self, message):
1985 def mcProgress(self, lineNr):
1988 def mcZChange(self, newZ):
1991 class bedLevelWizard(wx.wizard.Wizard):
1993 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1995 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1996 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1998 self.mainPage = bedLevelWizardMain(self)
1999 self.headOffsetCalibration = None
2001 self.RunWizard(self.mainPage)
2004 def OnPageChanging(self, e):
2005 e.GetPage().StoreData()
2007 def OnPageChanged(self, e):
2008 if e.GetPage().AllowNext():
2009 self.FindWindowById(wx.ID_FORWARD).Enable()
2011 self.FindWindowById(wx.ID_FORWARD).Disable()
2012 if e.GetPage().AllowBack():
2013 self.FindWindowById(wx.ID_BACKWARD).Enable()
2015 self.FindWindowById(wx.ID_BACKWARD).Disable()
2017 class headOffsetWizard(wx.wizard.Wizard):
2019 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
2021 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
2022 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
2024 self.mainPage = headOffsetCalibrationPage(self)
2026 self.RunWizard(self.mainPage)
2029 def OnPageChanging(self, e):
2030 e.GetPage().StoreData()
2032 def OnPageChanged(self, e):
2033 if e.GetPage().AllowNext():
2034 self.FindWindowById(wx.ID_FORWARD).Enable()
2036 self.FindWindowById(wx.ID_FORWARD).Disable()
2037 if e.GetPage().AllowBack():
2038 self.FindWindowById(wx.ID_BACKWARD).Enable()
2040 self.FindWindowById(wx.ID_BACKWARD).Disable()