1 from __future__ import absolute_import
\r
4 import wx, os, platform, types, webbrowser, threading, time, re
\r
7 from gui import firmwareInstall
\r
8 from gui import toolbarUtil
\r
9 from gui import printWindow
\r
10 from util import machineCom
\r
11 from util import profile
\r
13 class InfoBox(wx.Panel):
\r
14 def __init__(self, parent):
\r
15 super(InfoBox, self).__init__(parent)
\r
16 self.SetBackgroundColour('#FFFF80')
\r
18 self.sizer = wx.GridBagSizer(5, 5)
\r
19 self.SetSizer(self.sizer)
\r
21 self.attentionBitmap = toolbarUtil.getBitmapImage('attention.png')
\r
22 self.errorBitmap = toolbarUtil.getBitmapImage('error.png')
\r
23 self.readyBitmap = toolbarUtil.getBitmapImage('ready.png')
\r
24 self.busyBitmap = [toolbarUtil.getBitmapImage('busy-0.png'), toolbarUtil.getBitmapImage('busy-1.png'), toolbarUtil.getBitmapImage('busy-2.png'), toolbarUtil.getBitmapImage('busy-3.png')]
\r
26 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
\r
27 self.text = wx.StaticText(self, -1, '')
\r
28 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
\r
29 self.sizer.Add(self.bitmap, pos=(0,0), flag=wx.ALL, border=5)
\r
30 self.sizer.Add(self.text, pos=(0,1), flag=wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER_VERTICAL, border=5)
\r
31 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
\r
32 self.sizer.AddGrowableCol(1)
\r
34 self.extraInfoButton.Show(False)
\r
36 self.extraInfoUrl = ''
\r
37 self.busyState = None
\r
38 self.timer = wx.Timer(self)
\r
39 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
\r
40 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
\r
41 self.timer.Start(100)
\r
43 def SetInfo(self, info):
\r
44 self.SetBackgroundColour('#FFFF80')
\r
45 self.text.SetLabel(info)
\r
46 self.extraInfoButton.Show(False)
\r
49 def SetError(self, info, extraInfoUrl):
\r
50 self.extraInfoUrl = extraInfoUrl
\r
51 self.SetBackgroundColour('#FF8080')
\r
52 self.text.SetLabel(info)
\r
53 self.extraInfoButton.Show(True)
\r
55 self.SetErrorIndicator()
\r
58 def SetAttention(self, info):
\r
59 self.SetBackgroundColour('#FFFF80')
\r
60 self.text.SetLabel(info)
\r
61 self.extraInfoButton.Show(False)
\r
62 self.SetAttentionIndicator()
\r
65 def SetBusyIndicator(self):
\r
67 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
69 def doBusyUpdate(self, e):
\r
70 if self.busyState == None:
\r
73 if self.busyState >= len(self.busyBitmap):
\r
75 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
77 def doExtraInfo(self, e):
\r
78 webbrowser.open(self.extraInfoUrl)
\r
80 def SetReadyIndicator(self):
\r
81 self.busyState = None
\r
82 self.bitmap.SetBitmap(self.readyBitmap)
\r
84 def SetErrorIndicator(self):
\r
85 self.busyState = None
\r
86 self.bitmap.SetBitmap(self.errorBitmap)
\r
88 def SetAttentionIndicator(self):
\r
89 self.busyState = None
\r
90 self.bitmap.SetBitmap(self.attentionBitmap)
\r
92 class InfoPage(wx.wizard.WizardPageSimple):
\r
93 def __init__(self, parent, title):
\r
94 wx.wizard.WizardPageSimple.__init__(self, parent)
\r
96 sizer = wx.GridBagSizer(5, 5)
\r
98 self.SetSizer(sizer)
\r
100 title = wx.StaticText(self, -1, title)
\r
101 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
\r
102 sizer.Add(title, pos=(0, 0), span=(1,2), flag=wx.ALIGN_CENTRE|wx.ALL)
\r
103 sizer.Add(wx.StaticLine(self, -1), pos=(1,0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
104 sizer.AddGrowableCol(1)
\r
108 def AddText(self,info):
\r
109 text = wx.StaticText(self, -1, info)
\r
110 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)
\r
114 def AddSeperator(self):
\r
115 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
118 def AddHiddenSeperator(self):
\r
121 def AddInfoBox(self):
\r
122 infoBox = InfoBox(self)
\r
123 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT|wx.EXPAND)
\r
127 def AddRadioButton(self, label, style = 0):
\r
128 radio = wx.RadioButton(self, -1, label, style=style)
\r
129 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
133 def AddCheckbox(self, label, checked = False):
\r
134 check = wx.CheckBox(self, -1)
\r
135 text = wx.StaticText(self, -1, label)
\r
136 check.SetValue(checked)
\r
137 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT|wx.RIGHT)
\r
138 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1,2), flag=wx.ALL)
\r
142 def AddButton(self, label):
\r
143 button = wx.Button(self, -1, label)
\r
144 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
148 def AddDualButton(self, label1, label2):
\r
149 button1 = wx.Button(self, -1, label1)
\r
150 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
\r
151 button2 = wx.Button(self, -1, label2)
\r
152 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
\r
154 return button1, button2
\r
156 def AddTextCtrl(self, value):
\r
157 ret = wx.TextCtrl(self, -1, value)
\r
158 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
162 def AddLabelTextCtrl(self, info, value):
\r
163 text = wx.StaticText(self, -1, info)
\r
164 ret = wx.TextCtrl(self, -1, value)
\r
165 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
166 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
170 def AddTextCtrlButton(self, value, buttonText):
\r
171 text = wx.TextCtrl(self, -1, value)
\r
172 button = wx.Button(self, -1, buttonText)
\r
173 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
174 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
176 return text, button
\r
178 def AddBitmap(self, bitmap):
\r
179 bitmap = wx.StaticBitmap(self, -1, bitmap)
\r
180 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)
\r
184 def AddCheckmark(self, label, bitmap):
\r
185 check = wx.StaticBitmap(self, -1, bitmap)
\r
186 text = wx.StaticText(self, -1, label)
\r
187 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT|wx.RIGHT)
\r
188 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1,1), flag=wx.ALL)
\r
192 def AllowNext(self):
\r
195 def StoreData(self):
\r
198 class FirstInfoPage(InfoPage):
\r
199 def __init__(self, parent):
\r
200 super(FirstInfoPage, self).__init__(parent, "First time run wizard")
\r
201 self.AddText('Welcome, and thanks for trying Cura!')
\r
202 self.AddSeperator()
\r
203 self.AddText('This wizard will help you with the following steps:')
\r
204 self.AddText('* Configure Cura for your machine')
\r
205 self.AddText('* Upgrade your firmware')
\r
206 self.AddText('* Check if your machine is working safely')
\r
207 #self.AddText('* Calibrate your machine')
\r
208 #self.AddText('* Do your first print')
\r
210 class RepRapInfoPage(InfoPage):
\r
211 def __init__(self, parent):
\r
212 super(RepRapInfoPage, self).__init__(parent, "RepRap information")
\r
213 self.AddText('RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
\r
214 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
\r
215 self.AddSeperator()
\r
216 self.AddText('You will have to manually install Marlin or Sprinter firmware.')
\r
217 self.AddSeperator()
\r
218 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')
\r
219 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')
\r
220 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')
\r
221 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')
\r
222 self.heatedBed = self.AddCheckbox('Heated bed')
\r
224 def StoreData(self):
\r
225 profile.putPreference('machine_width', self.machineWidth.GetValue())
\r
226 profile.putPreference('machine_depth', self.machineDepth.GetValue())
\r
227 profile.putPreference('machine_height', self.machineHeight.GetValue())
\r
228 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
\r
229 profile.putProfileSetting('machine_center_x', profile.getPreferenceFloat('machine_width') / 2)
\r
230 profile.putProfileSetting('machine_center_y', profile.getPreferenceFloat('machine_depth') / 2)
\r
231 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
\r
232 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
\r
234 class MachineSelectPage(InfoPage):
\r
235 def __init__(self, parent):
\r
236 super(MachineSelectPage, self).__init__(parent, "Select your machine")
\r
237 self.AddText('What kind of machine do you have:')
\r
239 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)
\r
240 self.UltimakerRadio.SetValue(True)
\r
241 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
\r
242 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")
\r
243 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
\r
245 def OnUltimakerSelect(self, e):
\r
246 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
\r
248 def OnOtherSelect(self, e):
\r
249 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)
\r
251 def StoreData(self):
\r
252 if self.UltimakerRadio.GetValue():
\r
253 profile.putPreference('machine_width', '205')
\r
254 profile.putPreference('machine_depth', '205')
\r
255 profile.putPreference('machine_height', '200')
\r
256 profile.putPreference('machine_type', 'ultimaker')
\r
257 profile.putProfileSetting('nozzle_size', '0.4')
\r
258 profile.putProfileSetting('machine_center_x', '100')
\r
259 profile.putProfileSetting('machine_center_y', '100')
\r
261 profile.putPreference('machine_width', '80')
\r
262 profile.putPreference('machine_depth', '80')
\r
263 profile.putPreference('machine_height', '60')
\r
264 profile.putPreference('machine_type', 'reprap')
\r
265 profile.putPreference('startMode', 'Normal')
\r
266 profile.putProfileSetting('nozzle_size', '0.5')
\r
267 profile.putProfileSetting('machine_center_x', '40')
\r
268 profile.putProfileSetting('machine_center_y', '40')
\r
269 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
\r
271 class FirmwareUpgradePage(InfoPage):
\r
272 def __init__(self, parent):
\r
273 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
\r
274 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.')
\r
275 self.AddHiddenSeperator()
\r
276 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
\r
277 self.AddHiddenSeperator()
\r
278 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.')
\r
279 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
\r
280 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
\r
281 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
282 self.AddHiddenSeperator()
\r
283 self.AddText('Do not upgrade to this firmware if:')
\r
284 self.AddText('* You have an older machine based on ATMega1280')
\r
285 self.AddText('* Have other changes in the firmware')
\r
286 button = self.AddButton('Goto this page for a custom firmware')
\r
287 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
\r
289 def AllowNext(self):
\r
292 def OnUpgradeClick(self, e):
\r
293 if firmwareInstall.InstallFirmware():
\r
294 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
296 def OnSkipClick(self, e):
\r
297 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
299 def OnUrlClick(self, e):
\r
300 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
\r
302 class UltimakerCheckupPage(InfoPage):
\r
303 def __init__(self, parent):
\r
304 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
\r
306 self.checkBitmap = toolbarUtil.getBitmapImage('checkmark.png')
\r
307 self.crossBitmap = toolbarUtil.getBitmapImage('cross.png')
\r
308 self.unknownBitmap = toolbarUtil.getBitmapImage('question.png')
\r
309 self.endStopNoneBitmap = toolbarUtil.getBitmapImage('endstop_none.png')
\r
310 self.endStopXMinBitmap = toolbarUtil.getBitmapImage('endstop_xmin.png')
\r
311 self.endStopXMaxBitmap = toolbarUtil.getBitmapImage('endstop_xmax.png')
\r
312 self.endStopYMinBitmap = toolbarUtil.getBitmapImage('endstop_ymin.png')
\r
313 self.endStopYMaxBitmap = toolbarUtil.getBitmapImage('endstop_ymax.png')
\r
314 self.endStopZMinBitmap = toolbarUtil.getBitmapImage('endstop_zmin.png')
\r
315 self.endStopZMaxBitmap = toolbarUtil.getBitmapImage('endstop_zmax.png')
\r
317 self.AddText('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.')
\r
318 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
\r
319 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
\r
320 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
321 self.AddSeperator()
\r
322 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
\r
323 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
\r
324 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
\r
325 self.AddSeperator()
\r
326 self.infoBox = self.AddInfoBox()
\r
327 self.machineState = self.AddText('')
\r
328 self.temperatureLabel = self.AddText('')
\r
329 self.errorLogButton = self.AddButton('Show error log')
\r
330 self.errorLogButton.Show(False)
\r
331 self.AddSeperator()
\r
332 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
\r
334 self.xMinStop = False
\r
335 self.xMaxStop = False
\r
336 self.yMinStop = False
\r
337 self.yMaxStop = False
\r
338 self.zMinStop = False
\r
339 self.zMaxStop = False
\r
341 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
\r
344 if self.comm != None:
\r
347 def AllowNext(self):
\r
348 self.endstopBitmap.Show(False)
\r
351 def OnSkipClick(self, e):
\r
352 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
354 def OnCheckClick(self, e = None):
\r
355 self.errorLogButton.Show(False)
\r
356 if self.comm != None:
\r
360 wx.CallAfter(self.OnCheckClick)
\r
362 self.infoBox.SetInfo('Connecting to machine.')
\r
363 self.infoBox.SetBusyIndicator()
\r
364 self.commState.SetBitmap(self.unknownBitmap)
\r
365 self.tempState.SetBitmap(self.unknownBitmap)
\r
366 self.stopState.SetBitmap(self.unknownBitmap)
\r
367 self.checkupState = 0
\r
368 self.comm = machineCom.MachineCom(callbackObject=self)
\r
370 def OnErrorLog(self, e):
\r
371 printWindow.LogWindow('\n'.join(self.comm.getLog()))
\r
373 def mcLog(self, message):
\r
376 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
\r
377 if not self.comm.isOperational():
\r
379 if self.checkupState == 0:
\r
380 self.tempCheckTimeout = 20
\r
382 self.checkupState = 1
\r
383 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
\r
384 self.comm.sendCommand('M104 S0')
\r
385 self.comm.sendCommand('M104 S0')
\r
387 self.startTemp = temp
\r
388 self.checkupState = 2
\r
389 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
390 self.comm.sendCommand('M104 S200')
\r
391 self.comm.sendCommand('M104 S200')
\r
392 elif self.checkupState == 1:
\r
394 self.startTemp = temp
\r
395 self.checkupState = 2
\r
396 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
397 self.comm.sendCommand('M104 S200')
\r
398 self.comm.sendCommand('M104 S200')
\r
399 elif self.checkupState == 2:
\r
400 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
\r
401 if temp > self.startTemp + 40:
\r
402 self.checkupState = 3
\r
403 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
\r
404 wx.CallAfter(self.endstopBitmap.Show, True)
\r
405 wx.CallAfter(self.Layout)
\r
406 self.comm.sendCommand('M104 S0')
\r
407 self.comm.sendCommand('M104 S0')
\r
408 self.comm.sendCommand('M119')
\r
409 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
\r
411 self.tempCheckTimeout -= 1
\r
412 if self.tempCheckTimeout < 1:
\r
413 self.checkupState = -1
\r
414 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
\r
415 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!', 'http://wiki.ultimaker.com/Cura/Temperature_measurement_problems')
\r
416 self.comm.sendCommand('M104 S0')
\r
417 self.comm.sendCommand('M104 S0')
\r
418 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp))
\r
420 def mcStateChange(self, state):
\r
421 if self.comm == None:
\r
423 if self.comm.isOperational():
\r
424 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
\r
425 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
426 elif self.comm.isError():
\r
427 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
\r
428 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura/Connection_problems')
\r
429 wx.CallAfter(self.endstopBitmap.Show, False)
\r
430 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
\r
431 wx.CallAfter(self.errorLogButton.Show, True)
\r
432 wx.CallAfter(self.Layout)
\r
434 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
436 def mcMessage(self, message):
\r
437 if self.checkupState >= 3 and self.checkupState < 10 and 'x_min' in message:
\r
438 for data in message.split(' '):
\r
440 tag, value = data.split(':', 2)
\r
442 self.xMinStop = (value == 'H')
\r
444 self.xMaxStop = (value == 'H')
\r
446 self.yMinStop = (value == 'H')
\r
448 self.yMaxStop = (value == 'H')
\r
450 self.zMinStop = (value == 'H')
\r
452 self.zMaxStop = (value == 'H')
\r
453 self.comm.sendCommand('M119')
\r
455 if self.checkupState == 3:
\r
456 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
457 self.checkupState = 4
\r
458 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
\r
459 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
\r
460 elif self.checkupState == 4:
\r
461 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
462 self.checkupState = 5
\r
463 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
\r
464 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
\r
465 elif self.checkupState == 5:
\r
466 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
467 self.checkupState = 6
\r
468 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
\r
469 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
\r
470 elif self.checkupState == 6:
\r
471 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
472 self.checkupState = 7
\r
473 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
\r
474 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
\r
475 elif self.checkupState == 7:
\r
476 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
477 self.checkupState = 8
\r
478 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
\r
479 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
\r
480 elif self.checkupState == 8:
\r
481 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
\r
482 self.checkupState = 9
\r
483 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
\r
484 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
\r
485 elif self.checkupState == 9:
\r
486 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
\r
487 self.checkupState = 10
\r
489 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
\r
490 wx.CallAfter(self.infoBox.SetReadyIndicator)
\r
491 wx.CallAfter(self.endstopBitmap.Show, False)
\r
492 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
\r
493 wx.CallAfter(self.OnSkipClick, None)
\r
495 def mcProgress(self, lineNr):
\r
498 def mcZChange(self, newZ):
\r
501 class UltimakerCalibrationPage(InfoPage):
\r
502 def __init__(self, parent):
\r
503 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
\r
505 self.AddText("Your Ultimaker requires some calibration.")
\r
506 self.AddText("This calibration is needed for a proper extrusion amount.")
\r
507 self.AddSeperator()
\r
508 self.AddText("The following values are needed:")
\r
509 self.AddText("* Diameter of filament")
\r
510 self.AddText("* Number of steps per mm of filament extrusion")
\r
511 self.AddSeperator()
\r
512 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
\r
513 self.AddSeperator()
\r
514 self.AddText("First we need the diameter of your filament:")
\r
515 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
\r
516 self.AddText("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.")
\r
517 self.AddText("Note: This value can be changed later at any time.")
\r
519 def StoreData(self):
\r
520 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
\r
522 class UltimakerCalibrateStepsPerEPage(InfoPage):
\r
523 def __init__(self, parent):
\r
524 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
\r
526 if profile.getPreference('steps_per_e') == '0':
\r
527 profile.putPreference('steps_per_e', '865.888')
\r
529 self.AddText("Calibrating the Steps Per E requires some manual actions.")
\r
530 self.AddText("First remove any filament from your machine.")
\r
531 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
\r
532 self.AddText("We'll push the filament 100mm")
\r
533 self.extrudeButton = self.AddButton("Extrude 100mm filament")
\r
534 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
\r
535 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
\r
536 self.AddText("This results in the following steps per E:")
\r
537 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
\r
538 self.AddText("You can repeat these steps to get better calibration.")
\r
539 self.AddSeperator()
\r
540 self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
\r
541 self.heatButton = self.AddButton("Heatup for filament removal")
\r
543 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
\r
544 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
\r
545 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
\r
547 def OnSaveLengthClick(self, e):
\r
548 currentEValue = float(self.stepsPerEInput.GetValue())
\r
549 realExtrudeLength = float(self.lengthInput.GetValue())
\r
550 newEValue = currentEValue * 100 / realExtrudeLength
\r
551 self.stepsPerEInput.SetValue(str(newEValue))
\r
552 self.lengthInput.SetValue("100")
\r
554 def OnExtrudeClick(self, e):
\r
555 threading.Thread(target=self.OnExtrudeRun).start()
\r
557 def OnExtrudeRun(self):
\r
558 self.heatButton.Enable(False)
\r
559 self.extrudeButton.Enable(False)
\r
560 currentEValue = float(self.stepsPerEInput.GetValue())
\r
561 self.comm = machineCom.MachineCom()
\r
562 if not self.comm.isOpen():
\r
563 wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
564 self.heatButton.Enable(True)
\r
565 self.extrudeButton.Enable(True)
\r
568 line = self.comm.readline()
\r
571 if 'start' in line:
\r
573 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
\r
576 self.sendGCommand('M302') #Disable cold extrusion protection
\r
577 self.sendGCommand("M92 E%f" % (currentEValue))
\r
578 self.sendGCommand("G92 E0")
\r
579 self.sendGCommand("G1 E100 F600")
\r
582 self.extrudeButton.Enable()
\r
583 self.heatButton.Enable()
\r
585 def OnHeatClick(self, e):
\r
586 threading.Thread(target=self.OnHeatRun).start()
\r
588 def OnHeatRun(self):
\r
589 self.heatButton.Enable(False)
\r
590 self.extrudeButton.Enable(False)
\r
591 self.comm = machineCom.MachineCom()
\r
592 if not self.comm.isOpen():
\r
593 wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
594 self.heatButton.Enable(True)
\r
595 self.extrudeButton.Enable(True)
\r
598 line = self.comm.readline()
\r
600 self.heatButton.Enable(True)
\r
601 self.extrudeButton.Enable(True)
\r
603 if 'start' in line:
\r
605 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
\r
608 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
\r
609 wx.MessageBox('Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)', 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
\r
610 self.sendGCommand('M104 S0')
\r
613 self.heatButton.Enable(True)
\r
614 self.extrudeButton.Enable(True)
\r
616 def sendGCommand(self, cmd):
\r
617 self.comm.sendCommand(cmd) #Disable cold extrusion protection
\r
619 line = self.comm.readline()
\r
622 if line.startswith('ok'):
\r
625 def StoreData(self):
\r
626 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
\r
628 class configWizard(wx.wizard.Wizard):
\r
629 def __init__(self):
\r
630 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
\r
632 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
\r
633 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
\r
635 self.firstInfoPage = FirstInfoPage(self)
\r
636 self.machineSelectPage = MachineSelectPage(self)
\r
637 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
\r
638 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
\r
639 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
\r
640 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
\r
641 self.repRapInfoPage = RepRapInfoPage(self)
\r
643 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
\r
644 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerFirmwareUpgradePage)
\r
645 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
\r
646 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
\r
647 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
\r
649 self.FitToPage(self.firstInfoPage)
\r
650 self.GetPageAreaSizer().Add(self.firstInfoPage)
\r
652 self.RunWizard(self.firstInfoPage)
\r
655 def OnPageChanging(self, e):
\r
656 e.GetPage().StoreData()
\r
658 def OnPageChanged(self, e):
\r
659 if e.GetPage().AllowNext():
\r
660 self.FindWindowById(wx.ID_FORWARD).Enable()
\r
662 self.FindWindowById(wx.ID_FORWARD).Disable()
\r
663 self.FindWindowById(wx.ID_BACKWARD).Disable()
\r