chiark / gitweb /
Fixed #189
[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 util import machineCom\r
9 from util import profile\r
10 \r
11 class InfoPage(wx.wizard.WizardPageSimple):\r
12         def __init__(self, parent, title):\r
13                 wx.wizard.WizardPageSimple.__init__(self, parent)\r
14 \r
15                 sizer = wx.GridBagSizer(5, 5)\r
16                 self.sizer = sizer\r
17                 self.SetSizer(sizer)\r
18                 sizer.AddGrowableCol(1)\r
19 \r
20                 title = wx.StaticText(self, -1, title)\r
21                 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))\r
22                 sizer.Add(title, pos=(0, 0), span=(1,2), flag=wx.ALIGN_CENTRE|wx.ALL)\r
23                 sizer.Add(wx.StaticLine(self, -1), pos=(1,0), span=(1,2), flag=wx.EXPAND|wx.ALL)\r
24                 \r
25                 self.rowNr = 2\r
26         \r
27         def AddText(self,info):\r
28                 text = wx.StaticText(self, -1, info)\r
29                 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)\r
30                 self.rowNr += 1\r
31                 return text\r
32         \r
33         def AddSeperator(self):\r
34                 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)\r
35                 self.rowNr += 1\r
36         \r
37         def AddHiddenSeperator(self):\r
38                 self.AddText('')\r
39         \r
40         def AddRadioButton(self, label, style = 0):\r
41                 radio = wx.RadioButton(self, -1, label, style=style)\r
42                 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)\r
43                 self.rowNr += 1\r
44                 return radio\r
45 \r
46         def AddCheckbox(self, label, checked = False):\r
47                 check = wx.CheckBox(self, -1)\r
48                 text = wx.StaticText(self, -1, label)\r
49                 check.SetValue(checked)\r
50                 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT|wx.RIGHT)\r
51                 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1,2), flag=wx.ALL)\r
52                 self.rowNr += 1\r
53                 return check\r
54         \r
55         def AddButton(self, label):\r
56                 button = wx.Button(self, -1, label)\r
57                 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)\r
58                 self.rowNr += 1\r
59                 return button\r
60         \r
61         def AddDualButton(self, label1, label2):\r
62                 button1 = wx.Button(self, -1, label1)\r
63                 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)\r
64                 button2 = wx.Button(self, -1, label2)\r
65                 self.GetSizer().Add(button2, pos=(self.rowNr, 1))\r
66                 self.rowNr += 1\r
67                 return button1, button2\r
68         \r
69         def AddTextCtrl(self, value):\r
70                 ret = wx.TextCtrl(self, -1, value)\r
71                 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)\r
72                 self.rowNr += 1\r
73                 return ret\r
74 \r
75         def AddLabelTextCtrl(self, info, value):\r
76                 text = wx.StaticText(self, -1, info)\r
77                 ret = wx.TextCtrl(self, -1, value)\r
78                 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)\r
79                 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)\r
80                 self.rowNr += 1\r
81                 return ret\r
82         \r
83         def AddTextCtrlButton(self, value, buttonText):\r
84                 text = wx.TextCtrl(self, -1, value)\r
85                 button = wx.Button(self, -1, buttonText)\r
86                 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)\r
87                 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)\r
88                 return text, button\r
89                 \r
90         def AllowNext(self):\r
91                 return True\r
92         \r
93         def StoreData(self):\r
94                 pass\r
95 \r
96 class FirstInfoPage(InfoPage):\r
97         def __init__(self, parent):\r
98                 super(FirstInfoPage, self).__init__(parent, "First time run wizard")\r
99                 self.AddText('Welcome, and thanks for trying Cura!')\r
100                 self.AddSeperator()\r
101                 self.AddText('This wizard will help you with the following steps:')\r
102                 self.AddText('* Configure Cura for your machine')\r
103                 self.AddText('* Upgrade your firmware')\r
104                 self.AddText('* Calibrate your machine')\r
105                 #self.AddText('* Do your first print')\r
106 \r
107 class RepRapInfoPage(InfoPage):\r
108         def __init__(self, parent):\r
109                 super(RepRapInfoPage, self).__init__(parent, "RepRap information")\r
110                 self.AddText('RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')\r
111                 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')\r
112                 self.AddSeperator()\r
113                 self.AddText('You will have to manually install Marlin or Sprinter firmware.')\r
114                 self.AddSeperator()\r
115                 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')\r
116                 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')\r
117                 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')\r
118                 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')\r
119                 self.heatedBed = self.AddCheckbox('Heated bed')\r
120 \r
121         def StoreData(self):\r
122                 profile.putPreference('machine_width', self.machineWidth.GetValue())\r
123                 profile.putPreference('machine_depth', self.machineDepth.GetValue())\r
124                 profile.putPreference('machine_height', self.machineHeight.GetValue())\r
125                 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())\r
126                 profile.putProfileSetting('machine_center_x', profile.getPreferenceFloat('machine_width') / 2)\r
127                 profile.putProfileSetting('machine_center_y', profile.getPreferenceFloat('machine_depth') / 2)\r
128                 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)\r
129                 profile.putPreference('has_heated_bed', str(self.heatedBed.GetValue()))\r
130 \r
131 class MachineSelectPage(InfoPage):\r
132         def __init__(self, parent):\r
133                 super(MachineSelectPage, self).__init__(parent, "Select your machine")\r
134                 self.AddText('What kind of machine do you have:')\r
135 \r
136                 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)\r
137                 self.UltimakerRadio.SetValue(True)\r
138                 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)\r
139                 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")\r
140                 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)\r
141                 \r
142         def OnUltimakerSelect(self, e):\r
143                 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)\r
144                 \r
145         def OnOtherSelect(self, e):\r
146                 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)\r
147         \r
148         def StoreData(self):\r
149                 if self.UltimakerRadio.GetValue():\r
150                         profile.putPreference('machine_width', '205')\r
151                         profile.putPreference('machine_depth', '205')\r
152                         profile.putPreference('machine_height', '200')\r
153                         profile.putPreference('machine_type', 'ultimaker')\r
154                         profile.putProfileSetting('nozzle_size', '0.4')\r
155                         profile.putProfileSetting('machine_center_x', '100')\r
156                         profile.putProfileSetting('machine_center_y', '100')\r
157                 else:\r
158                         profile.putPreference('machine_width', '80')\r
159                         profile.putPreference('machine_depth', '80')\r
160                         profile.putPreference('machine_height', '60')\r
161                         profile.putPreference('machine_type', 'reprap')\r
162                         profile.putProfileSetting('nozzle_size', '0.5')\r
163                         profile.putProfileSetting('machine_center_x', '40')\r
164                         profile.putProfileSetting('machine_center_y', '40')\r
165                 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)\r
166 \r
167 class FirmwareUpgradePage(InfoPage):\r
168         def __init__(self, parent):\r
169                 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")\r
170                 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
171                 self.AddHiddenSeperator()\r
172                 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')\r
173                 self.AddHiddenSeperator()\r
174                 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
175                 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')\r
176                 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)\r
177                 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)\r
178                 self.AddHiddenSeperator()\r
179                 self.AddText('Do not upgrade to this firmware if:')\r
180                 self.AddText('* You have an older machine based on ATMega1280')\r
181                 self.AddText('* Have other changes in the firmware')\r
182                 button = self.AddButton('Goto this page for a custom firmware')\r
183                 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)\r
184         \r
185         def AllowNext(self):\r
186                 return False\r
187         \r
188         def OnUpgradeClick(self, e):\r
189                 if firmwareInstall.InstallFirmware():\r
190                         self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
191                 \r
192         def OnSkipClick(self, e):\r
193                 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
194         \r
195         def OnUrlClick(self, e):\r
196                 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')\r
197 \r
198 class UltimakerCheckupPage(InfoPage):\r
199         def __init__(self, parent):\r
200                 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")\r
201                 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
202                 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')\r
203                 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)\r
204                 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)\r
205                 self.AddSeperator()\r
206                 self.checkPanel = None\r
207         \r
208         def AllowNext(self):\r
209                 return False\r
210         \r
211         def OnSkipClick(self, e):\r
212                 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
213         \r
214         def OnCheckClick(self, e):\r
215                 if self.checkPanel != None:\r
216                         self.checkPanel.Destroy()\r
217                 self.checkPanel = wx.Panel(self)\r
218                 self.checkPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))\r
219                 self.GetSizer().Add(self.checkPanel, 0, wx.LEFT|wx.RIGHT, 5)\r
220                 threading.Thread(target=self.OnRun).start()\r
221 \r
222         def AddProgressText(self, info):\r
223                 text = wx.StaticText(self.checkPanel, -1, info)\r
224                 self.checkPanel.GetSizer().Add(text, 0)\r
225                 self.checkPanel.Layout()\r
226                 self.Layout()\r
227         \r
228         def OnRun(self):\r
229                 wx.CallAfter(self.AddProgressText, "Connecting to machine...")\r
230                 self.comm = machineCom.MachineCom()\r
231                 \r
232                 if not self.comm.isOpen():\r
233                         wx.CallAfter(self.AddProgressText, "Error: Failed to open serial port to machine")\r
234                         wx.CallAfter(self.AddProgressText, "If this keeps happening, try disconnecting and reconnecting the USB cable")\r
235                         return\r
236 \r
237                 wx.CallAfter(self.AddProgressText, "Checking start message...")\r
238                 if self.DoCommCommandWithTimeout(None, 'start') == False:\r
239                         wx.CallAfter(self.AddProgressText, "Error: Missing start message.")\r
240                         self.comm.close()\r
241                         return\r
242                 \r
243                 #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
244                 time.sleep(3)\r
245                 \r
246                 wx.CallAfter(self.AddProgressText, "Disabling step motors...")\r
247                 if self.DoCommCommandWithTimeout('M84') == False:\r
248                         wx.CallAfter(self.AddProgressText, "Error: Missing reply to Deactivate steppers (M84).")\r
249                         self.comm.close()\r
250                         return\r
251 \r
252                 if self.DoCommCommandWithTimeout("M104 S0") == False:\r
253                         wx.CallAfter(self.AddProgressText, "Failed to set temperature")\r
254                         self.comm.close()\r
255                         return\r
256 \r
257                 wx.MessageBox('Please move the printer head to the center of the machine\nalso move the platform so it is not at the highest or lowest position,\nand make sure the machine is powered on.', 'Machine check', wx.OK | wx.ICON_INFORMATION)\r
258                 \r
259                 idleTemp = self.readTemp()\r
260                 if idleTemp > 40:\r
261                         wx.CallAfter(self.AddProgressText, "Waiting for head to cool down before temperature test...")\r
262                         while idleTemp > 40:\r
263                                 idleTemp = self.readTemp()\r
264                                 time.sleep(1)\r
265                 \r
266                 wx.CallAfter(self.AddProgressText, "Checking heater and temperature sensor...")\r
267                 wx.CallAfter(self.AddProgressText, "(This takes about 30 seconds)")\r
268                 if self.DoCommCommandWithTimeout("M104 S100") == False:\r
269                         wx.CallAfter(self.AddProgressText, "Failed to set temperature")\r
270                         self.comm.close()\r
271                         return\r
272                 \r
273                 time.sleep(25)\r
274                 tempInc = self.readTemp() - idleTemp\r
275                 \r
276                 if self.DoCommCommandWithTimeout("M104 S0") == False:\r
277                         wx.CallAfter(self.AddProgressText, "Failed to set temperature")\r
278                         self.comm.close()\r
279                         return\r
280                 \r
281                 if tempInc < 15:\r
282                         wx.CallAfter(self.AddProgressText, "Your temperature sensor or heater is not working!")\r
283                         self.comm.close()\r
284                         return\r
285                 wx.CallAfter(self.AddProgressText, "Heater and temperature sensor working\nWarning: head might still be hot!")\r
286 \r
287                 wx.CallAfter(self.AddProgressText, "Checking endstops")\r
288                 if self.DoCommCommandWithTimeout('M119', 'x_min') != "x_min:L x_max:L y_min:L y_max:L z_min:L z_max:L":\r
289                         wx.CallAfter(self.AddProgressText, "Error: There is a problem in your endstops!\nOne of them seems to be pressed while it shouldn't\ncheck the cable connections and the switches themselfs.")\r
290                         self.comm.close()\r
291                         return\r
292                 wx.CallAfter(self.AddProgressText, "Please press the X end switch in the front left corner.")\r
293                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:H x_max:L y_min:L y_max:L z_min:L z_max:L"):\r
294                         wx.CallAfter(self.AddProgressText, "Failed to check the x_min endstop!")\r
295                         self.comm.close()\r
296                         return\r
297                 wx.CallAfter(self.AddProgressText, "Please press the X end switch in the front right corner.")\r
298                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:H y_min:L y_max:L z_min:L z_max:L"):\r
299                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
300                         self.comm.close()\r
301                         return\r
302                 wx.CallAfter(self.AddProgressText, "Please press the Y end switch in the front left corner.")\r
303                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:H y_max:L z_min:L z_max:L"):\r
304                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
305                         self.comm.close()\r
306                         return\r
307                 wx.CallAfter(self.AddProgressText, "Please press the Y end switch in the back left corner.")\r
308                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:H z_min:L z_max:L"):\r
309                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
310                         self.comm.close()\r
311                         return\r
312                 wx.CallAfter(self.AddProgressText, "Please press the Z end switch in the top.")\r
313                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:L z_min:H z_max:L"):\r
314                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
315                         self.comm.close()\r
316                         return\r
317                 wx.CallAfter(self.AddProgressText, "Please press the Z end switch in the bottom.")\r
318                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:L z_min:L z_max:H"):\r
319                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
320                         self.comm.close()\r
321                         return\r
322                 wx.CallAfter(self.AddProgressText, "End stops are working.")\r
323 \r
324                 wx.CallAfter(self.AddProgressText, "Done!")\r
325                 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)\r
326                 self.comm.close()\r
327                 \r
328         def readTemp(self):\r
329                 line = self.DoCommCommandWithTimeout("M105", "ok T:")\r
330                 if line == False:\r
331                         return -1\r
332                 return int(re.search('T:([0-9]*)', line).group(1))\r
333         \r
334         def DoCommCommandAndWaitForReply(self, cmd, replyStart, reply):\r
335                 while True:\r
336                         ret = self.DoCommCommandWithTimeout(cmd, replyStart)\r
337                         if ret == reply:\r
338                                 return True\r
339                         if ret == False:\r
340                                 return False\r
341                         time.sleep(1)\r
342         \r
343         def DoCommCommandWithTimeout(self, cmd = None, replyStart = 'ok'):\r
344                 if cmd != None:\r
345                         self.comm.sendCommand(cmd)\r
346                 t = threading.Timer(5, self.OnSerialTimeout)\r
347                 t.start()\r
348                 while True:\r
349                         line = self.comm.readline()\r
350                         if line == '' or line == None:\r
351                                 self.comm.close()\r
352                                 return False\r
353                         print line.rstrip()\r
354                         if replyStart in line:\r
355                                 break\r
356                 t.cancel()\r
357                 return line.rstrip()\r
358         \r
359         def OnSerialTimeout(self):\r
360                 self.comm.close()\r
361 \r
362 class UltimakerCalibrationPage(InfoPage):\r
363         def __init__(self, parent):\r
364                 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")\r
365                 \r
366                 self.AddText("Your Ultimaker requires some calibration.")\r
367                 self.AddText("This calibration is needed for a proper extrusion amount.")\r
368                 self.AddSeperator()\r
369                 self.AddText("The following values are needed:")\r
370                 self.AddText("* Diameter of filament")\r
371                 self.AddText("* Number of steps per mm of filament extrusion")\r
372                 self.AddSeperator()\r
373                 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")\r
374                 self.AddSeperator()\r
375                 self.AddText("First we need the diameter of your filament:")\r
376                 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))\r
377                 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
378                 self.AddText("Note: This value can be changed later at any time.")\r
379 \r
380         def StoreData(self):\r
381                 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())\r
382 \r
383 class UltimakerCalibrateStepsPerEPage(InfoPage):\r
384         def __init__(self, parent):\r
385                 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")\r
386 \r
387                 if profile.getPreference('steps_per_e') == '0':\r
388                         profile.putPreference('steps_per_e', '865.888')\r
389                 \r
390                 self.AddText("Calibrating the Steps Per E requires some manual actions.")\r
391                 self.AddText("First remove any filament from your machine.")\r
392                 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")\r
393                 self.AddText("We'll push the filament 100mm")\r
394                 self.extrudeButton = self.AddButton("Extrude 100mm filament")\r
395                 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")\r
396                 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')\r
397                 self.AddText("This results in the following steps per E:")\r
398                 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))\r
399                 self.AddText("You can repeat these steps to get better calibration.")\r
400                 self.AddSeperator()\r
401                 self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")\r
402                 self.heatButton = self.AddButton("Heatup for filament removal")\r
403                 \r
404                 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)\r
405                 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)\r
406                 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)\r
407         \r
408         def OnSaveLengthClick(self, e):\r
409                 currentEValue = float(self.stepsPerEInput.GetValue())\r
410                 realExtrudeLength = float(self.lengthInput.GetValue())\r
411                 newEValue = currentEValue * 100 / realExtrudeLength\r
412                 self.stepsPerEInput.SetValue(str(newEValue))\r
413                 self.lengthInput.SetValue("100")\r
414         \r
415         def OnExtrudeClick(self, e):\r
416                 threading.Thread(target=self.OnExtrudeRun).start()\r
417 \r
418         def OnExtrudeRun(self):\r
419                 self.heatButton.Enable(False)\r
420                 self.extrudeButton.Enable(False)\r
421                 currentEValue = float(self.stepsPerEInput.GetValue())\r
422                 self.comm = machineCom.MachineCom()\r
423                 if not self.comm.isOpen():\r
424                         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
425                         self.heatButton.Enable(True)\r
426                         self.extrudeButton.Enable(True)\r
427                         return\r
428                 while True:\r
429                         line = self.comm.readline()\r
430                         if line == '':\r
431                                 return\r
432                         if 'start' in line:\r
433                                 break\r
434                 #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
435                 time.sleep(3)\r
436                 \r
437                 self.sendGCommand('M302') #Disable cold extrusion protection\r
438                 self.sendGCommand("M92 E%f" % (currentEValue))\r
439                 self.sendGCommand("G92 E0")\r
440                 self.sendGCommand("G1 E100 F600")\r
441                 time.sleep(15)\r
442                 self.comm.close()\r
443                 self.extrudeButton.Enable()\r
444                 self.heatButton.Enable()\r
445 \r
446         def OnHeatClick(self, e):\r
447                 threading.Thread(target=self.OnHeatRun).start()\r
448         \r
449         def OnHeatRun(self):\r
450                 self.heatButton.Enable(False)\r
451                 self.extrudeButton.Enable(False)\r
452                 self.comm = machineCom.MachineCom()\r
453                 if not self.comm.isOpen():\r
454                         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
455                         self.heatButton.Enable(True)\r
456                         self.extrudeButton.Enable(True)\r
457                         return\r
458                 while True:\r
459                         line = self.comm.readline()\r
460                         if line == '':\r
461                                 self.heatButton.Enable(True)\r
462                                 self.extrudeButton.Enable(True)\r
463                                 return\r
464                         if 'start' in line:\r
465                                 break\r
466                 #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
467                 time.sleep(3)\r
468                 \r
469                 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.\r
470                 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
471                 self.sendGCommand('M104 S0')\r
472                 time.sleep(1)\r
473                 self.comm.close()\r
474                 self.heatButton.Enable(True)\r
475                 self.extrudeButton.Enable(True)\r
476         \r
477         def sendGCommand(self, cmd):\r
478                 self.comm.sendCommand(cmd) #Disable cold extrusion protection\r
479                 while True:\r
480                         line = self.comm.readline()\r
481                         if line == '':\r
482                                 return\r
483                         if line.startswith('ok'):\r
484                                 break\r
485         \r
486         def StoreData(self):\r
487                 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())\r
488 \r
489 class configWizard(wx.wizard.Wizard):\r
490         def __init__(self):\r
491                 super(configWizard, self).__init__(None, -1, "Configuration Wizard")\r
492                 \r
493                 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)\r
494                 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)\r
495 \r
496                 self.firstInfoPage = FirstInfoPage(self)\r
497                 self.machineSelectPage = MachineSelectPage(self)\r
498                 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)\r
499                 self.ultimakerCheckupPage = UltimakerCheckupPage(self)\r
500                 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)\r
501                 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)\r
502                 self.repRapInfoPage = RepRapInfoPage(self)\r
503 \r
504                 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)\r
505                 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerFirmwareUpgradePage)\r
506                 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)\r
507                 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)\r
508                 wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)\r
509                 \r
510                 self.FitToPage(self.firstInfoPage)\r
511                 self.GetPageAreaSizer().Add(self.firstInfoPage)\r
512                 \r
513                 self.RunWizard(self.firstInfoPage)\r
514                 self.Destroy()\r
515 \r
516         def OnPageChanging(self, e):\r
517                 e.GetPage().StoreData()\r
518 \r
519         def OnPageChanged(self, e):\r
520                 if e.GetPage().AllowNext():\r
521                         self.FindWindowById(wx.ID_FORWARD).Enable() \r
522                 else:\r
523                         self.FindWindowById(wx.ID_FORWARD).Disable() \r
524                 self.FindWindowById(wx.ID_BACKWARD).Disable() \r