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)
228 class FirstInfoPage(InfoPage):
229 def __init__(self, parent, addNew):
231 super(FirstInfoPage, self).__init__(parent, _("Add new machine wizard"))
233 super(FirstInfoPage, self).__init__(parent, _("First time run wizard"))
234 self.AddText(_("Welcome, and thanks for trying Cura!"))
236 self.AddText(_("This wizard will help you in setting up Cura for your machine."))
239 self._language_option = self.AddCombo(_("Select your language:"), map(lambda o: o[1], resources.getLanguageOptions()))
241 self._language_option = None
242 # self.AddText(_("This wizard will help you with the following steps:"))
243 # self.AddText(_("* Configure Cura for your machine"))
244 # self.AddText(_("* Optionally upgrade your firmware"))
245 # self.AddText(_("* Optionally check if your machine is working safely"))
246 # self.AddText(_("* Optionally level your printer bed"))
248 #self.AddText('* Calibrate your machine')
249 #self.AddText('* Do your first print')
255 if self._language_option is not None:
256 profile.putPreference('language', self._language_option.GetValue())
257 resources.setupLocalization(self._language_option.GetValue())
259 class PrintrbotPage(InfoPage):
260 def __init__(self, parent):
261 self._printer_info = [
262 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
263 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
264 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
265 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
266 (":" + _("Older models"),),
267 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
268 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
269 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
270 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
271 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
272 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
273 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
274 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
275 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
276 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
277 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
280 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
281 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
282 self.AddText(_("Select which Printrbot machine you have:"))
284 for printer in self._printer_info:
285 if printer[0].startswith(":"):
287 self.AddText(printer[0][1:])
289 item = self.AddRadioButton(printer[0])
290 item.data = printer[1:]
291 self._items.append(item)
294 profile.putMachineSetting('machine_name', 'Printrbot ???')
295 for item in self._items:
298 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
299 profile.putMachineSetting('machine_width', data[0])
300 profile.putMachineSetting('machine_depth', data[1])
301 profile.putMachineSetting('machine_height', data[2])
302 profile.putProfileSetting('nozzle_size', data[3])
303 profile.putProfileSetting('filament_diameter', data[4])
304 profile.putProfileSetting('print_temperature', data[5])
305 profile.putProfileSetting('print_speed', data[6])
306 profile.putProfileSetting('travel_speed', data[7])
307 profile.putProfileSetting('retraction_speed', data[8])
308 profile.putProfileSetting('retraction_amount', data[9])
309 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
310 profile.putMachineSetting('has_heated_bed', 'False')
311 profile.putMachineSetting('machine_center_is_zero', 'False')
312 profile.putMachineSetting('extruder_head_size_min_x', '0')
313 profile.putMachineSetting('extruder_head_size_min_y', '0')
314 profile.putMachineSetting('extruder_head_size_max_x', '0')
315 profile.putMachineSetting('extruder_head_size_max_y', '0')
316 profile.putMachineSetting('extruder_head_size_height', '0')
318 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
319 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
320 ;Print time: {print_time}
321 ;Filament used: {filament_amount}m {filament_weight}g
322 ;Filament cost: {filament_cost}
323 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
324 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
326 G90 ;absolute positioning
327 M82 ;set extruder to absolute mode
328 M107 ;start with the fan off
329 G28 X0 Y0 ;move X/Y to min endstops
330 G28 Z0 ;move Z to min endstops
331 G29 ;Run the auto bed leveling
332 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
333 G92 E0 ;zero the extruded length
334 G1 F200 E3 ;extrude 3mm of feed stock
335 G92 E0 ;zero the extruded length again
337 ;Put printing message on LCD screen
341 class OtherMachineSelectPage(InfoPage):
342 def __init__(self, parent):
343 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
344 self.AddText(_("The following pre-defined machine profiles are available"))
345 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."))
347 machines = resources.getDefaultMachineProfiles()
349 for filename in machines:
350 name = os.path.splitext(os.path.basename(filename))[0]
351 item = self.AddRadioButton(name)
352 item.filename = filename
353 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
354 self.options.append(item)
356 item = self.AddRadioButton(_('Custom...'))
358 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
360 def OnProfileSelect(self, e):
361 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
363 def OnOtherSelect(self, e):
364 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
367 for option in self.options:
368 if option.GetValue():
369 profile.loadProfile(option.filename)
370 profile.loadMachineSettings(option.filename)
372 class OtherMachineInfoPage(InfoPage):
373 def __init__(self, parent):
374 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
375 self.AddText(_("Cura is now ready to be used!"))
377 class CustomRepRapInfoPage(InfoPage):
378 def __init__(self, parent):
379 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
380 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
381 self.AddText(_("Be sure to review the default profile before running it on your machine."))
382 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
384 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
386 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
387 self.machineWidth = self.AddLabelTextCtrl(_("Machine width (mm)"), "80")
388 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth (mm)"), "80")
389 self.machineHeight = self.AddLabelTextCtrl(_("Machine height (mm)"), "55")
390 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
391 self.heatedBed = self.AddCheckbox(_("Heated bed"))
392 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
395 profile.putMachineSetting('machine_name', self.machineName.GetValue())
396 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
397 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
398 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
399 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
400 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
401 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
402 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
403 profile.putMachineSetting('extruder_head_size_min_x', '0')
404 profile.putMachineSetting('extruder_head_size_min_y', '0')
405 profile.putMachineSetting('extruder_head_size_max_x', '0')
406 profile.putMachineSetting('extruder_head_size_max_y', '0')
407 profile.putMachineSetting('extruder_head_size_height', '0')
408 profile.checkAndUpdateMachineName()
410 class MachineSelectPage(InfoPage):
411 def __init__(self, parent):
412 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
413 self.AddText(_("What kind of machine do you have:"))
415 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2", style=wx.RB_GROUP)
416 self.Ultimaker2Radio.SetValue(True)
417 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
418 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
419 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
420 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
421 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
422 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
423 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
424 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
425 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
426 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
427 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
428 self.LulzbotTazRadio = self.AddRadioButton("Lulzbot TAZ")
429 self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
430 self.LulzbotMiniRadio = self.AddRadioButton("Lulzbot Mini")
431 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
432 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
433 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
435 self.AddText(_("The collection of anonymous usage information helps with the continued improvement of Cura."))
436 self.AddText(_("This does NOT submit your models online nor gathers any privacy related information."))
437 self.SubmitUserStats = self.AddCheckbox(_("Submit anonymous usage information:"))
438 self.AddText(_("For full details see: http://wiki.ultimaker.com/Cura:stats"))
439 self.SubmitUserStats.SetValue(True)
441 def OnUltimaker2Select(self, e):
442 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
444 def OnUltimakerSelect(self, e):
445 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
447 def OnUltimakerOPSelect(self, e):
448 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
450 def OnPrintrbotSelect(self, e):
451 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
453 def OnLulzbotSelect(self, e):
454 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
456 def OnOtherSelect(self, e):
457 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
460 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
464 profile.putProfileSetting('retraction_enable', 'True')
465 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
466 if self.Ultimaker2Radio.GetValue():
467 profile.putMachineSetting('machine_width', '230')
468 profile.putMachineSetting('machine_depth', '225')
469 profile.putMachineSetting('machine_height', '205')
470 profile.putMachineSetting('machine_name', 'ultimaker2')
471 profile.putMachineSetting('machine_type', 'ultimaker2')
472 profile.putMachineSetting('has_heated_bed', 'True')
473 if self.Ultimaker2GoRadio.GetValue():
474 profile.putMachineSetting('machine_width', '120')
475 profile.putMachineSetting('machine_depth', '120')
476 profile.putMachineSetting('machine_height', '115')
477 profile.putMachineSetting('machine_name', 'ultimaker2go')
478 profile.putMachineSetting('machine_type', 'ultimaker2go')
479 profile.putMachineSetting('has_heated_bed', 'False')
480 if self.Ultimaker2ExtRadio.GetValue():
481 profile.putMachineSetting('machine_width', '230')
482 profile.putMachineSetting('machine_depth', '225')
483 profile.putMachineSetting('machine_height', '315')
484 profile.putMachineSetting('machine_name', 'ultimaker2extended')
485 profile.putMachineSetting('machine_type', 'ultimaker2extended')
486 profile.putMachineSetting('has_heated_bed', 'False')
487 profile.putMachineSetting('machine_center_is_zero', 'False')
488 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
489 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
490 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
491 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
492 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
493 profile.putMachineSetting('extruder_head_size_height', '48.0')
494 profile.putProfileSetting('nozzle_size', '0.4')
495 profile.putProfileSetting('fan_full_height', '5.0')
496 profile.putMachineSetting('extruder_offset_x1', '18.0')
497 profile.putMachineSetting('extruder_offset_y1', '0.0')
498 elif self.UltimakerRadio.GetValue():
499 profile.putMachineSetting('machine_width', '205')
500 profile.putMachineSetting('machine_depth', '205')
501 profile.putMachineSetting('machine_height', '200')
502 profile.putMachineSetting('machine_name', 'ultimaker original')
503 profile.putMachineSetting('machine_type', 'ultimaker')
504 profile.putMachineSetting('machine_center_is_zero', 'False')
505 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
506 profile.putProfileSetting('nozzle_size', '0.4')
507 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
508 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
509 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
510 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
511 profile.putMachineSetting('extruder_head_size_height', '55.0')
512 elif self.UltimakerOPRadio.GetValue():
513 profile.putMachineSetting('machine_width', '205')
514 profile.putMachineSetting('machine_depth', '205')
515 profile.putMachineSetting('machine_height', '200')
516 profile.putMachineSetting('machine_name', 'ultimaker original+')
517 profile.putMachineSetting('machine_type', 'ultimaker_plus')
518 profile.putMachineSetting('machine_center_is_zero', 'False')
519 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
520 profile.putProfileSetting('nozzle_size', '0.4')
521 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
522 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
523 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
524 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
525 profile.putMachineSetting('extruder_head_size_height', '55.0')
526 profile.putMachineSetting('has_heated_bed', 'True')
527 profile.putMachineSetting('extruder_amount', '1')
528 profile.putProfileSetting('retraction_enable', 'True')
529 elif self.LulzbotTazRadio.GetValue() or self.LulzbotMiniRadio.GetValue():
530 if self.LulzbotTazRadio.GetValue():
531 profile.putMachineSetting('machine_width', '298')
532 profile.putMachineSetting('machine_depth', '275')
533 profile.putMachineSetting('machine_height', '250')
534 profile.putProfileSetting('nozzle_size', '0.35')
535 profile.putMachineSetting('machine_name', 'Lulzbot TAZ')
537 profile.putMachineSetting('machine_width', '160')
538 profile.putMachineSetting('machine_depth', '160')
539 profile.putMachineSetting('machine_height', '160')
540 profile.putProfileSetting('nozzle_size', '0.5')
541 profile.putMachineSetting('machine_name', 'Lulzbot Mini')
542 profile.putMachineSetting('machine_type', 'Aleph Objects')
543 profile.putMachineSetting('machine_center_is_zero', 'False')
544 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
545 profile.putMachineSetting('has_heated_bed', 'True')
546 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
547 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
548 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
549 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
550 profile.putMachineSetting('extruder_head_size_height', '0.0')
552 profile.putMachineSetting('machine_width', '80')
553 profile.putMachineSetting('machine_depth', '80')
554 profile.putMachineSetting('machine_height', '60')
555 profile.putMachineSetting('machine_name', 'reprap')
556 profile.putMachineSetting('machine_type', 'reprap')
557 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
558 profile.putPreference('startMode', 'Normal')
559 profile.putProfileSetting('nozzle_size', '0.5')
560 profile.checkAndUpdateMachineName()
561 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
562 if self.SubmitUserStats.GetValue():
563 profile.putPreference('submit_slice_information', 'True')
565 profile.putPreference('submit_slice_information', 'False')
568 class SelectParts(InfoPage):
569 def __init__(self, parent):
570 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
571 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."))
573 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
574 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
575 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
576 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
578 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."))
579 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
580 self.springExtruder.SetValue(True)
583 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
584 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
585 profile.putMachineSetting('has_heated_bed', 'True')
587 profile.putMachineSetting('has_heated_bed', 'False')
588 if self.dualExtrusion.GetValue():
589 profile.putMachineSetting('extruder_amount', '2')
590 profile.putMachineSetting('machine_depth', '195')
592 profile.putMachineSetting('extruder_amount', '1')
593 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
594 profile.putProfileSetting('retraction_enable', 'True')
596 profile.putProfileSetting('retraction_enable', 'False')
599 class UltimakerFirmwareUpgradePage(InfoPage):
600 def __init__(self, parent):
601 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
602 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."))
603 self.AddHiddenSeperator()
604 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
605 self.AddHiddenSeperator()
606 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."))
607 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
608 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
609 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
610 self.AddHiddenSeperator()
611 if profile.getMachineSetting('machine_type') == 'ultimaker':
612 self.AddText(_("Do not upgrade to this firmware if:"))
613 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
614 self.AddText(_("* Build your own heated bed"))
615 self.AddText(_("* Have other changes in the firmware"))
616 # button = self.AddButton('Goto this page for a custom firmware')
617 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
622 def OnUpgradeClick(self, e):
623 if firmwareInstall.InstallFirmware():
624 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
626 def OnSkipClick(self, e):
627 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
628 self.GetParent().ShowPage(self.GetNext())
630 def OnUrlClick(self, e):
631 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
633 class UltimakerCheckupPage(InfoPage):
634 def __init__(self, parent):
635 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
637 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
638 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
639 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
640 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
641 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
642 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
643 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
644 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
645 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
646 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
649 _("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."))
650 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
651 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
652 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
654 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
655 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
656 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
658 self.infoBox = self.AddInfoBox()
659 self.machineState = self.AddText("")
660 self.temperatureLabel = self.AddText("")
661 self.errorLogButton = self.AddButton(_("Show error log"))
662 self.errorLogButton.Show(False)
664 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
666 self.xMinStop = False
667 self.xMaxStop = False
668 self.yMinStop = False
669 self.yMaxStop = False
670 self.zMinStop = False
671 self.zMaxStop = False
673 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
676 if self.comm is not None:
680 self.endstopBitmap.Show(False)
683 def OnSkipClick(self, e):
684 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
685 self.GetParent().ShowPage(self.GetNext())
687 def OnCheckClick(self, e=None):
688 self.errorLogButton.Show(False)
689 if self.comm is not None:
693 wx.CallAfter(self.OnCheckClick)
695 self.infoBox.SetBusy(_("Connecting to machine."))
696 self.commState.SetBitmap(self.unknownBitmap)
697 self.tempState.SetBitmap(self.unknownBitmap)
698 self.stopState.SetBitmap(self.unknownBitmap)
699 self.checkupState = 0
700 self.checkExtruderNr = 0
701 self.comm = machineCom.MachineCom(callbackObject=self)
703 def OnErrorLog(self, e):
704 printWindow.LogWindow('\n'.join(self.comm.getLog()))
706 def mcLog(self, message):
709 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
710 if not self.comm.isOperational():
712 if self.checkupState == 0:
713 self.tempCheckTimeout = 20
714 if temp[self.checkExtruderNr] > 70:
715 self.checkupState = 1
716 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
717 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
718 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
720 self.startTemp = temp[self.checkExtruderNr]
721 self.checkupState = 2
722 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
723 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
724 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
725 elif self.checkupState == 1:
726 if temp[self.checkExtruderNr] < 60:
727 self.startTemp = temp[self.checkExtruderNr]
728 self.checkupState = 2
729 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
730 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
731 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
732 elif self.checkupState == 2:
733 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
734 if temp[self.checkExtruderNr] > self.startTemp + 40:
735 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
736 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
737 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
738 self.checkExtruderNr = 0
739 self.checkupState = 3
740 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
741 wx.CallAfter(self.endstopBitmap.Show, True)
742 wx.CallAfter(self.Layout)
743 self.comm.sendCommand('M119')
744 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
746 self.checkupState = 0
747 self.checkExtruderNr += 1
749 self.tempCheckTimeout -= 1
750 if self.tempCheckTimeout < 1:
751 self.checkupState = -1
752 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
753 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
754 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
755 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
756 elif self.checkupState >= 3 and self.checkupState < 10:
757 self.comm.sendCommand('M119')
758 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
760 def mcStateChange(self, state):
761 if self.comm is None:
763 if self.comm.isOperational():
764 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
765 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
766 elif self.comm.isError():
767 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
768 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
769 wx.CallAfter(self.endstopBitmap.Show, False)
770 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
771 wx.CallAfter(self.errorLogButton.Show, True)
772 wx.CallAfter(self.Layout)
774 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
776 def mcMessage(self, message):
777 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
778 for data in message.split(' '):
780 tag, value = data.split(':', 1)
782 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
784 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
786 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
788 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
790 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
792 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
794 tag, value = map(str.strip, message.split(':', 1))
796 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
798 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
800 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
802 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
804 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
806 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
807 if 'z_max' in message:
808 self.comm.sendCommand('M119')
810 if self.checkupState == 3:
811 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
812 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
813 self.checkupState = 5
814 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
815 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
817 self.checkupState = 4
818 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
819 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
820 elif self.checkupState == 4:
821 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
822 self.checkupState = 5
823 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
824 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
825 elif self.checkupState == 5:
826 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
827 self.checkupState = 6
828 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
829 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
830 elif self.checkupState == 6:
831 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
832 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
833 self.checkupState = 8
834 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
835 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
837 self.checkupState = 7
838 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
839 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
840 elif self.checkupState == 7:
841 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
842 self.checkupState = 8
843 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
844 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
845 elif self.checkupState == 8:
846 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
847 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
848 self.checkupState = 10
850 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
851 wx.CallAfter(self.infoBox.SetReadyIndicator)
852 wx.CallAfter(self.endstopBitmap.Show, False)
853 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
854 wx.CallAfter(self.OnSkipClick, None)
856 self.checkupState = 9
857 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
858 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
859 elif self.checkupState == 9:
860 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
861 self.checkupState = 10
863 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
864 wx.CallAfter(self.infoBox.SetReadyIndicator)
865 wx.CallAfter(self.endstopBitmap.Show, False)
866 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
867 wx.CallAfter(self.OnSkipClick, None)
869 def mcProgress(self, lineNr):
872 def mcZChange(self, newZ):
876 class UltimakerCalibrationPage(InfoPage):
877 def __init__(self, parent):
878 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
880 self.AddText("Your Ultimaker requires some calibration.")
881 self.AddText("This calibration is needed for a proper extrusion amount.")
883 self.AddText("The following values are needed:")
884 self.AddText("* Diameter of filament")
885 self.AddText("* Number of steps per mm of filament extrusion")
887 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
889 self.AddText("First we need the diameter of your filament:")
890 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
892 "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.")
893 self.AddText("Note: This value can be changed later at any time.")
896 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
899 class UltimakerCalibrateStepsPerEPage(InfoPage):
900 def __init__(self, parent):
901 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
903 #if profile.getMachineSetting('steps_per_e') == '0':
904 # profile.putMachineSetting('steps_per_e', '865.888')
906 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
907 self.AddText(_("First remove any filament from your machine."))
908 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
909 self.AddText(_("We'll push the filament 100mm"))
910 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
911 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
912 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
913 self.AddText(_("This results in the following steps per E:"))
914 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
915 self.AddText(_("You can repeat these steps to get better calibration."))
918 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
919 self.heatButton = self.AddButton(_("Heatup for filament removal"))
921 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
922 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
923 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
925 def OnSaveLengthClick(self, e):
926 currentEValue = float(self.stepsPerEInput.GetValue())
927 realExtrudeLength = float(self.lengthInput.GetValue())
928 newEValue = currentEValue * 100 / realExtrudeLength
929 self.stepsPerEInput.SetValue(str(newEValue))
930 self.lengthInput.SetValue("100")
932 def OnExtrudeClick(self, e):
933 t = threading.Thread(target=self.OnExtrudeRun)
937 def OnExtrudeRun(self):
938 self.heatButton.Enable(False)
939 self.extrudeButton.Enable(False)
940 currentEValue = float(self.stepsPerEInput.GetValue())
941 self.comm = machineCom.MachineCom()
942 if not self.comm.isOpen():
944 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
945 'Printer error', wx.OK | wx.ICON_INFORMATION)
946 self.heatButton.Enable(True)
947 self.extrudeButton.Enable(True)
950 line = self.comm.readline()
955 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
958 self.sendGCommand('M302') #Disable cold extrusion protection
959 self.sendGCommand("M92 E%f" % (currentEValue))
960 self.sendGCommand("G92 E0")
961 self.sendGCommand("G1 E100 F600")
964 self.extrudeButton.Enable()
965 self.heatButton.Enable()
967 def OnHeatClick(self, e):
968 t = threading.Thread(target=self.OnHeatRun)
973 self.heatButton.Enable(False)
974 self.extrudeButton.Enable(False)
975 self.comm = machineCom.MachineCom()
976 if not self.comm.isOpen():
978 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
979 'Printer error', wx.OK | wx.ICON_INFORMATION)
980 self.heatButton.Enable(True)
981 self.extrudeButton.Enable(True)
984 line = self.comm.readline()
986 self.heatButton.Enable(True)
987 self.extrudeButton.Enable(True)
991 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
994 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
996 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
997 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
998 self.sendGCommand('M104 S0')
1001 self.heatButton.Enable(True)
1002 self.extrudeButton.Enable(True)
1004 def sendGCommand(self, cmd):
1005 self.comm.sendCommand(cmd) #Disable cold extrusion protection
1007 line = self.comm.readline()
1010 if line.startswith('ok'):
1013 def StoreData(self):
1014 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1016 class Ultimaker2ReadyPage(InfoPage):
1017 def __init__(self, parent):
1018 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1019 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1020 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1023 class LulzbotReadyPage(InfoPage):
1024 def __init__(self, parent):
1025 super(LulzbotReadyPage, self).__init__(parent, _("Lulzbot TAZ/Mini"))
1026 self.AddText(_('Cura is now ready to be used with your Lulzbot.'))
1029 class ConfigWizard(wx.wizard.Wizard):
1030 def __init__(self, addNew = False):
1031 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1033 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1035 profile.setActiveMachine(profile.getMachineCount())
1037 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1038 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1039 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1041 self.firstInfoPage = FirstInfoPage(self, addNew)
1042 self.machineSelectPage = MachineSelectPage(self)
1043 self.ultimakerSelectParts = SelectParts(self)
1044 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1045 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1046 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1047 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1048 self.bedLevelPage = bedLevelWizardMain(self)
1049 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1050 self.printrbotSelectType = PrintrbotPage(self)
1051 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1052 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1053 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1055 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1056 self.lulzbotReadyPage = LulzbotReadyPage(self)
1058 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
1059 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1060 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1061 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1062 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1063 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1064 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1065 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1066 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1068 self.FitToPage(self.firstInfoPage)
1069 self.GetPageAreaSizer().Add(self.firstInfoPage)
1071 self.RunWizard(self.firstInfoPage)
1074 def OnPageChanging(self, e):
1075 e.GetPage().StoreData()
1077 def OnPageChanged(self, e):
1078 if e.GetPage().AllowNext():
1079 self.FindWindowById(wx.ID_FORWARD).Enable()
1081 self.FindWindowById(wx.ID_FORWARD).Disable()
1082 if e.GetPage().AllowBack():
1083 self.FindWindowById(wx.ID_BACKWARD).Enable()
1085 self.FindWindowById(wx.ID_BACKWARD).Disable()
1087 def OnCancel(self, e):
1088 profile.setActiveMachine(self._old_machine_index)
1090 class bedLevelWizardMain(InfoPage):
1091 def __init__(self, parent):
1092 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1094 self.AddText(_('This wizard will help you in leveling your printer bed'))
1096 self.AddText(_('It will do the following steps'))
1097 self.AddText(_('* Move the printer head to each corner'))
1098 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1099 self.AddText(_('* Print a line around the bed to check if it is level'))
1102 self.connectButton = self.AddButton(_('Connect to printer'))
1105 self.infoBox = self.AddInfoBox()
1106 self.resumeButton = self.AddButton(_('Resume'))
1107 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1108 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1109 self.resumeButton.Enable(False)
1111 self.upButton.Enable(False)
1112 self.downButton.Enable(False)
1113 self.upButton2.Enable(False)
1114 self.downButton2.Enable(False)
1116 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1117 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1118 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1119 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1120 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1121 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1123 def OnConnect(self, e = None):
1124 if self.comm is not None:
1128 wx.CallAfter(self.OnConnect)
1130 self.connectButton.Enable(False)
1131 self.comm = machineCom.MachineCom(callbackObject=self)
1132 self.infoBox.SetBusy(_('Connecting to machine.'))
1133 self._wizardState = 0
1135 def OnBedUp(self, e):
1136 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1137 self.comm.sendCommand('G92 Z10')
1138 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1139 self.comm.sendCommand('M400')
1141 def OnBedDown(self, e):
1142 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1143 self.comm.sendCommand('G92 Z10')
1144 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1145 self.comm.sendCommand('M400')
1147 def OnBedUp2(self, e):
1148 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1149 self.comm.sendCommand('G92 Z10')
1150 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1151 self.comm.sendCommand('M400')
1153 def OnBedDown2(self, e):
1154 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1155 self.comm.sendCommand('G92 Z10')
1156 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1157 self.comm.sendCommand('M400')
1159 def AllowNext(self):
1160 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1161 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1164 def OnResume(self, e):
1165 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1166 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1167 if self._wizardState == -1:
1168 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1169 wx.CallAfter(self.upButton.Enable, False)
1170 wx.CallAfter(self.downButton.Enable, False)
1171 wx.CallAfter(self.upButton2.Enable, False)
1172 wx.CallAfter(self.downButton2.Enable, False)
1173 self.comm.sendCommand('M105')
1174 self.comm.sendCommand('G28')
1175 self._wizardState = 1
1176 elif self._wizardState == 2:
1177 if profile.getMachineSetting('has_heated_bed') == 'True':
1178 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1179 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1180 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1181 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1182 self.comm.sendCommand('M400')
1183 self._wizardState = 3
1185 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1186 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1187 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1188 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1189 self.comm.sendCommand('M400')
1190 self._wizardState = 3
1191 elif self._wizardState == 4:
1192 if profile.getMachineSetting('has_heated_bed') == 'True':
1193 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1194 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1195 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1196 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1197 self.comm.sendCommand('M400')
1198 self._wizardState = 7
1200 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1201 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1202 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1203 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1204 self.comm.sendCommand('M400')
1205 self._wizardState = 5
1206 elif self._wizardState == 6:
1207 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1208 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1209 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1210 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1211 self.comm.sendCommand('M400')
1212 self._wizardState = 7
1213 elif self._wizardState == 8:
1214 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1215 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1216 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1217 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1218 self._wizardState = 9
1219 elif self._wizardState == 10:
1220 self._wizardState = 11
1221 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1222 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1223 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1224 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1225 w = profile.getMachineSettingFloat('machine_width') - 10
1226 d = profile.getMachineSettingFloat('machine_depth')
1227 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1228 filamentArea = math.pi * filamentRadius * filamentRadius
1229 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1233 'G1 Z2 F%d' % (feedZ),
1235 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1236 'G1 Z0.3 F%d' % (feedZ)]
1238 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1240 for i in xrange(0, 3):
1241 dist = 5.0 + 0.4 * float(i)
1242 eValue += (d - 2.0*dist) * ePerMM
1243 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1244 eValue += (w - 2.0*dist) * ePerMM
1245 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1246 eValue += (d - 2.0*dist) * ePerMM
1247 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1248 eValue += (w - 2.0*dist) * ePerMM
1249 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1251 gcodeList.append('M400')
1252 self.comm.printGCode(gcodeList)
1253 self.resumeButton.Enable(False)
1255 def mcLog(self, message):
1256 print 'Log:', message
1258 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1259 if self._wizardState == 1:
1260 self._wizardState = 2
1261 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1262 wx.CallAfter(self.resumeButton.Enable, True)
1263 elif self._wizardState == 3:
1264 self._wizardState = 4
1265 if profile.getMachineSetting('has_heated_bed') == 'True':
1266 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1268 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1269 wx.CallAfter(self.resumeButton.Enable, True)
1270 elif self._wizardState == 5:
1271 self._wizardState = 6
1272 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1273 wx.CallAfter(self.resumeButton.Enable, True)
1274 elif self._wizardState == 7:
1275 self._wizardState = 8
1276 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1277 wx.CallAfter(self.resumeButton.Enable, True)
1278 elif self._wizardState == 9:
1279 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1280 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1282 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1283 wx.CallAfter(self.resumeButton.Enable, True)
1284 self._wizardState = 10
1286 def mcStateChange(self, state):
1287 if self.comm is None:
1289 if self.comm.isOperational():
1290 if self._wizardState == 0:
1291 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1292 wx.CallAfter(self.upButton.Enable, True)
1293 wx.CallAfter(self.downButton.Enable, True)
1294 wx.CallAfter(self.upButton2.Enable, True)
1295 wx.CallAfter(self.downButton2.Enable, True)
1296 wx.CallAfter(self.resumeButton.Enable, True)
1297 self._wizardState = -1
1298 elif self._wizardState == 11 and not self.comm.isPrinting():
1299 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1300 self.comm.sendCommand('G92 E0')
1301 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1302 self.comm.sendCommand('M104 S0')
1303 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1304 wx.CallAfter(self.infoBox.SetReadyIndicator)
1305 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1306 wx.CallAfter(self.connectButton.Enable, True)
1307 self._wizardState = 12
1308 elif self.comm.isError():
1309 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1311 def mcMessage(self, message):
1314 def mcProgress(self, lineNr):
1317 def mcZChange(self, newZ):
1320 class headOffsetCalibrationPage(InfoPage):
1321 def __init__(self, parent):
1322 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
1324 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1327 self.connectButton = self.AddButton(_('Connect to printer'))
1330 self.infoBox = self.AddInfoBox()
1331 self.textEntry = self.AddTextCtrl('')
1332 self.textEntry.Enable(False)
1333 self.resumeButton = self.AddButton(_('Resume'))
1334 self.resumeButton.Enable(False)
1336 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1337 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1339 def AllowBack(self):
1342 def OnConnect(self, e = None):
1343 if self.comm is not None:
1347 wx.CallAfter(self.OnConnect)
1349 self.connectButton.Enable(False)
1350 self.comm = machineCom.MachineCom(callbackObject=self)
1351 self.infoBox.SetBusy(_('Connecting to machine.'))
1352 self._wizardState = 0
1354 def OnResume(self, e):
1355 if self._wizardState == 2:
1356 self._wizardState = 3
1357 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1359 w = profile.getMachineSettingFloat('machine_width')
1360 d = profile.getMachineSettingFloat('machine_depth')
1362 gcode = gcodeGenerator.gcodeGenerator()
1363 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1364 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1371 gcode.addMove(w/2, 5)
1372 gcode.addMove(z=0.2)
1374 gcode.addExtrude(w/2, d-5.0)
1376 gcode.addMove(5, d/2)
1378 gcode.addExtrude(w-5.0, d/2)
1379 gcode.addRetract(15)
1382 gcode.addMove(w/2, 5)
1384 gcode.addExtrude(w/2, d-5.0)
1386 gcode.addMove(5, d/2)
1388 gcode.addExtrude(w-5.0, d/2)
1389 gcode.addRetract(15)
1394 gcode.addCmd('M400')
1396 self.comm.printGCode(gcode.list())
1397 self.resumeButton.Enable(False)
1398 elif self._wizardState == 4:
1400 float(self.textEntry.GetValue())
1403 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1404 self._wizardState = 5
1405 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1406 self.textEntry.SetValue('0.0')
1407 self.textEntry.Enable(True)
1408 elif self._wizardState == 5:
1410 float(self.textEntry.GetValue())
1413 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1414 self._wizardState = 6
1415 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1416 self.textEntry.SetValue('')
1417 self.textEntry.Enable(False)
1418 self.resumeButton.Enable(False)
1420 x = profile.getMachineSettingFloat('extruder_offset_x1')
1421 y = profile.getMachineSettingFloat('extruder_offset_y1')
1422 gcode = gcodeGenerator.gcodeGenerator()
1423 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1424 gcode.setPrintSpeed(25)
1427 gcode.addMove(50, 40, 0.2)
1429 for n in xrange(0, 10):
1430 gcode.addExtrude(50 + n * 10, 150)
1431 gcode.addExtrude(50 + n * 10 + 5, 150)
1432 gcode.addExtrude(50 + n * 10 + 5, 40)
1433 gcode.addExtrude(50 + n * 10 + 10, 40)
1434 gcode.addMove(40, 50)
1435 for n in xrange(0, 10):
1436 gcode.addExtrude(150, 50 + n * 10)
1437 gcode.addExtrude(150, 50 + n * 10 + 5)
1438 gcode.addExtrude(40, 50 + n * 10 + 5)
1439 gcode.addExtrude(40, 50 + n * 10 + 10)
1440 gcode.addRetract(15)
1443 gcode.addMove(50 - x, 30 - y, 0.2)
1445 for n in xrange(0, 10):
1446 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1447 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1448 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1449 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1450 gcode.addMove(30 - x, 50 - y, 0.2)
1451 for n in xrange(0, 10):
1452 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1453 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1454 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1455 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1456 gcode.addRetract(15)
1458 gcode.addCmd('M400')
1459 gcode.addCmd('M104 T0 S0')
1460 gcode.addCmd('M104 T1 S0')
1461 self.comm.printGCode(gcode.list())
1462 elif self._wizardState == 7:
1464 n = int(self.textEntry.GetValue()) - 1
1467 x = profile.getMachineSettingFloat('extruder_offset_x1')
1469 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1470 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1471 self.textEntry.SetValue('10')
1472 self._wizardState = 8
1473 elif self._wizardState == 8:
1475 n = int(self.textEntry.GetValue()) - 1
1478 y = profile.getMachineSettingFloat('extruder_offset_y1')
1480 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1481 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1482 self.infoBox.SetReadyIndicator()
1483 self._wizardState = 8
1485 self.resumeButton.Enable(False)
1487 def mcLog(self, message):
1488 print 'Log:', message
1490 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1491 if self._wizardState == 1:
1492 if temp[0] >= 210 and temp[1] >= 210:
1493 self._wizardState = 2
1494 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1495 wx.CallAfter(self.resumeButton.Enable, True)
1496 wx.CallAfter(self.resumeButton.SetFocus)
1498 def mcStateChange(self, state):
1499 if self.comm is None:
1501 if self.comm.isOperational():
1502 if self._wizardState == 0:
1503 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1504 self.comm.sendCommand('M105')
1505 self.comm.sendCommand('M104 S220 T0')
1506 self.comm.sendCommand('M104 S220 T1')
1507 self.comm.sendCommand('G28')
1508 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1509 self._wizardState = 1
1510 if not self.comm.isPrinting():
1511 if self._wizardState == 3:
1512 self._wizardState = 4
1513 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1514 wx.CallAfter(self.textEntry.SetValue, '0.0')
1515 wx.CallAfter(self.textEntry.Enable, True)
1516 wx.CallAfter(self.resumeButton.Enable, True)
1517 wx.CallAfter(self.resumeButton.SetFocus)
1518 elif self._wizardState == 6:
1519 self._wizardState = 7
1520 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1521 wx.CallAfter(self.textEntry.SetValue, '10')
1522 wx.CallAfter(self.textEntry.Enable, True)
1523 wx.CallAfter(self.resumeButton.Enable, True)
1524 wx.CallAfter(self.resumeButton.SetFocus)
1526 elif self.comm.isError():
1527 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1529 def mcMessage(self, message):
1532 def mcProgress(self, lineNr):
1535 def mcZChange(self, newZ):
1538 class bedLevelWizard(wx.wizard.Wizard):
1540 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1542 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1543 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1545 self.mainPage = bedLevelWizardMain(self)
1546 self.headOffsetCalibration = None
1548 self.FitToPage(self.mainPage)
1549 self.GetPageAreaSizer().Add(self.mainPage)
1551 self.RunWizard(self.mainPage)
1554 def OnPageChanging(self, e):
1555 e.GetPage().StoreData()
1557 def OnPageChanged(self, e):
1558 if e.GetPage().AllowNext():
1559 self.FindWindowById(wx.ID_FORWARD).Enable()
1561 self.FindWindowById(wx.ID_FORWARD).Disable()
1562 if e.GetPage().AllowBack():
1563 self.FindWindowById(wx.ID_BACKWARD).Enable()
1565 self.FindWindowById(wx.ID_BACKWARD).Disable()
1567 class headOffsetWizard(wx.wizard.Wizard):
1569 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1571 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1572 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1574 self.mainPage = headOffsetCalibrationPage(self)
1576 self.FitToPage(self.mainPage)
1577 self.GetPageAreaSizer().Add(self.mainPage)
1579 self.RunWizard(self.mainPage)
1582 def OnPageChanging(self, e):
1583 e.GetPage().StoreData()
1585 def OnPageChanged(self, e):
1586 if e.GetPage().AllowNext():
1587 self.FindWindowById(wx.ID_FORWARD).Enable()
1589 self.FindWindowById(wx.ID_FORWARD).Disable()
1590 if e.GetPage().AllowBack():
1591 self.FindWindowById(wx.ID_BACKWARD).Enable()
1593 self.FindWindowById(wx.ID_BACKWARD).Disable()