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 util import machineCom
\r
10 from util import profile
\r
12 class InfoBox(wx.Panel):
\r
13 def __init__(self, parent):
\r
14 super(InfoBox, self).__init__(parent)
\r
15 self.SetBackgroundColour('#FFFF80')
\r
17 self.sizer = wx.GridBagSizer(5, 5)
\r
18 self.SetSizer(self.sizer)
\r
20 self.attentionBitmap = toolbarUtil.getBitmapImage('attention.png')
\r
21 self.errorBitmap = toolbarUtil.getBitmapImage('error.png')
\r
22 self.readyBitmap = toolbarUtil.getBitmapImage('ready.png')
\r
23 self.busyBitmap = [toolbarUtil.getBitmapImage('busy-0.png'), toolbarUtil.getBitmapImage('busy-1.png'), toolbarUtil.getBitmapImage('busy-2.png'), toolbarUtil.getBitmapImage('busy-3.png')]
\r
25 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
\r
26 self.text = wx.StaticText(self, -1, '')
\r
27 self.sizer.Add(self.bitmap, pos=(0,0), flag=wx.ALL, border=5)
\r
28 self.sizer.Add(self.text, pos=(0,1), flag=wx.TOP|wx.BOTTOM|wx.ALIGN_CENTER_VERTICAL, border=5)
\r
30 self.busyState = None
\r
31 self.timer = wx.Timer(self)
\r
32 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
\r
33 self.timer.Start(100)
\r
35 def SetInfo(self, info):
\r
36 self.SetBackgroundColour('#FFFF80')
\r
37 self.text.SetLabel(info)
\r
40 def SetError(self, info):
\r
41 self.SetBackgroundColour('#FF8080')
\r
42 self.text.SetLabel(info)
\r
43 self.SetErrorIndicator()
\r
46 def SetAttention(self, info):
\r
47 self.SetBackgroundColour('#FFFF80')
\r
48 self.text.SetLabel(info)
\r
49 self.SetAttentionIndicator()
\r
52 def SetBusyIndicator(self):
\r
54 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
56 def doBusyUpdate(self, e):
\r
57 if self.busyState == None:
\r
60 if self.busyState >= len(self.busyBitmap):
\r
62 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
\r
64 def SetReadyIndicator(self):
\r
65 self.busyState = None
\r
66 self.bitmap.SetBitmap(self.readyBitmap)
\r
68 def SetErrorIndicator(self):
\r
69 self.busyState = None
\r
70 self.bitmap.SetBitmap(self.errorBitmap)
\r
72 def SetAttentionIndicator(self):
\r
73 self.busyState = None
\r
74 self.bitmap.SetBitmap(self.attentionBitmap)
\r
76 class InfoPage(wx.wizard.WizardPageSimple):
\r
77 def __init__(self, parent, title):
\r
78 wx.wizard.WizardPageSimple.__init__(self, parent)
\r
80 sizer = wx.GridBagSizer(5, 5)
\r
82 self.SetSizer(sizer)
\r
84 title = wx.StaticText(self, -1, title)
\r
85 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
\r
86 sizer.Add(title, pos=(0, 0), span=(1,2), flag=wx.ALIGN_CENTRE|wx.ALL)
\r
87 sizer.Add(wx.StaticLine(self, -1), pos=(1,0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
88 sizer.AddGrowableCol(1)
\r
92 def AddText(self,info):
\r
93 text = wx.StaticText(self, -1, info)
\r
94 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)
\r
98 def AddSeperator(self):
\r
99 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
102 def AddHiddenSeperator(self):
\r
105 def AddInfoBox(self):
\r
106 infoBox = InfoBox(self)
\r
107 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT|wx.EXPAND)
\r
111 def AddRadioButton(self, label, style = 0):
\r
112 radio = wx.RadioButton(self, -1, label, style=style)
\r
113 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
117 def AddCheckbox(self, label, checked = False):
\r
118 check = wx.CheckBox(self, -1)
\r
119 text = wx.StaticText(self, -1, label)
\r
120 check.SetValue(checked)
\r
121 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT|wx.RIGHT)
\r
122 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1,2), flag=wx.ALL)
\r
126 def AddButton(self, label):
\r
127 button = wx.Button(self, -1, label)
\r
128 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
132 def AddDualButton(self, label1, label2):
\r
133 button1 = wx.Button(self, -1, label1)
\r
134 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
\r
135 button2 = wx.Button(self, -1, label2)
\r
136 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
\r
138 return button1, button2
\r
140 def AddTextCtrl(self, value):
\r
141 ret = wx.TextCtrl(self, -1, value)
\r
142 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
146 def AddLabelTextCtrl(self, info, value):
\r
147 text = wx.StaticText(self, -1, info)
\r
148 ret = wx.TextCtrl(self, -1, value)
\r
149 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
150 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
154 def AddTextCtrlButton(self, value, buttonText):
\r
155 text = wx.TextCtrl(self, -1, value)
\r
156 button = wx.Button(self, -1, buttonText)
\r
157 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
158 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
160 return text, button
\r
162 def AddBitmap(self, bitmap):
\r
163 bitmap = wx.StaticBitmap(self, -1, bitmap)
\r
164 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)
\r
168 def AddCheckmark(self, label, bitmap):
\r
169 check = wx.StaticBitmap(self, -1, bitmap)
\r
170 text = wx.StaticText(self, -1, label)
\r
171 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT|wx.RIGHT)
\r
172 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1,1), flag=wx.ALL)
\r
176 def AllowNext(self):
\r
179 def StoreData(self):
\r
182 class FirstInfoPage(InfoPage):
\r
183 def __init__(self, parent):
\r
184 super(FirstInfoPage, self).__init__(parent, "First time run wizard")
\r
185 self.AddText('Welcome, and thanks for trying Cura!')
\r
186 self.AddSeperator()
\r
187 self.AddText('This wizard will help you with the following steps:')
\r
188 self.AddText('* Configure Cura for your machine')
\r
189 self.AddText('* Upgrade your firmware')
\r
190 self.AddText('* Check if your machine is working safely')
\r
191 #self.AddText('* Calibrate your machine')
\r
192 #self.AddText('* Do your first print')
\r
194 class RepRapInfoPage(InfoPage):
\r
195 def __init__(self, parent):
\r
196 super(RepRapInfoPage, self).__init__(parent, "RepRap information")
\r
197 self.AddText('RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
\r
198 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
\r
199 self.AddSeperator()
\r
200 self.AddText('You will have to manually install Marlin or Sprinter firmware.')
\r
201 self.AddSeperator()
\r
202 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')
\r
203 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')
\r
204 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')
\r
205 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')
\r
206 self.heatedBed = self.AddCheckbox('Heated bed')
\r
208 def StoreData(self):
\r
209 profile.putPreference('machine_width', self.machineWidth.GetValue())
\r
210 profile.putPreference('machine_depth', self.machineDepth.GetValue())
\r
211 profile.putPreference('machine_height', self.machineHeight.GetValue())
\r
212 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
\r
213 profile.putProfileSetting('machine_center_x', profile.getPreferenceFloat('machine_width') / 2)
\r
214 profile.putProfileSetting('machine_center_y', profile.getPreferenceFloat('machine_depth') / 2)
\r
215 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
\r
216 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))
\r
218 class MachineSelectPage(InfoPage):
\r
219 def __init__(self, parent):
\r
220 super(MachineSelectPage, self).__init__(parent, "Select your machine")
\r
221 self.AddText('What kind of machine do you have:')
\r
223 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)
\r
224 self.UltimakerRadio.SetValue(True)
\r
225 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
\r
226 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")
\r
227 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
\r
229 def OnUltimakerSelect(self, e):
\r
230 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
\r
232 def OnOtherSelect(self, e):
\r
233 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)
\r
235 def StoreData(self):
\r
236 if self.UltimakerRadio.GetValue():
\r
237 profile.putPreference('machine_width', '205')
\r
238 profile.putPreference('machine_depth', '205')
\r
239 profile.putPreference('machine_height', '200')
\r
240 profile.putPreference('machine_type', 'ultimaker')
\r
241 profile.putProfileSetting('nozzle_size', '0.4')
\r
242 profile.putProfileSetting('machine_center_x', '100')
\r
243 profile.putProfileSetting('machine_center_y', '100')
\r
245 profile.putPreference('machine_width', '80')
\r
246 profile.putPreference('machine_depth', '80')
\r
247 profile.putPreference('machine_height', '60')
\r
248 profile.putPreference('machine_type', 'reprap')
\r
249 profile.putProfileSetting('nozzle_size', '0.5')
\r
250 profile.putProfileSetting('machine_center_x', '40')
\r
251 profile.putProfileSetting('machine_center_y', '40')
\r
252 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
\r
254 class FirmwareUpgradePage(InfoPage):
\r
255 def __init__(self, parent):
\r
256 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
\r
257 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
258 self.AddHiddenSeperator()
\r
259 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
\r
260 self.AddHiddenSeperator()
\r
261 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
262 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
\r
263 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
\r
264 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
265 self.AddHiddenSeperator()
\r
266 self.AddText('Do not upgrade to this firmware if:')
\r
267 self.AddText('* You have an older machine based on ATMega1280')
\r
268 self.AddText('* Have other changes in the firmware')
\r
269 button = self.AddButton('Goto this page for a custom firmware')
\r
270 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
\r
272 def AllowNext(self):
\r
275 def OnUpgradeClick(self, e):
\r
276 if firmwareInstall.InstallFirmware():
\r
277 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
279 def OnSkipClick(self, e):
\r
280 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
282 def OnUrlClick(self, e):
\r
283 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
\r
285 class UltimakerCheckupPage(InfoPage):
\r
286 def __init__(self, parent):
\r
287 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
\r
289 self.checkBitmap = toolbarUtil.getBitmapImage('checkmark.png')
\r
290 self.crossBitmap = toolbarUtil.getBitmapImage('cross.png')
\r
291 self.unknownBitmap = toolbarUtil.getBitmapImage('question.png')
\r
292 self.endStopNoneBitmap = toolbarUtil.getBitmapImage('endstop_none.png')
\r
293 self.endStopXMinBitmap = toolbarUtil.getBitmapImage('endstop_xmin.png')
\r
294 self.endStopXMaxBitmap = toolbarUtil.getBitmapImage('endstop_xmax.png')
\r
295 self.endStopYMinBitmap = toolbarUtil.getBitmapImage('endstop_ymin.png')
\r
296 self.endStopYMaxBitmap = toolbarUtil.getBitmapImage('endstop_ymax.png')
\r
297 self.endStopZMinBitmap = toolbarUtil.getBitmapImage('endstop_zmin.png')
\r
298 self.endStopZMaxBitmap = toolbarUtil.getBitmapImage('endstop_zmax.png')
\r
300 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
301 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
\r
302 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
\r
303 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
304 self.AddSeperator()
\r
305 self.commState = self.AddCheckmark('Communication:', self.unknownBitmap)
\r
306 self.tempState = self.AddCheckmark('Temperature:', self.unknownBitmap)
\r
307 self.stopState = self.AddCheckmark('Endstops:', self.unknownBitmap)
\r
308 self.AddSeperator()
\r
309 self.infoBox = self.AddInfoBox()
\r
310 self.machineState = self.AddText('')
\r
311 self.temperatureLabel = self.AddText('')
\r
312 self.AddSeperator()
\r
313 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
\r
315 self.xMinStop = False
\r
316 self.xMaxStop = False
\r
317 self.yMinStop = False
\r
318 self.yMaxStop = False
\r
319 self.zMinStop = False
\r
320 self.zMaxStop = False
\r
323 if self.comm != None:
\r
326 def AllowNext(self):
\r
327 self.endstopBitmap.Show(False)
\r
330 def OnSkipClick(self, e):
\r
331 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
333 def OnCheckClick(self, e):
\r
334 if self.comm != None:
\r
337 self.infoBox.SetInfo('Connecting to machine.')
\r
338 self.infoBox.SetBusyIndicator()
\r
339 self.commState.SetBitmap(self.unknownBitmap)
\r
340 self.tempState.SetBitmap(self.unknownBitmap)
\r
341 self.stopState.SetBitmap(self.unknownBitmap)
\r
342 self.checkupState = 0
\r
343 self.comm = machineCom.MachineCom(callbackObject=self)
\r
345 def mcLog(self, message):
\r
348 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
\r
349 if not self.comm.isOperational():
\r
351 if self.checkupState == 0:
\r
352 self.tempCheckTimeout = 20
\r
354 self.checkupState = 1
\r
355 wx.CallAfter(self.infoBox.SetInfo, 'Cooldown before temperature check.')
\r
356 self.comm.sendCommand('M104 S0')
\r
357 self.comm.sendCommand('M104 S0')
\r
359 self.startTemp = temp
\r
360 self.checkupState = 2
\r
361 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
362 self.comm.sendCommand('M104 S200')
\r
363 self.comm.sendCommand('M104 S200')
\r
364 elif self.checkupState == 1:
\r
366 self.startTemp = temp
\r
367 self.checkupState = 2
\r
368 wx.CallAfter(self.infoBox.SetInfo, 'Checking the heater and temperature sensor.')
\r
369 self.comm.sendCommand('M104 S200')
\r
370 self.comm.sendCommand('M104 S200')
\r
371 elif self.checkupState == 2:
\r
372 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
\r
373 if temp > self.startTemp + 40:
\r
374 self.checkupState = 3
\r
375 wx.CallAfter(self.infoBox.SetAttention, 'Please make sure none of the endstops are pressed.')
\r
376 wx.CallAfter(self.endstopBitmap.Show, True)
\r
377 wx.CallAfter(self.Layout)
\r
378 self.comm.sendCommand('M104 S0')
\r
379 self.comm.sendCommand('M104 S0')
\r
380 self.comm.sendCommand('M119')
\r
381 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
\r
383 self.tempCheckTimeout -= 1
\r
384 if self.tempCheckTimeout < 1:
\r
385 self.checkupState = -1
\r
386 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
\r
387 wx.CallAfter(self.infoBox.SetError, 'Temperature measurement FAILED!')
\r
388 self.comm.sendCommand('M104 S0')
\r
389 self.comm.sendCommand('M104 S0')
\r
390 wx.CallAfter(self.temperatureLabel.SetLabel, 'Head temperature: %d' % (temp))
\r
392 def mcStateChange(self, state):
\r
393 if self.comm == None:
\r
395 if self.comm.isOperational():
\r
396 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
\r
397 elif self.comm.isError():
\r
398 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
\r
399 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.')
\r
400 wx.CallAfter(self.machineState.SetLabel, 'Communication State: %s' % (self.comm.getStateString()))
\r
402 def mcMessage(self, message):
\r
403 if self.checkupState >= 3 and self.checkupState < 10 and 'x_min' in message:
\r
404 for data in message.split(' '):
\r
406 tag, value = data.split(':', 2)
\r
408 self.xMinStop = (value == 'H')
\r
410 self.xMaxStop = (value == 'H')
\r
412 self.yMinStop = (value == 'H')
\r
414 self.yMaxStop = (value == 'H')
\r
416 self.zMinStop = (value == 'H')
\r
418 self.zMaxStop = (value == 'H')
\r
419 self.comm.sendCommand('M119')
\r
421 if self.checkupState == 3:
\r
422 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
423 self.checkupState = 4
\r
424 wx.CallAfter(self.infoBox.SetAttention, 'Please press the left X endstop.')
\r
425 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
\r
426 elif self.checkupState == 4:
\r
427 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
428 self.checkupState = 5
\r
429 wx.CallAfter(self.infoBox.SetAttention, 'Please press the right X endstop.')
\r
430 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
\r
431 elif self.checkupState == 5:
\r
432 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
433 self.checkupState = 6
\r
434 wx.CallAfter(self.infoBox.SetAttention, 'Please press the front Y endstop.')
\r
435 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
\r
436 elif self.checkupState == 6:
\r
437 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
438 self.checkupState = 7
\r
439 wx.CallAfter(self.infoBox.SetAttention, 'Please press the back Y endstop.')
\r
440 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
\r
441 elif self.checkupState == 7:
\r
442 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
\r
443 self.checkupState = 8
\r
444 wx.CallAfter(self.infoBox.SetAttention, 'Please press the top Z endstop.')
\r
445 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
\r
446 elif self.checkupState == 8:
\r
447 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
\r
448 self.checkupState = 9
\r
449 wx.CallAfter(self.infoBox.SetAttention, 'Please press the bottom Z endstop.')
\r
450 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
\r
451 elif self.checkupState == 9:
\r
452 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
\r
453 self.checkupState = 10
\r
455 wx.CallAfter(self.infoBox.SetInfo, 'Checkup finished')
\r
456 wx.CallAfter(self.infoBox.SetReadyIndicator)
\r
457 wx.CallAfter(self.endstopBitmap.Show, False)
\r
458 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
\r
459 wx.CallAfter(self.OnSkipClick, None)
\r
461 def mcProgress(self, lineNr):
\r
464 def mcZChange(self, newZ):
\r
467 class UltimakerCalibrationPage(InfoPage):
\r
468 def __init__(self, parent):
\r
469 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
\r
471 self.AddText("Your Ultimaker requires some calibration.")
\r
472 self.AddText("This calibration is needed for a proper extrusion amount.")
\r
473 self.AddSeperator()
\r
474 self.AddText("The following values are needed:")
\r
475 self.AddText("* Diameter of filament")
\r
476 self.AddText("* Number of steps per mm of filament extrusion")
\r
477 self.AddSeperator()
\r
478 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
\r
479 self.AddSeperator()
\r
480 self.AddText("First we need the diameter of your filament:")
\r
481 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
\r
482 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
483 self.AddText("Note: This value can be changed later at any time.")
\r
485 def StoreData(self):
\r
486 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
\r
488 class UltimakerCalibrateStepsPerEPage(InfoPage):
\r
489 def __init__(self, parent):
\r
490 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
\r
492 if profile.getPreference('steps_per_e') == '0':
\r
493 profile.putPreference('steps_per_e', '865.888')
\r
495 self.AddText("Calibrating the Steps Per E requires some manual actions.")
\r
496 self.AddText("First remove any filament from your machine.")
\r
497 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
\r
498 self.AddText("We'll push the filament 100mm")
\r
499 self.extrudeButton = self.AddButton("Extrude 100mm filament")
\r
500 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
\r
501 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
\r
502 self.AddText("This results in the following steps per E:")
\r
503 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
\r
504 self.AddText("You can repeat these steps to get better calibration.")
\r
505 self.AddSeperator()
\r
506 self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
\r
507 self.heatButton = self.AddButton("Heatup for filament removal")
\r
509 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
\r
510 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
\r
511 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
\r
513 def OnSaveLengthClick(self, e):
\r
514 currentEValue = float(self.stepsPerEInput.GetValue())
\r
515 realExtrudeLength = float(self.lengthInput.GetValue())
\r
516 newEValue = currentEValue * 100 / realExtrudeLength
\r
517 self.stepsPerEInput.SetValue(str(newEValue))
\r
518 self.lengthInput.SetValue("100")
\r
520 def OnExtrudeClick(self, e):
\r
521 threading.Thread(target=self.OnExtrudeRun).start()
\r
523 def OnExtrudeRun(self):
\r
524 self.heatButton.Enable(False)
\r
525 self.extrudeButton.Enable(False)
\r
526 currentEValue = float(self.stepsPerEInput.GetValue())
\r
527 self.comm = machineCom.MachineCom()
\r
528 if not self.comm.isOpen():
\r
529 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
530 self.heatButton.Enable(True)
\r
531 self.extrudeButton.Enable(True)
\r
534 line = self.comm.readline()
\r
537 if 'start' in line:
\r
539 #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
542 self.sendGCommand('M302') #Disable cold extrusion protection
\r
543 self.sendGCommand("M92 E%f" % (currentEValue))
\r
544 self.sendGCommand("G92 E0")
\r
545 self.sendGCommand("G1 E100 F600")
\r
548 self.extrudeButton.Enable()
\r
549 self.heatButton.Enable()
\r
551 def OnHeatClick(self, e):
\r
552 threading.Thread(target=self.OnHeatRun).start()
\r
554 def OnHeatRun(self):
\r
555 self.heatButton.Enable(False)
\r
556 self.extrudeButton.Enable(False)
\r
557 self.comm = machineCom.MachineCom()
\r
558 if not self.comm.isOpen():
\r
559 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
560 self.heatButton.Enable(True)
\r
561 self.extrudeButton.Enable(True)
\r
564 line = self.comm.readline()
\r
566 self.heatButton.Enable(True)
\r
567 self.extrudeButton.Enable(True)
\r
569 if 'start' in line:
\r
571 #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
574 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
\r
575 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
576 self.sendGCommand('M104 S0')
\r
579 self.heatButton.Enable(True)
\r
580 self.extrudeButton.Enable(True)
\r
582 def sendGCommand(self, cmd):
\r
583 self.comm.sendCommand(cmd) #Disable cold extrusion protection
\r
585 line = self.comm.readline()
\r
588 if line.startswith('ok'):
\r
591 def StoreData(self):
\r
592 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
\r
594 class configWizard(wx.wizard.Wizard):
\r
595 def __init__(self):
\r
596 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
\r
598 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
\r
599 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
\r
601 self.firstInfoPage = FirstInfoPage(self)
\r
602 self.machineSelectPage = MachineSelectPage(self)
\r
603 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
\r
604 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
\r
605 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
\r
606 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
\r
607 self.repRapInfoPage = RepRapInfoPage(self)
\r
609 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
\r
610 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerFirmwareUpgradePage)
\r
611 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
\r
612 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
\r
613 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
\r
615 self.FitToPage(self.firstInfoPage)
\r
616 self.GetPageAreaSizer().Add(self.firstInfoPage)
\r
618 self.RunWizard(self.firstInfoPage)
\r
621 def OnPageChanging(self, e):
\r
622 e.GetPage().StoreData()
\r
624 def OnPageChanged(self, e):
\r
625 if e.GetPage().AllowNext():
\r
626 self.FindWindowById(wx.ID_FORWARD).Enable()
\r
628 self.FindWindowById(wx.ID_FORWARD).Disable()
\r
629 self.FindWindowById(wx.ID_BACKWARD).Disable()
\r