def gotoLinePopup(self): self.popupContent = TouchNumberInput(done=self.dismiss_gotoLinePopup) self._popup = Popup(title="Go to gcode line", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open()
def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open()
def setDist(self): self.popupContent = TouchNumberInput(done=self.dismiss_popup) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup)
def gotoLinePopup(self): self.popupContent = TouchNumberInput(done=self.dismiss_gotoLinePopup) self._popup = Popup(title="Go to gcode line", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup)
def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup) self._popup = Popup(title="Number of links", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup)
def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data = self.data) self.popupContent.forceUnitsMM() self._popup = Popup(title="Set distance to move chain", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup)
def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data=self.data) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup)
def zAxisPopup(self): self.popupContent = ZAxisPopupContent(done=self.dismissZAxisPopup) self.popupContent.data = self.data self.popupContent.initialize(self.zStepSizeVal) self._popup = Popup(title="Z-Axis", content=self.popupContent, size_hint=(0.5, 0.5)) self._popup.open()
def setDist(self): self.popupContent = TouchNumberInput(done=self.dismiss_popup, data=self.data) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open()
def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup) self._popup = Popup(title="Load file", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open()
def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data = self.data) self.popupContent.forceUnitsMM() self._popup = Popup(title="Set distance to move chain", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup)
def enterDist(self): ''' Called when the "Enter Measurement" button is pressed ''' self.popupContent = TouchNumberInput(done=self.dismiss_popup, data=self.data) self._popup = Popup(title="Enter Measured Distance", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open()
class FrontPage(Screen, MakesmithInitFuncs): textconsole = ObjectProperty(None) connectmenu = ObjectProperty( None) #make ConnectMenu object accessible at this scope gcodecanvas = ObjectProperty(None) screenControls = ObjectProperty(None) connectionStatus = StringProperty("Not Connected") xReadoutPos = StringProperty("0 mm") yReadoutPos = StringProperty("0 mm") zReadoutPos = StringProperty("0 mm") percentComplete = StringProperty("0.0%") numericalPosX = 0.0 numericalPosY = 0.0 stepsizeval = 0 zStepSizeVal = .1 consoleText = StringProperty(" ") units = StringProperty("MM") gcodeLineNumber = StringProperty('0') def __init__(self, data, **kwargs): super(FrontPage, self).__init__(**kwargs) self.data = data def setPosReadout(self, xPos, yPos, zPos): self.xReadoutPos = "X: " + str(xPos) self.yReadoutPos = "Y: " + str(yPos) self.zReadoutPos = "Z: " + str(zPos) self.numericalPosX = xPos self.numericalPosY = yPos def setUpData(self, data): self.gcodecanvas.setUpData(data) self.screenControls.setUpData(data) self.data.bind(connectionStatus=self.updateConnectionStatus) self.data.bind(units=self.onUnitsSwitch) self.data.bind(gcodeIndex=self.onIndexMove) self.data.bind(gcodeFile=self.onGcodeFileChange) self.data.bind(uploadFlag=self.onUploadFlagChange) def updateConnectionStatus(self, callback, connected): if connected: self.connectionStatus = "Connected" else: self.connectionStatus = "Connection Lost" def switchUnits(self): if self.data.units == "INCHES": self.data.units = "MM" else: self.data.units = "INCHES" def onUnitsSwitch(self, callback, newUnits): self.units = newUnits INCHESTOMM = 1 / 25.4 MMTOINCHES = 25.4 if newUnits == "INCHES": self.data.gcode_queue.put('G20 ') self.moveDistInput.text = str(float(self.moveDistInput.text) / 25) self.data.tolerance = 0.020 else: self.data.gcode_queue.put('G21 ') self.moveDistInput.text = str(float(self.moveDistInput.text) * 25) self.data.tolerance = 0.5 def onIndexMove(self, callback, newIndex): self.gcodeLineNumber = str(newIndex) self.percentComplete = '%.1f' % (100 * (float(newIndex) / (len(self.data.gcode) - 1))) + "%" def onGcodeFileChange(self, callback, newGcode): pass def onUploadFlagChange(self, callback, newFlagValue): if self.data.uploadFlag is 0 and self.data.gcodeIndex > 1: #if the machine is stopped partway through a file self.holdBtn.text = "CONTINUE" else: self.holdBtn.text = "HOLD" def moveGcodeZ(self, moves): ''' Move the gcode index by z moves ''' dist = 0 for index, zMove in enumerate(self.data.zMoves): if moves > 0 and zMove > self.data.gcodeIndex: dist = self.data.zMoves[index + moves - 1] - self.data.gcodeIndex break if moves < 0 and zMove < self.data.gcodeIndex: dist = self.data.zMoves[index + moves + 1] - self.data.gcodeIndex self.moveGcodeIndex(dist) def moveGcodeIndex(self, dist): ''' Move the gcode index by a dist number of lines ''' maxIndex = len(self.data.gcode) - 1 targetIndex = self.data.gcodeIndex + dist #check to see if we are still within the length of the file if targetIndex < 0: #negative index not allowed self.data.gcodeIndex = 0 elif maxIndex < 0: #break if there is no data to read return elif targetIndex > maxIndex: #reading past the end of the file is not allowed self.data.gcodeIndex = maxIndex else: self.data.gcodeIndex = targetIndex gCodeLine = self.data.gcode[self.data.gcodeIndex] xTarget = 0 yTarget = 0 try: x = re.search("X(?=.)([+-]?([0-9]*)(\.([0-9]+))?)", gCodeLine) if x: xTarget = float(x.groups()[0]) else: if self.data.units == "INCHES": xTarget = self.gcodecanvas.positionIndicator.pos[0] / 25.4 else: xTarget = self.gcodecanvas.positionIndicator.pos[0] y = re.search("Y(?=.)([+-]?([0-9]*)(\.([0-9]+))?)", gCodeLine) if y: yTarget = float(y.groups()[0]) else: if self.data.units == "INCHES": yTarget = self.gcodecanvas.positionIndicator.pos[1] / 25.4 else: yTarget = self.gcodecanvas.positionIndicator.pos[1] self.gcodecanvas.positionIndicator.setPos(xTarget, yTarget, self.data.units) except: print "Unable to update position for new gcode line" def pause(self): if self.holdBtn.text == "HOLD": self.data.uploadFlag = 0 print("Run Paused") else: self.data.uploadFlag = 1 self.data.quick_queue.put( "~") #send cycle resume command to unpause the machine print("Run Resumed") def jmpsize(self): try: self.stepsizeval = float(self.moveDistInput.text) except: pass def test(self): print "test has no current function" def upLeft(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(-1 * self.stepsizeval) + " Y" + str(self.stepsizeval) + " G90 ") def upRight(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(self.stepsizeval) + " Y" + str(self.stepsizeval) + " G90 ") def up(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 Y" + str(self.stepsizeval) + " G90 ") def left(self): self.jmpsize() self.data.gcode_queue.put("G91 G0 X" + str(-1 * self.stepsizeval) + " G90 ") def right(self): self.jmpsize() self.data.gcode_queue.put("G91 G0 X" + str(self.stepsizeval) + " G90 ") def downLeft(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(-1 * self.stepsizeval) + " Y" + str(-1 * self.stepsizeval) + " G90 ") def down(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 Y" + str(-1 * self.stepsizeval) + " G90 ") def downRight(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(self.stepsizeval) + " Y" + str(-1 * self.stepsizeval) + " G90 ") def zAxisPopup(self): self.popupContent = ZAxisPopupContent(done=self.dismissZAxisPopup) self.popupContent.data = self.data self.popupContent.initialize(self.zStepSizeVal) self._popup = Popup(title="Z-Axis", content=self.popupContent, size_hint=(0.5, 0.5)) self._popup.open() def dismissZAxisPopup(self): ''' Close The Z-Axis Pop-up ''' try: self.zStepSizeVal = float(self.popupContent.distBtn.text) except: pass self._popup.dismiss() def home(self): ''' Return the machine to it's home position. (0,0) is the default unless the origin has been moved by the user. ''' self.data.gcode_queue.put("G90 ") #if the machine has a z-axis lift it then go home if int(self.data.config.get('Maslow Settings', 'zAxis')): if self.units == "INCHES": self.data.gcode_queue.put("G00 Z.25 ") else: self.data.gcode_queue.put("G00 Z5.0 ") self.data.gcode_queue.put("G00 X" + str(self.data.gcodeShift[0]) + " Y" + str(self.data.gcodeShift[1]) + " ") self.data.gcode_queue.put("G00 Z0 ") #if the machine does not have a z-axis, just go home else: self.data.gcode_queue.put("G00 X" + str(self.data.gcodeShift[0]) + " Y" + str(self.data.gcodeShift[1]) + " ") def moveOrigin(self): ''' Move the gcode origin to the current location ''' self.data.gcodeShift = [self.numericalPosX, self.numericalPosY] self.data.config.set('Advanced Settings', 'homeX', str(self.numericalPosX)) self.data.config.set('Advanced Settings', 'homeY', str(self.numericalPosY)) self.data.config.write() def startRun(self): self.data.uploadFlag = 1 self.sendLine() def sendLine(self): try: self.data.gcode_queue.put(self.data.gcode[self.data.gcodeIndex]) self.data.gcodeIndex = self.data.gcodeIndex + 1 except: print "gcode run complete" self.gcodecanvas.uploadFlag = 0 self.data.gcodeIndex = 0 def stopRun(self): self.data.uploadFlag = 0 self.data.gcodeIndex = 0 self.data.quick_queue.put("!") with self.data.gcode_queue.mutex: self.data.gcode_queue.queue.clear() self.onUploadFlagChange(self.stopRun, 0) print("Gode Stopped") def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() def dismiss_popup(self): ''' Close The Pop-up ''' try: float(self.popupContent.textInput.text) self.targetWidget.text = self.popupContent.textInput.text except: pass #If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def gotoLinePopup(self): self.popupContent = TouchNumberInput(done=self.dismiss_gotoLinePopup) self._popup = Popup(title="Go to gcode line", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() def dismiss_gotoLinePopup(self): ''' Close The Pop-up ''' try: line = int(self.popupContent.textInput.text) if line < 0: self.data.gcodeIndex = 0 elif line > len(self.data.gcode): self.data.gcodeIndex = len(self.data.gcode) else: self.data.gcodeIndex = line except: pass #If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def macro(self, index): ''' Execute user defined macro ''' self.data.gcode_queue.put( self.data.config.get('Maslow Settings', 'macro' + str(index)))
class MeasureMachinePopup(GridLayout): done = ObjectProperty(None) stepText = StringProperty("Step 1 of 10") numberOfTimesTestCutRun = -2 kinematicsType = 'Quadrilateral' def establishDataConnection(self, data): ''' Sets up the data connection between this popup and the shared data object ''' self.data = data self.setSprocketsVertical.data = data self.setSprocketsVertical.carousel = self.carousel self.measureOutChains.data = data self.measureOutChains.carousel = self.carousel self.measureOutChains.text = "Now we are going to measure out the chains and reattach the sled\n\nHook the first link of the right chain on the vertical tooth of the right sprocket\n as shown in the picture below\n\nThe left chain does not need to be moved, it can be left partly extended\n\nThe correct length of first the left and then the right chain will be measured out\n\nOnce both chains are finished attach the sled, then press Next\nPressing Next will move the sled to the center of the sheet.\n\nBe sure to keep an eye on the chains during this process to ensure that they do not become tangled\naround the sprocket. The motors are very powerful and the machine can damage itself this way" self.triangularCalibration.data = data self.triangularCalibration.carousel = self.carousel def backBtn(self, *args): ''' Runs when the back button is pressed ''' if self.carousel.index == 10 and self.kinematicsType == 'Quadrilateral': #if we're at the test cut for quadrilateral and we want to go back to choosing kinematics type self.carousel.load_slide(self.carousel.slides[8]) elif self.carousel.index == 11 and self.kinematicsType == 'Triangular': #if we're at the last step and need to go back but but we want to go back to the triangular kinematics test cut self.carousel.load_slide(self.carousel.slides[9]) else: self.carousel.load_previous() def fwdBtn(self, *args): ''' Runs when the skip button is pressed ''' if self.carousel.index == 8 and self.kinematicsType == 'Quadrilateral': #If the kinematics type is quadrilateral skip to the quadrilateral test self.carousel.load_slide(self.carousel.slides[10]) elif self.carousel.index == 9 and self.kinematicsType == 'Triangular': #If we're in the cut test shape triangular and we want to skip to the end self.carousel.load_slide(self.carousel.slides[11]) else: self.carousel.load_next() def slideJustChanged(self): if self.carousel.index == 0: #begin notes self.goBackBtn.disabled = True self.stepText = "Step 1 of 10" if self.carousel.index == 1: #pointing one sprocket up self.goBackBtn.disabled = False self.stepText = "Step 2 of 10" if self.carousel.index == 2: #measuring distance between motors self.data.measureRequest = self.readMotorSpacing self.stepText = "Step 3 of 10" if self.carousel.index == 3: #measure sled spacing self.stepText = "Step 4 of 10" pass if self.carousel.index == 4: #measure vertical distance to wood self.data.measureRequest = self.readVerticalOffset self.stepText = "Step 5 of 10" if self.carousel.index == 5: #review calculations self.updateReviewValuesText() self.stepText = "Step 6 of 10" if self.carousel.index == 6: #Calibrate chain lengths self.stepText = "Step 7 of 10" if self.carousel.index == 7: #set up z-axis if int(self.data.config.get('Maslow Settings', 'zAxis')) == 1: self.zAxisActiveSwitch.active = True else: self.zAxisActiveSwitch.active = False self.stepText = "Step 8 of 10" if self.carousel.index == 8: #Choose kinematics type self.stepText = "Step 9 of 10" if self.carousel.index == 9: #Cut test shape triangular self.data.pushSettings() self.stepText = "Step 10 of 10" self.goFwdBtn.disabled = False #if we're not supposed to be in triangular calibration go to the next page if self.kinematicsType != 'Triangular': self.carousel.load_next() if self.carousel.index == 10: #Cut test shape quadrilateral self.data.pushSettings() self.goFwdBtn.disabled = False self.stepText = "Step 10 of 10" #if we're not supposed to be in quadratic calibration go to finished if self.kinematicsType == 'Triangular': self.carousel.load_next() if self.carousel.index == 11: #Final finish step self.goFwdBtn.disabled = True finishString = "Your machine is now calibrated!\n\nCongratulations!\n\nThe final calibration values are:\n" finishString = finishString + "\nDistance between motors: " + self.data.config.get( 'Maslow Settings', 'motorSpacingX') + "mm" finishString = finishString + "\nVertical motor offset: " + self.data.config.get( 'Maslow Settings', 'motorOffsetY') + "mm" finishString = finishString + "\nKinematics type: " + self.data.config.get( 'Advanced Settings', 'kinematicsType') if self.data.config.get('Advanced Settings', 'kinematicsType') == 'Triangular': finishString = finishString + "\nRotation radius: " + self.data.config.get( 'Advanced Settings', 'rotationRadius') + "mm" else: finishString = finishString + "\nSled mount spacing: " + self.data.config.get( 'Maslow Settings', 'sledWidth') + "mm" self.finishText.text = finishString def begin(self): self.carousel.load_next() def defineInitialState(self): ''' Ensure that the calibration process begins with known initial conditions for where the axis think that they are are by setting both to zero. This prevents strange behavior when rotating each sprocket to 12:00 ''' self.data.gcode_queue.put("B06 L0 R0 ") self.carousel.load_next() def extendLeft(self, dist): self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L" + str(dist) + " ") self.data.gcode_queue.put("G90 ") def retractLeft(self, dist): self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L-" + str(dist) + " ") self.data.gcode_queue.put("G90 ") def measureLeft(self): self.data.gcode_queue.put("B10 L") def readMotorSpacing(self, dist): dist = dist - 2 * 6.35 #subtract off the extra two links print "Read motor spacing: " + str(dist) self.data.config.set('Maslow Settings', 'motorSpacingX', str(dist)) self.data.config.write() self.extendLeft(15) self.carousel.load_next() def readVerticalOffset(self, dist): print "vertical offset measured at: " + str(dist) self.data.config.set('Maslow Settings', 'motorOffsetY', str(dist)) self.data.config.write() #keep updating the values shown because sometimes it takes a while for the settings to write from kivy.clock import Clock Clock.schedule_once(self.updateReviewValuesText, .1) Clock.schedule_once(self.updateReviewValuesText, .2) Clock.schedule_once(self.updateReviewValuesText, .3) Clock.schedule_once(self.updateReviewValuesText, .4) self.carousel.load_next() def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data=self.data) self._popup = Popup(title="Number of links", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def dismiss_popup(self): try: tempfloat = float(self.popupContent.textInput.text) self.targetWidget.text = str( tempfloat ) # Update displayed text using standard numeric format except: pass # If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] == 'numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] == 'numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] == 'numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] == 'numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] == 'numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] == 'numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] == 'numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] == 'numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] == 'numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] == 'numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] == 'numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[: -1] elif (keycode[1] == 'enter') or (keycode[1] == 'numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape' ): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def countLinks(self): print "counting links, dist: " try: dist = float(self.linksTextInput.text) * 6.35 except: self.carousel.load_next() return self.data.config.set('Maslow Settings', 'sledWidth', str(dist)) self.data.config.write() self.carousel.load_next() def calibrateChainLengths(self): print "calibrating" self.data.gcode_queue.put("B02 ") def enableZaxis(self, *args): ''' Triggered when the switch to enable the z-axis is touched ''' self.data.config.set('Maslow Settings', 'zAxis', int(self.zAxisActiveSwitch.active)) self.data.config.write() def pullChainTight(self): #pull the left chain tight self.data.gcode_queue.put("B11 S50 T3 ") def updateReviewValuesText(self, *args): ''' Update the text which displays the measured values ''' self.reviewNumbers.text = "Let's review the measurements we've made so far to make sure they look correct\n\nMotor Spacing: " + str( self.data.config.get('Maslow Settings', 'motorSpacingX') ) + "mm\nSled Mount Spacing: " + str( self.data.config.get('Maslow Settings', 'sledWidth') ) + "mm\nVertical Offset: " + str( self.data.config.get('Maslow Settings', 'motorOffsetY') ) + "mm\n\nYou can go back and re-do any of these numbers if you would like" def finishChainCalibration(self, *args): #adjust chain lengths to put the sled in the center self.data.gcode_queue.put("B15 ") self.carousel.load_next() def setKinematicsType(self, kinematicsType, *args): ''' Update kinematics to the value shown in the drop down and move to the next step ''' self.kinematicsType = kinematicsType print "Kinematics set to: " print self.kinematicsType self.data.config.set('Advanced Settings', 'kinematicsType', self.kinematicsType) self.data.config.write() if self.kinematicsType == 'Triangular': try: #Get the value if it's already there... rotationRadius = self.data.config.get('Advanced Settings', 'rotationRadius') print "Rotation radius is " + str(rotationRadius) except: #Set up a good initial guess for the radius print "Rotation radius set to 260" self.data.config.set('Advanced Settings', 'rotationRadius', 260) self.data.config.write() self.carousel.load_next() else: self.carousel.load_slide(self.carousel.slides[10]) def cutTestPatern(self): #Credit for this test pattern to DavidLang self.data.units = "MM" self.data.gcode_queue.put("G21 ") self.data.gcode_queue.put("G90 ") self.data.gcode_queue.put("G40 ") self.data.gcode_queue.put("G0 Z5 ") self.data.gcode_queue.put("G0 X0 Y0 ") self.data.gcode_queue.put("G17 ") #(defines the center) self.data.gcode_queue.put("G0 X" + str(18 * self.numberOfTimesTestCutRun) + " Y" + str(-18 * self.numberOfTimesTestCutRun) + " ") self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("G0 X-300 Y300 ") self.data.gcode_queue.put("G1 Z-7 F500 ") self.data.gcode_queue.put("G1 Y18 ") self.data.gcode_queue.put("G1 Z7 ") self.data.gcode_queue.put("G0 X600 Y-18 ") self.data.gcode_queue.put("G1 Z-7 ") self.data.gcode_queue.put("G1 Y18 ") self.data.gcode_queue.put("G1 X-18 ") self.data.gcode_queue.put("G1 Z7 ") self.data.gcode_queue.put("G0 X18 Y-600 ") self.data.gcode_queue.put("G1 Z-7 ") self.data.gcode_queue.put("G1 X-18 ") self.data.gcode_queue.put("G1 Z7 ") self.data.gcode_queue.put("G0 X-600 ") self.data.gcode_queue.put("G90 ") self.numberOfTimesTestCutRun = self.numberOfTimesTestCutRun + 1 self.cutBtn.text = "Re-Cut Test\nPattern" self.cutBtn.disabled = True self.horizMeasure.disabled = False self.vertMeasure.disabled = False self.unitsBtn.disabled = False self.enterValues.disabled = False def enterTestPaternValues(self): dif = 0 try: dif = float(self.horizMeasure.text) - float(self.vertMeasure.text) except: self.data.message_queue.put( "Message: Couldn't make that into a number") return if self.unitsBtn.text == 'Inches': dif = dif * 25.4 acceptableTolerance = .5 if abs(dif) < acceptableTolerance: #if we're fully calibrated self.carousel.load_next() else: amtToChange = .9 * dif newSledSpacing = float( self.data.config.get('Maslow Settings', 'sledWidth')) + amtToChange print "Now trying spacing: " + str(newSledSpacing) self.data.config.set('Maslow Settings', 'sledWidth', str(newSledSpacing)) self.data.config.write() self.cutBtn.disabled = False self.data.pushSettings() def stopCut(self): self.data.quick_queue.put("!") with self.data.gcode_queue.mutex: self.data.gcode_queue.queue.clear() def switchUnits(self): if self.unitsBtn.text == 'MM': self.unitsBtn.text = 'Inches' else: self.unitsBtn.text = 'MM' def moveZ(self, dist): ''' Move the z-axis the specified distance ''' self.data.units = "MM" self.data.gcode_queue.put("G21 ") self.data.gcode_queue.put("G91 G00 Z" + str(dist) + " G90 ") def zeroZ(self): ''' Define the z-axis to be currently at height 0 ''' self.data.gcode_queue.put("G10 Z0 ") self.carousel.load_next()
class VertDistToMotorsGuess(GridLayout): readyToMoveOn = ObjectProperty(None) def on_Enter(self): ''' This function runs when the step is entered ''' self.data = App.get_running_app().data def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data = self.data) self.popupContent.forceUnitsMM() self._popup = Popup(title="Set distance to move chain", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] =='numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] =='numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] =='numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] =='numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] =='numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] =='numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] =='numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] =='numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] =='numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] =='numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] =='numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[:-1] elif (keycode[1] == 'enter') or (keycode[1] =='numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape'): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def dismiss_popup(self): try: tempfloat = float(self.popupContent.textInput.text) self.targetWidget.text = str(tempfloat) # Update displayed text using standard numeric format #self.distText.text = "Dist (" + self.data.units + "):" except: pass # If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def enterValues(self): try: dist = float(self.enterMeasurement.text) if dist > 300: self.data.config.set('Maslow Settings', 'motorOffsetY', str(dist)) else: self.data.message_queue.put("Message: Warning: The value you entered for the distance between the motors and the top of the work area is very small. This may cause too much strain on the motors at the top of the sheet.") self.readyToMoveOn() except: self.data.message_queue.put("Message: Couldn't convert that to a number...") def on_Exit(self): ''' This function run when the step is completed ''' pass
class MeasureDistBetweenMotors(GridLayout): ''' Provides a standard interface for measuring the distance between the motors. Assumes that both motors are in position zero at the begining ''' data = ObjectProperty(None) def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data=self.data) self.popupContent.forceUnitsMM() self._popup = Popup(title="Set distance to move chain", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] == 'numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] == 'numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] == 'numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] == 'numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] == 'numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] == 'numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] == 'numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] == 'numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] == 'numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] == 'numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] == 'numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[: -1] elif (keycode[1] == 'enter') or (keycode[1] == 'numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape' ): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def dismiss_popup(self): try: tempfloat = float(self.popupContent.textInput.text) self.targetWidget.text = str( tempfloat ) # Update displayed text using standard numeric format #self.distText.text = "Dist (" + self.data.units + "):" except: pass # If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def stopCut(self): self.data.quick_queue.put("!") with self.data.gcode_queue.mutex: self.data.gcode_queue.queue.clear() def extend(self): dist = float(self.distToMove.text) self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L" + str(dist) + " ") self.data.gcode_queue.put("G90 ") def retract(self): dist = float(self.distToMove.text) self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L" + str(-1 * dist) + " ") self.data.gcode_queue.put("G90 ") def measureLeft(self): self.data.gcode_queue.put("B10 L") def readMotorSpacing(self, dist): dist = dist - 2 * 6.35 #subtract off the extra two links print "Read motor spacing: " + str(dist) self.data.config.set('Maslow Settings', 'motorSpacingX', str(dist)) #put some slack in the chain self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L10 ") self.data.gcode_queue.put("G90 ") self.readyToMoveOn() def pullChainTightAndMeasure(self): #pull the left chain tight self.data.gcode_queue.put("B11 S255 T3 L ") #request a measurement self.data.gcode_queue.put("B10 L") def on_Enter(self): ''' This function runs when the step is entered ''' self.data = App.get_running_app().data self.data.measureRequest = self.readMotorSpacing self.originalChainOverSproketDir = App.get_running_app( ).data.config.get('Advanced Settings', 'chainOverSprocket') #pretend we are in the "Top" configuration during this step App.get_running_app().data.config.set('Advanced Settings', 'chainOverSprocket', 'Top') #set the threshold for warning that the machine is off target to 200mm esentially turning it off. We dont' want this to trigger when pulling the chain tight self.data.gcode_queue.put("$42=200 ") def on_Exit(self): ''' This function run when the process is completed or quit is pressed ''' #Restore original chain over sprocket direction App.get_running_app().data.config.set('Advanced Settings', 'chainOverSprocket', self.originalChainOverSproketDir) #restore all settings to the values stored in the current settings file self.data.gcode_queue.put("$$ ")
class FrontPage(Screen, MakesmithInitFuncs): textconsole = ObjectProperty(None) connectmenu = ObjectProperty( None) #make ConnectMenu object accessible at this scope gcodecanvas = ObjectProperty(None) screenControls = ObjectProperty(None) connectionStatus = StringProperty("Not Connected") xReadoutPos = StringProperty("0 mm") yReadoutPos = StringProperty("0 mm") zReadoutPos = StringProperty("0 mm") percentComplete = StringProperty("0.0%") numericalPosX = 0.0 numericalPosY = 0.0 previousPosX = 0.0 previousPosY = 0.0 stepsizeval = 0 zStepSizeVal = .1 consoleText = StringProperty(" ") units = StringProperty("MM") gcodeLineNumber = StringProperty('0') def __init__(self, data, **kwargs): super(FrontPage, self).__init__(**kwargs) self.data = data def buildReadoutString(self, value): ''' Generate the string for the the digital position readout ''' targetStringLength = 8 string = '%.2f' % (value) numberOfSpacesToPad = int(1.5 * (targetStringLength - len(string))) string = ' ' * numberOfSpacesToPad + string return string def setPosReadout(self, xPos, yPos, zPos): self.xReadoutPos = self.buildReadoutString(xPos) self.yReadoutPos = self.buildReadoutString(yPos) self.zReadoutPos = self.buildReadoutString(zPos) self.numericalPosX = xPos self.numericalPosY = yPos def setUpData(self, data): self.gcodecanvas.setUpData(data) self.screenControls.setUpData(data) self.data.bind(connectionStatus=self.updateConnectionStatus) self.data.bind(units=self.onUnitsSwitch) self.data.bind(gcodeIndex=self.onIndexMove) self.data.bind(gcodeFile=self.onGcodeFileChange) self.data.bind(uploadFlag=self.onUploadFlagChange) self.update_macro_titles() def updateConnectionStatus(self, callback, connected): if connected: self.connectionStatus = "Connected" else: self.connectionStatus = "Connection Lost" def switchUnits(self): if self.data.units == "INCHES": self.data.units = "MM" else: self.data.units = "INCHES" def onUnitsSwitch(self, callback, newUnits): self.units = newUnits INCHESTOMM = 1 / 25.4 MMTOINCHES = 25.4 if newUnits == "INCHES": self.data.gcode_queue.put('G20 ') self.moveDistInput.text = str(float(self.moveDistInput.text) / 25) self.data.tolerance = 0.020 else: self.data.gcode_queue.put('G21 ') self.moveDistInput.text = str(float(self.moveDistInput.text) * 25) self.data.tolerance = 0.5 def onIndexMove(self, callback, newIndex): self.gcodeLineNumber = str(newIndex) self.percentComplete = '%.1f' % (100 * (float(newIndex) / (len(self.data.gcode) - 1))) + "%" def onGcodeFileChange(self, callback, newGcode): pass def onUploadFlagChange(self, callback, newFlagValue): if self.data.uploadFlag is 0 and self.data.gcodeIndex > 1: #if the machine is stopped partway through a file self.holdBtn.text = "CONTINUE" else: self.holdBtn.text = "HOLD" def moveGcodeZ(self, moves): ''' Move the gcode index by z moves ''' dist = 0 for index, zMove in enumerate(self.data.zMoves): if moves > 0 and zMove > self.data.gcodeIndex: dist = self.data.zMoves[index + moves - 1] - self.data.gcodeIndex break if moves < 0 and zMove < self.data.gcodeIndex: dist = self.data.zMoves[index + moves + 1] - self.data.gcodeIndex self.moveGcodeIndex(dist) def moveGcodeIndex(self, dist): ''' Move the gcode index by a dist number of lines ''' maxIndex = len(self.data.gcode) - 1 targetIndex = self.data.gcodeIndex + dist #check to see if we are still within the length of the file if maxIndex < 0: #break if there is no data to read return elif targetIndex < 0: #negative index not allowed self.data.gcodeIndex = 0 elif targetIndex > maxIndex: #reading past the end of the file is not allowed self.data.gcodeIndex = maxIndex else: self.data.gcodeIndex = targetIndex gCodeLine = self.data.gcode[self.data.gcodeIndex] xTarget = 0 yTarget = 0 try: x = re.search("X(?=.)([+-]?([0-9]*)(\.([0-9]+))?)", gCodeLine) if x: xTarget = float(x.groups()[0]) self.previousPosX = xTarget else: xTarget = self.previousPosX y = re.search("Y(?=.)([+-]?([0-9]*)(\.([0-9]+))?)", gCodeLine) if y: yTarget = float(y.groups()[0]) self.previousPosY = yTarget else: yTarget = self.previousPosY self.gcodecanvas.positionIndicator.setPos(xTarget, yTarget, self.data.units) except: print "Unable to update position for new gcode line" def pause(self): if self.holdBtn.text == "HOLD": self.data.uploadFlag = 0 print("Run Paused") else: self.data.uploadFlag = 1 self.data.quick_queue.put( "~") #send cycle resume command to unpause the machine print("Run Resumed") def jmpsize(self): try: self.stepsizeval = float(self.moveDistInput.text) except: pass def test(self): print "test has no current function" def upLeft(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(-1 * self.stepsizeval) + " Y" + str(self.stepsizeval) + " G90 ") def upRight(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(self.stepsizeval) + " Y" + str(self.stepsizeval) + " G90 ") def up(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 Y" + str(self.stepsizeval) + " G90 ") def left(self): self.jmpsize() self.data.gcode_queue.put("G91 G0 X" + str(-1 * self.stepsizeval) + " G90 ") def right(self): self.jmpsize() self.data.gcode_queue.put("G91 G0 X" + str(self.stepsizeval) + " G90 ") def downLeft(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(-1 * self.stepsizeval) + " Y" + str(-1 * self.stepsizeval) + " G90 ") def down(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 Y" + str(-1 * self.stepsizeval) + " G90 ") def downRight(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(self.stepsizeval) + " Y" + str(-1 * self.stepsizeval) + " G90 ") def zAxisPopup(self): self.popupContent = ZAxisPopupContent(done=self.dismissZAxisPopup) self.popupContent.data = self.data self.popupContent.initialize(self.zStepSizeVal) self._popup = Popup(title="Z-Axis", content=self.popupContent, size_hint=(0.5, 0.5)) self._popup.open() def dismissZAxisPopup(self): ''' Close The Z-Axis Pop-up ''' try: self.zStepSizeVal = float(self.popupContent.distBtn.text) except: pass self._popup.dismiss() def home(self): ''' Return the machine to it's home position. (0,0) is the default unless the origin has been moved by the user. ''' self.data.gcode_queue.put("G90 ") #if the machine has a z-axis lift it then go home if int(self.data.config.get('Maslow Settings', 'zAxis')): if self.units == "INCHES": self.data.gcode_queue.put("G00 Z.25 ") else: self.data.gcode_queue.put("G00 Z5.0 ") self.data.gcode_queue.put("G00 X" + str(self.data.gcodeShift[0]) + " Y" + str(self.data.gcodeShift[1]) + " ") self.data.gcode_queue.put("G00 Z0 ") #if the machine does not have a z-axis, just go home else: self.data.gcode_queue.put("G00 X" + str(self.data.gcodeShift[0]) + " Y" + str(self.data.gcodeShift[1]) + " ") def moveOrigin(self): ''' Move the gcode origin to the current location ''' self.data.gcodeShift = [self.numericalPosX, self.numericalPosY] self.data.config.set('Advanced Settings', 'homeX', str(self.numericalPosX)) self.data.config.set('Advanced Settings', 'homeY', str(self.numericalPosY)) self.data.config.write() def startRun(self): self.data.uploadFlag = 1 self.sendLine() def sendLine(self): try: self.data.gcode_queue.put(self.data.gcode[self.data.gcodeIndex]) self.data.gcodeIndex = self.data.gcodeIndex + 1 except: print "gcode run complete" self.gcodecanvas.uploadFlag = 0 self.data.gcodeIndex = 0 def stopRun(self): self.data.uploadFlag = 0 self.data.gcodeIndex = 0 self.data.quick_queue.put("!") with self.data.gcode_queue.mutex: self.data.gcode_queue.queue.clear() self.onUploadFlagChange(self.stopRun, 0) print("Gode Stopped") def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] == 'numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] == 'numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] == 'numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] == 'numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] == 'numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] == 'numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] == 'numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] == 'numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] == 'numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] == 'numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] == 'numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[: -1] elif (keycode[1] == 'enter') or (keycode[1] == 'numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape' ): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def dismiss_popup(self): ''' Close The Pop-up ''' try: tempfloat = float(self.popupContent.textInput.text) self.targetWidget.text = str( tempfloat ) # Update displayed text using standard numeric format except: pass #If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def gotoLinePopup(self): self.popupContent = TouchNumberInput(done=self.dismiss_gotoLinePopup) self._popup = Popup(title="Go to gcode line", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def dismiss_gotoLinePopup(self): ''' Close The Pop-up ''' try: line = int(float(self.popupContent.textInput.text)) if line < 0: self.data.gcodeIndex = 0 elif line > len(self.data.gcode): self.data.gcodeIndex = len(self.data.gcode) else: self.data.gcodeIndex = line except: pass #If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def macro(self, index): ''' Execute user defined macro ''' self.data.gcode_queue.put( self.data.config.get('Maslow Settings', 'macro' + str(index))) def update_macro_titles(self): self.macro1Btn.text = self.data.config.get('Maslow Settings', 'macro1_title') self.macro2Btn.text = self.data.config.get('Maslow Settings', 'macro2_title')
class RotationRadiusGuess(GridLayout): readyToMoveOn = ObjectProperty(None) def on_Enter(self): ''' This function runs when the step is entered ''' self.data = App.get_running_app().data def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data=self.data) self.popupContent.forceUnitsMM() self._popup = Popup(title="Set rotation radius", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] == 'numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] == 'numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] == 'numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] == 'numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] == 'numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] == 'numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] == 'numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] == 'numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] == 'numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] == 'numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] == 'numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[: -1] elif (keycode[1] == 'enter') or (keycode[1] == 'numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape' ): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def dismiss_popup(self): try: tempfloat = float(self.popupContent.textInput.text) self.targetWidget.text = str( tempfloat ) # Update displayed text using standard numeric format #self.distText.text = "Dist (" + self.data.units + "):" except: pass # If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def enterValues(self): try: dist = float(self.enterMeasurement.text) self.data.config.set('Advanced Settings', 'rotationRadius', str(dist)) print "setting rotation radius to: " + str(dist) print self.data.config.get('Advanced Settings', 'rotationRadius') self.readyToMoveOn() except: self.data.message_queue.put( "Message: Couldn't convert that to a number...") def on_Exit(self): ''' This function run when the step is completed ''' pass
class MeasureDistBetweenMotors(GridLayout): ''' Provides a standard interface for measuring the distance between the motors. Assumes that both motors are in position zero at the begining ''' data = ObjectProperty(None) def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data = self.data) self.popupContent.forceUnitsMM() self._popup = Popup(title="Set distance to move chain", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] =='numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] =='numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] =='numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] =='numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] =='numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] =='numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] =='numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] =='numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] =='numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] =='numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] =='numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[:-1] elif (keycode[1] == 'enter') or (keycode[1] =='numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape'): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def dismiss_popup(self): try: tempfloat = float(self.popupContent.textInput.text) self.targetWidget.text = str(tempfloat) # Update displayed text using standard numeric format #self.distText.text = "Dist (" + self.data.units + "):" except: pass # If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def stopCut(self): self.data.quick_queue.put("!") with self.data.gcode_queue.mutex: self.data.gcode_queue.queue.clear() def extend(self): dist = float(self.distToMove.text) self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L" + str(dist) + " ") self.data.gcode_queue.put("G90 ") def retract(self): dist = float(self.distToMove.text) self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L" + str(-1*dist) + " ") self.data.gcode_queue.put("G90 ") def measureLeft(self): self.data.gcode_queue.put("B10 L") def readMotorSpacing(self, dist): dist = dist - 2*6.35 #subtract off the extra two links print "Read motor spacing: " + str(dist) self.data.config.set('Maslow Settings', 'motorSpacingX', str(dist)) #put some slack in the chain self.data.gcode_queue.put("G91 ") self.data.gcode_queue.put("B09 L10 ") self.data.gcode_queue.put("G90 ") self.readyToMoveOn() def pullChainTightAndMeasure(self): #pull the left chain tight self.data.gcode_queue.put("B11 S255 T3 L ") #request a measurement self.data.gcode_queue.put("B10 L") def on_Enter(self): ''' This function runs when the step is entered ''' self.data = App.get_running_app().data self.data.measureRequest = self.readMotorSpacing self.originalChainOverSproketDir = App.get_running_app().data.config.get('Advanced Settings', 'chainOverSprocket') #pretend we are in the "Top" configuration during this step App.get_running_app().data.config.set('Advanced Settings', 'chainOverSprocket', 'Top') #set the threshold for warning that the machine is off target to 200mm essentially turning it off. We don't want this to trigger when pulling the chain tight self.data.gcode_queue.put("$42=2000 ") def on_Exit(self): ''' This function run when the process is completed or quit is pressed ''' #Restore original chain over sprocket direction App.get_running_app().data.config.set('Advanced Settings', 'chainOverSprocket', self.originalChainOverSproketDir) #restore all settings to the values stored in the current settings file self.data.gcode_queue.put("$$ ")
class FrontPage(Screen, MakesmithInitFuncs): textconsole = ObjectProperty(None) connectmenu = ObjectProperty( None) #make ConnectMenu object accessible at this scope gcodecanvas = ObjectProperty(None) screenControls = ObjectProperty(None) connectionStatus = StringProperty("Not Connected") xReadoutPos = StringProperty("0 mm") yReadoutPos = StringProperty("0 mm") zReadoutPos = StringProperty("0 mm") ReadoutVel = StringProperty(" 0 mm/m") gcodeVel = StringProperty(" 0 mm/m") percentComplete = StringProperty("0.0%") numericalPosX = 0.0 numericalPosY = 0.0 previousPosX = 0.0 previousPosY = 0.0 lastpos = (0, 0, 0) lasttime = 0.0 tick = 0 stepsizeval = 0 consoleText = StringProperty(" ") units = StringProperty("MM") gcodeLineNumber = StringProperty('0') data = Data() def __init__(self, data, **kwargs): super(FrontPage, self).__init__(**kwargs) self.data = data self.upLeftArrow.btnBackground = self.data.iconPath + 'UpLeftArrow.png' self.upArrow.btnBackground = self.data.iconPath + 'UpArrow.png' self.upRightArrow.btnBackground = self.data.iconPath + 'UpRightArrow.png' self.leftArrow.btnBackground = self.data.iconPath + 'LeftArrow.png' self.homeBtn.btnBackground = self.data.iconPath + 'Home.png' self.rightArrow.btnBackground = self.data.iconPath + 'RightArrow.png' self.downLeftArrow.btnBackground = self.data.iconPath + 'DownLeftArrow.png' self.downArrow.btnBackground = self.data.iconPath + 'DownArrow.png' self.downRightArrow.btnBackground = self.data.iconPath + 'DownRightArrow.png' self.macro1Btn.btnBackground = self.data.iconPath + 'Generic.png' self.macro1Btn.textColor = self.data.fontColor self.macro2Btn.btnBackground = self.data.iconPath + 'Generic.png' self.macro2Btn.textColor = self.data.fontColor self.zAxisBtn.btnBackground = self.data.iconPath + 'Generic.png' self.zAxisBtn.textColor = self.data.fontColor self.moveDistInput.btnBackground = self.data.iconPath + 'Generic.png' self.moveDistInput.textColor = self.data.fontColor self.unitsBtn.btnBackground = self.data.iconPath + 'Generic.png' self.unitsBtn.textColor = self.data.fontColor self.defHomeBtn.btnBackground = self.data.iconPath + 'Generic.png' self.defHomeBtn.textColor = self.data.fontColor self.zRight.btnBackground = self.data.iconPath + 'Generic.png' self.zRight.textColor = self.data.fontColor self.zLeft.btnBackground = self.data.iconPath + 'Generic.png' self.zLeft.textColor = self.data.fontColor self.oneLeft.btnBackground = self.data.iconPath + 'Generic.png' self.oneLeft.textColor = self.data.fontColor self.oneRight.btnBackground = self.data.iconPath + 'Generic.png' self.oneRight.textColor = self.data.fontColor self.run.btnBackground = self.data.iconPath + 'RunGreen.png' self.holdBtn.btnBackground = self.data.iconPath + 'HoldYellow.png' self.holdBtn.secretText = "HOLD" self.stopBtn.btnBackground = self.data.iconPath + 'StopRed.png' self.goTo.btnBackground = self.data.iconPath + 'GoTo.png' def buildReadoutString(self, value): ''' Generate the string for the the digital position readout ''' targetStringLength = 8 string = '%.2f' % (value) numberOfSpacesToPad = int(1.5 * (targetStringLength - len(string))) string = ' ' * numberOfSpacesToPad + string return string def setPosReadout(self, xPos, yPos, zPos): self.xReadoutPos = self.buildReadoutString(xPos) self.yReadoutPos = self.buildReadoutString(yPos) self.zReadoutPos = self.buildReadoutString(zPos) #So other widgets can access the position self.data.zReadoutPos = zPos #Current Velocity is done here now, not in the firmware. self.tick += 1 if self.tick >= 4: #Can't do this every time... it's too noisy, so we do it every 5rd time (0.1s). self.tick = 0 if self.lasttime <> 0.0: try: delta = sqrt((xPos - self.lastpos[0]) * (xPos - self.lastpos[0]) + (yPos - self.lastpos[1]) * (yPos - self.lastpos[1]) + (zPos - self.lastpos[2]) * (zPos - self.lastpos[2])) Vel = delta / (time() - self.lasttime) * 60.0 #In XXXX/minute except: print "unable to compute velocity" Vel = 0 else: Vel = 0 self.lasttime = time() self.lastpos = (xPos, yPos, zPos) self.ReadoutVel = self.buildReadoutString(Vel) self.numericalPosX = xPos self.numericalPosY = yPos #ToDo: Do we want to start logging errors if self.RedoutVel < self.gcodeVel? How do we know if we're supposed to be moving? def setUpData(self, data): self.gcodecanvas.setUpData(data) self.screenControls.setUpData(data) self.screenControls.setButtonAppearance() self.data.bind(connectionStatus=self.updateConnectionStatus) self.data.bind(units=self.onUnitsSwitch) self.data.bind(gcodeIndex=self.onIndexMove) self.data.bind(gcodeFile=self.onGcodeFileChange) self.data.bind(uploadFlag=self.onUploadFlagChange) self.update_macro_titles() def updateConnectionStatus(self, callback, connected): if connected: self.connectionStatus = "Connected" else: self.connectionStatus = "Connection Lost" def switchUnits(self): if self.data.units == "INCHES": self.data.units = "MM" else: self.data.units = "INCHES" def onUnitsSwitch(self, callback, newUnits): self.units = newUnits INCHESTOMM = 1 / 25.4 MMTOINCHES = 25.4 if newUnits == "INCHES": self.data.gcode_queue.put('G20 ') self.moveDistInput.text = "{0:.2f}".format( float(self.moveDistInput.text) / MMTOINCHES) self.data.tolerance = 0.020 else: self.data.gcode_queue.put('G21 ') self.moveDistInput.text = "{0:.2f}".format( float(self.moveDistInput.text) / INCHESTOMM) self.data.tolerance = 0.5 def onIndexMove(self, callback, newIndex): self.gcodeLineNumber = str(newIndex) self.percentComplete = '%.1f' % (100 * (float(newIndex) / (len(self.data.gcode) - 1))) + "%" if newIndex >= 1: gCodeLine = self.data.gcode[ newIndex - 1] #We're executing newIndex-1... about to send newIndex F = re.search("F(?=.)(([ ]*)?[+-]?([0-9]*)(\.([0-9]+))?)", gCodeLine) if F: self.gcodeVel = F.groups()[ 0] #Otherwise, it stays what it was... def onGcodeFileChange(self, callback, newGcode): pass def onUploadFlagChange(self, callback, newFlagValue): if self.data.uploadFlag is 0 and self.data.gcodeIndex > 1: #if the machine is stopped partway through a file self.holdBtn.secretText = "CONTINUE" self.holdBtn.btnBackground = self.data.iconPath + 'ContinueYellow.png' else: self.holdBtn.secretText = "HOLD" self.holdBtn.btnBackground = self.data.iconPath + 'HoldYellow.png' def moveGcodeZ(self, moves): ''' Move the gcode index by z moves ''' dist = 0 for index, zMove in enumerate(self.data.zMoves): if moves > 0 and zMove > self.data.gcodeIndex: dist = self.data.zMoves[index + moves - 1] - self.data.gcodeIndex break if moves < 0 and zMove < self.data.gcodeIndex: dist = self.data.zMoves[index + moves + 1] - self.data.gcodeIndex self.moveGcodeIndex(dist) def moveGcodeIndex(self, dist): ''' Move the gcode index by a dist number of lines ''' maxIndex = len(self.data.gcode) - 1 targetIndex = self.data.gcodeIndex + dist #check to see if we are still within the length of the file if maxIndex < 0: #break if there is no data to read return elif targetIndex < 0: #negative index not allowed self.data.gcodeIndex = 0 elif targetIndex > maxIndex: #reading past the end of the file is not allowed self.data.gcodeIndex = maxIndex else: self.data.gcodeIndex = targetIndex gCodeLine = self.data.gcode[self.data.gcodeIndex] xTarget = 0 yTarget = 0 try: x = re.search("X(?=.)([+-]?([0-9]*)(\.([0-9]+))?)", gCodeLine) if x: xTarget = float(x.groups()[0]) self.previousPosX = xTarget else: xTarget = self.previousPosX y = re.search("Y(?=.)([+-]?([0-9]*)(\.([0-9]+))?)", gCodeLine) if y: yTarget = float(y.groups()[0]) self.previousPosY = yTarget else: yTarget = self.previousPosY self.gcodecanvas.positionIndicator.setPos(xTarget, yTarget, self.data.units) except: print "Unable to update position for new gcode line" def pause(self): if self.holdBtn.secretText == "HOLD": self.data.uploadFlag = 0 print("Run Paused") else: self.data.uploadFlag = 1 self.data.quick_queue.put( "~") #send cycle resume command to unpause the machine print("Run Resumed") def jmpsize(self): try: self.stepsizeval = float(self.moveDistInput.text) except: pass def test(self): print "test has no current function" def upLeft(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(-1 * self.stepsizeval) + " Y" + str(self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def upRight(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(self.stepsizeval) + " Y" + str(self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def up(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 Y" + str(self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def left(self): self.jmpsize() self.data.gcode_queue.put("G91 G0 X" + str(-1 * self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def right(self): self.jmpsize() self.data.gcode_queue.put("G91 G0 X" + str(self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def downLeft(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(-1 * self.stepsizeval) + " Y" + str(-1 * self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def down(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 Y" + str(-1 * self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def downRight(self): self.jmpsize() self.data.gcode_queue.put("G91 G00 X" + str(self.stepsizeval) + " Y" + str(-1 * self.stepsizeval) + " G90 ") self.gcodeVel = "[MAN]" def zAxisPopup(self): self.popupContent = ZAxisPopupContent(done=self.dismissZAxisPopup) self.popupContent.data = self.data self.popupContent.initialize() self._popup = Popup(title="Z-Axis", content=self.popupContent, size_hint=(0.5, 0.5)) self._popup.open() def dismissZAxisPopup(self): ''' Close The Z-Axis Pop-up ''' self._popup.dismiss() def home(self): ''' Return the machine to it's home position. (0,0) is the default unless the origin has been moved by the user. ''' self.data.gcode_queue.put("G90 ") self.gcodeVel = "[MAN]" safeHeightMM = float( self.data.config.get('Maslow Settings', 'zAxisSafeHeight')) safeHeightInches = safeHeightMM / 25.5 if self.data.units == "INCHES": self.data.gcode_queue.put("G00 Z" + '%.3f' % (safeHeightInches)) else: self.data.gcode_queue.put("G00 Z" + str(safeHeightMM)) self.data.gcode_queue.put("G00 X" + str(self.data.gcodeShift[0]) + " Y" + str(self.data.gcodeShift[1]) + " ") self.data.gcode_queue.put("G00 Z0 ") def moveOrigin(self): ''' Move the gcode origin to the current location ''' self.data.gcodeShift = [self.numericalPosX, self.numericalPosY] self.data.config.set('Advanced Settings', 'homeX', str(self.numericalPosX)) self.data.config.set('Advanced Settings', 'homeY', str(self.numericalPosY)) def startRun(self): self.data.uploadFlag = 1 self.sendLine() def sendLine(self): try: self.data.gcode_queue.put(self.data.gcode[self.data.gcodeIndex]) self.data.gcodeIndex = self.data.gcodeIndex + 1 except: print "gcode run complete" self.gcodecanvas.uploadFlag = 0 self.data.gcodeIndex = 0 def stopRun(self): self.data.uploadFlag = 0 self.data.gcodeIndex = 0 self.data.quick_queue.put("!") with self.data.gcode_queue.mutex: self.data.gcode_queue.queue.clear() self.onUploadFlagChange(self.stopRun, 0) print("Gcode Stopped") def textInputPopup(self, target): self.targetWidget = target self.popupContent = TouchNumberInput(done=self.dismiss_popup, data=self.data) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] == 'numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] == 'numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] == 'numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] == 'numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] == 'numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] == 'numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] == 'numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] == 'numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] == 'numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] == 'numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] == 'numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[: -1] elif (keycode[1] == 'enter') or (keycode[1] == 'numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape' ): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def dismiss_popup(self): ''' Close The Pop-up ''' try: tempfloat = float(self.popupContent.textInput.text) self.targetWidget.text = str( tempfloat ) # Update displayed text using standard numeric format except: pass #If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def gotoLinePopup(self): self.popupContent = TouchNumberInput(done=self.dismiss_gotoLinePopup, data=self.data) self._popup = Popup(title="Go to gcode line", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def dismiss_gotoLinePopup(self): ''' Close The Pop-up ''' try: line = int(float(self.popupContent.textInput.text)) if line < 0: self.data.gcodeIndex = 0 elif line > len(self.data.gcode): self.data.gcodeIndex = len(self.data.gcode) else: self.data.gcodeIndex = line except: pass #If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss() def macro(self, index): ''' Execute user defined macro ''' self.data.gcode_queue.put( self.data.config.get('Maslow Settings', 'macro' + str(index))) def update_macro_titles(self): self.macro1Btn.text = self.data.config.get('Maslow Settings', 'macro1_title') self.macro2Btn.text = self.data.config.get('Maslow Settings', 'macro2_title')
class ZAxisPopupContent(GridLayout): done = ObjectProperty(None) def initialize(self, zStepSizeVal): ''' Initialize the z-axis popup ''' self.unitsBtn.text = self.data.units self.distBtn.text = str(zStepSizeVal) def setDist(self): self.popupContent = TouchNumberInput(done=self.dismiss_popup) self._popup = Popup(title="Change increment size of machine movement", content=self.popupContent, size_hint=(0.9, 0.9)) self._popup.open() if global_variables._keyboard: global_variables._keyboard.bind(on_key_down=self.keydown_popup) self._popup.bind(on_dismiss=self.ondismiss_popup) def ondismiss_popup(self, event): if global_variables._keyboard: global_variables._keyboard.unbind(on_key_down=self.keydown_popup) def keydown_popup(self, keyboard, keycode, text, modifiers): if (keycode[1] == '0') or (keycode[1] =='numpad0'): self.popupContent.addText('0') elif (keycode[1] == '1') or (keycode[1] =='numpad1'): self.popupContent.addText('1') elif (keycode[1] == '2') or (keycode[1] =='numpad2'): self.popupContent.addText('2') elif (keycode[1] == '3') or (keycode[1] =='numpad3'): self.popupContent.addText('3') elif (keycode[1] == '4') or (keycode[1] =='numpad4'): self.popupContent.addText('4') elif (keycode[1] == '5') or (keycode[1] =='numpad5'): self.popupContent.addText('5') elif (keycode[1] == '6') or (keycode[1] =='numpad6'): self.popupContent.addText('6') elif (keycode[1] == '7') or (keycode[1] =='numpad7'): self.popupContent.addText('7') elif (keycode[1] == '8') or (keycode[1] =='numpad8'): self.popupContent.addText('8') elif (keycode[1] == '9') or (keycode[1] =='numpad9'): self.popupContent.addText('9') elif (keycode[1] == '.') or (keycode[1] =='numpaddecimal'): self.popupContent.addText('.') elif (keycode[1] == 'backspace'): self.popupContent.textInput.text = self.popupContent.textInput.text[:-1] elif (keycode[1] == 'enter') or (keycode[1] =='numpadenter'): self.popupContent.done() elif (keycode[1] == 'escape'): # abort entering a number, keep the old number self.popupContent.textInput.text = '' # clear text so it isn't converted to a number self.popupContent.done() return True # always swallow keypresses since this is a modal dialog def units(self): ''' Toggle the machine units. ''' if self.data.units == "INCHES": self.data.units = "MM" self.distBtn.text = str(25*float(self.distBtn.text)) else: self.data.units = "INCHES" self.distBtn.text = str(float(self.distBtn.text)/25) self.unitsBtn.text = self.data.units def zIn(self): ''' Move the z-axis in ''' self.data.gcode_queue.put("G91 G00 Z" + str(-1*float(self.distBtn.text)) + " G90 ") def zOut(self): ''' Move the z-axis out ''' self.data.gcode_queue.put("G91 G00 Z" + str(self.distBtn.text) + " G90 ") def zero(self): ''' Define the z-axis to be currently at height 0 ''' self.data.gcode_queue.put("G10 Z0 ") def dismiss_popup(self): ''' Close The Pop-up to enter distance information ''' try: tempfloat = float(self.popupContent.textInput.text) self.distBtn.text = str(tempfloat) # Update displayed text using standard numeric format except: pass #If what was entered cannot be converted to a number, leave the value the same self._popup.dismiss()