1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
12 from Cura.gui import firmwareInstall
13 from Cura.gui import printWindow
14 from Cura.util import machineCom
15 from Cura.util import profile
16 from Cura.util import gcodeGenerator
17 from Cura.util import resources
20 class InfoBox(wx.Panel):
21 def __init__(self, parent):
22 super(InfoBox, self).__init__(parent)
23 self.SetBackgroundColour('#FFFF80')
25 self.sizer = wx.GridBagSizer(5, 5)
26 self.SetSizer(self.sizer)
28 self.attentionBitmap = wx.Bitmap(resources.getPathForImage('attention.png'))
29 self.errorBitmap = wx.Bitmap(resources.getPathForImage('error.png'))
30 self.readyBitmap = wx.Bitmap(resources.getPathForImage('ready.png'))
32 wx.Bitmap(resources.getPathForImage('busy-0.png')),
33 wx.Bitmap(resources.getPathForImage('busy-1.png')),
34 wx.Bitmap(resources.getPathForImage('busy-2.png')),
35 wx.Bitmap(resources.getPathForImage('busy-3.png'))
38 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
39 self.text = wx.StaticText(self, -1, '')
40 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
41 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
42 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
43 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
44 self.sizer.AddGrowableCol(1)
46 self.extraInfoButton.Show(False)
48 self.extraInfoUrl = ''
50 self.timer = wx.Timer(self)
51 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
52 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
55 def SetInfo(self, info):
56 self.SetBackgroundColour('#FFFF80')
57 self.text.SetLabel(info)
58 self.extraInfoButton.Show(False)
61 def SetError(self, info, extraInfoUrl):
62 self.extraInfoUrl = extraInfoUrl
63 self.SetBackgroundColour('#FF8080')
64 self.text.SetLabel(info)
65 self.extraInfoButton.Show(True)
67 self.SetErrorIndicator()
70 def SetAttention(self, info):
71 self.SetBackgroundColour('#FFFF80')
72 self.text.SetLabel(info)
73 self.extraInfoButton.Show(False)
74 self.SetAttentionIndicator()
78 def SetBusy(self, info):
80 self.SetBusyIndicator()
82 def SetBusyIndicator(self):
84 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
86 def doExtraInfo(self, e):
87 webbrowser.open(self.extraInfoUrl)
89 def doBusyUpdate(self, e):
90 if self.busyState is None:
93 if self.busyState >= len(self.busyBitmap):
95 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
97 def SetReadyIndicator(self):
99 self.bitmap.SetBitmap(self.readyBitmap)
101 def SetErrorIndicator(self):
102 self.busyState = None
103 self.bitmap.SetBitmap(self.errorBitmap)
105 def SetAttentionIndicator(self):
106 self.busyState = None
107 self.bitmap.SetBitmap(self.attentionBitmap)
110 class InfoPage(wx.wizard.WizardPageSimple):
111 def __init__(self, parent, title):
112 wx.wizard.WizardPageSimple.__init__(self, parent)
114 sizer = wx.GridBagSizer(5, 5)
118 title = wx.StaticText(self, -1, title)
119 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
120 sizer.Add(title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
121 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
122 sizer.AddGrowableCol(1)
126 def AddText(self, info):
127 text = wx.StaticText(self, -1, info)
128 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
132 def AddSeperator(self):
133 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
136 def AddHiddenSeperator(self):
139 def AddInfoBox(self):
140 infoBox = InfoBox(self)
141 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
145 def AddRadioButton(self, label, style=0):
146 radio = wx.RadioButton(self, -1, label, style=style)
147 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
151 def AddCheckbox(self, label, checked=False):
152 check = wx.CheckBox(self, -1)
153 text = wx.StaticText(self, -1, label)
154 check.SetValue(checked)
155 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
156 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
160 def AddButton(self, label):
161 button = wx.Button(self, -1, label)
162 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
166 def AddDualButton(self, label1, label2):
167 button1 = wx.Button(self, -1, label1)
168 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
169 button2 = wx.Button(self, -1, label2)
170 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
172 return button1, button2
174 def AddTextCtrl(self, value):
175 ret = wx.TextCtrl(self, -1, value)
176 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
180 def AddLabelTextCtrl(self, info, value):
181 text = wx.StaticText(self, -1, info)
182 ret = wx.TextCtrl(self, -1, value)
183 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
184 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
188 def AddTextCtrlButton(self, value, buttonText):
189 text = wx.TextCtrl(self, -1, value)
190 button = wx.Button(self, -1, buttonText)
191 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
192 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
196 def AddBitmap(self, bitmap):
197 bitmap = wx.StaticBitmap(self, -1, bitmap)
198 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
202 def AddCheckmark(self, label, bitmap):
203 check = wx.StaticBitmap(self, -1, bitmap)
204 text = wx.StaticText(self, -1, label)
205 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
206 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
210 def AddCombo(self, label, options):
211 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
212 text = wx.StaticText(self, -1, label)
213 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
214 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
227 class PrintrbotPage(InfoPage):
228 def __init__(self, parent):
229 self._printer_info = [
230 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
231 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
232 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
233 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
234 (":" + _("Older models"),),
235 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
236 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
237 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
238 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
239 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
240 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
241 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
242 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
243 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
244 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
245 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
246 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
247 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
250 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
251 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
252 self.AddText(_("Select which Printrbot machine you have:"))
254 for printer in self._printer_info:
255 if printer[0].startswith(":"):
257 self.AddText(printer[0][1:])
259 item = self.AddRadioButton(printer[0])
260 item.data = printer[1:]
261 self._items.append(item)
264 profile.putMachineSetting('machine_name', 'Printrbot ???')
265 for item in self._items:
268 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
269 profile.putMachineSetting('machine_width', data[0])
270 profile.putMachineSetting('machine_depth', data[1])
271 profile.putMachineSetting('machine_height', data[2])
272 profile.putProfileSetting('nozzle_size', data[3])
273 profile.putProfileSetting('filament_diameter', data[4])
274 profile.putProfileSetting('print_temperature', data[5])
275 profile.putProfileSetting('print_speed', data[6])
276 profile.putProfileSetting('travel_speed', data[7])
277 profile.putProfileSetting('retraction_speed', data[8])
278 profile.putProfileSetting('retraction_amount', data[9])
279 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
280 profile.putMachineSetting('has_heated_bed', 'False')
281 profile.putMachineSetting('machine_center_is_zero', 'False')
282 profile.putMachineSetting('extruder_head_size_min_x', '0')
283 profile.putMachineSetting('extruder_head_size_min_y', '0')
284 profile.putMachineSetting('extruder_head_size_max_x', '0')
285 profile.putMachineSetting('extruder_head_size_max_y', '0')
286 profile.putMachineSetting('extruder_head_size_height', '0')
288 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
289 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
290 ;Print time: {print_time}
291 ;Filament used: {filament_amount}m {filament_weight}g
292 ;Filament cost: {filament_cost}
293 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
294 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
296 G90 ;absolute positioning
297 M82 ;set extruder to absolute mode
298 M107 ;start with the fan off
299 G28 X0 Y0 ;move X/Y to min endstops
300 G28 Z0 ;move Z to min endstops
301 G29 ;Run the auto bed leveling
302 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
303 G92 E0 ;zero the extruded length
304 G1 F200 E3 ;extrude 3mm of feed stock
305 G92 E0 ;zero the extruded length again
307 ;Put printing message on LCD screen
311 class OtherMachineSelectPage(InfoPage):
312 def __init__(self, parent):
313 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
314 self.AddText(_("The following pre-defined machine profiles are available"))
315 self.AddText(_("Note that these profiles are not guaranteed to give good results,\nor work at all. Extra tweaks might be required.\nIf you find issues with the predefined profiles,\nor want an extra profile.\nPlease report it at the github issue tracker."))
317 machines = resources.getDefaultMachineProfiles()
319 for filename in machines:
320 name = os.path.splitext(os.path.basename(filename))[0]
321 item = self.AddRadioButton(name)
322 item.filename = filename
323 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
324 self.options.append(item)
326 item = self.AddRadioButton(_('Custom...'))
328 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
330 def OnProfileSelect(self, e):
331 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
333 def OnOtherSelect(self, e):
334 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
337 for option in self.options:
338 if option.GetValue():
339 profile.loadProfile(option.filename)
340 profile.loadMachineSettings(option.filename)
342 class OtherMachineInfoPage(InfoPage):
343 def __init__(self, parent):
344 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
345 self.AddText(_("Cura is now ready to be used!"))
347 class CustomRepRapInfoPage(InfoPage):
348 def __init__(self, parent):
349 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
350 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
351 self.AddText(_("Be sure to review the default profile before running it on your machine."))
352 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
354 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
356 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
357 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
358 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
359 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
360 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
361 self.heatedBed = self.AddCheckbox(_("Heated bed"))
362 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
365 profile.putMachineSetting('machine_name', self.machineName.GetValue())
366 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
367 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
368 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
369 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
370 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
371 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
372 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
373 profile.putMachineSetting('extruder_head_size_min_x', '0')
374 profile.putMachineSetting('extruder_head_size_min_y', '0')
375 profile.putMachineSetting('extruder_head_size_max_x', '0')
376 profile.putMachineSetting('extruder_head_size_max_y', '0')
377 profile.putMachineSetting('extruder_head_size_height', '0')
378 profile.checkAndUpdateMachineName()
380 class MachineSelectPage(InfoPage):
381 def __init__(self, parent):
382 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
383 self.AddText(_("What kind of machine do you have:"))
385 self.LulzbotMiniRadio = self.AddRadioButton("LulzBot Mini", style=wx.RB_GROUP)
386 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
387 self.LulzbotMiniRadio.SetValue(True)
388 self.LulzbotTaz5Radio = self.AddRadioButton("LulzBot TAZ 5")
389 self.LulzbotTaz5Radio.Bind(wx.EVT_RADIOBUTTON, self.OnTaz5Select)
390 self.LulzbotTaz4Radio = self.AddRadioButton("LulzBot TAZ 4")
391 self.LulzbotTaz4Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
392 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
393 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
394 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
395 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
396 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
397 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
398 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
399 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
400 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
401 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
402 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
403 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
404 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
405 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
407 def OnUltimaker2Select(self, e):
408 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
410 def OnUltimakerSelect(self, e):
411 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
413 def OnUltimakerOPSelect(self, e):
414 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
416 def OnPrintrbotSelect(self, e):
417 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
419 def OnLulzbotSelect(self, e):
420 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
422 def OnTaz5Select(self, e):
423 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().taz5NozzleSelectPage)
424 wx.wizard.WizardPageSimple.Chain(self.GetParent().taz5NozzleSelectPage, self.GetParent().lulzbotReadyPage)
426 def OnOtherSelect(self, e):
427 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
436 profile.putProfileSetting('retraction_enable', 'True')
437 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
438 if self.Ultimaker2Radio.GetValue():
439 profile.putMachineSetting('machine_width', '230')
440 profile.putMachineSetting('machine_depth', '225')
441 profile.putMachineSetting('machine_height', '205')
442 profile.putMachineSetting('machine_name', 'ultimaker2')
443 profile.putMachineSetting('machine_type', 'ultimaker2')
444 profile.putMachineSetting('has_heated_bed', 'True')
445 if self.Ultimaker2GoRadio.GetValue():
446 profile.putMachineSetting('machine_width', '120')
447 profile.putMachineSetting('machine_depth', '120')
448 profile.putMachineSetting('machine_height', '115')
449 profile.putMachineSetting('machine_name', 'ultimaker2go')
450 profile.putMachineSetting('machine_type', 'ultimaker2go')
451 profile.putMachineSetting('has_heated_bed', 'False')
452 if self.Ultimaker2ExtRadio.GetValue():
453 profile.putMachineSetting('machine_width', '230')
454 profile.putMachineSetting('machine_depth', '225')
455 profile.putMachineSetting('machine_height', '315')
456 profile.putMachineSetting('machine_name', 'ultimaker2extended')
457 profile.putMachineSetting('machine_type', 'ultimaker2extended')
458 profile.putMachineSetting('has_heated_bed', 'False')
459 profile.putMachineSetting('machine_center_is_zero', 'False')
460 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
461 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
462 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
463 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
464 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
465 profile.putMachineSetting('extruder_head_size_height', '48.0')
466 profile.putProfileSetting('nozzle_size', '0.4')
467 profile.putProfileSetting('fan_full_height', '5.0')
468 profile.putMachineSetting('extruder_offset_x1', '18.0')
469 profile.putMachineSetting('extruder_offset_y1', '0.0')
470 elif self.UltimakerRadio.GetValue():
471 profile.putMachineSetting('machine_width', '205')
472 profile.putMachineSetting('machine_depth', '205')
473 profile.putMachineSetting('machine_height', '200')
474 profile.putMachineSetting('machine_name', 'ultimaker original')
475 profile.putMachineSetting('machine_type', 'ultimaker')
476 profile.putMachineSetting('machine_center_is_zero', 'False')
477 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
478 profile.putProfileSetting('nozzle_size', '0.4')
479 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
480 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
481 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
482 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
483 profile.putMachineSetting('extruder_head_size_height', '55.0')
484 elif self.UltimakerOPRadio.GetValue():
485 profile.putMachineSetting('machine_width', '205')
486 profile.putMachineSetting('machine_depth', '205')
487 profile.putMachineSetting('machine_height', '200')
488 profile.putMachineSetting('machine_name', 'ultimaker original+')
489 profile.putMachineSetting('machine_type', 'ultimaker_plus')
490 profile.putMachineSetting('machine_center_is_zero', 'False')
491 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
492 profile.putProfileSetting('nozzle_size', '0.4')
493 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
494 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
495 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
496 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
497 profile.putMachineSetting('extruder_head_size_height', '55.0')
498 profile.putMachineSetting('has_heated_bed', 'True')
499 profile.putMachineSetting('extruder_amount', '1')
500 profile.putProfileSetting('retraction_enable', 'True')
501 elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
502 if self.LulzbotTaz4Radio.GetValue():
503 profile.putMachineSetting('machine_width', '298')
504 profile.putMachineSetting('machine_depth', '275')
505 profile.putMachineSetting('machine_height', '250')
506 profile.putProfileSetting('nozzle_size', '0.35')
507 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
508 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
509 profile.putMachineSetting('serial_baud', '115200')
510 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
511 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
512 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
513 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
514 profile.putMachineSetting('extruder_head_size_height', '0.0')
515 elif self.LulzbotTaz5Radio.GetValue():
516 profile.putMachineSetting('machine_width', '298')
517 profile.putMachineSetting('machine_depth', '275')
518 profile.putMachineSetting('machine_height', '250')
519 profile.putMachineSetting('serial_baud', '115200')
520 # Machine type and name are set in the nozzle select page
521 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
522 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
523 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
524 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
525 profile.putMachineSetting('extruder_head_size_height', '0.0')
527 profile.putMachineSetting('machine_width', '155')
528 profile.putMachineSetting('machine_depth', '155')
529 profile.putMachineSetting('machine_height', '163')
530 profile.putProfileSetting('nozzle_size', '0.5')
531 profile.putMachineSetting('machine_name', 'LulzBot Mini')
532 profile.putMachineSetting('machine_type', 'lulzbot_mini')
533 profile.putMachineSetting('serial_baud', '115200')
534 profile.putMachineSetting('extruder_head_size_min_x', '40')
535 profile.putMachineSetting('extruder_head_size_max_x', '75')
536 profile.putMachineSetting('extruder_head_size_min_y', '25')
537 profile.putMachineSetting('extruder_head_size_max_y', '55')
538 profile.putMachineSetting('extruder_head_size_height', '17')
539 profile.putMachineSetting('machine_center_is_zero', 'False')
540 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
541 profile.putMachineSetting('has_heated_bed', 'True')
542 profile.putPreference('startMode', 'Simple')
544 profile.putMachineSetting('machine_width', '80')
545 profile.putMachineSetting('machine_depth', '80')
546 profile.putMachineSetting('machine_height', '60')
547 profile.putMachineSetting('machine_name', 'reprap')
548 profile.putMachineSetting('machine_type', 'reprap')
549 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
550 profile.putPreference('startMode', 'Normal')
551 profile.putProfileSetting('nozzle_size', '0.5')
552 profile.checkAndUpdateMachineName()
553 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
555 class SelectParts(InfoPage):
556 def __init__(self, parent):
557 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
558 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."))
560 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
561 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
562 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
563 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
565 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."))
566 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
567 self.springExtruder.SetValue(True)
570 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
571 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
572 profile.putMachineSetting('has_heated_bed', 'True')
574 profile.putMachineSetting('has_heated_bed', 'False')
575 if self.dualExtrusion.GetValue():
576 profile.putMachineSetting('extruder_amount', '2')
577 profile.putMachineSetting('machine_depth', '195')
579 profile.putMachineSetting('extruder_amount', '1')
580 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
581 profile.putProfileSetting('retraction_enable', 'True')
583 profile.putProfileSetting('retraction_enable', 'False')
586 class UltimakerFirmwareUpgradePage(InfoPage):
587 def __init__(self, parent):
588 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
589 self.AddText(_("Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the step motors, regulates the temperature\nand ultimately makes your printer work."))
590 self.AddHiddenSeperator()
591 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
592 self.AddHiddenSeperator()
593 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."))
594 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
595 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
596 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
597 self.AddHiddenSeperator()
598 if profile.getMachineSetting('machine_type') == 'ultimaker':
599 self.AddText(_("Do not upgrade to this firmware if:"))
600 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
601 self.AddText(_("* Build your own heated bed"))
602 self.AddText(_("* Have other changes in the firmware"))
603 # button = self.AddButton('Goto this page for a custom firmware')
604 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
609 def OnUpgradeClick(self, e):
610 if firmwareInstall.InstallFirmware():
611 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
613 def OnSkipClick(self, e):
614 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
615 self.GetParent().ShowPage(self.GetNext())
617 def OnUrlClick(self, e):
618 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
620 class UltimakerCheckupPage(InfoPage):
621 def __init__(self, parent):
622 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
624 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
625 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
626 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
627 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
628 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
629 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
630 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
631 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
632 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
633 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
636 _("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."))
637 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
638 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
639 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
641 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
642 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
643 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
645 self.infoBox = self.AddInfoBox()
646 self.machineState = self.AddText("")
647 self.temperatureLabel = self.AddText("")
648 self.errorLogButton = self.AddButton(_("Show error log"))
649 self.errorLogButton.Show(False)
651 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
653 self.xMinStop = False
654 self.xMaxStop = False
655 self.yMinStop = False
656 self.yMaxStop = False
657 self.zMinStop = False
658 self.zMaxStop = False
660 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
663 if self.comm is not None:
667 self.endstopBitmap.Show(False)
670 def OnSkipClick(self, e):
671 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
672 self.GetParent().ShowPage(self.GetNext())
674 def OnCheckClick(self, e=None):
675 self.errorLogButton.Show(False)
676 if self.comm is not None:
680 wx.CallAfter(self.OnCheckClick)
682 self.infoBox.SetBusy(_("Connecting to machine."))
683 self.commState.SetBitmap(self.unknownBitmap)
684 self.tempState.SetBitmap(self.unknownBitmap)
685 self.stopState.SetBitmap(self.unknownBitmap)
686 self.checkupState = 0
687 self.checkExtruderNr = 0
688 self.comm = machineCom.MachineCom(callbackObject=self)
690 def OnErrorLog(self, e):
691 printWindow.LogWindow('\n'.join(self.comm.getLog()))
693 def mcLog(self, message):
696 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
697 if not self.comm.isOperational():
699 if self.checkupState == 0:
700 self.tempCheckTimeout = 20
701 if temp[self.checkExtruderNr] > 70:
702 self.checkupState = 1
703 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
704 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
705 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
707 self.startTemp = temp[self.checkExtruderNr]
708 self.checkupState = 2
709 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
710 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
711 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
712 elif self.checkupState == 1:
713 if temp[self.checkExtruderNr] < 60:
714 self.startTemp = temp[self.checkExtruderNr]
715 self.checkupState = 2
716 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
717 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
718 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
719 elif self.checkupState == 2:
720 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
721 if temp[self.checkExtruderNr] > self.startTemp + 40:
722 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
723 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
724 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
725 self.checkExtruderNr = 0
726 self.checkupState = 3
727 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
728 wx.CallAfter(self.endstopBitmap.Show, True)
729 wx.CallAfter(self.Layout)
730 self.comm.sendCommand('M119')
731 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
733 self.checkupState = 0
734 self.checkExtruderNr += 1
736 self.tempCheckTimeout -= 1
737 if self.tempCheckTimeout < 1:
738 self.checkupState = -1
739 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
740 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
741 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
742 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
743 elif self.checkupState >= 3 and self.checkupState < 10:
744 self.comm.sendCommand('M119')
745 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
747 def mcStateChange(self, state):
748 if self.comm is None:
750 if self.comm.isOperational():
751 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
752 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
753 elif self.comm.isError():
754 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
755 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
756 wx.CallAfter(self.endstopBitmap.Show, False)
757 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
758 wx.CallAfter(self.errorLogButton.Show, True)
759 wx.CallAfter(self.Layout)
761 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
763 def mcMessage(self, message):
764 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
765 for data in message.split(' '):
767 tag, value = data.split(':', 1)
769 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
771 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
773 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
775 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
777 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
779 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
781 tag, value = map(str.strip, message.split(':', 1))
783 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
785 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
787 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
789 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
791 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
793 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
794 if 'z_max' in message:
795 self.comm.sendCommand('M119')
797 if self.checkupState == 3:
798 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
799 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
800 self.checkupState = 5
801 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
802 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
804 self.checkupState = 4
805 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
806 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
807 elif self.checkupState == 4:
808 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
809 self.checkupState = 5
810 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
811 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
812 elif self.checkupState == 5:
813 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
814 self.checkupState = 6
815 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
816 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
817 elif self.checkupState == 6:
818 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
819 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
820 self.checkupState = 8
821 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
822 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
824 self.checkupState = 7
825 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
826 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
827 elif self.checkupState == 7:
828 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
829 self.checkupState = 8
830 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
831 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
832 elif self.checkupState == 8:
833 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
834 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
835 self.checkupState = 10
837 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
838 wx.CallAfter(self.infoBox.SetReadyIndicator)
839 wx.CallAfter(self.endstopBitmap.Show, False)
840 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
841 wx.CallAfter(self.OnSkipClick, None)
843 self.checkupState = 9
844 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
845 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
846 elif self.checkupState == 9:
847 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
848 self.checkupState = 10
850 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
851 wx.CallAfter(self.infoBox.SetReadyIndicator)
852 wx.CallAfter(self.endstopBitmap.Show, False)
853 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
854 wx.CallAfter(self.OnSkipClick, None)
856 def mcProgress(self, lineNr):
859 def mcZChange(self, newZ):
863 class UltimakerCalibrationPage(InfoPage):
864 def __init__(self, parent):
865 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
867 self.AddText("Your Ultimaker requires some calibration.")
868 self.AddText("This calibration is needed for a proper extrusion amount.")
870 self.AddText("The following values are needed:")
871 self.AddText("* Diameter of filament")
872 self.AddText("* Number of steps per mm of filament extrusion")
874 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
876 self.AddText("First we need the diameter of your filament:")
877 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
879 "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.")
880 self.AddText("Note: This value can be changed later at any time.")
883 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
886 class UltimakerCalibrateStepsPerEPage(InfoPage):
887 def __init__(self, parent):
888 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
890 #if profile.getMachineSetting('steps_per_e') == '0':
891 # profile.putMachineSetting('steps_per_e', '865.888')
893 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
894 self.AddText(_("First remove any filament from your machine."))
895 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
896 self.AddText(_("We'll push the filament 100mm"))
897 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
898 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
899 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
900 self.AddText(_("This results in the following steps per E:"))
901 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
902 self.AddText(_("You can repeat these steps to get better calibration."))
905 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
906 self.heatButton = self.AddButton(_("Heatup for filament removal"))
908 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
909 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
910 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
912 def OnSaveLengthClick(self, e):
913 currentEValue = float(self.stepsPerEInput.GetValue())
914 realExtrudeLength = float(self.lengthInput.GetValue())
915 newEValue = currentEValue * 100 / realExtrudeLength
916 self.stepsPerEInput.SetValue(str(newEValue))
917 self.lengthInput.SetValue("100")
919 def OnExtrudeClick(self, e):
920 t = threading.Thread(target=self.OnExtrudeRun)
924 def OnExtrudeRun(self):
925 self.heatButton.Enable(False)
926 self.extrudeButton.Enable(False)
927 currentEValue = float(self.stepsPerEInput.GetValue())
928 self.comm = machineCom.MachineCom()
929 if not self.comm.isOpen():
931 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
932 'Printer error', wx.OK | wx.ICON_INFORMATION)
933 self.heatButton.Enable(True)
934 self.extrudeButton.Enable(True)
937 line = self.comm.readline()
942 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
945 self.sendGCommand('M302') #Disable cold extrusion protection
946 self.sendGCommand("M92 E%f" % (currentEValue))
947 self.sendGCommand("G92 E0")
948 self.sendGCommand("G1 E100 F600")
951 self.extrudeButton.Enable()
952 self.heatButton.Enable()
954 def OnHeatClick(self, e):
955 t = threading.Thread(target=self.OnHeatRun)
960 self.heatButton.Enable(False)
961 self.extrudeButton.Enable(False)
962 self.comm = machineCom.MachineCom()
963 if not self.comm.isOpen():
965 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
966 'Printer error', wx.OK | wx.ICON_INFORMATION)
967 self.heatButton.Enable(True)
968 self.extrudeButton.Enable(True)
971 line = self.comm.readline()
973 self.heatButton.Enable(True)
974 self.extrudeButton.Enable(True)
978 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
981 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
983 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
984 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
985 self.sendGCommand('M104 S0')
988 self.heatButton.Enable(True)
989 self.extrudeButton.Enable(True)
991 def sendGCommand(self, cmd):
992 self.comm.sendCommand(cmd) #Disable cold extrusion protection
994 line = self.comm.readline()
997 if line.startswith('ok'):
1000 def StoreData(self):
1001 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1003 class Ultimaker2ReadyPage(InfoPage):
1004 def __init__(self, parent):
1005 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1006 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1007 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1010 class LulzbotReadyPage(InfoPage):
1011 def __init__(self, parent):
1012 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1013 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1015 self.AddText(_('For more information about using Cura with your LulzBot'))
1016 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1019 class Taz5NozzleSelectPage(InfoPage):
1020 url='http://lulzbot.com/printer-identification'
1022 def __init__(self, parent):
1023 super(Taz5NozzleSelectPage, self).__init__(parent, _("LulzBot TAZ5"))
1024 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1026 self.AddText(_(' '))
1027 self.AddText(_('Please select nozzle size:'))
1028 self.Nozzle35Radio = self.AddRadioButton("0.35 mm", style=wx.RB_GROUP)
1029 self.Nozzle35Radio.SetValue(True)
1030 self.Nozzle50Radio = self.AddRadioButton("0.5 mm")
1031 self.AddText(_(' '))
1034 self.AddText(_('If you are not sure which nozzle size you have'))
1035 self.AddText(_('please check this webpage: '))
1036 button = self.AddButton(Taz5NozzleSelectPage.url)
1037 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
1039 def OnUrlClick(self, e):
1040 webbrowser.open(Taz5NozzleSelectPage.url)
1042 def StoreData(self):
1043 if self.Nozzle35Radio.GetValue():
1044 profile.putProfileSetting('nozzle_size', '0.35')
1045 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5 (0.35 nozzle)')
1046 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
1049 profile.putProfileSetting('nozzle_size', '0.5')
1050 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5 (0.5 nozzle)')
1051 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5_05nozzle')
1053 def OnPageChanging(self, e):
1054 e.GetPage().StoreData()
1056 class ConfigWizard(wx.wizard.Wizard):
1057 def __init__(self, addNew = False):
1058 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1060 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1062 profile.setActiveMachine(profile.getMachineCount())
1064 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1065 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1066 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1068 self.machineSelectPage = MachineSelectPage(self)
1069 self.ultimakerSelectParts = SelectParts(self)
1070 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1071 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1072 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1073 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1074 self.bedLevelPage = bedLevelWizardMain(self)
1075 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1076 self.printrbotSelectType = PrintrbotPage(self)
1077 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1078 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1079 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1081 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1082 self.lulzbotReadyPage = LulzbotReadyPage(self)
1083 self.taz5NozzleSelectPage = Taz5NozzleSelectPage(self)
1085 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1086 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1087 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1088 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1089 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1090 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1091 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1092 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1093 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.lulzbotReadyPage)
1095 self.FitToPage(self.machineSelectPage)
1096 self.GetPageAreaSizer().Add(self.machineSelectPage)
1098 self.RunWizard(self.machineSelectPage)
1101 def OnPageChanging(self, e):
1102 e.GetPage().StoreData()
1104 def OnPageChanged(self, e):
1105 if e.GetPage().AllowNext():
1106 self.FindWindowById(wx.ID_FORWARD).Enable()
1108 self.FindWindowById(wx.ID_FORWARD).Disable()
1109 if e.GetPage().AllowBack():
1110 self.FindWindowById(wx.ID_BACKWARD).Enable()
1112 self.FindWindowById(wx.ID_BACKWARD).Disable()
1114 def OnCancel(self, e):
1115 new_machine_index = int(profile.getPreferenceFloat('active_machine'))
1116 profile.setActiveMachine(self._old_machine_index)
1117 profile.removeMachine(new_machine_index)
1119 class bedLevelWizardMain(InfoPage):
1120 def __init__(self, parent):
1121 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1123 self.AddText(_('This wizard will help you in leveling your printer bed'))
1125 self.AddText(_('It will do the following steps'))
1126 self.AddText(_('* Move the printer head to each corner'))
1127 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1128 self.AddText(_('* Print a line around the bed to check if it is level'))
1131 self.connectButton = self.AddButton(_('Connect to printer'))
1134 self.infoBox = self.AddInfoBox()
1135 self.resumeButton = self.AddButton(_('Resume'))
1136 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1137 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1138 self.resumeButton.Enable(False)
1140 self.upButton.Enable(False)
1141 self.downButton.Enable(False)
1142 self.upButton2.Enable(False)
1143 self.downButton2.Enable(False)
1145 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1146 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1147 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1148 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1149 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1150 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1152 def OnConnect(self, e = None):
1153 if self.comm is not None:
1157 wx.CallAfter(self.OnConnect)
1159 self.connectButton.Enable(False)
1160 self.comm = machineCom.MachineCom(callbackObject=self)
1161 self.infoBox.SetBusy(_('Connecting to machine.'))
1162 self._wizardState = 0
1164 def OnBedUp(self, e):
1165 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1166 self.comm.sendCommand('G92 Z10')
1167 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1168 self.comm.sendCommand('M400')
1170 def OnBedDown(self, e):
1171 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1172 self.comm.sendCommand('G92 Z10')
1173 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1174 self.comm.sendCommand('M400')
1176 def OnBedUp2(self, e):
1177 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1178 self.comm.sendCommand('G92 Z10')
1179 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1180 self.comm.sendCommand('M400')
1182 def OnBedDown2(self, e):
1183 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1184 self.comm.sendCommand('G92 Z10')
1185 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1186 self.comm.sendCommand('M400')
1188 def AllowNext(self):
1189 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1190 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1193 def OnResume(self, e):
1194 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1195 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1196 if self._wizardState == -1:
1197 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1198 wx.CallAfter(self.upButton.Enable, False)
1199 wx.CallAfter(self.downButton.Enable, False)
1200 wx.CallAfter(self.upButton2.Enable, False)
1201 wx.CallAfter(self.downButton2.Enable, False)
1202 self.comm.sendCommand('M105')
1203 self.comm.sendCommand('G28')
1204 self._wizardState = 1
1205 elif self._wizardState == 2:
1206 if profile.getMachineSetting('has_heated_bed') == 'True':
1207 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1208 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1209 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1210 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1211 self.comm.sendCommand('M400')
1212 self._wizardState = 3
1214 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1215 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1216 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1217 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1218 self.comm.sendCommand('M400')
1219 self._wizardState = 3
1220 elif self._wizardState == 4:
1221 if profile.getMachineSetting('has_heated_bed') == 'True':
1222 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1223 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1224 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1225 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1226 self.comm.sendCommand('M400')
1227 self._wizardState = 7
1229 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1230 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1231 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1232 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1233 self.comm.sendCommand('M400')
1234 self._wizardState = 5
1235 elif self._wizardState == 6:
1236 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1237 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1238 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1239 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1240 self.comm.sendCommand('M400')
1241 self._wizardState = 7
1242 elif self._wizardState == 8:
1243 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1244 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1245 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1246 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1247 self._wizardState = 9
1248 elif self._wizardState == 10:
1249 self._wizardState = 11
1250 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1251 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1252 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1253 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1254 w = profile.getMachineSettingFloat('machine_width') - 10
1255 d = profile.getMachineSettingFloat('machine_depth')
1256 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1257 filamentArea = math.pi * filamentRadius * filamentRadius
1258 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1262 'G1 Z2 F%d' % (feedZ),
1264 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1265 'G1 Z0.3 F%d' % (feedZ)]
1267 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1269 for i in xrange(0, 3):
1270 dist = 5.0 + 0.4 * float(i)
1271 eValue += (d - 2.0*dist) * ePerMM
1272 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1273 eValue += (w - 2.0*dist) * ePerMM
1274 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1275 eValue += (d - 2.0*dist) * ePerMM
1276 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1277 eValue += (w - 2.0*dist) * ePerMM
1278 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1280 gcodeList.append('M400')
1281 self.comm.printGCode(gcodeList)
1282 self.resumeButton.Enable(False)
1284 def mcLog(self, message):
1285 print 'Log:', message
1287 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1288 if self._wizardState == 1:
1289 self._wizardState = 2
1290 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1291 wx.CallAfter(self.resumeButton.Enable, True)
1292 elif self._wizardState == 3:
1293 self._wizardState = 4
1294 if profile.getMachineSetting('has_heated_bed') == 'True':
1295 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1297 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1298 wx.CallAfter(self.resumeButton.Enable, True)
1299 elif self._wizardState == 5:
1300 self._wizardState = 6
1301 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1302 wx.CallAfter(self.resumeButton.Enable, True)
1303 elif self._wizardState == 7:
1304 self._wizardState = 8
1305 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1306 wx.CallAfter(self.resumeButton.Enable, True)
1307 elif self._wizardState == 9:
1308 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1309 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1311 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1312 wx.CallAfter(self.resumeButton.Enable, True)
1313 self._wizardState = 10
1315 def mcStateChange(self, state):
1316 if self.comm is None:
1318 if self.comm.isOperational():
1319 if self._wizardState == 0:
1320 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1321 wx.CallAfter(self.upButton.Enable, True)
1322 wx.CallAfter(self.downButton.Enable, True)
1323 wx.CallAfter(self.upButton2.Enable, True)
1324 wx.CallAfter(self.downButton2.Enable, True)
1325 wx.CallAfter(self.resumeButton.Enable, True)
1326 self._wizardState = -1
1327 elif self._wizardState == 11 and not self.comm.isPrinting():
1328 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1329 self.comm.sendCommand('G92 E0')
1330 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1331 self.comm.sendCommand('M104 S0')
1332 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1333 wx.CallAfter(self.infoBox.SetReadyIndicator)
1334 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1335 wx.CallAfter(self.connectButton.Enable, True)
1336 self._wizardState = 12
1337 elif self.comm.isError():
1338 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1340 def mcMessage(self, message):
1343 def mcProgress(self, lineNr):
1346 def mcZChange(self, newZ):
1349 class headOffsetCalibrationPage(InfoPage):
1350 def __init__(self, parent):
1351 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1353 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1356 self.connectButton = self.AddButton(_('Connect to printer'))
1359 self.infoBox = self.AddInfoBox()
1360 self.textEntry = self.AddTextCtrl('')
1361 self.textEntry.Enable(False)
1362 self.resumeButton = self.AddButton(_('Resume'))
1363 self.resumeButton.Enable(False)
1365 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1366 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1368 def AllowBack(self):
1371 def OnConnect(self, e = None):
1372 if self.comm is not None:
1376 wx.CallAfter(self.OnConnect)
1378 self.connectButton.Enable(False)
1379 self.comm = machineCom.MachineCom(callbackObject=self)
1380 self.infoBox.SetBusy(_('Connecting to machine.'))
1381 self._wizardState = 0
1383 def OnResume(self, e):
1384 if self._wizardState == 2:
1385 self._wizardState = 3
1386 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1388 w = profile.getMachineSettingFloat('machine_width')
1389 d = profile.getMachineSettingFloat('machine_depth')
1391 gcode = gcodeGenerator.gcodeGenerator()
1392 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1393 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1400 gcode.addMove(w/2, 5)
1401 gcode.addMove(z=0.2)
1403 gcode.addExtrude(w/2, d-5.0)
1405 gcode.addMove(5, d/2)
1407 gcode.addExtrude(w-5.0, d/2)
1408 gcode.addRetract(15)
1411 gcode.addMove(w/2, 5)
1413 gcode.addExtrude(w/2, d-5.0)
1415 gcode.addMove(5, d/2)
1417 gcode.addExtrude(w-5.0, d/2)
1418 gcode.addRetract(15)
1423 gcode.addCmd('M400')
1425 self.comm.printGCode(gcode.list())
1426 self.resumeButton.Enable(False)
1427 elif self._wizardState == 4:
1429 float(self.textEntry.GetValue())
1432 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1433 self._wizardState = 5
1434 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1435 self.textEntry.SetValue('0.0')
1436 self.textEntry.Enable(True)
1437 elif self._wizardState == 5:
1439 float(self.textEntry.GetValue())
1442 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1443 self._wizardState = 6
1444 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1445 self.textEntry.SetValue('')
1446 self.textEntry.Enable(False)
1447 self.resumeButton.Enable(False)
1449 x = profile.getMachineSettingFloat('extruder_offset_x1')
1450 y = profile.getMachineSettingFloat('extruder_offset_y1')
1451 gcode = gcodeGenerator.gcodeGenerator()
1452 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1453 gcode.setPrintSpeed(25)
1456 gcode.addMove(50, 40, 0.2)
1458 for n in xrange(0, 10):
1459 gcode.addExtrude(50 + n * 10, 150)
1460 gcode.addExtrude(50 + n * 10 + 5, 150)
1461 gcode.addExtrude(50 + n * 10 + 5, 40)
1462 gcode.addExtrude(50 + n * 10 + 10, 40)
1463 gcode.addMove(40, 50)
1464 for n in xrange(0, 10):
1465 gcode.addExtrude(150, 50 + n * 10)
1466 gcode.addExtrude(150, 50 + n * 10 + 5)
1467 gcode.addExtrude(40, 50 + n * 10 + 5)
1468 gcode.addExtrude(40, 50 + n * 10 + 10)
1469 gcode.addRetract(15)
1472 gcode.addMove(50 - x, 30 - y, 0.2)
1474 for n in xrange(0, 10):
1475 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1476 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1477 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1478 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1479 gcode.addMove(30 - x, 50 - y, 0.2)
1480 for n in xrange(0, 10):
1481 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1482 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1483 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1484 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1485 gcode.addRetract(15)
1487 gcode.addCmd('M400')
1488 gcode.addCmd('M104 T0 S0')
1489 gcode.addCmd('M104 T1 S0')
1490 self.comm.printGCode(gcode.list())
1491 elif self._wizardState == 7:
1493 n = int(self.textEntry.GetValue()) - 1
1496 x = profile.getMachineSettingFloat('extruder_offset_x1')
1498 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1499 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1500 self.textEntry.SetValue('10')
1501 self._wizardState = 8
1502 elif self._wizardState == 8:
1504 n = int(self.textEntry.GetValue()) - 1
1507 y = profile.getMachineSettingFloat('extruder_offset_y1')
1509 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1510 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1511 self.infoBox.SetReadyIndicator()
1512 self._wizardState = 8
1514 self.resumeButton.Enable(False)
1516 def mcLog(self, message):
1517 print 'Log:', message
1519 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1520 if self._wizardState == 1:
1521 if temp[0] >= 210 and temp[1] >= 210:
1522 self._wizardState = 2
1523 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1524 wx.CallAfter(self.resumeButton.Enable, True)
1525 wx.CallAfter(self.resumeButton.SetFocus)
1527 def mcStateChange(self, state):
1528 if self.comm is None:
1530 if self.comm.isOperational():
1531 if self._wizardState == 0:
1532 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1533 self.comm.sendCommand('M105')
1534 self.comm.sendCommand('M104 S220 T0')
1535 self.comm.sendCommand('M104 S220 T1')
1536 self.comm.sendCommand('G28')
1537 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1538 self._wizardState = 1
1539 if not self.comm.isPrinting():
1540 if self._wizardState == 3:
1541 self._wizardState = 4
1542 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1543 wx.CallAfter(self.textEntry.SetValue, '0.0')
1544 wx.CallAfter(self.textEntry.Enable, True)
1545 wx.CallAfter(self.resumeButton.Enable, True)
1546 wx.CallAfter(self.resumeButton.SetFocus)
1547 elif self._wizardState == 6:
1548 self._wizardState = 7
1549 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1550 wx.CallAfter(self.textEntry.SetValue, '10')
1551 wx.CallAfter(self.textEntry.Enable, True)
1552 wx.CallAfter(self.resumeButton.Enable, True)
1553 wx.CallAfter(self.resumeButton.SetFocus)
1555 elif self.comm.isError():
1556 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1558 def mcMessage(self, message):
1561 def mcProgress(self, lineNr):
1564 def mcZChange(self, newZ):
1567 class bedLevelWizard(wx.wizard.Wizard):
1569 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1571 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1572 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1574 self.mainPage = bedLevelWizardMain(self)
1575 self.headOffsetCalibration = None
1577 self.FitToPage(self.mainPage)
1578 self.GetPageAreaSizer().Add(self.mainPage)
1580 self.RunWizard(self.mainPage)
1583 def OnPageChanging(self, e):
1584 e.GetPage().StoreData()
1586 def OnPageChanged(self, e):
1587 if e.GetPage().AllowNext():
1588 self.FindWindowById(wx.ID_FORWARD).Enable()
1590 self.FindWindowById(wx.ID_FORWARD).Disable()
1591 if e.GetPage().AllowBack():
1592 self.FindWindowById(wx.ID_BACKWARD).Enable()
1594 self.FindWindowById(wx.ID_BACKWARD).Disable()
1596 class headOffsetWizard(wx.wizard.Wizard):
1598 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1600 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1601 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1603 self.mainPage = headOffsetCalibrationPage(self)
1605 self.FitToPage(self.mainPage)
1606 self.GetPageAreaSizer().Add(self.mainPage)
1608 self.RunWizard(self.mainPage)
1611 def OnPageChanging(self, e):
1612 e.GetPage().StoreData()
1614 def OnPageChanged(self, e):
1615 if e.GetPage().AllowNext():
1616 self.FindWindowById(wx.ID_FORWARD).Enable()
1618 self.FindWindowById(wx.ID_FORWARD).Disable()
1619 if e.GetPage().AllowBack():
1620 self.FindWindowById(wx.ID_BACKWARD).Enable()
1622 self.FindWindowById(wx.ID_BACKWARD).Disable()