1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
12 from Cura.gui import firmwareInstall
13 from Cura.gui import printWindow
14 from Cura.util import machineCom
15 from Cura.util import profile
16 from Cura.util import gcodeGenerator
17 from Cura.util import resources
20 class InfoBox(wx.Panel):
21 def __init__(self, parent):
22 super(InfoBox, self).__init__(parent)
23 self.SetBackgroundColour('#FFFF80')
25 self.sizer = wx.GridBagSizer(5, 5)
26 self.SetSizer(self.sizer)
28 self.attentionBitmap = wx.Bitmap(resources.getPathForImage('attention.png'))
29 self.errorBitmap = wx.Bitmap(resources.getPathForImage('error.png'))
30 self.readyBitmap = wx.Bitmap(resources.getPathForImage('ready.png'))
32 wx.Bitmap(resources.getPathForImage('busy-0.png')),
33 wx.Bitmap(resources.getPathForImage('busy-1.png')),
34 wx.Bitmap(resources.getPathForImage('busy-2.png')),
35 wx.Bitmap(resources.getPathForImage('busy-3.png'))
38 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
39 self.text = wx.StaticText(self, -1, '')
40 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
41 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
42 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
43 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
44 self.sizer.AddGrowableCol(1)
46 self.extraInfoButton.Show(False)
48 self.extraInfoUrl = ''
50 self.timer = wx.Timer(self)
51 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
52 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
55 def SetInfo(self, info):
56 self.SetBackgroundColour('#FFFF80')
57 self.text.SetLabel(info)
58 self.extraInfoButton.Show(False)
61 def SetError(self, info, extraInfoUrl):
62 self.extraInfoUrl = extraInfoUrl
63 self.SetBackgroundColour('#FF8080')
64 self.text.SetLabel(info)
66 self.extraInfoButton.Show(True)
68 self.SetErrorIndicator()
71 def SetAttention(self, info):
72 self.SetBackgroundColour('#FFFF80')
73 self.text.SetLabel(info)
74 self.extraInfoButton.Show(False)
75 self.SetAttentionIndicator()
79 def SetBusy(self, info):
81 self.SetBusyIndicator()
83 def SetBusyIndicator(self):
85 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
87 def doExtraInfo(self, e):
88 webbrowser.open(self.extraInfoUrl)
90 def doBusyUpdate(self, e):
91 if self.busyState is None:
94 if self.busyState >= len(self.busyBitmap):
96 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
98 def SetReadyIndicator(self):
100 self.bitmap.SetBitmap(self.readyBitmap)
102 def SetErrorIndicator(self):
103 self.busyState = None
104 self.bitmap.SetBitmap(self.errorBitmap)
106 def SetAttentionIndicator(self):
107 self.busyState = None
108 self.bitmap.SetBitmap(self.attentionBitmap)
110 class ImageButton(wx.Panel):
111 DefaultOverlay = wx.Bitmap(resources.getPathForImage('ImageButton_Overlay.png'))
114 __last_group__ = None
115 def __init__(self, parent, label, bitmap, extra_label=None, overlay=DefaultOverlay, style=None):
116 super(ImageButton, self).__init__(parent)
118 if style is ImageButton.IB_GROUP:
119 ImageButton.__last_group__ = self
120 ImageButton.__groups__[self] = [self]
123 if ImageButton.__last_group__:
124 ImageButton.__groups__[ImageButton.__last_group__].append(self)
125 self.group = ImageButton.__last_group__
128 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self), wx.VERTICAL)
129 self.SetSizer(self.sizer)
131 self.original_overlay = overlay
132 self.overlay = self.createOverlay(bitmap, overlay)
133 self.text = wx.StaticText(self, -1, label)
134 self.bmp = wx.StaticBitmap(self, -1, self.bitmap)
136 self.extra_text = wx.StaticText(self, -1, extra_label)
138 self.extra_text = None
139 self.selected = False
142 self.sizer.Add(self.text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
143 self.sizer.Add(self.bmp, 1, flag=wx.ALL|wx.ALIGN_CENTER|wx.EXPAND, border=5)
145 self.sizer.Add(self.extra_text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
146 self.bmp.Bind(wx.EVT_LEFT_UP, self.OnLeftClick)
150 ImageButton.__groups__[self.group].remove(self)
151 if self == self.group:
152 for ib in ImageButton.__groups__[self.group]:
154 del ImageButton.__groups__[self.group]
155 if ImageButton.__last_group__ == self:
156 ImageButton.__last_group__ = None
158 def OnLeftClick(self, e):
164 def SetValue(self, value):
165 old_value = self.selected
166 self.selected = bool(value)
167 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
168 if self.selected and self.group:
169 for ib in ImageButton.__groups__[self.group]:
174 if self.callback and not old_value and self.selected:
177 def SetLabel(self, label):
178 self.text.SetLabel(label)
181 def SetExtraLabel(self, label):
183 self.extra_text.SetLabel(label)
185 self.extra_text = wx.StaticText(self, -1, label)
186 self.sizer.Add(self.extra_text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
189 def SetBitmap(self, bitmap):
191 self.overlay = self.createOverlay(bitmap, self.original_overlay)
192 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
195 def SetOverlay(self, overlay):
196 self.original_overlay = overlay
197 self.overlay = self.createOverlay(self.bitmap, self.original_overlay)
198 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
201 def OnSelected(self, callback):
202 self.callback = callback
204 def createOverlay(self, bitmap, overlay):
205 result = bitmap.GetSubBitmap(wx.Rect(0, 0, *bitmap.Size))
206 (width, height) = bitmap.GetSize()
207 overlay_image = wx.ImageFromBitmap(overlay)
208 overlay_image = overlay_image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
209 overlay_scaled = wx.BitmapFromImage(overlay_image)
211 dc.SelectObject(result)
212 dc.DrawBitmap(overlay_scaled, 0, 0)
213 dc.SelectObject(wx.NullBitmap)
217 class InfoPage(wx.wizard.WizardPageSimple):
218 def __init__(self, parent, title):
219 wx.wizard.WizardPageSimple.__init__(self, parent)
221 parent.GetPageAreaSizer().Add(self)
222 sizer = wx.GridBagSizer(5, 5)
226 self.title = wx.StaticText(self, -1, title)
227 font = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)
228 self.title.SetFont(font)
229 # HACK ALERT: For some reason, the StaticText keeps its same size as if
230 # the font was not modified, this causes the text to wrap and to
231 # get out of bounds of the widgets area and hide other widgets.
232 # The only way I found for the widget to get its right size was to calculate
233 # the new font's extent and set the min size on the widget
234 self.title.SetMinSize(self.GetTextExtent(font, title))
235 sizer.Add(self.title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
236 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
237 sizer.AddGrowableCol(1)
241 def GetTextExtent(self, font, text):
244 w,h = dc.GetTextExtent(text)
247 def AddText(self, info):
248 text = wx.StaticText(self, -1, info)
249 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
253 def AddSeperator(self):
254 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
257 def AddHiddenSeperator(self):
260 def AddInfoBox(self):
261 infoBox = InfoBox(self)
262 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
266 def AddRadioButton(self, label, style=0):
267 radio = wx.RadioButton(self, -1, label, style=style)
268 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
272 def AddCheckbox(self, label, checked=False):
273 check = wx.CheckBox(self, -1)
274 text = wx.StaticText(self, -1, label)
275 check.SetValue(checked)
276 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
277 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
281 def AddButton(self, label):
282 button = wx.Button(self, -1, label)
283 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
287 def AddDualButton(self, label1, label2):
288 button1 = wx.Button(self, -1, label1)
289 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
290 button2 = wx.Button(self, -1, label2)
291 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
293 return button1, button2
295 def AddTextCtrl(self, value):
296 ret = wx.TextCtrl(self, -1, value)
297 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
301 def AddLabelTextCtrl(self, info, value):
302 text = wx.StaticText(self, -1, info)
303 ret = wx.TextCtrl(self, -1, value)
304 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
305 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
309 def AddTextCtrlButton(self, value, buttonText):
310 text = wx.TextCtrl(self, -1, value)
311 button = wx.Button(self, -1, buttonText)
312 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
313 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
317 def AddBitmap(self, bitmap):
318 bitmap = wx.StaticBitmap(self, -1, bitmap)
319 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
324 panel = wx.Panel(self, -1)
325 sizer = wx.GridBagSizer(2, 2)
326 panel.SetSizer(sizer)
327 self.GetSizer().Add(panel, pos=(self.rowNr, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND)
331 def AddCheckmark(self, label, bitmap):
332 check = wx.StaticBitmap(self, -1, bitmap)
333 text = wx.StaticText(self, -1, label)
334 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
335 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
339 def AddCombo(self, label, options):
340 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
341 text = wx.StaticText(self, -1, label)
342 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER)
343 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
347 def AddImageButton(self, panel, x, y, label, filename, image_size=None,
348 extra_label=None, overlay=ImageButton.DefaultOverlay, style=None):
349 ib = ImageButton(panel, label, self.GetBitmap(filename, image_size), extra_label, overlay, style)
350 panel.GetSizer().Add(ib, pos=(x, y), flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
353 def GetBitmap(self, filename, image_size):
354 if image_size == None:
355 return wx.Bitmap(resources.getPathForImage(filename))
357 image = wx.Image(resources.getPathForImage(filename))
358 image_scaled = image.Scale(image_size[0], image_size[1], wx.IMAGE_QUALITY_HIGH)
359 return wx.BitmapFromImage(image_scaled)
370 class PrintrbotPage(InfoPage):
371 def __init__(self, parent):
372 self._printer_info = [
373 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
374 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
375 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
376 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
377 (":" + _("Older models"),),
378 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
379 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
380 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
381 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
382 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
383 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
384 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
385 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
386 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
387 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
388 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
389 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
390 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
393 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
394 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
395 self.AddText(_("Select which Printrbot machine you have:"))
397 for printer in self._printer_info:
398 if printer[0].startswith(":"):
400 self.AddText(printer[0][1:])
402 item = self.AddRadioButton(printer[0])
403 item.data = printer[1:]
404 self._items.append(item)
407 profile.putMachineSetting('machine_name', 'Printrbot ???')
408 for item in self._items:
411 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
412 profile.putMachineSetting('machine_width', data[0])
413 profile.putMachineSetting('machine_depth', data[1])
414 profile.putMachineSetting('machine_height', data[2])
415 profile.putProfileSetting('nozzle_size', data[3])
416 profile.putProfileSetting('filament_diameter', data[4])
417 profile.putProfileSetting('print_temperature', data[5])
418 profile.putProfileSetting('print_speed', data[6])
419 profile.putProfileSetting('travel_speed', data[7])
420 profile.putProfileSetting('retraction_speed', data[8])
421 profile.putProfileSetting('retraction_amount', data[9])
422 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
423 profile.putMachineSetting('has_heated_bed', 'False')
424 profile.putMachineSetting('machine_center_is_zero', 'False')
425 profile.putMachineSetting('extruder_head_size_min_x', '0')
426 profile.putMachineSetting('extruder_head_size_min_y', '0')
427 profile.putMachineSetting('extruder_head_size_max_x', '0')
428 profile.putMachineSetting('extruder_head_size_max_y', '0')
429 profile.putMachineSetting('extruder_head_size_height', '0')
431 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
432 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
433 ;Print time: {print_time}
434 ;Filament used: {filament_amount}m {filament_weight}g
435 ;Filament cost: {filament_cost}
436 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
437 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
439 G90 ;absolute positioning
440 M82 ;set extruder to absolute mode
441 M107 ;start with the fan off
442 G28 X0 Y0 ;move X/Y to min endstops
443 G28 Z0 ;move Z to min endstops
444 G29 ;Run the auto bed leveling
445 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
446 G92 E0 ;zero the extruded length
447 G1 F200 E3 ;extrude 3mm of feed stock
448 G92 E0 ;zero the extruded length again
450 ;Put printing message on LCD screen
454 class OtherMachineSelectPage(InfoPage):
455 def __init__(self, parent):
456 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
457 self.AddText(_("The following pre-defined machine profiles are available"))
458 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."))
460 machines = resources.getDefaultMachineProfiles()
462 for filename in machines:
463 name = os.path.splitext(os.path.basename(filename))[0]
464 item = self.AddRadioButton(name)
465 item.filename = filename
466 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
467 self.options.append(item)
469 item = self.AddRadioButton(_('Custom...'))
471 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
473 def OnProfileSelect(self, e):
474 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
476 def OnOtherSelect(self, e):
477 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
480 for option in self.options:
481 if option.GetValue():
482 profile.loadProfile(option.filename)
483 profile.loadMachineSettings(option.filename)
485 class OtherMachineInfoPage(InfoPage):
486 def __init__(self, parent):
487 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
488 self.AddText(_("Cura is now ready to be used!"))
490 class CustomRepRapInfoPage(InfoPage):
491 def __init__(self, parent):
492 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
493 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
494 self.AddText(_("Be sure to review the default profile before running it on your machine."))
495 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
497 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
499 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
500 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
501 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
502 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
503 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
504 self.heatedBed = self.AddCheckbox(_("Heated bed"))
505 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
508 profile.putMachineSetting('machine_name', self.machineName.GetValue())
509 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
510 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
511 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
512 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
513 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
514 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
515 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
516 profile.putMachineSetting('extruder_head_size_min_x', '0')
517 profile.putMachineSetting('extruder_head_size_min_y', '0')
518 profile.putMachineSetting('extruder_head_size_max_x', '0')
519 profile.putMachineSetting('extruder_head_size_max_y', '0')
520 profile.putMachineSetting('extruder_head_size_height', '0')
521 profile.checkAndUpdateMachineName()
523 class MachineSelectPage(InfoPage):
524 def __init__(self, parent):
525 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
526 self.AddText(_("What kind of machine do you have:"))
528 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
529 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
530 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
531 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
532 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
533 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
534 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
535 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
536 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
537 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
538 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
539 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
540 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
541 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
543 def OnUltimaker2Select(self, e):
544 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
546 def OnUltimakerSelect(self, e):
547 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
549 def OnUltimakerOPSelect(self, e):
550 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
552 def OnPrintrbotSelect(self, e):
553 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
555 def OnOtherSelect(self, e):
556 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
559 profile.putProfileSetting('retraction_enable', 'True')
560 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
561 if self.Ultimaker2Radio.GetValue():
562 profile.putMachineSetting('machine_width', '230')
563 profile.putMachineSetting('machine_depth', '225')
564 profile.putMachineSetting('machine_height', '205')
565 profile.putMachineSetting('machine_name', 'ultimaker2')
566 profile.putMachineSetting('machine_type', 'ultimaker2')
567 profile.putMachineSetting('has_heated_bed', 'True')
568 if self.Ultimaker2GoRadio.GetValue():
569 profile.putMachineSetting('machine_width', '120')
570 profile.putMachineSetting('machine_depth', '120')
571 profile.putMachineSetting('machine_height', '115')
572 profile.putMachineSetting('machine_name', 'ultimaker2go')
573 profile.putMachineSetting('machine_type', 'ultimaker2go')
574 profile.putMachineSetting('has_heated_bed', 'False')
575 if self.Ultimaker2ExtRadio.GetValue():
576 profile.putMachineSetting('machine_width', '230')
577 profile.putMachineSetting('machine_depth', '225')
578 profile.putMachineSetting('machine_height', '315')
579 profile.putMachineSetting('machine_name', 'ultimaker2extended')
580 profile.putMachineSetting('machine_type', 'ultimaker2extended')
581 profile.putMachineSetting('has_heated_bed', 'False')
582 profile.putMachineSetting('machine_center_is_zero', 'False')
583 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
584 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
585 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
586 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
587 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
588 profile.putMachineSetting('extruder_head_size_height', '48.0')
589 profile.putProfileSetting('nozzle_size', '0.4')
590 profile.putProfileSetting('fan_full_height', '5.0')
591 profile.putMachineSetting('extruder_offset_x1', '18.0')
592 profile.putMachineSetting('extruder_offset_y1', '0.0')
593 elif self.UltimakerRadio.GetValue():
594 profile.putMachineSetting('machine_width', '205')
595 profile.putMachineSetting('machine_depth', '205')
596 profile.putMachineSetting('machine_height', '200')
597 profile.putMachineSetting('machine_name', 'ultimaker original')
598 profile.putMachineSetting('machine_type', 'ultimaker')
599 profile.putMachineSetting('machine_center_is_zero', 'False')
600 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
601 profile.putProfileSetting('nozzle_size', '0.4')
602 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
603 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
604 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
605 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
606 profile.putMachineSetting('extruder_head_size_height', '55.0')
607 elif self.UltimakerOPRadio.GetValue():
608 profile.putMachineSetting('machine_width', '205')
609 profile.putMachineSetting('machine_depth', '205')
610 profile.putMachineSetting('machine_height', '200')
611 profile.putMachineSetting('machine_name', 'ultimaker original+')
612 profile.putMachineSetting('machine_type', 'ultimaker_plus')
613 profile.putMachineSetting('machine_center_is_zero', 'False')
614 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
615 profile.putProfileSetting('nozzle_size', '0.4')
616 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
617 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
618 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
619 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
620 profile.putMachineSetting('extruder_head_size_height', '55.0')
621 profile.putMachineSetting('has_heated_bed', 'True')
622 profile.putMachineSetting('extruder_amount', '1')
623 profile.putProfileSetting('retraction_enable', 'True')
625 profile.putMachineSetting('machine_width', '80')
626 profile.putMachineSetting('machine_depth', '80')
627 profile.putMachineSetting('machine_height', '60')
628 profile.putMachineSetting('machine_name', 'reprap')
629 profile.putMachineSetting('machine_type', 'reprap')
630 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
631 profile.putPreference('startMode', 'Normal')
632 profile.putProfileSetting('nozzle_size', '0.5')
633 profile.checkAndUpdateMachineName()
634 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
636 class SelectParts(InfoPage):
637 def __init__(self, parent):
638 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
639 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."))
641 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
642 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
643 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
644 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
646 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."))
647 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
648 self.springExtruder.SetValue(True)
651 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
652 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
653 profile.putMachineSetting('has_heated_bed', 'True')
655 profile.putMachineSetting('has_heated_bed', 'False')
656 if self.dualExtrusion.GetValue():
657 profile.putMachineSetting('extruder_amount', '2')
658 profile.putMachineSetting('machine_depth', '195')
660 profile.putMachineSetting('extruder_amount', '1')
661 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
662 profile.putProfileSetting('retraction_enable', 'True')
664 profile.putProfileSetting('retraction_enable', 'False')
667 class UltimakerFirmwareUpgradePage(InfoPage):
668 def __init__(self, parent):
669 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
670 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."))
671 self.AddHiddenSeperator()
672 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
673 self.AddHiddenSeperator()
674 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."))
675 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
676 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
677 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
678 self.AddHiddenSeperator()
679 if profile.getMachineSetting('machine_type') == 'ultimaker':
680 self.AddText(_("Do not upgrade to this firmware if:"))
681 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
682 self.AddText(_("* Build your own heated bed"))
683 self.AddText(_("* Have other changes in the firmware"))
684 # button = self.AddButton('Goto this page for a custom firmware')
685 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
690 def OnUpgradeClick(self, e):
691 if firmwareInstall.InstallFirmware():
692 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
694 def OnSkipClick(self, e):
695 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
696 self.GetParent().ShowPage(self.GetNext())
698 def OnUrlClick(self, e):
699 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
701 class UltimakerCheckupPage(InfoPage):
702 def __init__(self, parent):
703 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
705 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
706 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
707 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
708 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
709 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
710 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
711 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
712 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
713 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
714 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
717 _("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."))
718 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
719 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
720 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
722 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
723 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
724 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
726 self.infoBox = self.AddInfoBox()
727 self.machineState = self.AddText("")
728 self.temperatureLabel = self.AddText("")
729 self.errorLogButton = self.AddButton(_("Show error log"))
730 self.errorLogButton.Show(False)
732 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
734 self.xMinStop = False
735 self.xMaxStop = False
736 self.yMinStop = False
737 self.yMaxStop = False
738 self.zMinStop = False
739 self.zMaxStop = False
741 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
744 if self.comm is not None:
748 self.endstopBitmap.Show(False)
751 def OnSkipClick(self, e):
752 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
753 self.GetParent().ShowPage(self.GetNext())
755 def OnCheckClick(self, e=None):
756 self.errorLogButton.Show(False)
757 if self.comm is not None:
761 wx.CallAfter(self.OnCheckClick)
763 self.infoBox.SetBusy(_("Connecting to machine."))
764 self.commState.SetBitmap(self.unknownBitmap)
765 self.tempState.SetBitmap(self.unknownBitmap)
766 self.stopState.SetBitmap(self.unknownBitmap)
767 self.checkupState = 0
768 self.checkExtruderNr = 0
769 self.comm = machineCom.MachineCom(callbackObject=self)
771 def OnErrorLog(self, e):
772 printWindow.LogWindow('\n'.join(self.comm.getLog()))
774 def mcLog(self, message):
777 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
778 if not self.comm.isOperational():
780 if self.checkupState == 0:
781 self.tempCheckTimeout = 20
782 if temp[self.checkExtruderNr] > 70:
783 self.checkupState = 1
784 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
785 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
786 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
788 self.startTemp = temp[self.checkExtruderNr]
789 self.checkupState = 2
790 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
791 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
792 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
793 elif self.checkupState == 1:
794 if temp[self.checkExtruderNr] < 60:
795 self.startTemp = temp[self.checkExtruderNr]
796 self.checkupState = 2
797 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
798 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
799 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
800 elif self.checkupState == 2:
801 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
802 if temp[self.checkExtruderNr] > self.startTemp + 40:
803 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
804 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
805 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
806 self.checkExtruderNr = 0
807 self.checkupState = 3
808 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
809 wx.CallAfter(self.endstopBitmap.Show, True)
810 wx.CallAfter(self.Layout)
811 self.comm.sendCommand('M119')
812 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
814 self.checkupState = 0
815 self.checkExtruderNr += 1
817 self.tempCheckTimeout -= 1
818 if self.tempCheckTimeout < 1:
819 self.checkupState = -1
820 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
821 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
822 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
823 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
824 elif self.checkupState >= 3 and self.checkupState < 10:
825 self.comm.sendCommand('M119')
826 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
828 def mcStateChange(self, state):
829 if self.comm is None:
831 if self.comm.isOperational():
832 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
833 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
834 elif self.comm.isError():
835 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
836 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
837 wx.CallAfter(self.endstopBitmap.Show, False)
838 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
839 wx.CallAfter(self.errorLogButton.Show, True)
840 wx.CallAfter(self.Layout)
842 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
844 def mcMessage(self, message):
845 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
846 for data in message.split(' '):
848 tag, value = data.split(':', 1)
850 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
852 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
854 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
856 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
858 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
860 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
862 tag, value = map(str.strip, message.split(':', 1))
864 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
866 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
868 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
870 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
872 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
874 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
875 if 'z_max' in message:
876 self.comm.sendCommand('M119')
878 if self.checkupState == 3:
879 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
880 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
881 self.checkupState = 5
882 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
883 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
885 self.checkupState = 4
886 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
887 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
888 elif self.checkupState == 4:
889 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
890 self.checkupState = 5
891 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
892 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
893 elif self.checkupState == 5:
894 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
895 self.checkupState = 6
896 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
897 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
898 elif self.checkupState == 6:
899 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
900 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
901 self.checkupState = 8
902 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
903 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
905 self.checkupState = 7
906 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
907 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
908 elif self.checkupState == 7:
909 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
910 self.checkupState = 8
911 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
912 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
913 elif self.checkupState == 8:
914 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
915 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
916 self.checkupState = 10
918 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
919 wx.CallAfter(self.infoBox.SetReadyIndicator)
920 wx.CallAfter(self.endstopBitmap.Show, False)
921 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
922 wx.CallAfter(self.OnSkipClick, None)
924 self.checkupState = 9
925 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
926 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
927 elif self.checkupState == 9:
928 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
929 self.checkupState = 10
931 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
932 wx.CallAfter(self.infoBox.SetReadyIndicator)
933 wx.CallAfter(self.endstopBitmap.Show, False)
934 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
935 wx.CallAfter(self.OnSkipClick, None)
937 def mcProgress(self, lineNr):
940 def mcZChange(self, newZ):
944 class UltimakerCalibrationPage(InfoPage):
945 def __init__(self, parent):
946 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
948 self.AddText("Your Ultimaker requires some calibration.")
949 self.AddText("This calibration is needed for a proper extrusion amount.")
951 self.AddText("The following values are needed:")
952 self.AddText("* Diameter of filament")
953 self.AddText("* Number of steps per mm of filament extrusion")
955 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
957 self.AddText("First we need the diameter of your filament:")
958 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
960 "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.")
961 self.AddText("Note: This value can be changed later at any time.")
964 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
967 class UltimakerCalibrateStepsPerEPage(InfoPage):
968 def __init__(self, parent):
969 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
971 #if profile.getMachineSetting('steps_per_e') == '0':
972 # profile.putMachineSetting('steps_per_e', '865.888')
974 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
975 self.AddText(_("First remove any filament from your machine."))
976 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
977 self.AddText(_("We'll push the filament 100mm"))
978 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
979 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
980 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
981 self.AddText(_("This results in the following steps per E:"))
982 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
983 self.AddText(_("You can repeat these steps to get better calibration."))
986 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
987 self.heatButton = self.AddButton(_("Heatup for filament removal"))
989 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
990 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
991 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
993 def OnSaveLengthClick(self, e):
994 currentEValue = float(self.stepsPerEInput.GetValue())
995 realExtrudeLength = float(self.lengthInput.GetValue())
996 newEValue = currentEValue * 100 / realExtrudeLength
997 self.stepsPerEInput.SetValue(str(newEValue))
998 self.lengthInput.SetValue("100")
1000 def OnExtrudeClick(self, e):
1001 t = threading.Thread(target=self.OnExtrudeRun)
1005 def OnExtrudeRun(self):
1006 self.heatButton.Enable(False)
1007 self.extrudeButton.Enable(False)
1008 currentEValue = float(self.stepsPerEInput.GetValue())
1009 self.comm = machineCom.MachineCom()
1010 if not self.comm.isOpen():
1012 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1013 'Printer error', wx.OK | wx.ICON_INFORMATION)
1014 self.heatButton.Enable(True)
1015 self.extrudeButton.Enable(True)
1018 line = self.comm.readline()
1023 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1026 self.sendGCommand('M302') #Disable cold extrusion protection
1027 self.sendGCommand("M92 E%f" % (currentEValue))
1028 self.sendGCommand("G92 E0")
1029 self.sendGCommand("G1 E100 F600")
1032 self.extrudeButton.Enable()
1033 self.heatButton.Enable()
1035 def OnHeatClick(self, e):
1036 t = threading.Thread(target=self.OnHeatRun)
1040 def OnHeatRun(self):
1041 self.heatButton.Enable(False)
1042 self.extrudeButton.Enable(False)
1043 self.comm = machineCom.MachineCom()
1044 if not self.comm.isOpen():
1046 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1047 'Printer error', wx.OK | wx.ICON_INFORMATION)
1048 self.heatButton.Enable(True)
1049 self.extrudeButton.Enable(True)
1052 line = self.comm.readline()
1054 self.heatButton.Enable(True)
1055 self.extrudeButton.Enable(True)
1059 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1062 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
1064 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
1065 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
1066 self.sendGCommand('M104 S0')
1069 self.heatButton.Enable(True)
1070 self.extrudeButton.Enable(True)
1072 def sendGCommand(self, cmd):
1073 self.comm.sendCommand(cmd) #Disable cold extrusion protection
1075 line = self.comm.readline()
1078 if line.startswith('ok'):
1081 def StoreData(self):
1082 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1084 class Ultimaker2ReadyPage(InfoPage):
1085 def __init__(self, parent):
1086 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1087 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1088 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1091 class LulzbotMachineSelectPage(InfoPage):
1095 def __init__(self, parent):
1096 super(LulzbotMachineSelectPage, self).__init__(parent, _("Select your machine"))
1097 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1098 self.AddText(_("Select your printer :"))
1100 self.panel = self.AddPanel()
1102 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1103 self.LulzbotMini = self.AddImageButton(self.panel, 0, 0, _("LulzBot Mini"),
1104 'Lulzbot_mini.jpg', image_size, style=ImageButton.IB_GROUP)
1105 self.LulzbotMini.OnSelected(self.OnLulzbotMiniSelected)
1106 self.LulzbotMini.SetValue(True)
1107 self.LulzbotTaz5 = self.AddImageButton(self.panel, 0, 1, _("LulzBot TAZ 5"),
1108 'Lulzbot_TAZ5.jpg', image_size)
1109 self.LulzbotTaz5.OnSelected(self.OnLulzbotTazSelected)
1110 self.LulzbotTaz4 = self.AddImageButton(self.panel, 1, 0, _("LulzBot TAZ 4"),
1111 'Lulzbot_TAZ4.jpg', image_size)
1112 self.LulzbotTaz4.OnSelected(self.OnLulzbotTazSelected)
1113 self.OtherPrinters = self.AddImageButton(self.panel, 1, 1, _("Other Printers"),
1114 'Generic-3D-Printer.png', image_size)
1115 self.OtherPrinters.OnSelected(self.OnOthersSelected)
1117 def OnOthersSelected(self):
1118 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().machineSelectPage)
1120 def OnLulzbotMiniSelected(self):
1121 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotMiniToolheadPage)
1122 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotMiniToolheadPage,
1123 self.GetParent().lulzbotFirmwarePage)
1125 def OnLulzbotTazSelected(self):
1126 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTazHotendPage)
1128 def AllowNext(self):
1131 def AllowBack(self):
1134 def StoreData(self):
1135 if self.LulzbotTaz4.GetValue() or self.LulzbotTaz5.GetValue() or self.LulzbotMini.GetValue():
1136 if self.LulzbotTaz4.GetValue():
1137 # Nozzle size will be set in the toolhead selection page
1138 # We set the machine_type here so later pages can differenciate between TAZ 4 and 5
1139 profile.putMachineSetting('machine_width', '290')
1140 profile.putMachineSetting('machine_depth', '275')
1141 profile.putMachineSetting('machine_height', '250')
1142 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
1143 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
1144 profile.putMachineSetting('serial_baud', '115200')
1145 elif self.LulzbotTaz5.GetValue():
1146 # Nozzle size will be set in the toolhead selection page
1147 # We set the machine_type here so later pages can differenciate between TAZ 4 and 5
1148 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
1149 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
1150 profile.putMachineSetting('machine_width', '290')
1151 profile.putMachineSetting('machine_depth', '275')
1152 profile.putMachineSetting('machine_height', '250')
1153 profile.putMachineSetting('serial_baud', '115200')
1155 # Nozzle size and machine type will be set in the toolhead selection page
1156 profile.putMachineSetting('machine_name', 'LulzBot Mini')
1157 profile.putMachineSetting('machine_width', '155')
1158 profile.putMachineSetting('machine_depth', '155')
1159 profile.putMachineSetting('machine_height', '163')
1160 profile.putMachineSetting('serial_baud', '115200')
1161 profile.putMachineSetting('extruder_head_size_min_x', '40')
1162 profile.putMachineSetting('extruder_head_size_max_x', '75')
1163 profile.putMachineSetting('extruder_head_size_min_y', '25')
1164 profile.putMachineSetting('extruder_head_size_max_y', '55')
1165 profile.putMachineSetting('extruder_head_size_height', '17')
1167 profile.putMachineSetting('machine_center_is_zero', 'False')
1168 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
1169 profile.putMachineSetting('has_heated_bed', 'True')
1170 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
1171 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
1172 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
1173 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
1174 profile.putMachineSetting('extruder_head_size_height', '0.0')
1175 profile.putProfileSetting('retraction_enable', 'True')
1176 profile.putPreference('startMode', 'Simple')
1177 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
1178 profile.checkAndUpdateMachineName()
1180 class LulzbotReadyPage(InfoPage):
1181 def __init__(self, parent):
1182 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1183 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1184 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1186 self.AddText(_('For more information about using Cura with your LulzBot'))
1187 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1190 class LulzbotToolheadSelectPage(InfoPage):
1191 def __init__(self, parent, title):
1192 super(LulzbotToolheadSelectPage, self).__init__(parent, title)
1193 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1194 self.AddText(_('Please select your currently installed Tool Head'))
1195 txt = self.AddText(_('WARNING: Carefully select the right Tool Head.\nFlashing the firmware with the wrong Tool Head can damage your LulzBot printer.'))
1196 txt.SetForegroundColour(wx.RED)
1199 class LulzbotMiniToolheadSelectPage(LulzbotToolheadSelectPage):
1200 def __init__(self, parent, allowBack = True):
1201 super(LulzbotMiniToolheadSelectPage, self).__init__(parent, _("LulzBot Mini Toolhead Selection"))
1203 self.allowBack = allowBack
1204 self.panel = self.AddPanel()
1205 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1206 self.standard = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v2'),
1207 'Lulzbot_Toolhead_Mini_Standard.jpg', image_size,
1208 style=ImageButton.IB_GROUP)
1209 self.flexy = self.AddImageButton(self.panel, 0, 1, _('Flexystruder v2'),
1210 'Lulzbot_Toolhead_Mini_Flexystruder.jpg', image_size)
1211 self.standard.SetValue(True)
1213 def AllowBack(self):
1214 return self.allowBack
1216 def StoreData(self):
1217 if self.standard.GetValue():
1218 profile.putProfileSetting('nozzle_size', '0.5')
1219 profile.putMachineSetting('extruder_amount', '1')
1220 profile.putMachineSetting('toolhead', 'Single Extruder V2')
1221 profile.putMachineSetting('toolhead_shortname', '')
1222 profile.putMachineSetting('machine_type', 'lulzbot_mini')
1224 profile.putProfileSetting('nozzle_size', '0.6')
1225 profile.putMachineSetting('extruder_amount', '1')
1226 profile.putMachineSetting('toolhead', 'Flexystruder V2')
1227 profile.putMachineSetting('toolhead_shortname', 'Flexystruder')
1228 profile.putMachineSetting('machine_type', 'lulzbot_mini_flexystruder')
1231 class LulzbotTazToolheadSelectPage(LulzbotToolheadSelectPage):
1232 def __init__(self, parent):
1233 super(LulzbotTazToolheadSelectPage, self).__init__(parent, _("LulzBot TAZ Toolhead Selection"))
1235 self.panel = self.AddPanel()
1236 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1237 self.single = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v1'),
1238 'Lulzbot_Toolhead_TAZ_Single_v1.jpg', image_size,
1239 style=ImageButton.IB_GROUP)
1240 self.flexy = self.AddImageButton(self.panel, 0, 1, _('Flexystruder v1'),
1241 'Lulzbot_Toolhead_TAZ_Flexystruder_v1.jpg', image_size)
1242 self.dually = self.AddImageButton(self.panel, 1, 0, _('Dual Extruder v1'),
1243 'Lulzbot_Toolhead_TAZ_Dually_v1.jpg', image_size)
1244 self.flexydually = self.AddImageButton(self.panel, 1, 1, _('FlexyDually v1'),
1245 'Lulzbot_Toolhead_TAZ_FlexyDually_v1.jpg', image_size)
1247 self.single.SetValue(True)
1249 def SetVersion(self, version):
1250 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1251 self.single.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Single_v%d.jpg' % version, image_size))
1252 self.single.SetLabel(_('Single Extruder v%d' % version))
1253 self.flexy.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Flexystruder_v%d.jpg' % version, image_size))
1254 self.flexy.SetLabel(_('Flexystruder v%d' % version))
1255 self.dually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Dually_v%d.jpg' % version, image_size))
1256 self.dually.SetLabel(_('Dual Extruder v%d' % version))
1257 self.flexydually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_FlexyDually_v%d.jpg' % version, image_size))
1258 self.flexydually.SetLabel(_('FlexyDually v%d' % version))
1259 self.version = version
1261 self.single.OnSelected(None)
1262 self.flexy.OnSelected(None)
1263 self.dually.OnSelected(None)
1264 self.flexydually.OnSelected(None)
1265 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1267 self.single.OnSelected(self.OnSingleV2)
1268 self.flexy.OnSelected(self.OnNonSingle)
1269 self.dually.OnSelected(self.OnNonSingle)
1270 self.flexydually.OnSelected(self.OnNonSingle)
1271 if self.single.GetValue():
1272 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1273 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotFirmwarePage)
1275 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1277 def OnSingleV2(self):
1278 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1279 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotFirmwarePage)
1281 def OnNonSingle(self):
1282 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotFirmwarePage)
1284 def StoreData(self):
1285 if profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1289 version = (taz_version, self.version)
1290 if self.single.GetValue():
1291 profile.putProfileSetting('nozzle_size', '0.5' if self.version == 2 else '0.35')
1292 profile.putMachineSetting('extruder_amount', '1')
1293 profile.putMachineSetting('toolhead', 'Single Extruder V%d' % self.version)
1294 profile.putMachineSetting('toolhead_shortname', '')
1295 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_SingleV%d' % version)
1296 elif self.flexy.GetValue():
1297 profile.putProfileSetting('nozzle_size', '0.6')
1298 profile.putMachineSetting('extruder_amount', '1')
1299 profile.putMachineSetting('toolhead', 'Flexystruder V%d' % self.version)
1300 profile.putMachineSetting('toolhead_shortname', 'Flexystruder v%d' % self.version)
1301 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_FlexystruderV%d' % version)
1302 elif self.dually.GetValue():
1303 profile.putProfileSetting('nozzle_size', '0.5')
1304 profile.putMachineSetting('extruder_amount', '2')
1305 profile.putMachineSetting('extruder_offset_x1', '0.0')
1306 profile.putMachineSetting('extruder_offset_y1', '-50.0' if self.version == 2 else '-52.00')
1307 profile.putMachineSetting('toolhead', 'Dual Extruder V%d' % self.version)
1308 profile.putMachineSetting('toolhead_shortname', 'Dually v%d' % self.version)
1309 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_DuallyV%d' % version)
1310 elif self.flexydually.GetValue():
1311 profile.putProfileSetting('nozzle_size', '0.6')
1312 profile.putMachineSetting('extruder_amount', '2')
1313 profile.putMachineSetting('extruder_offset_x1', '0.0')
1314 profile.putMachineSetting('extruder_offset_y1', '-50.0' if self.version == 2 else '-52.00')
1315 profile.putMachineSetting('toolhead', 'FlexyDually V%d' % self.version)
1316 profile.putMachineSetting('toolhead_shortname', 'FlexyDually v%d' % self.version)
1317 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_FlexyDuallyV%d' % version)
1320 class LulzbotHotendSelectPage(LulzbotToolheadSelectPage):
1321 def __init__(self, parent, allowBack = True):
1322 super(LulzbotHotendSelectPage, self).__init__(parent, _("LulzBot Toolhead Hotend Selection"))
1324 self.allowBack = allowBack
1325 self.panel = self.AddPanel()
1326 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1327 self.v1 = self.AddImageButton(self.panel, 0, 0, _('v1 (Budaschnozzle Hotends)'),
1328 'Lulzbot_Toolhead_v1.jpg', image_size,
1329 style=ImageButton.IB_GROUP)
1330 self.v2 = self.AddImageButton(self.panel, 0, 1, _('v2 (Hexagon Hotends)'),
1331 'Lulzbot_Toolhead_v2.jpg', image_size)
1332 self.v1.SetValue(True)
1334 def AllowBack(self):
1335 return self.allowBack
1337 def StoreData(self):
1338 self.GetParent().lulzbotTazToolheadPage.SetVersion(1 if self.v1.GetValue() else 2)
1340 class LulzbotTaz5NozzleSelectPage(LulzbotToolheadSelectPage):
1341 url2='http://lulzbot.com/printer-identification'
1343 def __init__(self, parent):
1344 super(LulzbotTaz5NozzleSelectPage, self).__init__(parent, _("LulzBot TAZ Single V2 Nozzle Selection"))
1346 self.AddText(_('Please select your Hexagon hotend\'s nozzle size:'))
1347 self.Nozzle35Radio = self.AddRadioButton("0.35 mm", style=wx.RB_GROUP)
1348 self.Nozzle35Radio.SetValue(True)
1349 self.Nozzle50Radio = self.AddRadioButton("0.5 mm")
1350 self.AddText(_(' '))
1353 self.AddText(_('If you are not sure which nozzle size you have'))
1354 self.AddText(_('please check this webpage: '))
1355 button = self.AddButton(LulzbotTaz5NozzleSelectPage.url2)
1356 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
1358 def OnUrlClick(self, e):
1359 webbrowser.open(LulzbotTaz5NozzleSelectPage.url2)
1361 def StoreData(self):
1362 if profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1366 if self.Nozzle35Radio.GetValue():
1367 profile.putProfileSetting('nozzle_size', '0.35')
1368 profile.putMachineSetting('toolhead', 'Single Extruder V2 (0.35mm nozzle)')
1369 profile.putMachineSetting('toolhead_shortname', '0.35 nozzle')
1370 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_035nozzle' % taz_version)
1373 profile.putProfileSetting('nozzle_size', '0.5')
1374 profile.putMachineSetting('toolhead', 'Single Extruder V2 (0.5mm nozzle)')
1375 profile.putMachineSetting('toolhead_shortname', '0.5 nozzle')
1376 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_05nozzle' % taz_version)
1378 class LulzbotFirmwareUpdatePage(InfoPage):
1379 def __init__(self, parent):
1380 super(LulzbotFirmwareUpdatePage, self).__init__(parent, _("LulzBot Firmware Update"))
1382 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1384 self.AddText(_('Your Lulzbot printer\'s firmware will now be updated'))
1386 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."))
1387 self.AddHiddenSeperator()
1388 self.AddText(_("The firmware shipping with new Lulzbot printers works, but upgrades may be available\nwhich improve the functionality of your printer.\nIf you changed your toolhead, you will also need to flash\na new firmware or you may risk damaging the toolhead."))
1389 self.AddHiddenSeperator()
1390 self.AddText(_("To avoid any possible confusion, make sure to disconnect all printers from your PC\nexpect the printer that you are currently configuring."))
1391 self.AddHiddenSeperator()
1392 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Flash the firmware'), _('Skip upgrade'))
1393 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
1394 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
1396 def AllowNext(self):
1399 def OnUpgradeClick(self, e):
1400 if firmwareInstall.InstallFirmware():
1401 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
1403 def OnSkipClick(self, e):
1404 dlg = wx.MessageDialog(self, _("Are you sure you want to skip the firmware upgrade?\n" +
1405 "It could damage your printer if you changed your toolhead and have not updated thefirmware!"),
1406 _('Skip firmware upgrade?'), wx.YES_NO | wx.ICON_EXCLAMATION)
1407 skip = dlg.ShowModal() == wx.ID_YES
1410 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
1411 self.GetParent().ShowPage(self.GetNext())
1413 class LulzbotChangeToolheadWizard(wx.wizard.Wizard):
1415 super(LulzbotChangeToolheadWizard, self).__init__(None, -1, _("Change Lulzbot Toolhead Wizard"))
1417 self._nozzle_size = profile.getProfileSettingFloat('nozzle_size')
1418 self._machine_name = profile.getMachineSetting('machine_name')
1419 self._machine_type = profile.getMachineSetting('machine_type')
1420 self._extruder_amount = int(profile.getMachineSettingFloat('extruder_amount'))
1422 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1423 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1424 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1426 self.lulzbotReadyPage = LulzbotReadyPage(self)
1427 self.lulzbotFirmwarePage = LulzbotFirmwareUpdatePage(self)
1428 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self, False)
1429 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1430 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self, False)
1431 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1433 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotFirmwarePage)
1434 wx.wizard.WizardPageSimple.Chain(self.lulzbotFirmwarePage, self.lulzbotReadyPage)
1435 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1437 if profile.getMachineSetting('machine_type').startswith('lulzbot_mini'):
1438 self.RunWizard(self.lulzbotMiniToolheadPage)
1440 self.RunWizard(self.lulzbotTazHotendPage)
1443 def OnPageChanging(self, e):
1444 e.GetPage().StoreData()
1446 def OnPageChanged(self, e):
1447 if e.GetPage().AllowNext():
1448 self.FindWindowById(wx.ID_FORWARD).Enable()
1450 self.FindWindowById(wx.ID_FORWARD).Disable()
1451 if e.GetPage().AllowBack():
1452 self.FindWindowById(wx.ID_BACKWARD).Enable()
1454 self.FindWindowById(wx.ID_BACKWARD).Disable()
1456 def OnCancel(self, e):
1457 profile.putProfileSetting('nozzle_size', self._nozzle_size)
1458 profile.putMachineSetting('machine_name', self._machine_name)
1459 profile.putMachineSetting('machine_type', self._machine_type)
1460 profile.putMachineSetting('extruder_amount', self._extruder_amount)
1462 class ConfigWizard(wx.wizard.Wizard):
1463 def __init__(self, addNew = False):
1464 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1466 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1468 profile.setActiveMachine(profile.getMachineCount())
1470 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1471 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1472 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1474 self.machineSelectPage = MachineSelectPage(self)
1475 self.ultimakerSelectParts = SelectParts(self)
1476 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1477 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1478 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1479 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1480 self.bedLevelPage = bedLevelWizardMain(self)
1481 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1482 self.printrbotSelectType = PrintrbotPage(self)
1483 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1484 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1485 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1487 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1488 self.lulzbotReadyPage = LulzbotReadyPage(self)
1489 self.lulzbotFirmwarePage = LulzbotFirmwareUpdatePage(self)
1490 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self)
1491 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1492 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self)
1493 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1494 self.lulzbotMachineSelectPage = LulzbotMachineSelectPage(self)
1496 wx.wizard.WizardPageSimple.Chain(self.lulzbotMachineSelectPage, self.lulzbotMiniToolheadPage)
1497 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotFirmwarePage)
1498 wx.wizard.WizardPageSimple.Chain(self.lulzbotFirmwarePage, self.lulzbotReadyPage)
1499 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1500 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1501 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1502 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1503 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1504 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1505 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1507 self.RunWizard(self.lulzbotMachineSelectPage)
1510 def OnPageChanging(self, e):
1511 e.GetPage().StoreData()
1513 def OnPageChanged(self, e):
1514 if e.GetPage().AllowNext():
1515 self.FindWindowById(wx.ID_FORWARD).Enable()
1517 self.FindWindowById(wx.ID_FORWARD).Disable()
1518 if e.GetPage().AllowBack():
1519 self.FindWindowById(wx.ID_BACKWARD).Enable()
1521 self.FindWindowById(wx.ID_BACKWARD).Disable()
1523 def OnCancel(self, e):
1524 new_machine_index = int(profile.getPreferenceFloat('active_machine'))
1525 profile.setActiveMachine(self._old_machine_index)
1526 profile.removeMachine(new_machine_index)
1528 class bedLevelWizardMain(InfoPage):
1529 def __init__(self, parent):
1530 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1532 self.AddText(_('This wizard will help you in leveling your printer bed'))
1534 self.AddText(_('It will do the following steps'))
1535 self.AddText(_('* Move the printer head to each corner'))
1536 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1537 self.AddText(_('* Print a line around the bed to check if it is level'))
1540 self.connectButton = self.AddButton(_('Connect to printer'))
1543 self.infoBox = self.AddInfoBox()
1544 self.resumeButton = self.AddButton(_('Resume'))
1545 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1546 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1547 self.resumeButton.Enable(False)
1549 self.upButton.Enable(False)
1550 self.downButton.Enable(False)
1551 self.upButton2.Enable(False)
1552 self.downButton2.Enable(False)
1554 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1555 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1556 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1557 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1558 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1559 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1561 def OnConnect(self, e = None):
1562 if self.comm is not None:
1566 wx.CallAfter(self.OnConnect)
1568 self.connectButton.Enable(False)
1569 self.comm = machineCom.MachineCom(callbackObject=self)
1570 self.infoBox.SetBusy(_('Connecting to machine.'))
1571 self._wizardState = 0
1573 def OnBedUp(self, e):
1574 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1575 self.comm.sendCommand('G92 Z10')
1576 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1577 self.comm.sendCommand('M400')
1579 def OnBedDown(self, e):
1580 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1581 self.comm.sendCommand('G92 Z10')
1582 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1583 self.comm.sendCommand('M400')
1585 def OnBedUp2(self, e):
1586 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1587 self.comm.sendCommand('G92 Z10')
1588 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1589 self.comm.sendCommand('M400')
1591 def OnBedDown2(self, e):
1592 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1593 self.comm.sendCommand('G92 Z10')
1594 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1595 self.comm.sendCommand('M400')
1597 def AllowNext(self):
1598 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1599 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1602 def OnResume(self, e):
1603 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1604 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1605 if self._wizardState == -1:
1606 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1607 wx.CallAfter(self.upButton.Enable, False)
1608 wx.CallAfter(self.downButton.Enable, False)
1609 wx.CallAfter(self.upButton2.Enable, False)
1610 wx.CallAfter(self.downButton2.Enable, False)
1611 self.comm.sendCommand('M105')
1612 self.comm.sendCommand('G28')
1613 self._wizardState = 1
1614 elif self._wizardState == 2:
1615 if profile.getMachineSetting('has_heated_bed') == 'True':
1616 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1617 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1618 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1619 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1620 self.comm.sendCommand('M400')
1621 self._wizardState = 3
1623 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1624 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1625 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1626 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1627 self.comm.sendCommand('M400')
1628 self._wizardState = 3
1629 elif self._wizardState == 4:
1630 if profile.getMachineSetting('has_heated_bed') == 'True':
1631 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1632 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1633 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1634 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1635 self.comm.sendCommand('M400')
1636 self._wizardState = 7
1638 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1639 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1640 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1641 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1642 self.comm.sendCommand('M400')
1643 self._wizardState = 5
1644 elif self._wizardState == 6:
1645 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1646 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1647 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1648 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1649 self.comm.sendCommand('M400')
1650 self._wizardState = 7
1651 elif self._wizardState == 8:
1652 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1653 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1654 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1655 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1656 self._wizardState = 9
1657 elif self._wizardState == 10:
1658 self._wizardState = 11
1659 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1660 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1661 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1662 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1663 w = profile.getMachineSettingFloat('machine_width') - 10
1664 d = profile.getMachineSettingFloat('machine_depth')
1665 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1666 filamentArea = math.pi * filamentRadius * filamentRadius
1667 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1671 'G1 Z2 F%d' % (feedZ),
1673 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1674 'G1 Z0.3 F%d' % (feedZ)]
1676 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1678 for i in xrange(0, 3):
1679 dist = 5.0 + 0.4 * float(i)
1680 eValue += (d - 2.0*dist) * ePerMM
1681 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1682 eValue += (w - 2.0*dist) * ePerMM
1683 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1684 eValue += (d - 2.0*dist) * ePerMM
1685 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1686 eValue += (w - 2.0*dist) * ePerMM
1687 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1689 gcodeList.append('M400')
1690 self.comm.printGCode(gcodeList)
1691 self.resumeButton.Enable(False)
1693 def mcLog(self, message):
1694 print 'Log:', message
1696 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1697 if self._wizardState == 1:
1698 self._wizardState = 2
1699 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1700 wx.CallAfter(self.resumeButton.Enable, True)
1701 elif self._wizardState == 3:
1702 self._wizardState = 4
1703 if profile.getMachineSetting('has_heated_bed') == 'True':
1704 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1706 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1707 wx.CallAfter(self.resumeButton.Enable, True)
1708 elif self._wizardState == 5:
1709 self._wizardState = 6
1710 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1711 wx.CallAfter(self.resumeButton.Enable, True)
1712 elif self._wizardState == 7:
1713 self._wizardState = 8
1714 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1715 wx.CallAfter(self.resumeButton.Enable, True)
1716 elif self._wizardState == 9:
1717 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1718 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1720 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1721 wx.CallAfter(self.resumeButton.Enable, True)
1722 self._wizardState = 10
1724 def mcStateChange(self, state):
1725 if self.comm is None:
1727 if self.comm.isOperational():
1728 if self._wizardState == 0:
1729 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1730 wx.CallAfter(self.upButton.Enable, True)
1731 wx.CallAfter(self.downButton.Enable, True)
1732 wx.CallAfter(self.upButton2.Enable, True)
1733 wx.CallAfter(self.downButton2.Enable, True)
1734 wx.CallAfter(self.resumeButton.Enable, True)
1735 self._wizardState = -1
1736 elif self._wizardState == 11 and not self.comm.isPrinting():
1737 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1738 self.comm.sendCommand('G92 E0')
1739 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1740 self.comm.sendCommand('M104 S0')
1741 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1742 wx.CallAfter(self.infoBox.SetReadyIndicator)
1743 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1744 wx.CallAfter(self.connectButton.Enable, True)
1745 self._wizardState = 12
1746 elif self.comm.isError():
1747 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1749 def mcMessage(self, message):
1752 def mcProgress(self, lineNr):
1755 def mcZChange(self, newZ):
1758 class headOffsetCalibrationPage(InfoPage):
1759 def __init__(self, parent):
1760 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1762 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1765 self.connectButton = self.AddButton(_('Connect to printer'))
1768 self.infoBox = self.AddInfoBox()
1769 self.textEntry = self.AddTextCtrl('')
1770 self.textEntry.Enable(False)
1771 self.resumeButton = self.AddButton(_('Resume'))
1772 self.resumeButton.Enable(False)
1774 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1775 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1777 def AllowBack(self):
1780 def OnConnect(self, e = None):
1781 if self.comm is not None:
1785 wx.CallAfter(self.OnConnect)
1787 self.connectButton.Enable(False)
1788 self.comm = machineCom.MachineCom(callbackObject=self)
1789 self.infoBox.SetBusy(_('Connecting to machine.'))
1790 self._wizardState = 0
1792 def OnResume(self, e):
1793 if self._wizardState == 2:
1794 self._wizardState = 3
1795 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1797 w = profile.getMachineSettingFloat('machine_width')
1798 d = profile.getMachineSettingFloat('machine_depth')
1800 gcode = gcodeGenerator.gcodeGenerator()
1801 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1802 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1809 gcode.addMove(w/2, 5)
1810 gcode.addMove(z=0.2)
1812 gcode.addExtrude(w/2, d-5.0)
1814 gcode.addMove(5, d/2)
1816 gcode.addExtrude(w-5.0, d/2)
1817 gcode.addRetract(15)
1820 gcode.addMove(w/2, 5)
1822 gcode.addExtrude(w/2, d-5.0)
1824 gcode.addMove(5, d/2)
1826 gcode.addExtrude(w-5.0, d/2)
1827 gcode.addRetract(15)
1832 gcode.addCmd('M400')
1834 self.comm.printGCode(gcode.list())
1835 self.resumeButton.Enable(False)
1836 elif self._wizardState == 4:
1838 float(self.textEntry.GetValue())
1841 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1842 self._wizardState = 5
1843 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1844 self.textEntry.SetValue('0.0')
1845 self.textEntry.Enable(True)
1846 elif self._wizardState == 5:
1848 float(self.textEntry.GetValue())
1851 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1852 self._wizardState = 6
1853 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1854 self.textEntry.SetValue('')
1855 self.textEntry.Enable(False)
1856 self.resumeButton.Enable(False)
1858 x = profile.getMachineSettingFloat('extruder_offset_x1')
1859 y = profile.getMachineSettingFloat('extruder_offset_y1')
1860 gcode = gcodeGenerator.gcodeGenerator()
1861 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1862 gcode.setPrintSpeed(25)
1865 gcode.addMove(50, 40, 0.2)
1867 for n in xrange(0, 10):
1868 gcode.addExtrude(50 + n * 10, 150)
1869 gcode.addExtrude(50 + n * 10 + 5, 150)
1870 gcode.addExtrude(50 + n * 10 + 5, 40)
1871 gcode.addExtrude(50 + n * 10 + 10, 40)
1872 gcode.addMove(40, 50)
1873 for n in xrange(0, 10):
1874 gcode.addExtrude(150, 50 + n * 10)
1875 gcode.addExtrude(150, 50 + n * 10 + 5)
1876 gcode.addExtrude(40, 50 + n * 10 + 5)
1877 gcode.addExtrude(40, 50 + n * 10 + 10)
1878 gcode.addRetract(15)
1881 gcode.addMove(50 - x, 30 - y, 0.2)
1883 for n in xrange(0, 10):
1884 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1885 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1886 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1887 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1888 gcode.addMove(30 - x, 50 - y, 0.2)
1889 for n in xrange(0, 10):
1890 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1891 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1892 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1893 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1894 gcode.addRetract(15)
1896 gcode.addCmd('M400')
1897 gcode.addCmd('M104 T0 S0')
1898 gcode.addCmd('M104 T1 S0')
1899 self.comm.printGCode(gcode.list())
1900 elif self._wizardState == 7:
1902 n = int(self.textEntry.GetValue()) - 1
1905 x = profile.getMachineSettingFloat('extruder_offset_x1')
1907 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1908 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1909 self.textEntry.SetValue('10')
1910 self._wizardState = 8
1911 elif self._wizardState == 8:
1913 n = int(self.textEntry.GetValue()) - 1
1916 y = profile.getMachineSettingFloat('extruder_offset_y1')
1918 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1919 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1920 self.infoBox.SetReadyIndicator()
1921 self._wizardState = 8
1923 self.resumeButton.Enable(False)
1925 def mcLog(self, message):
1926 print 'Log:', message
1928 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1929 if self._wizardState == 1:
1930 if temp[0] >= 210 and temp[1] >= 210:
1931 self._wizardState = 2
1932 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1933 wx.CallAfter(self.resumeButton.Enable, True)
1934 wx.CallAfter(self.resumeButton.SetFocus)
1936 def mcStateChange(self, state):
1937 if self.comm is None:
1939 if self.comm.isOperational():
1940 if self._wizardState == 0:
1941 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1942 self.comm.sendCommand('M105')
1943 self.comm.sendCommand('M104 S220 T0')
1944 self.comm.sendCommand('M104 S220 T1')
1945 self.comm.sendCommand('G28')
1946 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1947 self._wizardState = 1
1948 if not self.comm.isPrinting():
1949 if self._wizardState == 3:
1950 self._wizardState = 4
1951 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1952 wx.CallAfter(self.textEntry.SetValue, '0.0')
1953 wx.CallAfter(self.textEntry.Enable, True)
1954 wx.CallAfter(self.resumeButton.Enable, True)
1955 wx.CallAfter(self.resumeButton.SetFocus)
1956 elif self._wizardState == 6:
1957 self._wizardState = 7
1958 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1959 wx.CallAfter(self.textEntry.SetValue, '10')
1960 wx.CallAfter(self.textEntry.Enable, True)
1961 wx.CallAfter(self.resumeButton.Enable, True)
1962 wx.CallAfter(self.resumeButton.SetFocus)
1964 elif self.comm.isError():
1965 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1967 def mcMessage(self, message):
1970 def mcProgress(self, lineNr):
1973 def mcZChange(self, newZ):
1976 class bedLevelWizard(wx.wizard.Wizard):
1978 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1980 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1981 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1983 self.mainPage = bedLevelWizardMain(self)
1984 self.headOffsetCalibration = None
1986 self.RunWizard(self.mainPage)
1989 def OnPageChanging(self, e):
1990 e.GetPage().StoreData()
1992 def OnPageChanged(self, e):
1993 if e.GetPage().AllowNext():
1994 self.FindWindowById(wx.ID_FORWARD).Enable()
1996 self.FindWindowById(wx.ID_FORWARD).Disable()
1997 if e.GetPage().AllowBack():
1998 self.FindWindowById(wx.ID_BACKWARD).Enable()
2000 self.FindWindowById(wx.ID_BACKWARD).Disable()
2002 class headOffsetWizard(wx.wizard.Wizard):
2004 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
2006 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
2007 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
2009 self.mainPage = headOffsetCalibrationPage(self)
2011 self.RunWizard(self.mainPage)
2014 def OnPageChanging(self, e):
2015 e.GetPage().StoreData()
2017 def OnPageChanged(self, e):
2018 if e.GetPage().AllowNext():
2019 self.FindWindowById(wx.ID_FORWARD).Enable()
2021 self.FindWindowById(wx.ID_FORWARD).Disable()
2022 if e.GetPage().AllowBack():
2023 self.FindWindowById(wx.ID_BACKWARD).Enable()
2025 self.FindWindowById(wx.ID_BACKWARD).Disable()