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.OnLulzbotSelect)
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 OnOtherSelect(self, e):
423 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
426 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
430 profile.putProfileSetting('retraction_enable', 'True')
431 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
432 if self.Ultimaker2Radio.GetValue():
433 profile.putMachineSetting('machine_width', '230')
434 profile.putMachineSetting('machine_depth', '225')
435 profile.putMachineSetting('machine_height', '205')
436 profile.putMachineSetting('machine_name', 'ultimaker2')
437 profile.putMachineSetting('machine_type', 'ultimaker2')
438 profile.putMachineSetting('has_heated_bed', 'True')
439 if self.Ultimaker2GoRadio.GetValue():
440 profile.putMachineSetting('machine_width', '120')
441 profile.putMachineSetting('machine_depth', '120')
442 profile.putMachineSetting('machine_height', '115')
443 profile.putMachineSetting('machine_name', 'ultimaker2go')
444 profile.putMachineSetting('machine_type', 'ultimaker2go')
445 profile.putMachineSetting('has_heated_bed', 'False')
446 if self.Ultimaker2ExtRadio.GetValue():
447 profile.putMachineSetting('machine_width', '230')
448 profile.putMachineSetting('machine_depth', '225')
449 profile.putMachineSetting('machine_height', '315')
450 profile.putMachineSetting('machine_name', 'ultimaker2extended')
451 profile.putMachineSetting('machine_type', 'ultimaker2extended')
452 profile.putMachineSetting('has_heated_bed', 'False')
453 profile.putMachineSetting('machine_center_is_zero', 'False')
454 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
455 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
456 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
457 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
458 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
459 profile.putMachineSetting('extruder_head_size_height', '48.0')
460 profile.putProfileSetting('nozzle_size', '0.4')
461 profile.putProfileSetting('fan_full_height', '5.0')
462 profile.putMachineSetting('extruder_offset_x1', '18.0')
463 profile.putMachineSetting('extruder_offset_y1', '0.0')
464 elif self.UltimakerRadio.GetValue():
465 profile.putMachineSetting('machine_width', '205')
466 profile.putMachineSetting('machine_depth', '205')
467 profile.putMachineSetting('machine_height', '200')
468 profile.putMachineSetting('machine_name', 'ultimaker original')
469 profile.putMachineSetting('machine_type', 'ultimaker')
470 profile.putMachineSetting('machine_center_is_zero', 'False')
471 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
472 profile.putProfileSetting('nozzle_size', '0.4')
473 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
474 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
475 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
476 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
477 profile.putMachineSetting('extruder_head_size_height', '55.0')
478 elif self.UltimakerOPRadio.GetValue():
479 profile.putMachineSetting('machine_width', '205')
480 profile.putMachineSetting('machine_depth', '205')
481 profile.putMachineSetting('machine_height', '200')
482 profile.putMachineSetting('machine_name', 'ultimaker original+')
483 profile.putMachineSetting('machine_type', 'ultimaker_plus')
484 profile.putMachineSetting('machine_center_is_zero', 'False')
485 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
486 profile.putProfileSetting('nozzle_size', '0.4')
487 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
488 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
489 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
490 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
491 profile.putMachineSetting('extruder_head_size_height', '55.0')
492 profile.putMachineSetting('has_heated_bed', 'True')
493 profile.putMachineSetting('extruder_amount', '1')
494 profile.putProfileSetting('retraction_enable', 'True')
495 elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
496 if self.LulzbotTaz4Radio.GetValue():
497 profile.putMachineSetting('machine_width', '298')
498 profile.putMachineSetting('machine_depth', '275')
499 profile.putMachineSetting('machine_height', '250')
500 profile.putProfileSetting('nozzle_size', '0.35')
501 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
502 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
503 profile.putMachineSetting('serial_baud', '115200')
504 elif self.LulzbotTaz5Radio.GetValue():
505 profile.putMachineSetting('machine_width', '298')
506 profile.putMachineSetting('machine_depth', '275')
507 profile.putMachineSetting('machine_height', '250')
508 profile.putProfileSetting('nozzle_size', '0.35')
509 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
510 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
511 profile.putMachineSetting('serial_baud', '115200')
513 profile.putMachineSetting('machine_width', '155')
514 profile.putMachineSetting('machine_depth', '155')
515 profile.putMachineSetting('machine_height', '163')
516 profile.putProfileSetting('nozzle_size', '0.5')
517 profile.putMachineSetting('machine_name', 'LulzBot Mini')
518 profile.putMachineSetting('machine_type', 'lulzbot_mini')
519 profile.putMachineSetting('serial_baud', '115200')
520 profile.putMachineSetting('extruder_head_size_min_x', '40')
521 profile.putMachineSetting('extruder_head_size_max_x', '75')
522 profile.putMachineSetting('extruder_head_size_min_y', '25')
523 profile.putMachineSetting('extruder_head_size_max_y', '55')
524 profile.putMachineSetting('extruder_head_size_height', '17')
526 profile.putMachineSetting('machine_center_is_zero', 'False')
527 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
528 profile.putMachineSetting('has_heated_bed', 'True')
529 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
530 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
531 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
532 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
533 profile.putMachineSetting('extruder_head_size_height', '0.0')
534 profile.putPreference('startMode', 'Simple')
536 profile.putMachineSetting('machine_width', '80')
537 profile.putMachineSetting('machine_depth', '80')
538 profile.putMachineSetting('machine_height', '60')
539 profile.putMachineSetting('machine_name', 'reprap')
540 profile.putMachineSetting('machine_type', 'reprap')
541 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
542 profile.putPreference('startMode', 'Normal')
543 profile.putProfileSetting('nozzle_size', '0.5')
544 profile.checkAndUpdateMachineName()
545 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
547 class SelectParts(InfoPage):
548 def __init__(self, parent):
549 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
550 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."))
552 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
553 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
554 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
555 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
557 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."))
558 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
559 self.springExtruder.SetValue(True)
562 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
563 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
564 profile.putMachineSetting('has_heated_bed', 'True')
566 profile.putMachineSetting('has_heated_bed', 'False')
567 if self.dualExtrusion.GetValue():
568 profile.putMachineSetting('extruder_amount', '2')
569 profile.putMachineSetting('machine_depth', '195')
571 profile.putMachineSetting('extruder_amount', '1')
572 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
573 profile.putProfileSetting('retraction_enable', 'True')
575 profile.putProfileSetting('retraction_enable', 'False')
578 class UltimakerFirmwareUpgradePage(InfoPage):
579 def __init__(self, parent):
580 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
581 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."))
582 self.AddHiddenSeperator()
583 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
584 self.AddHiddenSeperator()
585 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."))
586 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
587 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
588 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
589 self.AddHiddenSeperator()
590 if profile.getMachineSetting('machine_type') == 'ultimaker':
591 self.AddText(_("Do not upgrade to this firmware if:"))
592 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
593 self.AddText(_("* Build your own heated bed"))
594 self.AddText(_("* Have other changes in the firmware"))
595 # button = self.AddButton('Goto this page for a custom firmware')
596 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
601 def OnUpgradeClick(self, e):
602 if firmwareInstall.InstallFirmware():
603 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
605 def OnSkipClick(self, e):
606 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
607 self.GetParent().ShowPage(self.GetNext())
609 def OnUrlClick(self, e):
610 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
612 class UltimakerCheckupPage(InfoPage):
613 def __init__(self, parent):
614 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
616 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
617 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
618 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
619 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
620 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
621 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
622 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
623 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
624 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
625 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
628 _("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."))
629 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
630 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
631 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
633 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
634 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
635 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
637 self.infoBox = self.AddInfoBox()
638 self.machineState = self.AddText("")
639 self.temperatureLabel = self.AddText("")
640 self.errorLogButton = self.AddButton(_("Show error log"))
641 self.errorLogButton.Show(False)
643 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
645 self.xMinStop = False
646 self.xMaxStop = False
647 self.yMinStop = False
648 self.yMaxStop = False
649 self.zMinStop = False
650 self.zMaxStop = False
652 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
655 if self.comm is not None:
659 self.endstopBitmap.Show(False)
662 def OnSkipClick(self, e):
663 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
664 self.GetParent().ShowPage(self.GetNext())
666 def OnCheckClick(self, e=None):
667 self.errorLogButton.Show(False)
668 if self.comm is not None:
672 wx.CallAfter(self.OnCheckClick)
674 self.infoBox.SetBusy(_("Connecting to machine."))
675 self.commState.SetBitmap(self.unknownBitmap)
676 self.tempState.SetBitmap(self.unknownBitmap)
677 self.stopState.SetBitmap(self.unknownBitmap)
678 self.checkupState = 0
679 self.checkExtruderNr = 0
680 self.comm = machineCom.MachineCom(callbackObject=self)
682 def OnErrorLog(self, e):
683 printWindow.LogWindow('\n'.join(self.comm.getLog()))
685 def mcLog(self, message):
688 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
689 if not self.comm.isOperational():
691 if self.checkupState == 0:
692 self.tempCheckTimeout = 20
693 if temp[self.checkExtruderNr] > 70:
694 self.checkupState = 1
695 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
696 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
697 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
699 self.startTemp = temp[self.checkExtruderNr]
700 self.checkupState = 2
701 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
702 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
703 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
704 elif self.checkupState == 1:
705 if temp[self.checkExtruderNr] < 60:
706 self.startTemp = temp[self.checkExtruderNr]
707 self.checkupState = 2
708 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
709 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
710 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
711 elif self.checkupState == 2:
712 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
713 if temp[self.checkExtruderNr] > self.startTemp + 40:
714 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
715 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
716 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
717 self.checkExtruderNr = 0
718 self.checkupState = 3
719 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
720 wx.CallAfter(self.endstopBitmap.Show, True)
721 wx.CallAfter(self.Layout)
722 self.comm.sendCommand('M119')
723 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
725 self.checkupState = 0
726 self.checkExtruderNr += 1
728 self.tempCheckTimeout -= 1
729 if self.tempCheckTimeout < 1:
730 self.checkupState = -1
731 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
732 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
733 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
734 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
735 elif self.checkupState >= 3 and self.checkupState < 10:
736 self.comm.sendCommand('M119')
737 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
739 def mcStateChange(self, state):
740 if self.comm is None:
742 if self.comm.isOperational():
743 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
744 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
745 elif self.comm.isError():
746 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
747 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
748 wx.CallAfter(self.endstopBitmap.Show, False)
749 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
750 wx.CallAfter(self.errorLogButton.Show, True)
751 wx.CallAfter(self.Layout)
753 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
755 def mcMessage(self, message):
756 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
757 for data in message.split(' '):
759 tag, value = data.split(':', 1)
761 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
763 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
765 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
767 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
769 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
771 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
773 tag, value = map(str.strip, message.split(':', 1))
775 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
777 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
779 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
781 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
783 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
785 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
786 if 'z_max' in message:
787 self.comm.sendCommand('M119')
789 if self.checkupState == 3:
790 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
791 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
792 self.checkupState = 5
793 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
794 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
796 self.checkupState = 4
797 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
798 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
799 elif self.checkupState == 4:
800 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
801 self.checkupState = 5
802 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
803 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
804 elif self.checkupState == 5:
805 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
806 self.checkupState = 6
807 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
808 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
809 elif self.checkupState == 6:
810 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
811 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
812 self.checkupState = 8
813 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
814 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
816 self.checkupState = 7
817 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
818 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
819 elif self.checkupState == 7:
820 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
821 self.checkupState = 8
822 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
823 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
824 elif self.checkupState == 8:
825 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
826 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
827 self.checkupState = 10
829 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
830 wx.CallAfter(self.infoBox.SetReadyIndicator)
831 wx.CallAfter(self.endstopBitmap.Show, False)
832 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
833 wx.CallAfter(self.OnSkipClick, None)
835 self.checkupState = 9
836 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
837 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
838 elif self.checkupState == 9:
839 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
840 self.checkupState = 10
842 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
843 wx.CallAfter(self.infoBox.SetReadyIndicator)
844 wx.CallAfter(self.endstopBitmap.Show, False)
845 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
846 wx.CallAfter(self.OnSkipClick, None)
848 def mcProgress(self, lineNr):
851 def mcZChange(self, newZ):
855 class UltimakerCalibrationPage(InfoPage):
856 def __init__(self, parent):
857 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
859 self.AddText("Your Ultimaker requires some calibration.")
860 self.AddText("This calibration is needed for a proper extrusion amount.")
862 self.AddText("The following values are needed:")
863 self.AddText("* Diameter of filament")
864 self.AddText("* Number of steps per mm of filament extrusion")
866 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
868 self.AddText("First we need the diameter of your filament:")
869 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
871 "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.")
872 self.AddText("Note: This value can be changed later at any time.")
875 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
878 class UltimakerCalibrateStepsPerEPage(InfoPage):
879 def __init__(self, parent):
880 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
882 #if profile.getMachineSetting('steps_per_e') == '0':
883 # profile.putMachineSetting('steps_per_e', '865.888')
885 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
886 self.AddText(_("First remove any filament from your machine."))
887 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
888 self.AddText(_("We'll push the filament 100mm"))
889 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
890 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
891 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
892 self.AddText(_("This results in the following steps per E:"))
893 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
894 self.AddText(_("You can repeat these steps to get better calibration."))
897 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
898 self.heatButton = self.AddButton(_("Heatup for filament removal"))
900 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
901 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
902 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
904 def OnSaveLengthClick(self, e):
905 currentEValue = float(self.stepsPerEInput.GetValue())
906 realExtrudeLength = float(self.lengthInput.GetValue())
907 newEValue = currentEValue * 100 / realExtrudeLength
908 self.stepsPerEInput.SetValue(str(newEValue))
909 self.lengthInput.SetValue("100")
911 def OnExtrudeClick(self, e):
912 t = threading.Thread(target=self.OnExtrudeRun)
916 def OnExtrudeRun(self):
917 self.heatButton.Enable(False)
918 self.extrudeButton.Enable(False)
919 currentEValue = float(self.stepsPerEInput.GetValue())
920 self.comm = machineCom.MachineCom()
921 if not self.comm.isOpen():
923 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
924 'Printer error', wx.OK | wx.ICON_INFORMATION)
925 self.heatButton.Enable(True)
926 self.extrudeButton.Enable(True)
929 line = self.comm.readline()
934 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
937 self.sendGCommand('M302') #Disable cold extrusion protection
938 self.sendGCommand("M92 E%f" % (currentEValue))
939 self.sendGCommand("G92 E0")
940 self.sendGCommand("G1 E100 F600")
943 self.extrudeButton.Enable()
944 self.heatButton.Enable()
946 def OnHeatClick(self, e):
947 t = threading.Thread(target=self.OnHeatRun)
952 self.heatButton.Enable(False)
953 self.extrudeButton.Enable(False)
954 self.comm = machineCom.MachineCom()
955 if not self.comm.isOpen():
957 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
958 'Printer error', wx.OK | wx.ICON_INFORMATION)
959 self.heatButton.Enable(True)
960 self.extrudeButton.Enable(True)
963 line = self.comm.readline()
965 self.heatButton.Enable(True)
966 self.extrudeButton.Enable(True)
970 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
973 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
975 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
976 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
977 self.sendGCommand('M104 S0')
980 self.heatButton.Enable(True)
981 self.extrudeButton.Enable(True)
983 def sendGCommand(self, cmd):
984 self.comm.sendCommand(cmd) #Disable cold extrusion protection
986 line = self.comm.readline()
989 if line.startswith('ok'):
993 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
995 class Ultimaker2ReadyPage(InfoPage):
996 def __init__(self, parent):
997 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
998 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
999 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1002 class LulzbotReadyPage(InfoPage):
1003 def __init__(self, parent):
1004 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1005 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1007 self.AddText(_('For more information about using Cura with your LulzBot'))
1008 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1011 class ConfigWizard(wx.wizard.Wizard):
1012 def __init__(self, addNew = False):
1013 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1015 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1017 profile.setActiveMachine(profile.getMachineCount())
1019 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1020 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1021 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1023 self.machineSelectPage = MachineSelectPage(self)
1024 self.ultimakerSelectParts = SelectParts(self)
1025 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1026 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1027 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1028 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1029 self.bedLevelPage = bedLevelWizardMain(self)
1030 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1031 self.printrbotSelectType = PrintrbotPage(self)
1032 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1033 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1034 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1036 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1037 self.lulzbotReadyPage = LulzbotReadyPage(self)
1039 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1040 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1041 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1042 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1043 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1044 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1045 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1046 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1048 self.FitToPage(self.machineSelectPage)
1049 self.GetPageAreaSizer().Add(self.machineSelectPage)
1051 self.RunWizard(self.machineSelectPage)
1054 def OnPageChanging(self, e):
1055 e.GetPage().StoreData()
1057 def OnPageChanged(self, e):
1058 if e.GetPage().AllowNext():
1059 self.FindWindowById(wx.ID_FORWARD).Enable()
1061 self.FindWindowById(wx.ID_FORWARD).Disable()
1062 if e.GetPage().AllowBack():
1063 self.FindWindowById(wx.ID_BACKWARD).Enable()
1065 self.FindWindowById(wx.ID_BACKWARD).Disable()
1067 def OnCancel(self, e):
1068 profile.setActiveMachine(self._old_machine_index)
1070 class bedLevelWizardMain(InfoPage):
1071 def __init__(self, parent):
1072 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1074 self.AddText(_('This wizard will help you in leveling your printer bed'))
1076 self.AddText(_('It will do the following steps'))
1077 self.AddText(_('* Move the printer head to each corner'))
1078 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1079 self.AddText(_('* Print a line around the bed to check if it is level'))
1082 self.connectButton = self.AddButton(_('Connect to printer'))
1085 self.infoBox = self.AddInfoBox()
1086 self.resumeButton = self.AddButton(_('Resume'))
1087 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1088 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1089 self.resumeButton.Enable(False)
1091 self.upButton.Enable(False)
1092 self.downButton.Enable(False)
1093 self.upButton2.Enable(False)
1094 self.downButton2.Enable(False)
1096 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1097 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1098 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1099 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1100 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1101 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1103 def OnConnect(self, e = None):
1104 if self.comm is not None:
1108 wx.CallAfter(self.OnConnect)
1110 self.connectButton.Enable(False)
1111 self.comm = machineCom.MachineCom(callbackObject=self)
1112 self.infoBox.SetBusy(_('Connecting to machine.'))
1113 self._wizardState = 0
1115 def OnBedUp(self, e):
1116 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1117 self.comm.sendCommand('G92 Z10')
1118 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1119 self.comm.sendCommand('M400')
1121 def OnBedDown(self, e):
1122 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1123 self.comm.sendCommand('G92 Z10')
1124 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1125 self.comm.sendCommand('M400')
1127 def OnBedUp2(self, e):
1128 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1129 self.comm.sendCommand('G92 Z10')
1130 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1131 self.comm.sendCommand('M400')
1133 def OnBedDown2(self, e):
1134 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1135 self.comm.sendCommand('G92 Z10')
1136 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1137 self.comm.sendCommand('M400')
1139 def AllowNext(self):
1140 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1141 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1144 def OnResume(self, e):
1145 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1146 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1147 if self._wizardState == -1:
1148 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1149 wx.CallAfter(self.upButton.Enable, False)
1150 wx.CallAfter(self.downButton.Enable, False)
1151 wx.CallAfter(self.upButton2.Enable, False)
1152 wx.CallAfter(self.downButton2.Enable, False)
1153 self.comm.sendCommand('M105')
1154 self.comm.sendCommand('G28')
1155 self._wizardState = 1
1156 elif self._wizardState == 2:
1157 if profile.getMachineSetting('has_heated_bed') == 'True':
1158 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1159 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1160 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1161 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1162 self.comm.sendCommand('M400')
1163 self._wizardState = 3
1165 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1166 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1167 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1168 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1169 self.comm.sendCommand('M400')
1170 self._wizardState = 3
1171 elif self._wizardState == 4:
1172 if profile.getMachineSetting('has_heated_bed') == 'True':
1173 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1174 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1175 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1176 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1177 self.comm.sendCommand('M400')
1178 self._wizardState = 7
1180 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1181 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1182 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1183 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1184 self.comm.sendCommand('M400')
1185 self._wizardState = 5
1186 elif self._wizardState == 6:
1187 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1188 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1189 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1190 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1191 self.comm.sendCommand('M400')
1192 self._wizardState = 7
1193 elif self._wizardState == 8:
1194 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1195 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1196 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1197 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1198 self._wizardState = 9
1199 elif self._wizardState == 10:
1200 self._wizardState = 11
1201 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1202 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1203 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1204 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1205 w = profile.getMachineSettingFloat('machine_width') - 10
1206 d = profile.getMachineSettingFloat('machine_depth')
1207 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1208 filamentArea = math.pi * filamentRadius * filamentRadius
1209 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1213 'G1 Z2 F%d' % (feedZ),
1215 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1216 'G1 Z0.3 F%d' % (feedZ)]
1218 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1220 for i in xrange(0, 3):
1221 dist = 5.0 + 0.4 * float(i)
1222 eValue += (d - 2.0*dist) * ePerMM
1223 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1224 eValue += (w - 2.0*dist) * ePerMM
1225 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1226 eValue += (d - 2.0*dist) * ePerMM
1227 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1228 eValue += (w - 2.0*dist) * ePerMM
1229 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1231 gcodeList.append('M400')
1232 self.comm.printGCode(gcodeList)
1233 self.resumeButton.Enable(False)
1235 def mcLog(self, message):
1236 print 'Log:', message
1238 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1239 if self._wizardState == 1:
1240 self._wizardState = 2
1241 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1242 wx.CallAfter(self.resumeButton.Enable, True)
1243 elif self._wizardState == 3:
1244 self._wizardState = 4
1245 if profile.getMachineSetting('has_heated_bed') == 'True':
1246 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1248 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1249 wx.CallAfter(self.resumeButton.Enable, True)
1250 elif self._wizardState == 5:
1251 self._wizardState = 6
1252 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1253 wx.CallAfter(self.resumeButton.Enable, True)
1254 elif self._wizardState == 7:
1255 self._wizardState = 8
1256 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1257 wx.CallAfter(self.resumeButton.Enable, True)
1258 elif self._wizardState == 9:
1259 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1260 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1262 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1263 wx.CallAfter(self.resumeButton.Enable, True)
1264 self._wizardState = 10
1266 def mcStateChange(self, state):
1267 if self.comm is None:
1269 if self.comm.isOperational():
1270 if self._wizardState == 0:
1271 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1272 wx.CallAfter(self.upButton.Enable, True)
1273 wx.CallAfter(self.downButton.Enable, True)
1274 wx.CallAfter(self.upButton2.Enable, True)
1275 wx.CallAfter(self.downButton2.Enable, True)
1276 wx.CallAfter(self.resumeButton.Enable, True)
1277 self._wizardState = -1
1278 elif self._wizardState == 11 and not self.comm.isPrinting():
1279 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1280 self.comm.sendCommand('G92 E0')
1281 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1282 self.comm.sendCommand('M104 S0')
1283 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1284 wx.CallAfter(self.infoBox.SetReadyIndicator)
1285 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1286 wx.CallAfter(self.connectButton.Enable, True)
1287 self._wizardState = 12
1288 elif self.comm.isError():
1289 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1291 def mcMessage(self, message):
1294 def mcProgress(self, lineNr):
1297 def mcZChange(self, newZ):
1300 class headOffsetCalibrationPage(InfoPage):
1301 def __init__(self, parent):
1302 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1304 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1307 self.connectButton = self.AddButton(_('Connect to printer'))
1310 self.infoBox = self.AddInfoBox()
1311 self.textEntry = self.AddTextCtrl('')
1312 self.textEntry.Enable(False)
1313 self.resumeButton = self.AddButton(_('Resume'))
1314 self.resumeButton.Enable(False)
1316 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1317 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1319 def AllowBack(self):
1322 def OnConnect(self, e = None):
1323 if self.comm is not None:
1327 wx.CallAfter(self.OnConnect)
1329 self.connectButton.Enable(False)
1330 self.comm = machineCom.MachineCom(callbackObject=self)
1331 self.infoBox.SetBusy(_('Connecting to machine.'))
1332 self._wizardState = 0
1334 def OnResume(self, e):
1335 if self._wizardState == 2:
1336 self._wizardState = 3
1337 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1339 w = profile.getMachineSettingFloat('machine_width')
1340 d = profile.getMachineSettingFloat('machine_depth')
1342 gcode = gcodeGenerator.gcodeGenerator()
1343 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1344 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1351 gcode.addMove(w/2, 5)
1352 gcode.addMove(z=0.2)
1354 gcode.addExtrude(w/2, d-5.0)
1356 gcode.addMove(5, d/2)
1358 gcode.addExtrude(w-5.0, d/2)
1359 gcode.addRetract(15)
1362 gcode.addMove(w/2, 5)
1364 gcode.addExtrude(w/2, d-5.0)
1366 gcode.addMove(5, d/2)
1368 gcode.addExtrude(w-5.0, d/2)
1369 gcode.addRetract(15)
1374 gcode.addCmd('M400')
1376 self.comm.printGCode(gcode.list())
1377 self.resumeButton.Enable(False)
1378 elif self._wizardState == 4:
1380 float(self.textEntry.GetValue())
1383 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1384 self._wizardState = 5
1385 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1386 self.textEntry.SetValue('0.0')
1387 self.textEntry.Enable(True)
1388 elif self._wizardState == 5:
1390 float(self.textEntry.GetValue())
1393 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1394 self._wizardState = 6
1395 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1396 self.textEntry.SetValue('')
1397 self.textEntry.Enable(False)
1398 self.resumeButton.Enable(False)
1400 x = profile.getMachineSettingFloat('extruder_offset_x1')
1401 y = profile.getMachineSettingFloat('extruder_offset_y1')
1402 gcode = gcodeGenerator.gcodeGenerator()
1403 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1404 gcode.setPrintSpeed(25)
1407 gcode.addMove(50, 40, 0.2)
1409 for n in xrange(0, 10):
1410 gcode.addExtrude(50 + n * 10, 150)
1411 gcode.addExtrude(50 + n * 10 + 5, 150)
1412 gcode.addExtrude(50 + n * 10 + 5, 40)
1413 gcode.addExtrude(50 + n * 10 + 10, 40)
1414 gcode.addMove(40, 50)
1415 for n in xrange(0, 10):
1416 gcode.addExtrude(150, 50 + n * 10)
1417 gcode.addExtrude(150, 50 + n * 10 + 5)
1418 gcode.addExtrude(40, 50 + n * 10 + 5)
1419 gcode.addExtrude(40, 50 + n * 10 + 10)
1420 gcode.addRetract(15)
1423 gcode.addMove(50 - x, 30 - y, 0.2)
1425 for n in xrange(0, 10):
1426 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1427 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1428 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1429 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1430 gcode.addMove(30 - x, 50 - y, 0.2)
1431 for n in xrange(0, 10):
1432 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1433 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1434 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1435 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1436 gcode.addRetract(15)
1438 gcode.addCmd('M400')
1439 gcode.addCmd('M104 T0 S0')
1440 gcode.addCmd('M104 T1 S0')
1441 self.comm.printGCode(gcode.list())
1442 elif self._wizardState == 7:
1444 n = int(self.textEntry.GetValue()) - 1
1447 x = profile.getMachineSettingFloat('extruder_offset_x1')
1449 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1450 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1451 self.textEntry.SetValue('10')
1452 self._wizardState = 8
1453 elif self._wizardState == 8:
1455 n = int(self.textEntry.GetValue()) - 1
1458 y = profile.getMachineSettingFloat('extruder_offset_y1')
1460 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1461 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1462 self.infoBox.SetReadyIndicator()
1463 self._wizardState = 8
1465 self.resumeButton.Enable(False)
1467 def mcLog(self, message):
1468 print 'Log:', message
1470 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1471 if self._wizardState == 1:
1472 if temp[0] >= 210 and temp[1] >= 210:
1473 self._wizardState = 2
1474 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1475 wx.CallAfter(self.resumeButton.Enable, True)
1476 wx.CallAfter(self.resumeButton.SetFocus)
1478 def mcStateChange(self, state):
1479 if self.comm is None:
1481 if self.comm.isOperational():
1482 if self._wizardState == 0:
1483 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1484 self.comm.sendCommand('M105')
1485 self.comm.sendCommand('M104 S220 T0')
1486 self.comm.sendCommand('M104 S220 T1')
1487 self.comm.sendCommand('G28')
1488 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1489 self._wizardState = 1
1490 if not self.comm.isPrinting():
1491 if self._wizardState == 3:
1492 self._wizardState = 4
1493 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1494 wx.CallAfter(self.textEntry.SetValue, '0.0')
1495 wx.CallAfter(self.textEntry.Enable, True)
1496 wx.CallAfter(self.resumeButton.Enable, True)
1497 wx.CallAfter(self.resumeButton.SetFocus)
1498 elif self._wizardState == 6:
1499 self._wizardState = 7
1500 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1501 wx.CallAfter(self.textEntry.SetValue, '10')
1502 wx.CallAfter(self.textEntry.Enable, True)
1503 wx.CallAfter(self.resumeButton.Enable, True)
1504 wx.CallAfter(self.resumeButton.SetFocus)
1506 elif self.comm.isError():
1507 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1509 def mcMessage(self, message):
1512 def mcProgress(self, lineNr):
1515 def mcZChange(self, newZ):
1518 class bedLevelWizard(wx.wizard.Wizard):
1520 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1522 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1523 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1525 self.mainPage = bedLevelWizardMain(self)
1526 self.headOffsetCalibration = None
1528 self.FitToPage(self.mainPage)
1529 self.GetPageAreaSizer().Add(self.mainPage)
1531 self.RunWizard(self.mainPage)
1534 def OnPageChanging(self, e):
1535 e.GetPage().StoreData()
1537 def OnPageChanged(self, e):
1538 if e.GetPage().AllowNext():
1539 self.FindWindowById(wx.ID_FORWARD).Enable()
1541 self.FindWindowById(wx.ID_FORWARD).Disable()
1542 if e.GetPage().AllowBack():
1543 self.FindWindowById(wx.ID_BACKWARD).Enable()
1545 self.FindWindowById(wx.ID_BACKWARD).Disable()
1547 class headOffsetWizard(wx.wizard.Wizard):
1549 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1551 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1552 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1554 self.mainPage = headOffsetCalibrationPage(self)
1556 self.FitToPage(self.mainPage)
1557 self.GetPageAreaSizer().Add(self.mainPage)
1559 self.RunWizard(self.mainPage)
1562 def OnPageChanging(self, e):
1563 e.GetPage().StoreData()
1565 def OnPageChanged(self, e):
1566 if e.GetPage().AllowNext():
1567 self.FindWindowById(wx.ID_FORWARD).Enable()
1569 self.FindWindowById(wx.ID_FORWARD).Disable()
1570 if e.GetPage().AllowBack():
1571 self.FindWindowById(wx.ID_BACKWARD).Enable()
1573 self.FindWindowById(wx.ID_BACKWARD).Disable()