2 from __future__ import absolute_import
11 from Cura.gui import firmwareInstall
12 from Cura.gui import printWindow
13 from Cura.util import machineCom
14 from Cura.util import profile
15 from Cura.util.resources import getPathForImage
17 class InfoBox(wx.Panel):
18 def __init__(self, parent):
19 super(InfoBox, self).__init__(parent)
20 self.SetBackgroundColour('#FFFF80')
22 self.sizer = wx.GridBagSizer(5, 5)
23 self.SetSizer(self.sizer)
25 self.attentionBitmap = wx.Bitmap(getPathForImage('attention.png'))
26 self.errorBitmap = wx.Bitmap(getPathForImage('error.png'))
27 self.readyBitmap = wx.Bitmap(getPathForImage('ready.png'))
29 wx.Bitmap(getPathForImage('busy-0.png')),
30 wx.Bitmap(getPathForImage('busy-1.png')),
31 wx.Bitmap(getPathForImage('busy-2.png')),
32 wx.Bitmap(getPathForImage('busy-3.png'))
35 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
36 self.text = wx.StaticText(self, -1, '')
37 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
38 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
39 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
40 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
41 self.sizer.AddGrowableCol(1)
43 self.extraInfoButton.Show(False)
45 self.extraInfoUrl = ''
47 self.timer = wx.Timer(self)
48 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
49 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
52 def SetInfo(self, info):
53 self.SetBackgroundColour('#FFFF80')
54 self.text.SetLabel(info)
55 self.extraInfoButton.Show(False)
58 def SetError(self, info, extraInfoUrl):
59 self.extraInfoUrl = extraInfoUrl
60 self.SetBackgroundColour('#FF8080')
61 self.text.SetLabel(info)
62 self.extraInfoButton.Show(True)
64 self.SetErrorIndicator()
67 def SetAttention(self, info):
68 self.SetBackgroundColour('#FFFF80')
69 self.text.SetLabel(info)
70 self.extraInfoButton.Show(False)
71 self.SetAttentionIndicator()
74 def SetBusyIndicator(self):
76 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
78 def doExtraInfo(self, e):
79 webbrowser.open(self.extraInfoUrl)
81 def doBusyUpdate(self, e):
82 if self.busyState == None:
85 if self.busyState >= len(self.busyBitmap):
87 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
89 def SetReadyIndicator(self):
91 self.bitmap.SetBitmap(self.readyBitmap)
93 def SetErrorIndicator(self):
95 self.bitmap.SetBitmap(self.errorBitmap)
97 def SetAttentionIndicator(self):
99 self.bitmap.SetBitmap(self.attentionBitmap)
102 class InfoPage(wx.wizard.WizardPageSimple):
103 def __init__(self, parent, title):
104 wx.wizard.WizardPageSimple.__init__(self, parent)
106 sizer = wx.GridBagSizer(5, 5)
110 title = wx.StaticText(self, -1, title)
111 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
112 sizer.Add(title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
113 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
114 sizer.AddGrowableCol(1)
118 def AddText(self, info):
119 text = wx.StaticText(self, -1, info)
120 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
124 def AddSeperator(self):
125 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
128 def AddHiddenSeperator(self):
131 def AddInfoBox(self):
132 infoBox = InfoBox(self)
133 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
137 def AddRadioButton(self, label, style=0):
138 radio = wx.RadioButton(self, -1, label, style=style)
139 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
143 def AddCheckbox(self, label, checked=False):
144 check = wx.CheckBox(self, -1)
145 text = wx.StaticText(self, -1, label)
146 check.SetValue(checked)
147 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
148 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
152 def AddButton(self, label):
153 button = wx.Button(self, -1, label)
154 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
158 def AddDualButton(self, label1, label2):
159 button1 = wx.Button(self, -1, label1)
160 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
161 button2 = wx.Button(self, -1, label2)
162 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
164 return button1, button2
166 def AddTextCtrl(self, value):
167 ret = wx.TextCtrl(self, -1, value)
168 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
172 def AddLabelTextCtrl(self, info, value):
173 text = wx.StaticText(self, -1, info)
174 ret = wx.TextCtrl(self, -1, value)
175 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
176 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
180 def AddTextCtrlButton(self, value, buttonText):
181 text = wx.TextCtrl(self, -1, value)
182 button = wx.Button(self, -1, buttonText)
183 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
184 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
188 def AddBitmap(self, bitmap):
189 bitmap = wx.StaticBitmap(self, -1, bitmap)
190 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
194 def AddCheckmark(self, label, bitmap):
195 check = wx.StaticBitmap(self, -1, bitmap)
196 text = wx.StaticText(self, -1, label)
197 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
198 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
209 class FirstInfoPage(InfoPage):
210 def __init__(self, parent):
211 super(FirstInfoPage, self).__init__(parent, "First time run wizard")
212 self.AddText('Welcome, and thanks for trying Cura!')
214 self.AddText('This wizard will help you with the following steps:')
215 self.AddText('* Configure Cura for your machine')
216 self.AddText('* Upgrade your firmware')
217 self.AddText('* Check if your machine is working safely')
219 #self.AddText('* Calibrate your machine')
220 #self.AddText('* Do your first print')
223 class RepRapInfoPage(InfoPage):
224 def __init__(self, parent):
225 super(RepRapInfoPage, self).__init__(parent, "RepRap information")
227 'RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
228 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
230 self.AddText('You will have to manually install Marlin or Sprinter firmware.')
232 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')
233 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')
234 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')
235 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')
236 self.heatedBed = self.AddCheckbox('Heated bed')
239 profile.putPreference('machine_width', self.machineWidth.GetValue())
240 profile.putPreference('machine_depth', self.machineDepth.GetValue())
241 profile.putPreference('machine_height', self.machineHeight.GetValue())
242 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
243 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
244 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
247 class MachineSelectPage(InfoPage):
248 def __init__(self, parent):
249 super(MachineSelectPage, self).__init__(parent, "Select your machine")
250 self.AddText('What kind of machine do you have:')
252 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)
253 self.UltimakerRadio.SetValue(True)
254 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
255 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")
256 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
258 def OnUltimakerSelect(self, e):
259 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
261 def OnOtherSelect(self, e):
262 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)
265 if self.UltimakerRadio.GetValue():
266 profile.putPreference('machine_width', '205')
267 profile.putPreference('machine_depth', '205')
268 profile.putPreference('machine_height', '200')
269 profile.putPreference('machine_type', 'ultimaker')
270 profile.putProfileSetting('nozzle_size', '0.4')
272 profile.putPreference('machine_width', '80')
273 profile.putPreference('machine_depth', '80')
274 profile.putPreference('machine_height', '60')
275 profile.putPreference('machine_type', 'reprap')
276 profile.putPreference('startMode', 'Normal')
277 profile.putProfileSetting('nozzle_size', '0.5')
278 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
281 class SelectParts(InfoPage):
282 def __init__(self, parent):
283 super(SelectParts, self).__init__(parent, "Select upgraded parts you have")
284 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.')
286 self.springExtruder = self.AddCheckbox('Extruder drive upgrade')
287 self.heatedBed = self.AddCheckbox('Heated printer bed (self build)')
288 self.dualExtrusion = self.AddCheckbox('Dual extrusion (experimental)')
290 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 reliablity.')
291 self.AddText('This upgrade can be bought from the Ultimaker webshop shop\nor found on thingiverse as thing:26094')
292 self.springExtruder.SetValue(True)
295 profile.putPreference('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
296 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
297 if self.dualExtrusion.GetValue():
298 profile.putPreference('extruder_amount', '2')
299 if profile.getPreference('ultimaker_extruder_upgrade') == 'True':
300 profile.putProfileSetting('retraction_enable', 'True')
303 class FirmwareUpgradePage(InfoPage):
304 def __init__(self, parent):
305 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
307 '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.')
308 self.AddHiddenSeperator()
310 'The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
311 self.AddHiddenSeperator()
313 '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.')
314 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
315 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
316 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
317 self.AddHiddenSeperator()
318 self.AddText('Do not upgrade to this firmware if:')
319 self.AddText('* You have an older machine based on ATMega1280')
320 self.AddText('* Have other changes in the firmware')
321 button = self.AddButton('Goto this page for a custom firmware')
322 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
327 def OnUpgradeClick(self, e):
328 if firmwareInstall.InstallFirmware():
329 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
331 def OnSkipClick(self, e):
332 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
334 def OnUrlClick(self, e):
335 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
338 class UltimakerCheckupPage(InfoPage):
339 def __init__(self, parent):
340 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
342 self.checkBitmap = wx.Bitmap(getPathForImage('checkmark.png'))
343 self.crossBitmap = wx.Bitmap(getPathForImage('cross.png'))
344 self.unknownBitmap = wx.Bitmap(getPathForImage('question.png'))
345 self.endStopNoneBitmap = wx.Bitmap(getPathForImage('endstop_none.png'))
346 self.endStopXMinBitmap = wx.Bitmap(getPathForImage('endstop_xmin.png'))
347 self.endStopXMaxBitmap = wx.Bitmap(getPathForImage('endstop_xmax.png'))
348 self.endStopYMinBitmap = wx.Bitmap(getPathForImage('endstop_ymin.png'))
349 self.endStopYMaxBitmap = wx.Bitmap(getPathForImage('endstop_ymax.png'))
350 self.endStopZMinBitmap = wx.Bitmap(getPathForImage('endstop_zmin.png'))
351 self.endStopZMaxBitmap = wx.Bitmap(getPathForImage('endstop_zmax.png'))
354 '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.')
355 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
356 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
357 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
359 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
360 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
361 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
363 self.infoBox = self.AddInfoBox()
364 self.machineState = self.AddText('')
365 self.temperatureLabel = self.AddText('')
366 self.errorLogButton = self.AddButton('Show error log')
367 self.errorLogButton.Show(False)
369 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
371 self.xMinStop = False
372 self.xMaxStop = False
373 self.yMinStop = False
374 self.yMaxStop = False
375 self.zMinStop = False
376 self.zMaxStop = False
378 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
381 if self.comm != None:
385 self.endstopBitmap.Show(False)
388 def OnSkipClick(self, e):
389 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
391 def OnCheckClick(self, e=None):
392 self.errorLogButton.Show(False)
393 if self.comm != None:
397 wx.CallAfter(self.OnCheckClick)
399 self.infoBox.SetInfo('Connecting to machine.')
400 self.infoBox.SetBusyIndicator()
401 self.commState.SetBitmap(self.unknownBitmap)
402 self.tempState.SetBitmap(self.unknownBitmap)
403 self.stopState.SetBitmap(self.unknownBitmap)
404 self.checkupState = 0
405 self.comm = machineCom.MachineCom(callbackObject=self)
407 def OnErrorLog(self, e):
408 printWindow.LogWindow('\n'.join(self.comm.getLog()))
410 def mcLog(self, message):
413 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
414 if not self.comm.isOperational():
416 if self.checkupState == 0:
417 self.tempCheckTimeout = 20
419 self.checkupState = 1
420 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
421 self.comm.sendCommand('M104 S0')
422 self.comm.sendCommand('M104 S0')
424 self.startTemp = temp
425 self.checkupState = 2
426 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
427 self.comm.sendCommand('M104 S200')
428 self.comm.sendCommand('M104 S200')
429 elif self.checkupState == 1:
431 self.startTemp = temp
432 self.checkupState = 2
433 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
434 self.comm.sendCommand('M104 S200')
435 self.comm.sendCommand('M104 S200')
436 elif self.checkupState == 2:
437 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
438 if temp > self.startTemp + 40:
439 self.checkupState = 3
440 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
441 wx.CallAfter(self.endstopBitmap.Show, True)
442 wx.CallAfter(self.Layout)
443 self.comm.sendCommand('M104 S0')
444 self.comm.sendCommand('M104 S0')
445 self.comm.sendCommand('M119')
446 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
448 self.tempCheckTimeout -= 1
449 if self.tempCheckTimeout < 1:
450 self.checkupState = -1
451 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
452 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura/Temperature_measurement_problems')
453 self.comm.sendCommand('M104 S0')
454 self.comm.sendCommand('M104 S0')
455 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp))
457 def mcStateChange(self, state):
458 if self.comm == None:
460 if self.comm.isOperational():
461 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
462 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
463 elif self.comm.isError():
464 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
465 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura/Connection_problems')
466 wx.CallAfter(self.endstopBitmap.Show, False)
467 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
468 wx.CallAfter(self.errorLogButton.Show, True)
469 wx.CallAfter(self.Layout)
471 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
473 def mcMessage(self, message):
474 if self.checkupState >= 3 and self.checkupState < 10 and 'x_min' in message:
475 for data in message.split(' '):
477 tag, value = data.split(':', 2)
479 self.xMinStop = (value == 'H')
481 self.xMaxStop = (value == 'H')
483 self.yMinStop = (value == 'H')
485 self.yMaxStop = (value == 'H')
487 self.zMinStop = (value == 'H')
489 self.zMaxStop = (value == 'H')
490 self.comm.sendCommand('M119')
492 if self.checkupState == 3:
493 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
494 self.checkupState = 4
495 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
496 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
497 elif self.checkupState == 4:
498 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
499 self.checkupState = 5
500 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
501 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
502 elif self.checkupState == 5:
503 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
504 self.checkupState = 6
505 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
506 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
507 elif self.checkupState == 6:
508 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
509 self.checkupState = 7
510 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
511 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
512 elif self.checkupState == 7:
513 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
514 self.checkupState = 8
515 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
516 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
517 elif self.checkupState == 8:
518 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
519 self.checkupState = 9
520 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
521 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
522 elif self.checkupState == 9:
523 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
524 self.checkupState = 10
526 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
527 wx.CallAfter(self.infoBox.SetReadyIndicator)
528 wx.CallAfter(self.endstopBitmap.Show, False)
529 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
530 wx.CallAfter(self.OnSkipClick, None)
532 def mcProgress(self, lineNr):
535 def mcZChange(self, newZ):
539 class UltimakerCalibrationPage(InfoPage):
540 def __init__(self, parent):
541 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
543 self.AddText("Your Ultimaker requires some calibration.")
544 self.AddText("This calibration is needed for a proper extrusion amount.")
546 self.AddText("The following values are needed:")
547 self.AddText("* Diameter of filament")
548 self.AddText("* Number of steps per mm of filament extrusion")
550 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
552 self.AddText("First we need the diameter of your filament:")
553 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
555 "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.")
556 self.AddText("Note: This value can be changed later at any time.")
559 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
562 class UltimakerCalibrateStepsPerEPage(InfoPage):
563 def __init__(self, parent):
564 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
566 if profile.getPreference('steps_per_e') == '0':
567 profile.putPreference('steps_per_e', '865.888')
569 self.AddText("Calibrating the Steps Per E requires some manual actions.")
570 self.AddText("First remove any filament from your machine.")
571 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
572 self.AddText("We'll push the filament 100mm")
573 self.extrudeButton = self.AddButton("Extrude 100mm filament")
574 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
575 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
576 self.AddText("This results in the following steps per E:")
577 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
578 self.AddText("You can repeat these steps to get better calibration.")
581 "If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
582 self.heatButton = self.AddButton("Heatup for filament removal")
584 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
585 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
586 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
588 def OnSaveLengthClick(self, e):
589 currentEValue = float(self.stepsPerEInput.GetValue())
590 realExtrudeLength = float(self.lengthInput.GetValue())
591 newEValue = currentEValue * 100 / realExtrudeLength
592 self.stepsPerEInput.SetValue(str(newEValue))
593 self.lengthInput.SetValue("100")
595 def OnExtrudeClick(self, e):
596 threading.Thread(target=self.OnExtrudeRun).start()
598 def OnExtrudeRun(self):
599 self.heatButton.Enable(False)
600 self.extrudeButton.Enable(False)
601 currentEValue = float(self.stepsPerEInput.GetValue())
602 self.comm = machineCom.MachineCom()
603 if not self.comm.isOpen():
605 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
606 'Printer error', wx.OK | wx.ICON_INFORMATION)
607 self.heatButton.Enable(True)
608 self.extrudeButton.Enable(True)
611 line = self.comm.readline()
616 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
619 self.sendGCommand('M302') #Disable cold extrusion protection
620 self.sendGCommand("M92 E%f" % (currentEValue))
621 self.sendGCommand("G92 E0")
622 self.sendGCommand("G1 E100 F600")
625 self.extrudeButton.Enable()
626 self.heatButton.Enable()
628 def OnHeatClick(self, e):
629 threading.Thread(target=self.OnHeatRun).start()
632 self.heatButton.Enable(False)
633 self.extrudeButton.Enable(False)
634 self.comm = machineCom.MachineCom()
635 if not self.comm.isOpen():
637 "Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable",
638 'Printer error', wx.OK | wx.ICON_INFORMATION)
639 self.heatButton.Enable(True)
640 self.extrudeButton.Enable(True)
643 line = self.comm.readline()
645 self.heatButton.Enable(True)
646 self.extrudeButton.Enable(True)
650 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
653 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
655 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
656 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
657 self.sendGCommand('M104 S0')
660 self.heatButton.Enable(True)
661 self.extrudeButton.Enable(True)
663 def sendGCommand(self, cmd):
664 self.comm.sendCommand(cmd) #Disable cold extrusion protection
666 line = self.comm.readline()
669 if line.startswith('ok'):
673 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
676 class configWizard(wx.wizard.Wizard):
678 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
680 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
681 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
683 self.firstInfoPage = FirstInfoPage(self)
684 self.machineSelectPage = MachineSelectPage(self)
685 self.ultimakerSelectParts = SelectParts(self)
686 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
687 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
688 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
689 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
690 self.repRapInfoPage = RepRapInfoPage(self)
692 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
693 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
694 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
695 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
696 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
697 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
699 self.FitToPage(self.firstInfoPage)
700 self.GetPageAreaSizer().Add(self.firstInfoPage)
702 self.RunWizard(self.firstInfoPage)
705 def OnPageChanging(self, e):
706 e.GetPage().StoreData()
708 def OnPageChanged(self, e):
709 if e.GetPage().AllowNext():
710 self.FindWindowById(wx.ID_FORWARD).Enable()
712 self.FindWindowById(wx.ID_FORWARD).Disable()
713 self.FindWindowById(wx.ID_BACKWARD).Disable()