chiark / gitweb /
Fix the checkup wizard, we get temperature readings before the machinie is operational.
[cura.git] / Cura / gui / configWizard.py
1 from __future__ import absolute_import\r
2 import __init__\r
3 \r
4 import wx, os, platform, types, webbrowser, threading, time, re\r
5 import wx.wizard\r
6 \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
11 \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
16                 \r
17                 self.sizer = wx.GridBagSizer(5, 5)\r
18                 self.SetSizer(self.sizer)\r
19                 \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
24                 \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
29                 \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
34 \r
35         def SetInfo(self, info):\r
36                 self.SetBackgroundColour('#FFFF80')\r
37                 self.text.SetLabel(info)\r
38                 self.Refresh()\r
39 \r
40         def SetError(self, info):\r
41                 self.SetBackgroundColour('#FF8080')\r
42                 self.text.SetLabel(info)\r
43                 self.SetErrorIndicator()\r
44                 self.Refresh()\r
45         \r
46         def SetAttention(self, info):\r
47                 self.SetBackgroundColour('#FFFF80')\r
48                 self.text.SetLabel(info)\r
49                 self.SetAttentionIndicator()\r
50                 self.Refresh()\r
51         \r
52         def SetBusyIndicator(self):\r
53                 self.busyState = 0\r
54                 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])\r
55         \r
56         def doBusyUpdate(self, e):\r
57                 if self.busyState == None:\r
58                         return\r
59                 self.busyState += 1\r
60                 if self.busyState >= len(self.busyBitmap):\r
61                         self.busyState = 0\r
62                 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])\r
63         \r
64         def SetReadyIndicator(self):\r
65                 self.busyState = None\r
66                 self.bitmap.SetBitmap(self.readyBitmap)\r
67         \r
68         def SetErrorIndicator(self):\r
69                 self.busyState = None\r
70                 self.bitmap.SetBitmap(self.errorBitmap)\r
71         \r
72         def SetAttentionIndicator(self):\r
73                 self.busyState = None\r
74                 self.bitmap.SetBitmap(self.attentionBitmap)\r
75 \r
76 class InfoPage(wx.wizard.WizardPageSimple):\r
77         def __init__(self, parent, title):\r
78                 wx.wizard.WizardPageSimple.__init__(self, parent)\r
79 \r
80                 sizer = wx.GridBagSizer(5, 5)\r
81                 self.sizer = sizer\r
82                 self.SetSizer(sizer)\r
83 \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
89                 \r
90                 self.rowNr = 2\r
91         \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
95                 self.rowNr += 1\r
96                 return text\r
97         \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
100                 self.rowNr += 1\r
101         \r
102         def AddHiddenSeperator(self):\r
103                 self.AddText('')\r
104 \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
108                 self.rowNr += 1\r
109                 return infoBox\r
110         \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
114                 self.rowNr += 1\r
115                 return radio\r
116 \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
123                 self.rowNr += 1\r
124                 return check\r
125         \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
129                 self.rowNr += 1\r
130                 return button\r
131         \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
137                 self.rowNr += 1\r
138                 return button1, button2\r
139         \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
143                 self.rowNr += 1\r
144                 return ret\r
145 \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
151                 self.rowNr += 1\r
152                 return ret\r
153         \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
159                 self.rowNr += 1\r
160                 return text, button\r
161 \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
165                 self.rowNr += 1\r
166                 return bitmap\r
167 \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
173                 self.rowNr += 1\r
174                 return check\r
175                 \r
176         def AllowNext(self):\r
177                 return True\r
178         \r
179         def StoreData(self):\r
180                 pass\r
181 \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
193 \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
207 \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
217 \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
222 \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
228                 \r
229         def OnUltimakerSelect(self, e):\r
230                 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)\r
231                 \r
232         def OnOtherSelect(self, e):\r
233                 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)\r
234         \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
244                 else:\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
253 \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
271         \r
272         def AllowNext(self):\r
273                 return False\r
274         \r
275         def OnUpgradeClick(self, e):\r
276                 if firmwareInstall.InstallFirmware():\r
277                         self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
278                 \r
279         def OnSkipClick(self, e):\r
280                 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
281         \r
282         def OnUrlClick(self, e):\r
283                 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')\r
284 \r
285 class UltimakerCheckupPage(InfoPage):\r
286         def __init__(self, parent):\r
287                 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")\r
288 \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
299 \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
314                 self.comm = None\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
321 \r
322         def __del__(self):\r
323                 if self.comm != None:\r
324                         self.comm.close()\r
325         \r
326         def AllowNext(self):\r
327                 self.endstopBitmap.Show(False)\r
328                 return False\r
329         \r
330         def OnSkipClick(self, e):\r
331                 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
332         \r
333         def OnCheckClick(self, e):\r
334                 if self.comm != None:\r
335                         self.comm.close()\r
336                         del self.comm\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
344 \r
345         def mcLog(self, message):\r
346                 pass\r
347 \r
348         def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):\r
349                 if not self.comm.isOperational():\r
350                         return\r
351                 if self.checkupState == 0:\r
352                         self.tempCheckTimeout = 20\r
353                         if temp > 70:\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
358                         else:\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
365                         if temp < 60:\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
382                         else:\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
391 \r
392         def mcStateChange(self, state):\r
393                 if self.comm == None:\r
394                         return\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
401         \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
405                                 if ':' in data:\r
406                                         tag, value = data.split(':', 2)\r
407                                         if tag == 'x_min':\r
408                                                 self.xMinStop = (value == 'H')\r
409                                         if tag == 'x_max':\r
410                                                 self.xMaxStop = (value == 'H')\r
411                                         if tag == 'y_min':\r
412                                                 self.yMinStop = (value == 'H')\r
413                                         if tag == 'y_max':\r
414                                                 self.yMaxStop = (value == 'H')\r
415                                         if tag == 'z_min':\r
416                                                 self.zMinStop = (value == 'H')\r
417                                         if tag == 'z_max':\r
418                                                 self.zMaxStop = (value == 'H')\r
419                         self.comm.sendCommand('M119')\r
420                         \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
454                                         self.comm.close()\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
460 \r
461         def mcProgress(self, lineNr):\r
462                 pass\r
463         \r
464         def mcZChange(self, newZ):\r
465                 pass\r
466 \r
467 class UltimakerCalibrationPage(InfoPage):\r
468         def __init__(self, parent):\r
469                 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")\r
470                 \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
484 \r
485         def StoreData(self):\r
486                 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())\r
487 \r
488 class UltimakerCalibrateStepsPerEPage(InfoPage):\r
489         def __init__(self, parent):\r
490                 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")\r
491 \r
492                 if profile.getPreference('steps_per_e') == '0':\r
493                         profile.putPreference('steps_per_e', '865.888')\r
494                 \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
508                 \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
512         \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
519         \r
520         def OnExtrudeClick(self, e):\r
521                 threading.Thread(target=self.OnExtrudeRun).start()\r
522 \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
532                         return\r
533                 while True:\r
534                         line = self.comm.readline()\r
535                         if line == '':\r
536                                 return\r
537                         if 'start' in line:\r
538                                 break\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
540                 time.sleep(3)\r
541                 \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
546                 time.sleep(15)\r
547                 self.comm.close()\r
548                 self.extrudeButton.Enable()\r
549                 self.heatButton.Enable()\r
550 \r
551         def OnHeatClick(self, e):\r
552                 threading.Thread(target=self.OnHeatRun).start()\r
553         \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
562                         return\r
563                 while True:\r
564                         line = self.comm.readline()\r
565                         if line == '':\r
566                                 self.heatButton.Enable(True)\r
567                                 self.extrudeButton.Enable(True)\r
568                                 return\r
569                         if 'start' in line:\r
570                                 break\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
572                 time.sleep(3)\r
573                 \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
577                 time.sleep(1)\r
578                 self.comm.close()\r
579                 self.heatButton.Enable(True)\r
580                 self.extrudeButton.Enable(True)\r
581         \r
582         def sendGCommand(self, cmd):\r
583                 self.comm.sendCommand(cmd) #Disable cold extrusion protection\r
584                 while True:\r
585                         line = self.comm.readline()\r
586                         if line == '':\r
587                                 return\r
588                         if line.startswith('ok'):\r
589                                 break\r
590         \r
591         def StoreData(self):\r
592                 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())\r
593 \r
594 class configWizard(wx.wizard.Wizard):\r
595         def __init__(self):\r
596                 super(configWizard, self).__init__(None, -1, "Configuration Wizard")\r
597                 \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
600 \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
608 \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
614                 \r
615                 self.FitToPage(self.firstInfoPage)\r
616                 self.GetPageAreaSizer().Add(self.firstInfoPage)\r
617                 \r
618                 self.RunWizard(self.firstInfoPage)\r
619                 self.Destroy()\r
620 \r
621         def OnPageChanging(self, e):\r
622                 e.GetPage().StoreData()\r
623 \r
624         def OnPageChanged(self, e):\r
625                 if e.GetPage().AllowNext():\r
626                         self.FindWindowById(wx.ID_FORWARD).Enable() \r
627                 else:\r
628                         self.FindWindowById(wx.ID_FORWARD).Disable() \r
629                 self.FindWindowById(wx.ID_BACKWARD).Disable() \r