from Cura.gui import printWindow
from Cura.util import machineCom
from Cura.util import profile
+from Cura.util import gcodeGenerator
from Cura.util.resources import getPathForImage
class InfoBox(wx.Panel):
self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
self.bedLevelPage = bedLevelWizardMain(self)
+ self.headOffsetCalibration = headOffsetCalibrationPage(self)
self.repRapInfoPage = RepRapInfoPage(self)
wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
self._wizardState = 0
def AllowNext(self):
+ if self.GetParent().headOffsetCalibration is not None and int(profile.getPreference('extruder_amount')) > 1:
+ wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
return True
def OnResume(self, e):
wx.CallAfter(self.resumeButton.Enable, True)
elif self._wizardState == 9:
if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
- wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp, profile.getProfileSettingFloat('print_temperature')))
+ wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature')))
else:
wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.')
wx.CallAfter(self.resumeButton.Enable, True)
def mcZChange(self, newZ):
pass
+class headOffsetCalibrationPage(InfoPage):
+ def __init__(self, parent):
+ super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration (WIP)")
+
+ self.AddText('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine')
+ self.AddSeperator()
+
+ self.connectButton = self.AddButton('Connect to printer')
+ self.comm = None
+
+ self.infoBox = self.AddInfoBox()
+ self.textEntry = self.AddTextCtrl('')
+ self.textEntry.Enable(False)
+ self.resumeButton = self.AddButton('Resume')
+ self.resumeButton.Enable(False)
+
+ self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
+ self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
+
+ def OnConnect(self, e = None):
+ if self.comm is not None:
+ self.comm.close()
+ del self.comm
+ self.comm = None
+ wx.CallAfter(self.OnConnect)
+ return
+ self.connectButton.Enable(False)
+ self.comm = machineCom.MachineCom(callbackObject=self)
+ self.infoBox.SetBusy('Connecting to machine.')
+ self._wizardState = 0
+
+ def OnResume(self, e):
+ if self._wizardState == 2:
+ self._wizardState = 3
+ wx.CallAfter(self.infoBox.SetBusy, 'Printing initial calibration cross')
+
+ w = profile.getPreferenceFloat('machine_width')
+ d = profile.getPreferenceFloat('machine_depth')
+
+ gcode = gcodeGenerator.gcodeGenerator()
+ gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.3)
+ gcode.addCmd('T0')
+ gcode.addPrime(15)
+ gcode.addCmd('T1')
+ gcode.addPrime(15)
+
+ gcode.addCmd('T0')
+ gcode.addMove(w/2, 5, 0.3)
+ gcode.addExtrude(w/2, d-5.0)
+ gcode.addRetract()
+ gcode.addMove(5, d/2)
+ gcode.addPrime()
+ gcode.addExtrude(w-5.0, d/2)
+ gcode.addRetract(15)
+
+ gcode.addCmd('T1')
+ gcode.addMove(w/2, 5)
+ gcode.addExtrude(w/2, d-5.0)
+ gcode.addRetract()
+ gcode.addMove(5, d/2)
+ gcode.addPrime()
+ gcode.addExtrude(w-5.0, d/2)
+ gcode.addCmd('T0')
+ gcode.addRetract(15)
+
+ gcode.addMove(z=25)
+
+ self.comm.printGCode(gcode.list())
+ self.resumeButton.Enable(False)
+ if self._wizardState == 4:
+ try:
+ float(self.textEntry.GetValue())
+ except ValueError:
+ return
+ profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
+ self._wizardState = 5
+ self.infoBox.SetAttention('Please measure the distance between the horizontal lines in millimeters.')
+ self.textEntry.SetValue('0.0')
+ self.textEntry.Enable(True)
+ if self._wizardState == 5:
+ try:
+ float(self.textEntry.GetValue())
+ except ValueError:
+ return
+ profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
+ self._wizardState = 6
+ self.infoBox.SetBusy('Printing the fine calibration lines.')
+ self.textEntry.SetValue('')
+ self.textEntry.Enable(False)
+ self.resumeButton.Enable(False)
+
+ def mcLog(self, message):
+ print 'Log:', message
+
+ def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
+ if self._wizardState == 1:
+ if temp[0] >= 210 and temp[1] >= 210:
+ self._wizardState = 2
+ wx.CallAfter(self.infoBox.SetAttention, 'Please load both extruders with PLA.')
+ wx.CallAfter(self.resumeButton.Enable, True)
+
+ def mcStateChange(self, state):
+ if self.comm is None:
+ return
+ if self.comm.isOperational():
+ if self._wizardState == 0:
+ wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.')
+ self.comm.sendCommand('M105')
+ self.comm.sendCommand('G28')
+ self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
+ self.comm.sendCommand('M104 S220 T0')
+ self.comm.sendCommand('M104 S220 T1')
+ self._wizardState = 1
+ if not self.comm.isPrinting():
+ if self._wizardState == 3:
+ self._wizardState = 4
+ wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.')
+ wx.CallAfter(self.textEntry.SetValue, '0.0')
+ wx.CallAfter(self.textEntry.Enable, True)
+ wx.CallAfter(self.resumeButton.Enable, True)
+ wx.CallAfter(self.resumeButton.SetFocus)
+ elif self.comm.isError():
+ wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
+
+ def mcMessage(self, message):
+ pass
+
+ def mcProgress(self, lineNr):
+ pass
+
+ def mcZChange(self, newZ):
+ pass
+
class bedLevelWizard(wx.wizard.Wizard):
def __init__(self):
super(bedLevelWizard, self).__init__(None, -1, "Bed leveling wizard")
self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
self.mainPage = bedLevelWizardMain(self)
+ self.headOffsetCalibration = None
self.FitToPage(self.mainPage)
self.GetPageAreaSizer().Add(self.mainPage)
--- /dev/null
+from __future__ import absolute_import
+
+import math
+
+from Cura.util import profile
+
+class gcodeGenerator(object):
+ def __init__(self):
+ self._feedPrint = profile.getProfileSettingFloat('print_speed') * 60
+ self._feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
+ self._feedRetract = profile.getProfileSettingFloat('retraction_speed') * 60
+ filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
+ filamentArea = math.pi * filamentRadius * filamentRadius
+ self._ePerMM = (profile.getProfileSettingFloat('nozzle_size') * 0.1) / filamentArea
+ self._eValue = 0.0
+ self._x = 0
+ self._y = 0
+ self._z = 0
+
+ self._list = ['G92 E0']
+
+ def setExtrusionRate(self, lineWidth, layerHeight):
+ filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
+ filamentArea = math.pi * filamentRadius * filamentRadius
+ self._ePerMM = (lineWidth * layerHeight) / filamentArea
+
+ def home(self):
+ self._x = 0
+ self._y = 0
+ self._z = 0
+ self._list += ['G28']
+
+ def addMove(self, x=None, y=None, z=None):
+ cmd = "G0 "
+ if x is not None:
+ cmd += "X%f " % (x)
+ self._x = x
+ if y is not None:
+ cmd += "Y%f " % (y)
+ self._y = y
+ if z is not None:
+ cmd += "Z%f " % (z)
+ self._z = z
+ cmd += "F%d" % (self._feedTravel)
+ self._list += [cmd]
+
+ def addPrime(self, amount=5):
+ self._eValue += amount
+ self._list += ['G1 E%f F%f' % (self._eValue, self._feedRetract)]
+
+ def addRetract(self, amount=5):
+ self._eValue -= amount
+ self._list += ['G1 E%f F%f' % (self._eValue, self._feedRetract)]
+
+ def addExtrude(self, x=None, y=None, z=None):
+ cmd = "G1 "
+ oldX = self._x
+ oldY = self._y
+ if x is not None:
+ cmd += "X%f " % (x)
+ self._x = x
+ if y is not None:
+ cmd += "Y%f " % (y)
+ self._y = y
+ if z is not None:
+ cmd += "Z%f " % (z)
+ self._z = z
+ self._eValue += math.sqrt((self._x - oldX) * (self._x - oldX) + (self._y - oldY) * (self._y - oldY)) * self._ePerMM
+ cmd += "E%f F%d" % (self._eValue, self._feedPrint)
+ self._list += [cmd]
+
+ def addCmd(self, cmd):
+ self._list += [cmd]
+
+ def list(self):
+ return self._list
\ No newline at end of file