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