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.5, 1.75, 208, 40, 70, 30, 1, False),
269 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.5, 1.75, 208, 40, 70, 30, 1, False),
270 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.5, 1.75, 208, 40, 70, 30, 1, False),
271 ("Simple Maker's Edition v4 (Model 1405)", 100, 100, 100, 0.5, 1.75, 208, 40, 70, 30, 1, False),
272 ("Jr v1", 150, 100, 80, 0.5, 1.75, 208, 40, 70, 30, 1, False),
273 ("Jr v2", 150, 150, 150, 0.5, 1.75, 208, 40, 70, 30, 1, False),
274 ("LC v2", 150, 150, 150, 0.5, 1.75, 208, 40, 70, 30, 1, False),
275 ("Plus v2", 200, 200, 200, 0.5, 1.75, 208, 40, 70, 30, 1, False),
276 ("Plus v2.1", 200, 200, 200, 0.5, 1.75, 208, 40, 70, 30, 1, False),
277 ("Plus v2.2 (Model 1404/140422)", 250, 250, 250, 0.5, 1.75, 208, 40, 70, 30, 1, False),
278 ("Plus v2.3 (Model 140501)", 250, 250, 250, 0.5, 1.75, 208, 40, 70, 30, 1, False),
279 ("Plus v2.4 (Model 140507)", 250, 250, 250, 0.5, 1.75, 208, 40, 70, 30, 1, False),
280 ("Go v2 Large", 609, 305, 305, 0.5, 1.75, 208, 35, 70, 30, 1, False),
283 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
284 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
285 self.AddText(_("Select which Printrbot machine you have:"))
287 for printer in self._printer_info:
288 if printer[0].startswith(":"):
290 self.AddText(printer[0][1:])
292 item = self.AddRadioButton(printer[0])
293 item.data = printer[1:]
294 self._items.append(item)
297 profile.putMachineSetting('machine_name', 'Printrbot ???')
298 for item in self._items:
301 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
302 profile.putMachineSetting('machine_width', data[0])
303 profile.putMachineSetting('machine_depth', data[1])
304 profile.putMachineSetting('machine_height', data[2])
305 profile.putProfileSetting('nozzle_size', data[3])
306 profile.putProfileSetting('filament_diameter', data[4])
307 profile.putProfileSetting('print_temperature', data[5])
308 profile.putProfileSetting('print_speed', data[6])
309 profile.putProfileSetting('travel_speed', data[7])
310 profile.putProfileSetting('retraction_speed', data[8])
311 profile.putProfileSetting('retraction_amount', data[9])
312 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
313 profile.putMachineSetting('has_heated_bed', 'False')
314 profile.putMachineSetting('machine_center_is_zero', 'False')
315 profile.putMachineSetting('extruder_head_size_min_x', '0')
316 profile.putMachineSetting('extruder_head_size_min_y', '0')
317 profile.putMachineSetting('extruder_head_size_max_x', '0')
318 profile.putMachineSetting('extruder_head_size_max_y', '0')
319 profile.putMachineSetting('extruder_head_size_height', '0')
321 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
322 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
323 ;Print time: {print_time}
324 ;Filament used: {filament_amount}m {filament_weight}g
325 ;Filament cost: {filament_cost}
326 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
327 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
329 G90 ;absolute positioning
330 M82 ;set extruder to absolute mode
331 M107 ;start with the fan off
333 G28 X0 Y0 ;move X/Y to min endstops
334 G28 Z0 ;move Z to min endstops
335 G29 ;Run the auto bed leveling
337 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
339 G92 E0 ;zero the extruded length
340 G1 F200 E3 ;extrude 3mm of feed stock
341 G92 E0 ;zero the extruded length again
343 ;Put printing message on LCD screen
347 class OtherMachineSelectPage(InfoPage):
348 def __init__(self, parent):
349 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
350 self.AddText(_("The following pre-defined machine profiles are available"))
351 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."))
353 machines = resources.getDefaultMachineProfiles()
355 for filename in machines:
356 name = os.path.splitext(os.path.basename(filename))[0]
357 item = self.AddRadioButton(name)
358 item.filename = filename
359 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
360 self.options.append(item)
362 item = self.AddRadioButton(_('Custom...'))
364 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
366 def OnProfileSelect(self, e):
367 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
369 def OnOtherSelect(self, e):
370 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
373 for option in self.options:
374 if option.GetValue():
375 profile.loadProfile(option.filename)
376 profile.loadMachineSettings(option.filename)
378 class OtherMachineInfoPage(InfoPage):
379 def __init__(self, parent):
380 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
381 self.AddText(_("Cura is now ready to be used!"))
383 class CustomRepRapInfoPage(InfoPage):
384 def __init__(self, parent):
385 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
386 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
387 self.AddText(_("Be sure to review the default profile before running it on your machine."))
388 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
390 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
392 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
393 self.machineWidth = self.AddLabelTextCtrl(_("Machine width (mm)"), "80")
394 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth (mm)"), "80")
395 self.machineHeight = self.AddLabelTextCtrl(_("Machine height (mm)"), "55")
396 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
397 self.heatedBed = self.AddCheckbox(_("Heated bed"))
398 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
401 profile.putMachineSetting('machine_name', self.machineName.GetValue())
402 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
403 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
404 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
405 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
406 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
407 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
408 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
409 profile.putMachineSetting('extruder_head_size_min_x', '0')
410 profile.putMachineSetting('extruder_head_size_min_y', '0')
411 profile.putMachineSetting('extruder_head_size_max_x', '0')
412 profile.putMachineSetting('extruder_head_size_max_y', '0')
413 profile.putMachineSetting('extruder_head_size_height', '0')
414 profile.checkAndUpdateMachineName()
416 class MachineSelectPage(InfoPage):
417 def __init__(self, parent):
418 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
419 self.AddText(_("What kind of machine do you have:"))
421 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2", style=wx.RB_GROUP)
422 self.Ultimaker2Radio.SetValue(True)
423 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
424 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
425 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
426 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
427 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
428 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
429 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
430 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
431 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
432 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
433 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
434 self.LulzbotTazRadio = self.AddRadioButton("Lulzbot TAZ")
435 self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
436 self.LulzbotMiniRadio = self.AddRadioButton("Lulzbot Mini")
437 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
438 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
439 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
441 self.AddText(_("The collection of anonymous usage information helps with the continued improvement of Cura."))
442 self.AddText(_("This does NOT submit your models online nor gathers any privacy related information."))
443 self.SubmitUserStats = self.AddCheckbox(_("Submit anonymous usage information:"))
444 self.AddText(_("For full details see: http://wiki.ultimaker.com/Cura:stats"))
445 self.SubmitUserStats.SetValue(True)
447 def OnUltimaker2Select(self, e):
448 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
450 def OnUltimakerSelect(self, e):
451 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
453 def OnUltimakerOPSelect(self, e):
454 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
456 def OnPrintrbotSelect(self, e):
457 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
459 def OnLulzbotSelect(self, e):
460 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
462 def OnOtherSelect(self, e):
463 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
466 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
470 profile.putProfileSetting('retraction_enable', 'True')
471 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
472 if self.Ultimaker2Radio.GetValue():
473 profile.putMachineSetting('machine_width', '230')
474 profile.putMachineSetting('machine_depth', '225')
475 profile.putMachineSetting('machine_height', '205')
476 profile.putMachineSetting('machine_name', 'ultimaker2')
477 profile.putMachineSetting('machine_type', 'ultimaker2')
478 profile.putMachineSetting('has_heated_bed', 'True')
479 if self.Ultimaker2GoRadio.GetValue():
480 profile.putMachineSetting('machine_width', '120')
481 profile.putMachineSetting('machine_depth', '120')
482 profile.putMachineSetting('machine_height', '115')
483 profile.putMachineSetting('machine_name', 'ultimaker2go')
484 profile.putMachineSetting('machine_type', 'ultimaker2go')
485 profile.putMachineSetting('has_heated_bed', 'False')
486 if self.Ultimaker2ExtRadio.GetValue():
487 profile.putMachineSetting('machine_width', '230')
488 profile.putMachineSetting('machine_depth', '225')
489 profile.putMachineSetting('machine_height', '305')
490 profile.putMachineSetting('machine_name', 'ultimaker2extended')
491 profile.putMachineSetting('machine_type', 'ultimaker2extended')
492 profile.putMachineSetting('has_heated_bed', 'False')
493 profile.putMachineSetting('machine_center_is_zero', 'False')
494 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
495 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
496 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
497 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
498 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
499 profile.putMachineSetting('extruder_head_size_height', '48.0')
500 profile.putProfileSetting('nozzle_size', '0.4')
501 profile.putProfileSetting('fan_full_height', '5.0')
502 profile.putMachineSetting('extruder_offset_x1', '18.0')
503 profile.putMachineSetting('extruder_offset_y1', '0.0')
504 elif self.UltimakerRadio.GetValue():
505 profile.putMachineSetting('machine_width', '205')
506 profile.putMachineSetting('machine_depth', '205')
507 profile.putMachineSetting('machine_height', '200')
508 profile.putMachineSetting('machine_name', 'ultimaker original')
509 profile.putMachineSetting('machine_type', 'ultimaker')
510 profile.putMachineSetting('machine_center_is_zero', 'False')
511 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
512 profile.putProfileSetting('nozzle_size', '0.4')
513 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
514 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
515 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
516 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
517 profile.putMachineSetting('extruder_head_size_height', '55.0')
518 elif self.UltimakerOPRadio.GetValue():
519 profile.putMachineSetting('machine_width', '205')
520 profile.putMachineSetting('machine_depth', '205')
521 profile.putMachineSetting('machine_height', '200')
522 profile.putMachineSetting('machine_name', 'ultimaker original+')
523 profile.putMachineSetting('machine_type', 'ultimaker_plus')
524 profile.putMachineSetting('machine_center_is_zero', 'False')
525 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
526 profile.putProfileSetting('nozzle_size', '0.4')
527 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
528 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
529 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
530 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
531 profile.putMachineSetting('extruder_head_size_height', '55.0')
532 profile.putMachineSetting('has_heated_bed', 'True')
533 profile.putMachineSetting('extruder_amount', '1')
534 profile.putProfileSetting('retraction_enable', 'True')
535 elif self.LulzbotTazRadio.GetValue() or self.LulzbotMiniRadio.GetValue():
536 if self.LulzbotTazRadio.GetValue():
537 profile.putMachineSetting('machine_width', '298')
538 profile.putMachineSetting('machine_depth', '275')
539 profile.putMachineSetting('machine_height', '250')
540 profile.putProfileSetting('nozzle_size', '0.35')
541 profile.putMachineSetting('machine_name', 'Lulzbot TAZ')
543 profile.putMachineSetting('machine_width', '160')
544 profile.putMachineSetting('machine_depth', '160')
545 profile.putMachineSetting('machine_height', '160')
546 profile.putProfileSetting('nozzle_size', '0.5')
547 profile.putMachineSetting('machine_name', 'Lulzbot Mini')
548 profile.putMachineSetting('machine_type', 'Aleph Objects')
549 profile.putMachineSetting('machine_center_is_zero', 'False')
550 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
551 profile.putMachineSetting('has_heated_bed', 'True')
552 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
553 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
554 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
555 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
556 profile.putMachineSetting('extruder_head_size_height', '0.0')
558 profile.putMachineSetting('machine_width', '80')
559 profile.putMachineSetting('machine_depth', '80')
560 profile.putMachineSetting('machine_height', '60')
561 profile.putMachineSetting('machine_name', 'reprap')
562 profile.putMachineSetting('machine_type', 'reprap')
563 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
564 profile.putPreference('startMode', 'Normal')
565 profile.putProfileSetting('nozzle_size', '0.5')
566 profile.checkAndUpdateMachineName()
567 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
568 if self.SubmitUserStats.GetValue():
569 profile.putPreference('submit_slice_information', 'True')
571 profile.putPreference('submit_slice_information', 'False')
574 class SelectParts(InfoPage):
575 def __init__(self, parent):
576 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
577 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."))
579 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
580 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
581 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
582 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
584 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."))
585 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
586 self.springExtruder.SetValue(True)
589 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
590 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
591 profile.putMachineSetting('has_heated_bed', 'True')
593 profile.putMachineSetting('has_heated_bed', 'False')
594 if self.dualExtrusion.GetValue():
595 profile.putMachineSetting('extruder_amount', '2')
596 profile.putMachineSetting('machine_depth', '195')
598 profile.putMachineSetting('extruder_amount', '1')
599 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
600 profile.putProfileSetting('retraction_enable', 'True')
602 profile.putProfileSetting('retraction_enable', 'False')
605 class UltimakerFirmwareUpgradePage(InfoPage):
606 def __init__(self, parent):
607 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
608 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."))
609 self.AddHiddenSeperator()
610 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
611 self.AddHiddenSeperator()
612 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."))
613 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
614 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
615 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
616 self.AddHiddenSeperator()
617 if profile.getMachineSetting('machine_type') == 'ultimaker':
618 self.AddText(_("Do not upgrade to this firmware if:"))
619 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
620 self.AddText(_("* Build your own heated bed"))
621 self.AddText(_("* Have other changes in the firmware"))
622 # button = self.AddButton('Goto this page for a custom firmware')
623 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
628 def OnUpgradeClick(self, e):
629 if firmwareInstall.InstallFirmware():
630 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
632 def OnSkipClick(self, e):
633 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
634 self.GetParent().ShowPage(self.GetNext())
636 def OnUrlClick(self, e):
637 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
639 class UltimakerCheckupPage(InfoPage):
640 def __init__(self, parent):
641 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
643 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
644 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
645 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
646 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
647 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
648 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
649 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
650 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
651 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
652 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
655 _("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."))
656 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
657 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
658 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
660 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
661 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
662 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
664 self.infoBox = self.AddInfoBox()
665 self.machineState = self.AddText("")
666 self.temperatureLabel = self.AddText("")
667 self.errorLogButton = self.AddButton(_("Show error log"))
668 self.errorLogButton.Show(False)
670 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
672 self.xMinStop = False
673 self.xMaxStop = False
674 self.yMinStop = False
675 self.yMaxStop = False
676 self.zMinStop = False
677 self.zMaxStop = False
679 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
682 if self.comm is not None:
686 self.endstopBitmap.Show(False)
689 def OnSkipClick(self, e):
690 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
691 self.GetParent().ShowPage(self.GetNext())
693 def OnCheckClick(self, e=None):
694 self.errorLogButton.Show(False)
695 if self.comm is not None:
699 wx.CallAfter(self.OnCheckClick)
701 self.infoBox.SetBusy(_("Connecting to machine."))
702 self.commState.SetBitmap(self.unknownBitmap)
703 self.tempState.SetBitmap(self.unknownBitmap)
704 self.stopState.SetBitmap(self.unknownBitmap)
705 self.checkupState = 0
706 self.checkExtruderNr = 0
707 self.comm = machineCom.MachineCom(callbackObject=self)
709 def OnErrorLog(self, e):
710 printWindow.LogWindow('\n'.join(self.comm.getLog()))
712 def mcLog(self, message):
715 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
716 if not self.comm.isOperational():
718 if self.checkupState == 0:
719 self.tempCheckTimeout = 20
720 if temp[self.checkExtruderNr] > 70:
721 self.checkupState = 1
722 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
723 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
724 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
726 self.startTemp = temp[self.checkExtruderNr]
727 self.checkupState = 2
728 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
729 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
730 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
731 elif self.checkupState == 1:
732 if temp[self.checkExtruderNr] < 60:
733 self.startTemp = temp[self.checkExtruderNr]
734 self.checkupState = 2
735 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
736 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
737 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
738 elif self.checkupState == 2:
739 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
740 if temp[self.checkExtruderNr] > self.startTemp + 40:
741 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
742 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
743 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
744 self.checkExtruderNr = 0
745 self.checkupState = 3
746 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
747 wx.CallAfter(self.endstopBitmap.Show, True)
748 wx.CallAfter(self.Layout)
749 self.comm.sendCommand('M119')
750 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
752 self.checkupState = 0
753 self.checkExtruderNr += 1
755 self.tempCheckTimeout -= 1
756 if self.tempCheckTimeout < 1:
757 self.checkupState = -1
758 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
759 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
760 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
761 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
762 elif self.checkupState >= 3 and self.checkupState < 10:
763 self.comm.sendCommand('M119')
764 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
766 def mcStateChange(self, state):
767 if self.comm is None:
769 if self.comm.isOperational():
770 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
771 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
772 elif self.comm.isError():
773 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
774 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
775 wx.CallAfter(self.endstopBitmap.Show, False)
776 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
777 wx.CallAfter(self.errorLogButton.Show, True)
778 wx.CallAfter(self.Layout)
780 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
782 def mcMessage(self, message):
783 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
784 for data in message.split(' '):
786 tag, value = data.split(':', 1)
788 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
790 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
792 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
794 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
796 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
798 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
800 tag, value = map(str.strip, message.split(':', 1))
802 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
804 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
806 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
808 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
810 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
812 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
813 if 'z_max' in message:
814 self.comm.sendCommand('M119')
816 if self.checkupState == 3:
817 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
818 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
819 self.checkupState = 5
820 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
821 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
823 self.checkupState = 4
824 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
825 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
826 elif self.checkupState == 4:
827 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
828 self.checkupState = 5
829 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
830 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
831 elif self.checkupState == 5:
832 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
833 self.checkupState = 6
834 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
835 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
836 elif self.checkupState == 6:
837 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
838 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
839 self.checkupState = 8
840 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
841 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
843 self.checkupState = 7
844 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
845 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
846 elif self.checkupState == 7:
847 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
848 self.checkupState = 8
849 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
850 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
851 elif self.checkupState == 8:
852 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
853 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
854 self.checkupState = 10
856 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
857 wx.CallAfter(self.infoBox.SetReadyIndicator)
858 wx.CallAfter(self.endstopBitmap.Show, False)
859 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
860 wx.CallAfter(self.OnSkipClick, None)
862 self.checkupState = 9
863 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
864 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
865 elif self.checkupState == 9:
866 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
867 self.checkupState = 10
869 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
870 wx.CallAfter(self.infoBox.SetReadyIndicator)
871 wx.CallAfter(self.endstopBitmap.Show, False)
872 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
873 wx.CallAfter(self.OnSkipClick, None)
875 def mcProgress(self, lineNr):
878 def mcZChange(self, newZ):
882 class UltimakerCalibrationPage(InfoPage):
883 def __init__(self, parent):
884 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
886 self.AddText("Your Ultimaker requires some calibration.")
887 self.AddText("This calibration is needed for a proper extrusion amount.")
889 self.AddText("The following values are needed:")
890 self.AddText("* Diameter of filament")
891 self.AddText("* Number of steps per mm of filament extrusion")
893 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
895 self.AddText("First we need the diameter of your filament:")
896 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
898 "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.")
899 self.AddText("Note: This value can be changed later at any time.")
902 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
905 class UltimakerCalibrateStepsPerEPage(InfoPage):
906 def __init__(self, parent):
907 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
909 #if profile.getMachineSetting('steps_per_e') == '0':
910 # profile.putMachineSetting('steps_per_e', '865.888')
912 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
913 self.AddText(_("First remove any filament from your machine."))
914 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
915 self.AddText(_("We'll push the filament 100mm"))
916 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
917 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
918 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
919 self.AddText(_("This results in the following steps per E:"))
920 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
921 self.AddText(_("You can repeat these steps to get better calibration."))
924 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
925 self.heatButton = self.AddButton(_("Heatup for filament removal"))
927 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
928 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
929 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
931 def OnSaveLengthClick(self, e):
932 currentEValue = float(self.stepsPerEInput.GetValue())
933 realExtrudeLength = float(self.lengthInput.GetValue())
934 newEValue = currentEValue * 100 / realExtrudeLength
935 self.stepsPerEInput.SetValue(str(newEValue))
936 self.lengthInput.SetValue("100")
938 def OnExtrudeClick(self, e):
939 t = threading.Thread(target=self.OnExtrudeRun)
943 def OnExtrudeRun(self):
944 self.heatButton.Enable(False)
945 self.extrudeButton.Enable(False)
946 currentEValue = float(self.stepsPerEInput.GetValue())
947 self.comm = machineCom.MachineCom()
948 if not self.comm.isOpen():
950 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
951 'Printer error', wx.OK | wx.ICON_INFORMATION)
952 self.heatButton.Enable(True)
953 self.extrudeButton.Enable(True)
956 line = self.comm.readline()
961 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
964 self.sendGCommand('M302') #Disable cold extrusion protection
965 self.sendGCommand("M92 E%f" % (currentEValue))
966 self.sendGCommand("G92 E0")
967 self.sendGCommand("G1 E100 F600")
970 self.extrudeButton.Enable()
971 self.heatButton.Enable()
973 def OnHeatClick(self, e):
974 t = threading.Thread(target=self.OnHeatRun)
979 self.heatButton.Enable(False)
980 self.extrudeButton.Enable(False)
981 self.comm = machineCom.MachineCom()
982 if not self.comm.isOpen():
984 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
985 'Printer error', wx.OK | wx.ICON_INFORMATION)
986 self.heatButton.Enable(True)
987 self.extrudeButton.Enable(True)
990 line = self.comm.readline()
992 self.heatButton.Enable(True)
993 self.extrudeButton.Enable(True)
997 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1000 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
1002 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
1003 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
1004 self.sendGCommand('M104 S0')
1007 self.heatButton.Enable(True)
1008 self.extrudeButton.Enable(True)
1010 def sendGCommand(self, cmd):
1011 self.comm.sendCommand(cmd) #Disable cold extrusion protection
1013 line = self.comm.readline()
1016 if line.startswith('ok'):
1019 def StoreData(self):
1020 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1022 class Ultimaker2ReadyPage(InfoPage):
1023 def __init__(self, parent):
1024 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1025 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1026 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1029 class LulzbotReadyPage(InfoPage):
1030 def __init__(self, parent):
1031 super(LulzbotReadyPage, self).__init__(parent, _("Lulzbot TAZ/Mini"))
1032 self.AddText(_('Cura is now ready to be used with your Lulzbot.'))
1035 class ConfigWizard(wx.wizard.Wizard):
1036 def __init__(self, addNew = False):
1037 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1039 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1041 profile.setActiveMachine(profile.getMachineCount())
1043 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1044 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1045 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1047 self.firstInfoPage = FirstInfoPage(self, addNew)
1048 self.machineSelectPage = MachineSelectPage(self)
1049 self.ultimakerSelectParts = SelectParts(self)
1050 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1051 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1052 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1053 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1054 self.bedLevelPage = bedLevelWizardMain(self)
1055 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1056 self.printrbotSelectType = PrintrbotPage(self)
1057 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1058 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1059 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1061 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1062 self.lulzbotReadyPage = LulzbotReadyPage(self)
1064 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
1065 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1066 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1067 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1068 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1069 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1070 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1071 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1072 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1074 self.FitToPage(self.firstInfoPage)
1075 self.GetPageAreaSizer().Add(self.firstInfoPage)
1077 self.RunWizard(self.firstInfoPage)
1080 def OnPageChanging(self, e):
1081 e.GetPage().StoreData()
1083 def OnPageChanged(self, e):
1084 if e.GetPage().AllowNext():
1085 self.FindWindowById(wx.ID_FORWARD).Enable()
1087 self.FindWindowById(wx.ID_FORWARD).Disable()
1088 if e.GetPage().AllowBack():
1089 self.FindWindowById(wx.ID_BACKWARD).Enable()
1091 self.FindWindowById(wx.ID_BACKWARD).Disable()
1093 def OnCancel(self, e):
1094 profile.setActiveMachine(self._old_machine_index)
1096 class bedLevelWizardMain(InfoPage):
1097 def __init__(self, parent):
1098 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1100 self.AddText(_('This wizard will help you in leveling your printer bed'))
1102 self.AddText(_('It will do the following steps'))
1103 self.AddText(_('* Move the printer head to each corner'))
1104 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1105 self.AddText(_('* Print a line around the bed to check if it is level'))
1108 self.connectButton = self.AddButton(_('Connect to printer'))
1111 self.infoBox = self.AddInfoBox()
1112 self.resumeButton = self.AddButton(_('Resume'))
1113 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1114 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1115 self.resumeButton.Enable(False)
1117 self.upButton.Enable(False)
1118 self.downButton.Enable(False)
1119 self.upButton2.Enable(False)
1120 self.downButton2.Enable(False)
1122 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1123 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1124 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1125 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1126 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1127 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1129 def OnConnect(self, e = None):
1130 if self.comm is not None:
1134 wx.CallAfter(self.OnConnect)
1136 self.connectButton.Enable(False)
1137 self.comm = machineCom.MachineCom(callbackObject=self)
1138 self.infoBox.SetBusy(_('Connecting to machine.'))
1139 self._wizardState = 0
1141 def OnBedUp(self, e):
1142 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1143 self.comm.sendCommand('G92 Z10')
1144 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1145 self.comm.sendCommand('M400')
1147 def OnBedDown(self, e):
1148 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1149 self.comm.sendCommand('G92 Z10')
1150 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1151 self.comm.sendCommand('M400')
1153 def OnBedUp2(self, e):
1154 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1155 self.comm.sendCommand('G92 Z10')
1156 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1157 self.comm.sendCommand('M400')
1159 def OnBedDown2(self, e):
1160 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1161 self.comm.sendCommand('G92 Z10')
1162 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1163 self.comm.sendCommand('M400')
1165 def AllowNext(self):
1166 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1167 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1170 def OnResume(self, e):
1171 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1172 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1173 if self._wizardState == -1:
1174 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1175 wx.CallAfter(self.upButton.Enable, False)
1176 wx.CallAfter(self.downButton.Enable, False)
1177 wx.CallAfter(self.upButton2.Enable, False)
1178 wx.CallAfter(self.downButton2.Enable, False)
1179 self.comm.sendCommand('M105')
1180 self.comm.sendCommand('G28')
1181 self._wizardState = 1
1182 elif self._wizardState == 2:
1183 if profile.getMachineSetting('has_heated_bed') == 'True':
1184 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1185 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1186 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1187 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1188 self.comm.sendCommand('M400')
1189 self._wizardState = 3
1191 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1192 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1193 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1194 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1195 self.comm.sendCommand('M400')
1196 self._wizardState = 3
1197 elif self._wizardState == 4:
1198 if profile.getMachineSetting('has_heated_bed') == 'True':
1199 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1200 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1201 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1202 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1203 self.comm.sendCommand('M400')
1204 self._wizardState = 7
1206 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1207 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1208 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1209 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1210 self.comm.sendCommand('M400')
1211 self._wizardState = 5
1212 elif self._wizardState == 6:
1213 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1214 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1215 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1216 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1217 self.comm.sendCommand('M400')
1218 self._wizardState = 7
1219 elif self._wizardState == 8:
1220 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1221 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1222 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1223 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1224 self._wizardState = 9
1225 elif self._wizardState == 10:
1226 self._wizardState = 11
1227 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1228 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1229 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1230 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1231 w = profile.getMachineSettingFloat('machine_width') - 10
1232 d = profile.getMachineSettingFloat('machine_depth')
1233 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1234 filamentArea = math.pi * filamentRadius * filamentRadius
1235 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1239 'G1 Z2 F%d' % (feedZ),
1241 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1242 'G1 Z0.3 F%d' % (feedZ)]
1244 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1246 for i in xrange(0, 3):
1247 dist = 5.0 + 0.4 * float(i)
1248 eValue += (d - 2.0*dist) * ePerMM
1249 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1250 eValue += (w - 2.0*dist) * ePerMM
1251 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1252 eValue += (d - 2.0*dist) * ePerMM
1253 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1254 eValue += (w - 2.0*dist) * ePerMM
1255 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1257 gcodeList.append('M400')
1258 self.comm.printGCode(gcodeList)
1259 self.resumeButton.Enable(False)
1261 def mcLog(self, message):
1262 print 'Log:', message
1264 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1265 if self._wizardState == 1:
1266 self._wizardState = 2
1267 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1268 wx.CallAfter(self.resumeButton.Enable, True)
1269 elif self._wizardState == 3:
1270 self._wizardState = 4
1271 if profile.getMachineSetting('has_heated_bed') == 'True':
1272 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1274 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1275 wx.CallAfter(self.resumeButton.Enable, True)
1276 elif self._wizardState == 5:
1277 self._wizardState = 6
1278 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1279 wx.CallAfter(self.resumeButton.Enable, True)
1280 elif self._wizardState == 7:
1281 self._wizardState = 8
1282 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1283 wx.CallAfter(self.resumeButton.Enable, True)
1284 elif self._wizardState == 9:
1285 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1286 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1288 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1289 wx.CallAfter(self.resumeButton.Enable, True)
1290 self._wizardState = 10
1292 def mcStateChange(self, state):
1293 if self.comm is None:
1295 if self.comm.isOperational():
1296 if self._wizardState == 0:
1297 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1298 wx.CallAfter(self.upButton.Enable, True)
1299 wx.CallAfter(self.downButton.Enable, True)
1300 wx.CallAfter(self.upButton2.Enable, True)
1301 wx.CallAfter(self.downButton2.Enable, True)
1302 wx.CallAfter(self.resumeButton.Enable, True)
1303 self._wizardState = -1
1304 elif self._wizardState == 11 and not self.comm.isPrinting():
1305 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1306 self.comm.sendCommand('G92 E0')
1307 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1308 self.comm.sendCommand('M104 S0')
1309 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1310 wx.CallAfter(self.infoBox.SetReadyIndicator)
1311 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1312 wx.CallAfter(self.connectButton.Enable, True)
1313 self._wizardState = 12
1314 elif self.comm.isError():
1315 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1317 def mcMessage(self, message):
1320 def mcProgress(self, lineNr):
1323 def mcZChange(self, newZ):
1326 class headOffsetCalibrationPage(InfoPage):
1327 def __init__(self, parent):
1328 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
1330 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1333 self.connectButton = self.AddButton(_('Connect to printer'))
1336 self.infoBox = self.AddInfoBox()
1337 self.textEntry = self.AddTextCtrl('')
1338 self.textEntry.Enable(False)
1339 self.resumeButton = self.AddButton(_('Resume'))
1340 self.resumeButton.Enable(False)
1342 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1343 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1345 def AllowBack(self):
1348 def OnConnect(self, e = None):
1349 if self.comm is not None:
1353 wx.CallAfter(self.OnConnect)
1355 self.connectButton.Enable(False)
1356 self.comm = machineCom.MachineCom(callbackObject=self)
1357 self.infoBox.SetBusy(_('Connecting to machine.'))
1358 self._wizardState = 0
1360 def OnResume(self, e):
1361 if self._wizardState == 2:
1362 self._wizardState = 3
1363 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1365 w = profile.getMachineSettingFloat('machine_width')
1366 d = profile.getMachineSettingFloat('machine_depth')
1368 gcode = gcodeGenerator.gcodeGenerator()
1369 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1370 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1377 gcode.addMove(w/2, 5)
1378 gcode.addMove(z=0.2)
1380 gcode.addExtrude(w/2, d-5.0)
1382 gcode.addMove(5, d/2)
1384 gcode.addExtrude(w-5.0, d/2)
1385 gcode.addRetract(15)
1388 gcode.addMove(w/2, 5)
1390 gcode.addExtrude(w/2, d-5.0)
1392 gcode.addMove(5, d/2)
1394 gcode.addExtrude(w-5.0, d/2)
1395 gcode.addRetract(15)
1400 gcode.addCmd('M400')
1402 self.comm.printGCode(gcode.list())
1403 self.resumeButton.Enable(False)
1404 elif self._wizardState == 4:
1406 float(self.textEntry.GetValue())
1409 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1410 self._wizardState = 5
1411 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1412 self.textEntry.SetValue('0.0')
1413 self.textEntry.Enable(True)
1414 elif self._wizardState == 5:
1416 float(self.textEntry.GetValue())
1419 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1420 self._wizardState = 6
1421 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1422 self.textEntry.SetValue('')
1423 self.textEntry.Enable(False)
1424 self.resumeButton.Enable(False)
1426 x = profile.getMachineSettingFloat('extruder_offset_x1')
1427 y = profile.getMachineSettingFloat('extruder_offset_y1')
1428 gcode = gcodeGenerator.gcodeGenerator()
1429 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1430 gcode.setPrintSpeed(25)
1433 gcode.addMove(50, 40, 0.2)
1435 for n in xrange(0, 10):
1436 gcode.addExtrude(50 + n * 10, 150)
1437 gcode.addExtrude(50 + n * 10 + 5, 150)
1438 gcode.addExtrude(50 + n * 10 + 5, 40)
1439 gcode.addExtrude(50 + n * 10 + 10, 40)
1440 gcode.addMove(40, 50)
1441 for n in xrange(0, 10):
1442 gcode.addExtrude(150, 50 + n * 10)
1443 gcode.addExtrude(150, 50 + n * 10 + 5)
1444 gcode.addExtrude(40, 50 + n * 10 + 5)
1445 gcode.addExtrude(40, 50 + n * 10 + 10)
1446 gcode.addRetract(15)
1449 gcode.addMove(50 - x, 30 - y, 0.2)
1451 for n in xrange(0, 10):
1452 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1453 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1454 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1455 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1456 gcode.addMove(30 - x, 50 - y, 0.2)
1457 for n in xrange(0, 10):
1458 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1459 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1460 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1461 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1462 gcode.addRetract(15)
1464 gcode.addCmd('M400')
1465 gcode.addCmd('M104 T0 S0')
1466 gcode.addCmd('M104 T1 S0')
1467 self.comm.printGCode(gcode.list())
1468 elif self._wizardState == 7:
1470 n = int(self.textEntry.GetValue()) - 1
1473 x = profile.getMachineSettingFloat('extruder_offset_x1')
1475 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1476 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1477 self.textEntry.SetValue('10')
1478 self._wizardState = 8
1479 elif self._wizardState == 8:
1481 n = int(self.textEntry.GetValue()) - 1
1484 y = profile.getMachineSettingFloat('extruder_offset_y1')
1486 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1487 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1488 self.infoBox.SetReadyIndicator()
1489 self._wizardState = 8
1491 self.resumeButton.Enable(False)
1493 def mcLog(self, message):
1494 print 'Log:', message
1496 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1497 if self._wizardState == 1:
1498 if temp[0] >= 210 and temp[1] >= 210:
1499 self._wizardState = 2
1500 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1501 wx.CallAfter(self.resumeButton.Enable, True)
1502 wx.CallAfter(self.resumeButton.SetFocus)
1504 def mcStateChange(self, state):
1505 if self.comm is None:
1507 if self.comm.isOperational():
1508 if self._wizardState == 0:
1509 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1510 self.comm.sendCommand('M105')
1511 self.comm.sendCommand('M104 S220 T0')
1512 self.comm.sendCommand('M104 S220 T1')
1513 self.comm.sendCommand('G28')
1514 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1515 self._wizardState = 1
1516 if not self.comm.isPrinting():
1517 if self._wizardState == 3:
1518 self._wizardState = 4
1519 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1520 wx.CallAfter(self.textEntry.SetValue, '0.0')
1521 wx.CallAfter(self.textEntry.Enable, True)
1522 wx.CallAfter(self.resumeButton.Enable, True)
1523 wx.CallAfter(self.resumeButton.SetFocus)
1524 elif self._wizardState == 6:
1525 self._wizardState = 7
1526 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1527 wx.CallAfter(self.textEntry.SetValue, '10')
1528 wx.CallAfter(self.textEntry.Enable, True)
1529 wx.CallAfter(self.resumeButton.Enable, True)
1530 wx.CallAfter(self.resumeButton.SetFocus)
1532 elif self.comm.isError():
1533 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1535 def mcMessage(self, message):
1538 def mcProgress(self, lineNr):
1541 def mcZChange(self, newZ):
1544 class bedLevelWizard(wx.wizard.Wizard):
1546 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1548 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1549 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1551 self.mainPage = bedLevelWizardMain(self)
1552 self.headOffsetCalibration = None
1554 self.FitToPage(self.mainPage)
1555 self.GetPageAreaSizer().Add(self.mainPage)
1557 self.RunWizard(self.mainPage)
1560 def OnPageChanging(self, e):
1561 e.GetPage().StoreData()
1563 def OnPageChanged(self, e):
1564 if e.GetPage().AllowNext():
1565 self.FindWindowById(wx.ID_FORWARD).Enable()
1567 self.FindWindowById(wx.ID_FORWARD).Disable()
1568 if e.GetPage().AllowBack():
1569 self.FindWindowById(wx.ID_BACKWARD).Enable()
1571 self.FindWindowById(wx.ID_BACKWARD).Disable()
1573 class headOffsetWizard(wx.wizard.Wizard):
1575 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1577 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1578 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1580 self.mainPage = headOffsetCalibrationPage(self)
1582 self.FitToPage(self.mainPage)
1583 self.GetPageAreaSizer().Add(self.mainPage)
1585 self.RunWizard(self.mainPage)
1588 def OnPageChanging(self, e):
1589 e.GetPage().StoreData()
1591 def OnPageChanged(self, e):
1592 if e.GetPage().AllowNext():
1593 self.FindWindowById(wx.ID_FORWARD).Enable()
1595 self.FindWindowById(wx.ID_FORWARD).Disable()
1596 if e.GetPage().AllowBack():
1597 self.FindWindowById(wx.ID_BACKWARD).Enable()
1599 self.FindWindowById(wx.ID_BACKWARD).Disable()