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 parent.GetPageAreaSizer().Add(self)
115 sizer = wx.GridBagSizer(5, 5)
119 title = wx.StaticText(self, -1, title)
120 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
121 sizer.Add(title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
122 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
123 sizer.AddGrowableCol(1)
127 def AddText(self, info):
128 text = wx.StaticText(self, -1, info)
129 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
133 def AddSeperator(self):
134 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
137 def AddHiddenSeperator(self):
140 def AddInfoBox(self):
141 infoBox = InfoBox(self)
142 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
146 def AddRadioButton(self, label, style=0):
147 radio = wx.RadioButton(self, -1, label, style=style)
148 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
152 def AddCheckbox(self, label, checked=False):
153 check = wx.CheckBox(self, -1)
154 text = wx.StaticText(self, -1, label)
155 check.SetValue(checked)
156 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
157 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
161 def AddButton(self, label):
162 button = wx.Button(self, -1, label)
163 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
167 def AddDualButton(self, label1, label2):
168 button1 = wx.Button(self, -1, label1)
169 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
170 button2 = wx.Button(self, -1, label2)
171 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
173 return button1, button2
175 def AddTextCtrl(self, value):
176 ret = wx.TextCtrl(self, -1, value)
177 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
181 def AddLabelTextCtrl(self, info, value):
182 text = wx.StaticText(self, -1, info)
183 ret = wx.TextCtrl(self, -1, value)
184 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
185 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
189 def AddTextCtrlButton(self, value, buttonText):
190 text = wx.TextCtrl(self, -1, value)
191 button = wx.Button(self, -1, buttonText)
192 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
193 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
197 def AddBitmap(self, bitmap):
198 bitmap = wx.StaticBitmap(self, -1, bitmap)
199 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
203 def AddCheckmark(self, label, bitmap):
204 check = wx.StaticBitmap(self, -1, bitmap)
205 text = wx.StaticText(self, -1, label)
206 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
207 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
211 def AddCombo(self, label, options):
212 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
213 text = wx.StaticText(self, -1, label)
214 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
215 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
228 class PrintrbotPage(InfoPage):
229 def __init__(self, parent):
230 self._printer_info = [
231 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
232 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
233 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
234 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
235 (":" + _("Older models"),),
236 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
237 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
238 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
239 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
240 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
241 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
242 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
243 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
244 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
245 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
246 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
247 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
248 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
251 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
252 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
253 self.AddText(_("Select which Printrbot machine you have:"))
255 for printer in self._printer_info:
256 if printer[0].startswith(":"):
258 self.AddText(printer[0][1:])
260 item = self.AddRadioButton(printer[0])
261 item.data = printer[1:]
262 self._items.append(item)
265 profile.putMachineSetting('machine_name', 'Printrbot ???')
266 for item in self._items:
269 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
270 profile.putMachineSetting('machine_width', data[0])
271 profile.putMachineSetting('machine_depth', data[1])
272 profile.putMachineSetting('machine_height', data[2])
273 profile.putProfileSetting('nozzle_size', data[3])
274 profile.putProfileSetting('filament_diameter', data[4])
275 profile.putProfileSetting('print_temperature', data[5])
276 profile.putProfileSetting('print_speed', data[6])
277 profile.putProfileSetting('travel_speed', data[7])
278 profile.putProfileSetting('retraction_speed', data[8])
279 profile.putProfileSetting('retraction_amount', data[9])
280 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
281 profile.putMachineSetting('has_heated_bed', 'False')
282 profile.putMachineSetting('machine_center_is_zero', 'False')
283 profile.putMachineSetting('extruder_head_size_min_x', '0')
284 profile.putMachineSetting('extruder_head_size_min_y', '0')
285 profile.putMachineSetting('extruder_head_size_max_x', '0')
286 profile.putMachineSetting('extruder_head_size_max_y', '0')
287 profile.putMachineSetting('extruder_head_size_height', '0')
289 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
290 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
291 ;Print time: {print_time}
292 ;Filament used: {filament_amount}m {filament_weight}g
293 ;Filament cost: {filament_cost}
294 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
295 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
297 G90 ;absolute positioning
298 M82 ;set extruder to absolute mode
299 M107 ;start with the fan off
300 G28 X0 Y0 ;move X/Y to min endstops
301 G28 Z0 ;move Z to min endstops
302 G29 ;Run the auto bed leveling
303 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
304 G92 E0 ;zero the extruded length
305 G1 F200 E3 ;extrude 3mm of feed stock
306 G92 E0 ;zero the extruded length again
308 ;Put printing message on LCD screen
312 class OtherMachineSelectPage(InfoPage):
313 def __init__(self, parent):
314 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
315 self.AddText(_("The following pre-defined machine profiles are available"))
316 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."))
318 machines = resources.getDefaultMachineProfiles()
320 for filename in machines:
321 name = os.path.splitext(os.path.basename(filename))[0]
322 item = self.AddRadioButton(name)
323 item.filename = filename
324 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
325 self.options.append(item)
327 item = self.AddRadioButton(_('Custom...'))
329 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
331 def OnProfileSelect(self, e):
332 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
334 def OnOtherSelect(self, e):
335 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
338 for option in self.options:
339 if option.GetValue():
340 profile.loadProfile(option.filename)
341 profile.loadMachineSettings(option.filename)
343 class OtherMachineInfoPage(InfoPage):
344 def __init__(self, parent):
345 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
346 self.AddText(_("Cura is now ready to be used!"))
348 class CustomRepRapInfoPage(InfoPage):
349 def __init__(self, parent):
350 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
351 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
352 self.AddText(_("Be sure to review the default profile before running it on your machine."))
353 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
355 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
357 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
358 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
359 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
360 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
361 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
362 self.heatedBed = self.AddCheckbox(_("Heated bed"))
363 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
366 profile.putMachineSetting('machine_name', self.machineName.GetValue())
367 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
368 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
369 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
370 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
371 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
372 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
373 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
374 profile.putMachineSetting('extruder_head_size_min_x', '0')
375 profile.putMachineSetting('extruder_head_size_min_y', '0')
376 profile.putMachineSetting('extruder_head_size_max_x', '0')
377 profile.putMachineSetting('extruder_head_size_max_y', '0')
378 profile.putMachineSetting('extruder_head_size_height', '0')
379 profile.checkAndUpdateMachineName()
381 class MachineSelectPage(InfoPage):
382 def __init__(self, parent):
383 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
384 self.AddText(_("What kind of machine do you have:"))
386 self.LulzbotMiniRadio = self.AddRadioButton("LulzBot Mini", style=wx.RB_GROUP)
387 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
388 self.LulzbotMiniRadio.SetValue(True)
389 self.LulzbotTaz5Radio = self.AddRadioButton("LulzBot TAZ 5")
390 self.LulzbotTaz5Radio.Bind(wx.EVT_RADIOBUTTON, self.OnTaz5Select)
391 self.LulzbotTaz4Radio = self.AddRadioButton("LulzBot TAZ 4")
392 self.LulzbotTaz4Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
393 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
394 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
395 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
396 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
397 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
398 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
399 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
400 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
401 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
402 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
403 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
404 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
405 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
406 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
408 def OnUltimaker2Select(self, e):
409 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
411 def OnUltimakerSelect(self, e):
412 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
414 def OnUltimakerOPSelect(self, e):
415 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
417 def OnPrintrbotSelect(self, e):
418 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
420 def OnLulzbotSelect(self, e):
421 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
423 def OnTaz5Select(self, e):
424 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().taz5NozzleSelectPage)
425 wx.wizard.WizardPageSimple.Chain(self.GetParent().taz5NozzleSelectPage, self.GetParent().lulzbotReadyPage)
427 def OnOtherSelect(self, e):
428 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
437 profile.putProfileSetting('retraction_enable', 'True')
438 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
439 if self.Ultimaker2Radio.GetValue():
440 profile.putMachineSetting('machine_width', '230')
441 profile.putMachineSetting('machine_depth', '225')
442 profile.putMachineSetting('machine_height', '205')
443 profile.putMachineSetting('machine_name', 'ultimaker2')
444 profile.putMachineSetting('machine_type', 'ultimaker2')
445 profile.putMachineSetting('has_heated_bed', 'True')
446 if self.Ultimaker2GoRadio.GetValue():
447 profile.putMachineSetting('machine_width', '120')
448 profile.putMachineSetting('machine_depth', '120')
449 profile.putMachineSetting('machine_height', '115')
450 profile.putMachineSetting('machine_name', 'ultimaker2go')
451 profile.putMachineSetting('machine_type', 'ultimaker2go')
452 profile.putMachineSetting('has_heated_bed', 'False')
453 if self.Ultimaker2ExtRadio.GetValue():
454 profile.putMachineSetting('machine_width', '230')
455 profile.putMachineSetting('machine_depth', '225')
456 profile.putMachineSetting('machine_height', '315')
457 profile.putMachineSetting('machine_name', 'ultimaker2extended')
458 profile.putMachineSetting('machine_type', 'ultimaker2extended')
459 profile.putMachineSetting('has_heated_bed', 'False')
460 profile.putMachineSetting('machine_center_is_zero', 'False')
461 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
462 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
463 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
464 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
465 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
466 profile.putMachineSetting('extruder_head_size_height', '48.0')
467 profile.putProfileSetting('nozzle_size', '0.4')
468 profile.putProfileSetting('fan_full_height', '5.0')
469 profile.putMachineSetting('extruder_offset_x1', '18.0')
470 profile.putMachineSetting('extruder_offset_y1', '0.0')
471 elif self.UltimakerRadio.GetValue():
472 profile.putMachineSetting('machine_width', '205')
473 profile.putMachineSetting('machine_depth', '205')
474 profile.putMachineSetting('machine_height', '200')
475 profile.putMachineSetting('machine_name', 'ultimaker original')
476 profile.putMachineSetting('machine_type', 'ultimaker')
477 profile.putMachineSetting('machine_center_is_zero', 'False')
478 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
479 profile.putProfileSetting('nozzle_size', '0.4')
480 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
481 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
482 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
483 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
484 profile.putMachineSetting('extruder_head_size_height', '55.0')
485 elif self.UltimakerOPRadio.GetValue():
486 profile.putMachineSetting('machine_width', '205')
487 profile.putMachineSetting('machine_depth', '205')
488 profile.putMachineSetting('machine_height', '200')
489 profile.putMachineSetting('machine_name', 'ultimaker original+')
490 profile.putMachineSetting('machine_type', 'ultimaker_plus')
491 profile.putMachineSetting('machine_center_is_zero', 'False')
492 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
493 profile.putProfileSetting('nozzle_size', '0.4')
494 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
495 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
496 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
497 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
498 profile.putMachineSetting('extruder_head_size_height', '55.0')
499 profile.putMachineSetting('has_heated_bed', 'True')
500 profile.putMachineSetting('extruder_amount', '1')
501 profile.putProfileSetting('retraction_enable', 'True')
502 elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
503 if self.LulzbotTaz4Radio.GetValue():
504 profile.putMachineSetting('machine_width', '290')
505 profile.putMachineSetting('machine_depth', '275')
506 profile.putMachineSetting('machine_height', '250')
507 profile.putProfileSetting('nozzle_size', '0.35')
508 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
509 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
510 profile.putMachineSetting('serial_baud', '115200')
511 elif self.LulzbotTaz5Radio.GetValue():
512 profile.putMachineSetting('machine_width', '290')
513 profile.putMachineSetting('machine_depth', '275')
514 profile.putMachineSetting('machine_height', '250')
515 profile.putMachineSetting('serial_baud', '115200')
516 # Machine type and name are set in the nozzle select page
518 profile.putMachineSetting('machine_width', '155')
519 profile.putMachineSetting('machine_depth', '155')
520 profile.putMachineSetting('machine_height', '163')
521 profile.putProfileSetting('nozzle_size', '0.5')
522 profile.putMachineSetting('machine_name', 'LulzBot Mini')
523 profile.putMachineSetting('machine_type', 'lulzbot_mini')
524 profile.putMachineSetting('serial_baud', '115200')
525 profile.putMachineSetting('extruder_head_size_min_x', '40')
526 profile.putMachineSetting('extruder_head_size_max_x', '75')
527 profile.putMachineSetting('extruder_head_size_min_y', '25')
528 profile.putMachineSetting('extruder_head_size_max_y', '55')
529 profile.putMachineSetting('extruder_head_size_height', '17')
531 profile.putMachineSetting('machine_center_is_zero', 'False')
532 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
533 profile.putMachineSetting('has_heated_bed', 'True')
534 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
535 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
536 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
537 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
538 profile.putMachineSetting('extruder_head_size_height', '0.0')
539 profile.putPreference('startMode', 'Simple')
541 profile.putMachineSetting('machine_width', '80')
542 profile.putMachineSetting('machine_depth', '80')
543 profile.putMachineSetting('machine_height', '60')
544 profile.putMachineSetting('machine_name', 'reprap')
545 profile.putMachineSetting('machine_type', 'reprap')
546 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
547 profile.putPreference('startMode', 'Normal')
548 profile.putProfileSetting('nozzle_size', '0.5')
549 profile.checkAndUpdateMachineName()
550 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
552 class SelectParts(InfoPage):
553 def __init__(self, parent):
554 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
555 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."))
557 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
558 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
559 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
560 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
562 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."))
563 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
564 self.springExtruder.SetValue(True)
567 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
568 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
569 profile.putMachineSetting('has_heated_bed', 'True')
571 profile.putMachineSetting('has_heated_bed', 'False')
572 if self.dualExtrusion.GetValue():
573 profile.putMachineSetting('extruder_amount', '2')
574 profile.putMachineSetting('machine_depth', '195')
576 profile.putMachineSetting('extruder_amount', '1')
577 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
578 profile.putProfileSetting('retraction_enable', 'True')
580 profile.putProfileSetting('retraction_enable', 'False')
583 class UltimakerFirmwareUpgradePage(InfoPage):
584 def __init__(self, parent):
585 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
586 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."))
587 self.AddHiddenSeperator()
588 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
589 self.AddHiddenSeperator()
590 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."))
591 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
592 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
593 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
594 self.AddHiddenSeperator()
595 if profile.getMachineSetting('machine_type') == 'ultimaker':
596 self.AddText(_("Do not upgrade to this firmware if:"))
597 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
598 self.AddText(_("* Build your own heated bed"))
599 self.AddText(_("* Have other changes in the firmware"))
600 # button = self.AddButton('Goto this page for a custom firmware')
601 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
606 def OnUpgradeClick(self, e):
607 if firmwareInstall.InstallFirmware():
608 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
610 def OnSkipClick(self, e):
611 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
612 self.GetParent().ShowPage(self.GetNext())
614 def OnUrlClick(self, e):
615 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
617 class UltimakerCheckupPage(InfoPage):
618 def __init__(self, parent):
619 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
621 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
622 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
623 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
624 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
625 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
626 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
627 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
628 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
629 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
630 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
633 _("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."))
634 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
635 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
636 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
638 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
639 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
640 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
642 self.infoBox = self.AddInfoBox()
643 self.machineState = self.AddText("")
644 self.temperatureLabel = self.AddText("")
645 self.errorLogButton = self.AddButton(_("Show error log"))
646 self.errorLogButton.Show(False)
648 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
650 self.xMinStop = False
651 self.xMaxStop = False
652 self.yMinStop = False
653 self.yMaxStop = False
654 self.zMinStop = False
655 self.zMaxStop = False
657 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
660 if self.comm is not None:
664 self.endstopBitmap.Show(False)
667 def OnSkipClick(self, e):
668 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
669 self.GetParent().ShowPage(self.GetNext())
671 def OnCheckClick(self, e=None):
672 self.errorLogButton.Show(False)
673 if self.comm is not None:
677 wx.CallAfter(self.OnCheckClick)
679 self.infoBox.SetBusy(_("Connecting to machine."))
680 self.commState.SetBitmap(self.unknownBitmap)
681 self.tempState.SetBitmap(self.unknownBitmap)
682 self.stopState.SetBitmap(self.unknownBitmap)
683 self.checkupState = 0
684 self.checkExtruderNr = 0
685 self.comm = machineCom.MachineCom(callbackObject=self)
687 def OnErrorLog(self, e):
688 printWindow.LogWindow('\n'.join(self.comm.getLog()))
690 def mcLog(self, message):
693 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
694 if not self.comm.isOperational():
696 if self.checkupState == 0:
697 self.tempCheckTimeout = 20
698 if temp[self.checkExtruderNr] > 70:
699 self.checkupState = 1
700 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
701 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
702 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
704 self.startTemp = temp[self.checkExtruderNr]
705 self.checkupState = 2
706 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
707 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
708 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
709 elif self.checkupState == 1:
710 if temp[self.checkExtruderNr] < 60:
711 self.startTemp = temp[self.checkExtruderNr]
712 self.checkupState = 2
713 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
714 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
715 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
716 elif self.checkupState == 2:
717 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
718 if temp[self.checkExtruderNr] > self.startTemp + 40:
719 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
720 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
721 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
722 self.checkExtruderNr = 0
723 self.checkupState = 3
724 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
725 wx.CallAfter(self.endstopBitmap.Show, True)
726 wx.CallAfter(self.Layout)
727 self.comm.sendCommand('M119')
728 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
730 self.checkupState = 0
731 self.checkExtruderNr += 1
733 self.tempCheckTimeout -= 1
734 if self.tempCheckTimeout < 1:
735 self.checkupState = -1
736 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
737 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
738 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
739 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
740 elif self.checkupState >= 3 and self.checkupState < 10:
741 self.comm.sendCommand('M119')
742 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
744 def mcStateChange(self, state):
745 if self.comm is None:
747 if self.comm.isOperational():
748 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
749 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
750 elif self.comm.isError():
751 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
752 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
753 wx.CallAfter(self.endstopBitmap.Show, False)
754 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
755 wx.CallAfter(self.errorLogButton.Show, True)
756 wx.CallAfter(self.Layout)
758 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
760 def mcMessage(self, message):
761 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
762 for data in message.split(' '):
764 tag, value = data.split(':', 1)
766 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
768 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
770 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
772 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
774 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
776 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
778 tag, value = map(str.strip, message.split(':', 1))
780 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
782 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
784 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
786 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
788 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
790 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
791 if 'z_max' in message:
792 self.comm.sendCommand('M119')
794 if self.checkupState == 3:
795 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
796 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
797 self.checkupState = 5
798 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
799 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
801 self.checkupState = 4
802 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
803 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
804 elif self.checkupState == 4:
805 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
806 self.checkupState = 5
807 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
808 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
809 elif self.checkupState == 5:
810 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
811 self.checkupState = 6
812 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
813 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
814 elif self.checkupState == 6:
815 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
816 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
817 self.checkupState = 8
818 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
819 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
821 self.checkupState = 7
822 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
823 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
824 elif self.checkupState == 7:
825 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
826 self.checkupState = 8
827 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
828 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
829 elif self.checkupState == 8:
830 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
831 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
832 self.checkupState = 10
834 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
835 wx.CallAfter(self.infoBox.SetReadyIndicator)
836 wx.CallAfter(self.endstopBitmap.Show, False)
837 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
838 wx.CallAfter(self.OnSkipClick, None)
840 self.checkupState = 9
841 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
842 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
843 elif self.checkupState == 9:
844 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
845 self.checkupState = 10
847 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
848 wx.CallAfter(self.infoBox.SetReadyIndicator)
849 wx.CallAfter(self.endstopBitmap.Show, False)
850 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
851 wx.CallAfter(self.OnSkipClick, None)
853 def mcProgress(self, lineNr):
856 def mcZChange(self, newZ):
860 class UltimakerCalibrationPage(InfoPage):
861 def __init__(self, parent):
862 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
864 self.AddText("Your Ultimaker requires some calibration.")
865 self.AddText("This calibration is needed for a proper extrusion amount.")
867 self.AddText("The following values are needed:")
868 self.AddText("* Diameter of filament")
869 self.AddText("* Number of steps per mm of filament extrusion")
871 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
873 self.AddText("First we need the diameter of your filament:")
874 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
876 "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.")
877 self.AddText("Note: This value can be changed later at any time.")
880 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
883 class UltimakerCalibrateStepsPerEPage(InfoPage):
884 def __init__(self, parent):
885 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
887 #if profile.getMachineSetting('steps_per_e') == '0':
888 # profile.putMachineSetting('steps_per_e', '865.888')
890 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
891 self.AddText(_("First remove any filament from your machine."))
892 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
893 self.AddText(_("We'll push the filament 100mm"))
894 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
895 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
896 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
897 self.AddText(_("This results in the following steps per E:"))
898 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
899 self.AddText(_("You can repeat these steps to get better calibration."))
902 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
903 self.heatButton = self.AddButton(_("Heatup for filament removal"))
905 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
906 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
907 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
909 def OnSaveLengthClick(self, e):
910 currentEValue = float(self.stepsPerEInput.GetValue())
911 realExtrudeLength = float(self.lengthInput.GetValue())
912 newEValue = currentEValue * 100 / realExtrudeLength
913 self.stepsPerEInput.SetValue(str(newEValue))
914 self.lengthInput.SetValue("100")
916 def OnExtrudeClick(self, e):
917 t = threading.Thread(target=self.OnExtrudeRun)
921 def OnExtrudeRun(self):
922 self.heatButton.Enable(False)
923 self.extrudeButton.Enable(False)
924 currentEValue = float(self.stepsPerEInput.GetValue())
925 self.comm = machineCom.MachineCom()
926 if not self.comm.isOpen():
928 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
929 'Printer error', wx.OK | wx.ICON_INFORMATION)
930 self.heatButton.Enable(True)
931 self.extrudeButton.Enable(True)
934 line = self.comm.readline()
939 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
942 self.sendGCommand('M302') #Disable cold extrusion protection
943 self.sendGCommand("M92 E%f" % (currentEValue))
944 self.sendGCommand("G92 E0")
945 self.sendGCommand("G1 E100 F600")
948 self.extrudeButton.Enable()
949 self.heatButton.Enable()
951 def OnHeatClick(self, e):
952 t = threading.Thread(target=self.OnHeatRun)
957 self.heatButton.Enable(False)
958 self.extrudeButton.Enable(False)
959 self.comm = machineCom.MachineCom()
960 if not self.comm.isOpen():
962 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
963 'Printer error', wx.OK | wx.ICON_INFORMATION)
964 self.heatButton.Enable(True)
965 self.extrudeButton.Enable(True)
968 line = self.comm.readline()
970 self.heatButton.Enable(True)
971 self.extrudeButton.Enable(True)
975 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
978 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
980 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
981 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
982 self.sendGCommand('M104 S0')
985 self.heatButton.Enable(True)
986 self.extrudeButton.Enable(True)
988 def sendGCommand(self, cmd):
989 self.comm.sendCommand(cmd) #Disable cold extrusion protection
991 line = self.comm.readline()
994 if line.startswith('ok'):
998 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1000 class Ultimaker2ReadyPage(InfoPage):
1001 def __init__(self, parent):
1002 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1003 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1004 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1007 class LulzbotReadyPage(InfoPage):
1008 def __init__(self, parent):
1009 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1010 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1012 self.AddText(_('For more information about using Cura with your LulzBot'))
1013 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1016 class ToolheadSelectPage(InfoPage):
1017 def __init__(self, parent):
1018 super(ToolheadSelectPage, self).__init__(parent, _("LulzBot Toolhead Selection"))
1019 printer_name = profile.getMachineSetting('machine_type')
1021 self.AddText(_('Selected printer is ({}).'.format(printer_name)))
1025 print("This is a test!")
1027 class Taz5NozzleSelectPage(InfoPage):
1028 url='http://lulzbot.com/printer-identification'
1030 def __init__(self, parent):
1031 super(Taz5NozzleSelectPage, self).__init__(parent, _("LulzBot TAZ5"))
1032 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1034 self.AddText(_(' '))
1035 self.AddText(_('Please select nozzle size:'))
1036 self.Nozzle35Radio = self.AddRadioButton("0.35 mm", style=wx.RB_GROUP)
1037 self.Nozzle35Radio.SetValue(True)
1038 self.Nozzle50Radio = self.AddRadioButton("0.5 mm")
1039 self.AddText(_(' '))
1042 self.AddText(_('If you are not sure which nozzle size you have'))
1043 self.AddText(_('please check this webpage: '))
1044 button = self.AddButton(Taz5NozzleSelectPage.url)
1045 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
1047 def OnUrlClick(self, e):
1048 webbrowser.open(Taz5NozzleSelectPage.url)
1050 def StoreData(self):
1051 if self.Nozzle35Radio.GetValue():
1052 profile.putProfileSetting('nozzle_size', '0.35')
1053 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5 (0.35 nozzle)')
1054 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
1057 profile.putProfileSetting('nozzle_size', '0.5')
1058 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5 (0.5 nozzle)')
1059 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5_05nozzle')
1061 def OnPageChanging(self, e):
1062 e.GetPage().StoreData()
1064 class ConfigWizard(wx.wizard.Wizard):
1065 def __init__(self, addNew = False):
1066 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1068 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1070 profile.setActiveMachine(profile.getMachineCount())
1072 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1073 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1074 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1076 self.machineSelectPage = MachineSelectPage(self)
1077 self.ultimakerSelectParts = SelectParts(self)
1078 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1079 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1080 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1081 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1082 self.bedLevelPage = bedLevelWizardMain(self)
1083 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1084 self.printrbotSelectType = PrintrbotPage(self)
1085 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1086 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1087 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1089 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1090 self.lulzbotReadyPage = LulzbotReadyPage(self)
1091 self.taz5NozzleSelectPage = Taz5NozzleSelectPage(self)
1093 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1094 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1095 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1096 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1097 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1098 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1099 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1100 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1101 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.lulzbotReadyPage)
1103 self.FitToPage(self.machineSelectPage)
1105 self.RunWizard(self.machineSelectPage)
1108 def OnPageChanging(self, e):
1109 e.GetPage().StoreData()
1111 def OnPageChanged(self, e):
1112 if e.GetPage().AllowNext():
1113 self.FindWindowById(wx.ID_FORWARD).Enable()
1115 self.FindWindowById(wx.ID_FORWARD).Disable()
1116 if e.GetPage().AllowBack():
1117 self.FindWindowById(wx.ID_BACKWARD).Enable()
1119 self.FindWindowById(wx.ID_BACKWARD).Disable()
1121 def OnCancel(self, e):
1122 new_machine_index = int(profile.getPreferenceFloat('active_machine'))
1123 profile.setActiveMachine(self._old_machine_index)
1124 profile.removeMachine(new_machine_index)
1126 class bedLevelWizardMain(InfoPage):
1127 def __init__(self, parent):
1128 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1130 self.AddText(_('This wizard will help you in leveling your printer bed'))
1132 self.AddText(_('It will do the following steps'))
1133 self.AddText(_('* Move the printer head to each corner'))
1134 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1135 self.AddText(_('* Print a line around the bed to check if it is level'))
1138 self.connectButton = self.AddButton(_('Connect to printer'))
1141 self.infoBox = self.AddInfoBox()
1142 self.resumeButton = self.AddButton(_('Resume'))
1143 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1144 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1145 self.resumeButton.Enable(False)
1147 self.upButton.Enable(False)
1148 self.downButton.Enable(False)
1149 self.upButton2.Enable(False)
1150 self.downButton2.Enable(False)
1152 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1153 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1154 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1155 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1156 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1157 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1159 def OnConnect(self, e = None):
1160 if self.comm is not None:
1164 wx.CallAfter(self.OnConnect)
1166 self.connectButton.Enable(False)
1167 self.comm = machineCom.MachineCom(callbackObject=self)
1168 self.infoBox.SetBusy(_('Connecting to machine.'))
1169 self._wizardState = 0
1171 def OnBedUp(self, e):
1172 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1173 self.comm.sendCommand('G92 Z10')
1174 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1175 self.comm.sendCommand('M400')
1177 def OnBedDown(self, e):
1178 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1179 self.comm.sendCommand('G92 Z10')
1180 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1181 self.comm.sendCommand('M400')
1183 def OnBedUp2(self, e):
1184 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1185 self.comm.sendCommand('G92 Z10')
1186 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1187 self.comm.sendCommand('M400')
1189 def OnBedDown2(self, e):
1190 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1191 self.comm.sendCommand('G92 Z10')
1192 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1193 self.comm.sendCommand('M400')
1195 def AllowNext(self):
1196 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1197 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1200 def OnResume(self, e):
1201 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1202 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1203 if self._wizardState == -1:
1204 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1205 wx.CallAfter(self.upButton.Enable, False)
1206 wx.CallAfter(self.downButton.Enable, False)
1207 wx.CallAfter(self.upButton2.Enable, False)
1208 wx.CallAfter(self.downButton2.Enable, False)
1209 self.comm.sendCommand('M105')
1210 self.comm.sendCommand('G28')
1211 self._wizardState = 1
1212 elif self._wizardState == 2:
1213 if profile.getMachineSetting('has_heated_bed') == 'True':
1214 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1215 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1216 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1217 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1218 self.comm.sendCommand('M400')
1219 self._wizardState = 3
1221 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1222 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1223 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1224 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1225 self.comm.sendCommand('M400')
1226 self._wizardState = 3
1227 elif self._wizardState == 4:
1228 if profile.getMachineSetting('has_heated_bed') == 'True':
1229 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front 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, 5, feedTravel))
1232 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1233 self.comm.sendCommand('M400')
1234 self._wizardState = 7
1236 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back 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, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1239 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1240 self.comm.sendCommand('M400')
1241 self._wizardState = 5
1242 elif self._wizardState == 6:
1243 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1244 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1245 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1246 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1247 self.comm.sendCommand('M400')
1248 self._wizardState = 7
1249 elif self._wizardState == 8:
1250 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1251 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1252 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1253 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1254 self._wizardState = 9
1255 elif self._wizardState == 10:
1256 self._wizardState = 11
1257 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1258 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1259 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1260 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1261 w = profile.getMachineSettingFloat('machine_width') - 10
1262 d = profile.getMachineSettingFloat('machine_depth')
1263 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1264 filamentArea = math.pi * filamentRadius * filamentRadius
1265 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1269 'G1 Z2 F%d' % (feedZ),
1271 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1272 'G1 Z0.3 F%d' % (feedZ)]
1274 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1276 for i in xrange(0, 3):
1277 dist = 5.0 + 0.4 * float(i)
1278 eValue += (d - 2.0*dist) * ePerMM
1279 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1280 eValue += (w - 2.0*dist) * ePerMM
1281 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1282 eValue += (d - 2.0*dist) * ePerMM
1283 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1284 eValue += (w - 2.0*dist) * ePerMM
1285 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1287 gcodeList.append('M400')
1288 self.comm.printGCode(gcodeList)
1289 self.resumeButton.Enable(False)
1291 def mcLog(self, message):
1292 print 'Log:', message
1294 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1295 if self._wizardState == 1:
1296 self._wizardState = 2
1297 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1298 wx.CallAfter(self.resumeButton.Enable, True)
1299 elif self._wizardState == 3:
1300 self._wizardState = 4
1301 if profile.getMachineSetting('has_heated_bed') == 'True':
1302 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1304 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1305 wx.CallAfter(self.resumeButton.Enable, True)
1306 elif self._wizardState == 5:
1307 self._wizardState = 6
1308 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1309 wx.CallAfter(self.resumeButton.Enable, True)
1310 elif self._wizardState == 7:
1311 self._wizardState = 8
1312 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1313 wx.CallAfter(self.resumeButton.Enable, True)
1314 elif self._wizardState == 9:
1315 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1316 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1318 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1319 wx.CallAfter(self.resumeButton.Enable, True)
1320 self._wizardState = 10
1322 def mcStateChange(self, state):
1323 if self.comm is None:
1325 if self.comm.isOperational():
1326 if self._wizardState == 0:
1327 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1328 wx.CallAfter(self.upButton.Enable, True)
1329 wx.CallAfter(self.downButton.Enable, True)
1330 wx.CallAfter(self.upButton2.Enable, True)
1331 wx.CallAfter(self.downButton2.Enable, True)
1332 wx.CallAfter(self.resumeButton.Enable, True)
1333 self._wizardState = -1
1334 elif self._wizardState == 11 and not self.comm.isPrinting():
1335 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1336 self.comm.sendCommand('G92 E0')
1337 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1338 self.comm.sendCommand('M104 S0')
1339 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1340 wx.CallAfter(self.infoBox.SetReadyIndicator)
1341 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1342 wx.CallAfter(self.connectButton.Enable, True)
1343 self._wizardState = 12
1344 elif self.comm.isError():
1345 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1347 def mcMessage(self, message):
1350 def mcProgress(self, lineNr):
1353 def mcZChange(self, newZ):
1356 class headOffsetCalibrationPage(InfoPage):
1357 def __init__(self, parent):
1358 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1360 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1363 self.connectButton = self.AddButton(_('Connect to printer'))
1366 self.infoBox = self.AddInfoBox()
1367 self.textEntry = self.AddTextCtrl('')
1368 self.textEntry.Enable(False)
1369 self.resumeButton = self.AddButton(_('Resume'))
1370 self.resumeButton.Enable(False)
1372 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1373 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1375 def AllowBack(self):
1378 def OnConnect(self, e = None):
1379 if self.comm is not None:
1383 wx.CallAfter(self.OnConnect)
1385 self.connectButton.Enable(False)
1386 self.comm = machineCom.MachineCom(callbackObject=self)
1387 self.infoBox.SetBusy(_('Connecting to machine.'))
1388 self._wizardState = 0
1390 def OnResume(self, e):
1391 if self._wizardState == 2:
1392 self._wizardState = 3
1393 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1395 w = profile.getMachineSettingFloat('machine_width')
1396 d = profile.getMachineSettingFloat('machine_depth')
1398 gcode = gcodeGenerator.gcodeGenerator()
1399 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1400 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1407 gcode.addMove(w/2, 5)
1408 gcode.addMove(z=0.2)
1410 gcode.addExtrude(w/2, d-5.0)
1412 gcode.addMove(5, d/2)
1414 gcode.addExtrude(w-5.0, d/2)
1415 gcode.addRetract(15)
1418 gcode.addMove(w/2, 5)
1420 gcode.addExtrude(w/2, d-5.0)
1422 gcode.addMove(5, d/2)
1424 gcode.addExtrude(w-5.0, d/2)
1425 gcode.addRetract(15)
1430 gcode.addCmd('M400')
1432 self.comm.printGCode(gcode.list())
1433 self.resumeButton.Enable(False)
1434 elif self._wizardState == 4:
1436 float(self.textEntry.GetValue())
1439 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1440 self._wizardState = 5
1441 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1442 self.textEntry.SetValue('0.0')
1443 self.textEntry.Enable(True)
1444 elif self._wizardState == 5:
1446 float(self.textEntry.GetValue())
1449 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1450 self._wizardState = 6
1451 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1452 self.textEntry.SetValue('')
1453 self.textEntry.Enable(False)
1454 self.resumeButton.Enable(False)
1456 x = profile.getMachineSettingFloat('extruder_offset_x1')
1457 y = profile.getMachineSettingFloat('extruder_offset_y1')
1458 gcode = gcodeGenerator.gcodeGenerator()
1459 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1460 gcode.setPrintSpeed(25)
1463 gcode.addMove(50, 40, 0.2)
1465 for n in xrange(0, 10):
1466 gcode.addExtrude(50 + n * 10, 150)
1467 gcode.addExtrude(50 + n * 10 + 5, 150)
1468 gcode.addExtrude(50 + n * 10 + 5, 40)
1469 gcode.addExtrude(50 + n * 10 + 10, 40)
1470 gcode.addMove(40, 50)
1471 for n in xrange(0, 10):
1472 gcode.addExtrude(150, 50 + n * 10)
1473 gcode.addExtrude(150, 50 + n * 10 + 5)
1474 gcode.addExtrude(40, 50 + n * 10 + 5)
1475 gcode.addExtrude(40, 50 + n * 10 + 10)
1476 gcode.addRetract(15)
1479 gcode.addMove(50 - x, 30 - y, 0.2)
1481 for n in xrange(0, 10):
1482 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1483 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1484 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1485 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1486 gcode.addMove(30 - x, 50 - y, 0.2)
1487 for n in xrange(0, 10):
1488 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1489 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1490 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1491 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1492 gcode.addRetract(15)
1494 gcode.addCmd('M400')
1495 gcode.addCmd('M104 T0 S0')
1496 gcode.addCmd('M104 T1 S0')
1497 self.comm.printGCode(gcode.list())
1498 elif self._wizardState == 7:
1500 n = int(self.textEntry.GetValue()) - 1
1503 x = profile.getMachineSettingFloat('extruder_offset_x1')
1505 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1506 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1507 self.textEntry.SetValue('10')
1508 self._wizardState = 8
1509 elif self._wizardState == 8:
1511 n = int(self.textEntry.GetValue()) - 1
1514 y = profile.getMachineSettingFloat('extruder_offset_y1')
1516 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1517 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1518 self.infoBox.SetReadyIndicator()
1519 self._wizardState = 8
1521 self.resumeButton.Enable(False)
1523 def mcLog(self, message):
1524 print 'Log:', message
1526 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1527 if self._wizardState == 1:
1528 if temp[0] >= 210 and temp[1] >= 210:
1529 self._wizardState = 2
1530 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1531 wx.CallAfter(self.resumeButton.Enable, True)
1532 wx.CallAfter(self.resumeButton.SetFocus)
1534 def mcStateChange(self, state):
1535 if self.comm is None:
1537 if self.comm.isOperational():
1538 if self._wizardState == 0:
1539 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1540 self.comm.sendCommand('M105')
1541 self.comm.sendCommand('M104 S220 T0')
1542 self.comm.sendCommand('M104 S220 T1')
1543 self.comm.sendCommand('G28')
1544 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1545 self._wizardState = 1
1546 if not self.comm.isPrinting():
1547 if self._wizardState == 3:
1548 self._wizardState = 4
1549 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1550 wx.CallAfter(self.textEntry.SetValue, '0.0')
1551 wx.CallAfter(self.textEntry.Enable, True)
1552 wx.CallAfter(self.resumeButton.Enable, True)
1553 wx.CallAfter(self.resumeButton.SetFocus)
1554 elif self._wizardState == 6:
1555 self._wizardState = 7
1556 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1557 wx.CallAfter(self.textEntry.SetValue, '10')
1558 wx.CallAfter(self.textEntry.Enable, True)
1559 wx.CallAfter(self.resumeButton.Enable, True)
1560 wx.CallAfter(self.resumeButton.SetFocus)
1562 elif self.comm.isError():
1563 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1565 def mcMessage(self, message):
1568 def mcProgress(self, lineNr):
1571 def mcZChange(self, newZ):
1574 class bedLevelWizard(wx.wizard.Wizard):
1576 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1578 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1579 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1581 self.mainPage = bedLevelWizardMain(self)
1582 self.headOffsetCalibration = None
1584 self.FitToPage(self.mainPage)
1586 self.RunWizard(self.mainPage)
1589 def OnPageChanging(self, e):
1590 e.GetPage().StoreData()
1592 def OnPageChanged(self, e):
1593 if e.GetPage().AllowNext():
1594 self.FindWindowById(wx.ID_FORWARD).Enable()
1596 self.FindWindowById(wx.ID_FORWARD).Disable()
1597 if e.GetPage().AllowBack():
1598 self.FindWindowById(wx.ID_BACKWARD).Enable()
1600 self.FindWindowById(wx.ID_BACKWARD).Disable()
1602 class headOffsetWizard(wx.wizard.Wizard):
1604 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1606 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1607 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1609 self.mainPage = headOffsetCalibrationPage(self)
1611 self.FitToPage(self.mainPage)
1613 self.RunWizard(self.mainPage)
1616 def OnPageChanging(self, e):
1617 e.GetPage().StoreData()
1619 def OnPageChanged(self, e):
1620 if e.GetPage().AllowNext():
1621 self.FindWindowById(wx.ID_FORWARD).Enable()
1623 self.FindWindowById(wx.ID_FORWARD).Disable()
1624 if e.GetPage().AllowBack():
1625 self.FindWindowById(wx.ID_BACKWARD).Enable()
1627 self.FindWindowById(wx.ID_BACKWARD).Disable()