From 5af2532e2a224f54cc7a7e02f4a8ec39f636d3ea Mon Sep 17 00:00:00 2001 From: daid303 Date: Mon, 6 May 2013 11:43:55 +0200 Subject: [PATCH] Possible fix for the fluxline selection problem. Added first part of the dual-extrusion nozzle calibration. --- Cura/gui/configWizard.py | 140 +++++++++++++++++++++++++++++++++++- Cura/gui/sceneView.py | 4 +- Cura/util/gcodeGenerator.py | 76 ++++++++++++++++++++ 3 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 Cura/util/gcodeGenerator.py diff --git a/Cura/gui/configWizard.py b/Cura/gui/configWizard.py index 88675d66..eab29df3 100644 --- a/Cura/gui/configWizard.py +++ b/Cura/gui/configWizard.py @@ -13,6 +13,7 @@ from Cura.gui import firmwareInstall 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): @@ -744,6 +745,7 @@ class configWizard(wx.wizard.Wizard): 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) @@ -804,6 +806,8 @@ class bedLevelWizardMain(InfoPage): 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): @@ -894,7 +898,7 @@ class bedLevelWizardMain(InfoPage): 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) @@ -931,6 +935,139 @@ class bedLevelWizardMain(InfoPage): 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") @@ -939,6 +1076,7 @@ class bedLevelWizard(wx.wizard.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) diff --git a/Cura/gui/sceneView.py b/Cura/gui/sceneView.py index 5cb6376c..eef4478f 100644 --- a/Cura/gui/sceneView.py +++ b/Cura/gui/sceneView.py @@ -758,12 +758,12 @@ void main(void) if self.viewMode != 'gcode': for n in xrange(0, len(self._scene.objects())): obj = self._scene.objects()[n] - glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF) + glColor4ub((n >> 16) & 0xFF, (n >> 8) & 0xFF, (n >> 0) & 0xFF, 0xFF) self._renderObject(obj) if self._mouseX > -1: glFlush() - n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0] + n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0] >> 8 if n < len(self._scene.objects()): self._focusObj = self._scene.objects()[n] else: diff --git a/Cura/util/gcodeGenerator.py b/Cura/util/gcodeGenerator.py new file mode 100644 index 00000000..50f33158 --- /dev/null +++ b/Cura/util/gcodeGenerator.py @@ -0,0 +1,76 @@ +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 -- 2.30.2