#!/usr/bin/env python3 # # This is PNCconf, a graphical configuration editor for LinuxCNC # Copyright 2007 Jeff Epler # Pncconf 1.1 revamped by Chris Morley 2014 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # This builds the HAL files from the collected data. # import os import time import shutil class HAL: def __init__(self,app): # access to: self.d = app.d # collected data global SIG SIG = app._p # private data (signal names) self.a = app # The parent, pncconf global _PD _PD = app._p # private data def write_halfile(self, base): def writebackup(origname): path, ext = os.path.splitext(origname) name = path.replace(base+"/","") print(base) print(path,name,ext) shutil.copy(origname ,os.path.join(base,"backups",name + str(time.time()).replace('.', '') + ext) ) self._substitution_list = [] axis_convert = ("x","y","z","a") halui_cmd_count = 0 filename = os.path.join(base, self.d.machinename + ".hal") file = open(filename, "w") print(_("# Generated by PNCconf at %s") % time.asctime(), file=file) print(_("# Using LinuxCNC version: %s") % self.d.linuxcnc_version, file=file) print(_("# If you make changes to this file, they will be"), file=file) print(_("# overwritten when you run PNCconf again"), file=file) print(file=file) if self.d.pyvcp and not self.d.frontend == _PD._AXIS and not self.d.frontend == _PD._QTPLASMAC: size = pos = geo = "" if self.d.pyvcpposition or self.d.pyvcpsize: if self.d.pyvcpposition: pos = "+%d+%d"% (self.d.pyvcpxpos,self.d.pyvcpypos) if self.d.pyvcpsize: size = "%dx%d"% (self.d.pyvcpwidth,self.d.pyvcpheight) geo = " -g %s%s"%(size,pos) print("loadusr -Wn pyvcp pyvcp%s -c pyvcp [DISPLAY](PYVCP)"%(geo), file=file) if self.d.gladevcp and self.d.standalonegvcp: fmax = geo = pos = size = "" if self.d.gladevcpposition or self.d.gladevcpsize: if self.d.gladevcpposition: pos = "+%d+%d"% (self.d.gladevcpxpos,self.d.gladevcpypos) if self.d.gladevcpsize: size = "%dx%d"% (self.d.gladevcpwidth,self.d.gladevcpheight) geo = " -g %s%s"%(size,pos) if self.d.gladevcpforcemax: fmax = " -m True" theme = self.d.gladevcptheme if theme == "Follow System Theme":theme = "" else: theme = " -t "+theme print("loadusr -Wn gladevcp gladevcp -c gladevcp%s%s%s -H gvcp_call_list.hal gvcp-panel.ui"%(theme,fmax,geo), file=file) print("loadrt [KINS]KINEMATICS", file=file) # qtplasmac requires 3 spindles if self.d.frontend == _PD._QTPLASMAC: print("loadrt [EMCMOT]EMCMOT servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS num_spindles=[TRAJ]SPINDLES", file=file) else: print("loadrt [EMCMOT]EMCMOT servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS", file=file) # pre process mesa commands mesa_load_cmnd,mesa_read_cmnd,mesa_write_cmnd = self.a.hostmot2_command_string(substitution = self.d.useinisubstitution) if self.d.number_pports: # pre process pport commands pport_load_cmnd,pport_read_cmnd,pport_write_cmnd = self.a.pport_command_string() # print(the mesa load commands) for i in mesa_load_cmnd: print("%s"%i, file=file) if self.d.number_pports>0: # print(the pport load commands) for i in pport_load_cmnd: print("%s"%i, file=file) if self.d.joystickjog: print("loadusr -W hal_input -KRAL %s\n"% self.d.usbdevicename, file=file) spindle_enc = counter = probe = pwm = pump = estop = False spindle_on = spindle_cw = spindle_ccw = False mist = flood = brake = at_speed = bldc = False cstart = abort = sstep = False if self.a.findsignal("s-encoder-a"): spindle_enc = True if self.a.findsignal("probe"): probe = True if self.a.findsignal("abort"): abort = True if self.a.findsignal("s-pwm-pulse"): pwm = True if self.a.findsignal("charge-pump"): pump = True if self.a.findsignal("cycle-start"): cstart = True if self.a.findsignal("estop-ext"): estop = True if self.a.findsignal("single-step"): sstep = True if self.a.findsignal("spindle-enable"): spindle_on = True if self.a.findsignal("spindle-cw"): spindle_cw = True if self.a.findsignal("spindle-ccw"): spindle_ccw = True if self.a.findsignal("coolant-mist"): mist = True if self.a.findsignal("coolant-flood"): flood = True if self.a.findsignal("spindle-brake"): brake = True if self.a.findsignal("spindle-at-speed"): at_speed = True for i in self.d.available_axes: if self.d[i+"bldc_option"]: bldc = True break chargepump = self.a.findsignal("charge-pump-out") # load PID component: # if axis needs PID- (has pwm signal) then add its letter to pidlist temp = "" for i in self.d.available_axes: #print("looking at available axis : ",i) #if not self.a.findsignal(i+"-encoder-a") and not self.a.findsignal(i+"-resolver"): # continue temp = temp + "pid.%s,"%i tandemjoint = self.a.tandem_check(i) if tandemjoint: temp = temp + "pid.%s2,"%i # if user requested PID components add them to the list as well, starting at 0 and working up for i in range(0,self.d.userneededpid): temp=temp+"pid.%d,"% (i) pidlist = temp.rstrip(",") if not pidlist == "": print("loadrt pid names=%s"% pidlist, file=file) if bldc or self.d.userneededbldc: self.d._bldcconfigstring = "" if bldc: for i in self.d.available_axes: temp = self.d[i+"bldc_config"] #print(i,temp) if temp: self.d._bldcconfigstring = self.d._bldcconfigstring + temp + "," if self.d.userneededbldc: self.d._bldcconfigstring = self.d._bldcconfigstring + self.d.userneededbldc + "," temp = self.d._bldcconfigstring.rstrip(",") if not temp == "": print("loadrt bldc cfg=%s"% temp, file=file) if (self.d.pyvcp and self.d.pyvcpconnect == 1) or self.d.gladevcp or self.d.userneededabs >0: self.d.absnames="" needed = False if self.d.gladevcp and self.d.spindlespeedbar: needed = True if self.d.pyvcphaltype == 1 and self.d.pyvcpconnect == 1 and self.d.pyvcp: needed = True if needed: self.d.absnames=self.d.absnames+"abs.spindle" if self.d.userneededabs >0: self.d.absnames=self.d.absnames+"," for i in range(0,self.d.userneededabs): self.d.absnames = self.d.absnames+"abs.%d"% (i) if i != self.d.userneededabs-1: self.d.absnames = self.d.absnames+"," if not self.d.absnames == "": print("loadrt abs names=%s"% self.d.absnames, file=file) if (self.d.pyvcp and self.d.pyvcpconnect == 1) or self.d.gladevcp or self.d.userneededlowpass >0: self.d.lowpassnames="" needed = False for i in range(0,self.d.userneededlowpass): self.d.lowpassnames = self.d.lowpassnames+"lowpass.%d,"% (i) if self.d.pyvcphaltype == 1 and self.d.pyvcpconnect == 1 and self.d.pyvcp: needed = True if self.d.gladevcp and self.d.spindlespeedbar: needed = True if needed: self.d.lowpassnames=self.d.lowpassnames+"lowpass.spindle" temp = self.d.lowpassnames.rstrip(",") self.d.lowpassnames = temp if not self.d.lowpassnames == "": print("loadrt lowpass names=%s"% temp, file=file) pytest = self.d.pyvcp and self.d.pyvcphaltype == 1 and self.d.pyvcpconnect == 1 gladetest = self.d.gladevcp and self.d.spindlespeedbar self.d.scalenames=[] names='' if spindle_enc and (pytest or gladetest): self.d.scalenames.append("scale.spindle") if self.d.suseoutputrange2: self.d.scalenames.append("scale.gear") if self.d.userneededscale >0: for i in range(0,self.d.userneededscale): self.d.scalenames.append("scale.%d"% (i)) if not self.d.scalenames == []: for num,temp in enumerate(self.d.scalenames): if num ==0: names+='%s'%temp else: names+=',%s'%temp print("loadrt scale names=%s"% names, file=file) if pump: print("loadrt charge_pump", file=file) if not at_speed and self.d.suseatspeed: print("loadrt near", file=file) if self.d.classicladder: print(("loadrt classicladder_rt numPhysInputs=%d numPhysOutputs=%d numS32in=%d" " numS32out=%d numFloatIn=%d numFloatOut=%d numBits=%d numWords=%d") \ %(self.d.digitsin , self.d.digitsout , self.d.s32in, self.d.s32out, self.d.floatsin, self.d.floatsout,self.d.bitmem,self.d.wordmem), file=file) # load mux16 self.d.mux16names="" for i in range(0,self.d.userneededmux16): self.d.mux16names = self.d.mux16names+"mux16.%d,"% (i) if self.d.joystickjog: self.d.mux16names = self.d.mux16names+"jogspeed," if self.d.externalmpg: self.d.mux16names = self.d.mux16names+"jogincr," if self.d.externalfo: self.d.mux16names = self.d.mux16names+"foincr," if self.d.externalmvo: self.d.mux16names = self.d.mux16names+"mvoincr," if self.d.externalso: self.d.mux16names = self.d.mux16names+"soincr," if self.d.scaleselect: self.d.mux16names = self.d.mux16names+"ratio_select," temp = self.d.mux16names.rstrip(",") self.d.mux16names = temp if temp: print("loadrt mux16 names=%s"% (self.d.mux16names), file=file) # qtplasmac requires plasmac.comp if self.d.frontend == _PD._QTPLASMAC: print("loadrt plasmac", file=file) # load user custom components for i in self.d.loadcompbase: if i == '': continue else: print(i, file=file) for i in self.d.loadcompservo: if i == '': continue else: print(i, file=file) print(file=file) # print(parport read commands) if self.d.number_pports: for i in pport_read_cmnd: print("%s"%i, file=file) if pump: print("addf charge-pump servo-thread", file=file) for i in self.d.addcompbase: if not i == '': print(i +" base-thread", file=file) # print(mesa read commands) if self.d.number_mesa: for i in mesa_read_cmnd: print("%s"%i, file=file) print("addf motion-command-handler servo-thread", file=file) print("addf motion-controller servo-thread", file=file) if not pidlist == "": temp = pidlist.split(",") for i in temp: print("addf %s.do-pid-calcs servo-thread"% i, file=file) if bldc or self.d.userneededbldc: temp=self.d._bldcconfigstring.split(",") for num,j in enumerate(temp): print("addf bldc.%d servo-thread"% num, file=file) if self.d.classicladder: print("addf classicladder.0.refresh servo-thread", file=file) # mux16 addf temp=self.d.mux16names.split(",") if not temp == ['']: for j in (temp): j ='{0:<24}'.format(j) print("addf %s servo-thread"% j, file=file) # scale addf needed = False if not self.d.scalenames == '': for j in self.d.scalenames: j ='{0:<24}'.format(j) print("addf %s servo-thread"% j, file=file) # abs addf needed = False if self.d.pyvcp and self.d.pyvcphaltype == 1 and self.d.pyvcpconnect == 1: needed = True if self.d.userneededabs > 0 or (self.d.gladevcp and self.d.spindlespeedbar): needed = True if needed: temp=self.d.absnames.split(",") for j in (temp): j ='{0:<24}'.format(j) print("addf %s servo-thread"% j, file=file) # lowpass addf needed = False if self.d.pyvcp and self.d.pyvcphaltype == 1 and self.d.pyvcpconnect == 1: needed = True if self.d.userneededlowpass > 0 or (self.d.gladevcp and self.d.spindlespeedbar): needed = True if needed: temp=self.d.lowpassnames.split(",") for j in (temp): j ='{0:<24}'.format(j) print("addf %s servo-thread"% j, file=file) for i in self.d.addcompservo: if not i == '': print(i +" servo-thread", file=file) if not at_speed and self.d.suseatspeed: print("addf near.0 servo-thread", file=file) # qtplasmac addf if self.d.frontend == _PD._QTPLASMAC: print("addf plasmac servo-thread", file=file) # print(parport write commands) if self.d.number_pports: for i in pport_write_cmnd: print("%s"%i, file=file) if self.d.number_mesa: # print(mesa write commands) for i in mesa_write_cmnd: print("%s"%i, file=file) if chargepump: steppinname = self.a.make_pinname(chargepump, substitution = self.d.useinisubstitution) print(file=file) print(_("# ---Chargepump StepGen: 0.25 velocity = 10Khz square wave output---"), file=file) print(file=file) print("setp " + steppinname + ".dirsetup 100", file=file) print("setp " + steppinname + ".dirhold 100", file=file) print("setp " + steppinname + ".steplen 100", file=file) print("setp " + steppinname + ".stepspace 100", file=file) print("setp " + steppinname + ".position-scale 10000", file=file) print("setp " + steppinname + ".step_type 2", file=file) print("setp " + steppinname + ".control-type 1", file=file) print("setp " + steppinname + ".maxaccel 0", file=file) print("setp " + steppinname + ".maxvel 0", file=file) print("setp " + steppinname + ".velocity-cmd 0.25", file=file) print(file=file) print("net x-enable => " + steppinname +".enable", file=file) # do the qtplasmac connections and preferences file if self.d.frontend == _PD._QTPLASMAC: self.qtplasmac_connections(file, base) prefsfile = os.path.join(base, self.d.machinename + ".prefs") self.qtplasmac_prefs(prefsfile) print(file=file) self.connect_output(file) print(file=file) self.connect_input(file) print(file=file) ############################################################## # connect joints ############################################################## # self.d.axes: # 0 = xyz # 1 = xz # 2 = xyza if not self.d.axes in(0,1,2): print('error in number of axis identity: ', self.d.axes) return jnum = 0 coords = ['x'] # Always add X axis self.connect_joint(file, jnum, 'x') tandemjoint = self.a.tandem_check('x') if tandemjoint: jnum += 1 coords.append('x2') self.connect_joint(file, jnum, 'x2') # Maybe add Y Axis ################### if self.d.axes in(0,1): jnum += 1 coords.append('y') self.connect_joint(file, jnum, 'y') tandemjoint = self.a.tandem_check('y') if tandemjoint: jnum += 1 coords.append('y2') self.connect_joint(file, jnum, 'y2') # Always add Z Axis ################## jnum += 1 coords.append('z') self.connect_joint(file, jnum, 'z') tandemjoint = self.a.tandem_check('z') if tandemjoint: jnum += 1 coords.append('z2') self.connect_joint(file, jnum, 'z2') # Maybe add A axis ################### if self.d.axes == 1: jnum += 1 coords.append('a') self.connect_joint(file, jnum, 'a') tandemjoint = self.a.tandem_check('a') if tandemjoint: jnum += 1 coords.append('a2') self.connect_joint(file, jnum, 'a2') # qtplasmac doesn't require these: if self.d.frontend != _PD._QTPLASMAC: # usually add Spindle ################## if self.d.include_spindle: self.connect_joint(file, 0, 's') # 9 for [SPINDLE_9] print(file=file) print("#******************************", file=file) print(_("# connect miscellaneous signals"), file=file) print("#******************************", file=file) print(file=file) print(_("# ---HALUI signals---"), file=file) print(file=file) for axletter in coords: if len(axletter) == 1: # support for KINEMATICS_IDENTITY kins only # Assumption: gui uses halui teleop jogging for KINEMATICS_IDENTITY configs # (axis gui does this for joints_axes) print("net axis-select-%s halui.axis.%s.select"% (axletter,axletter), file=file) print("net jog-%s-pos halui.axis.%s.plus"% (axletter,axletter), file=file) print("net jog-%s-neg halui.axis.%s.minus"% (axletter,axletter), file=file) print("net jog-%s-analog halui.axis.%s.analog"% (axletter,axletter), file=file) # joints only items (no corresponding axis item): print("net %s-is-homed halui.joint.%d.is-homed"% (axletter,coords.index(axletter)), file=file) else: print("net %s-is-homed halui.joint.%d.is-homed"% (axletter,coords.index(axletter)), file=file) print("net jog-selected-pos halui.axis.selected.plus", file=file) print("net jog-selected-neg halui.axis.selected.minus", file=file) print("net spindle-manual-cw halui.spindle.0.forward", file=file) print("net spindle-manual-ccw halui.spindle.0.reverse", file=file) print("net spindle-manual-stop halui.spindle.0.stop", file=file) print("net machine-is-on halui.machine.is-on", file=file) print("net jog-speed halui.axis.jog-speed", file=file) print("net MDI-mode halui.mode.is-mdi", file=file) if not self.d.frontend == _PD._TOUCHY and cstart == True: print("net cycle-start halui.program.run", file=file) if sstep == True: print("net single-step halui.program.step", file=file) if abort == True: print("net abort halui.abort", file=file) print(file=file) if pump: print(_("# ---charge pump signals---"), file=file) print("net estop-out => charge-pump.enable", file=file) print("net charge-pump <= charge-pump.out", file=file) print(file=file) print(_("# ---coolant signals---"), file=file) print(file=file) print("net coolant-mist <= iocontrol.0.coolant-mist", file=file) print("net coolant-flood <= iocontrol.0.coolant-flood", file=file) print(file=file) print(_("# ---probe signal---"), file=file) print(file=file) print("net probe-in => motion.probe-input", file=file) print(file=file) if self.d.externaljog: print(_("# ---jog button signals---"), file=file) print(file=file) print("sets jog-speed %f"% self.d.jograpidrate, file=file) print(file=file) if self.d.joystickjog: print(_("# ---USB device jog button signals---"), file=file) print(file=file) print(_("# connect selectable mpg jog speeds "), file=file) print("net jog-speed-a => jogspeed.sel0", file=file) print("net jog-speed-b => jogspeed.sel1", file=file) print("net jog-speed <= jogspeed.out-f", file=file) print("setp jogspeed.in00 %f"% (self.d.joystickjograpidrate0), file=file) print("setp jogspeed.in01 %f"% (self.d.joystickjograpidrate1), file=file) print("setp jogspeed.in02 %f"% (self.d.joystickjograpidrate2), file=file) print("setp jogspeed.in03 %f"% (self.d.joystickjograpidrate3), file=file) if not self.d.joycmdrapida =="": print("net jog-speed-a <= %s"% (self.d.joycmdrapida), file=file) if not self.d.joycmdrapidb =="": print("net jog-speed-b <= %s"% (self.d.joycmdrapidb), file=file) for axletter in axis_convert: if axletter in self.d.available_axes: pin_pos = self.d["joycmd"+axletter+"pos"] pin_neg = self.d["joycmd"+axletter+"neg"] if not pin_pos == "" and not pin_neg =="": print("net jog-%s-pos %s"% (axletter,pin_pos), file=file) print("net jog-%s-neg %s"% (axletter,pin_neg), file=file) pin_analog = self.d["joycmdanalog"+axletter] if not pin_analog == "": print("net jog-%s-analog %s"% (axletter,pin_analog), file=file) print(file=file) # check for shared MPG pinname = self.a.make_pinname(self.a.findsignal("select-mpg-a"), substitution = self.d.useinisubstitution) if pinname: print("shared MPG", pinname) ending = "" if "enc" in pinname: ending = ".count" print(_("# ---jogwheel signals to mesa encoder - shared MPG---"), file=file) print(file=file) print("net axis-selected-count <= %s%s"% (pinname,ending), file=file) if 'encoder' in ending: print("setp %s.filter true" % pinname, file=file) print("setp %s.counter-mode true" % pinname, file=file) print(file=file) # was jogging MPG option selected? if self.d.externalmpg: print(_("# ---mpg signals---"), file=file) print(file=file) if not self.d.multimpg: for axletter in axis_convert: if axletter in self.d.available_axes: print(_("# for axis %s MPG") % axletter, file=file) print("setp axis.%s.jog-vel-mode 0" % axletter, file=file) print("net selected-jog-incr => axis.%s.jog-scale" % axletter, file=file) print("net axis-select-%s => axis.%s.jog-enable"% (axletter,axletter), file=file) print("net axis-selected-count => axis.%s.jog-counts"% axletter, file=file) print(file=file) # check for dedicated axis MPG jogging option for axletter in axis_convert: if axletter in self.d.available_axes: pinname = self.a.make_pinname(self.a.findsignal(axletter+"-mpg-a"), substitution = self.d.useinisubstitution) if pinname: ending = "" if "enc" in pinname: ending = ".count" print(_("# ---jogwheel signals to mesa encoder - %s axis MPG---") % axletter, file=file) print(file=file) print("net %s-jog-count <= %s%s"% (axletter, pinname,ending), file=file) if 'encoder' in ending: print("setp %s.filter true" % pinname, file=file) print("setp %s.counter-mode false" % pinname, file=file) print(file=file) if self.d.externalmpg: print(_("# ---mpg signals---"), file=file) print(file=file) if self.d.multimpg: # means MPG per axis print("setp axis.%s.jog-vel-mode 0" % axletter, file=file) print("net %s-jog-enable => axis.%s.jog-enable"% (axletter, axletter), file=file) print("net %s-jog-count => axis.%s.jog-counts" % (axletter, axletter), file=file) print("net selected-jog-incr => axis.%s.jog-scale" % axletter, file=file) print("sets %s-jog-enable true"% (axletter), file=file) print(file=file) if self.d.externalmpg and not self.d.frontend == _PD._TOUCHY:# TOUCHY GUI sets its own jog increments: if self.d.incrselect : print(_("# connect selectable mpg jog increments "), file=file) print(file=file) print("net jog-incr-a => jogincr.sel0", file=file) print("net jog-incr-b => jogincr.sel1", file=file) print("net jog-incr-c => jogincr.sel2", file=file) print("net jog-incr-d => jogincr.sel3", file=file) print("net selected-jog-incr <= jogincr.out-f", file=file) if self.d.mpgdebounce: print(" setp jogincr.debounce-time %f"% self.d.mpgdebouncetime, file=file) print(" setp jogincr.use-graycode %s"% self.d.mpggraycode, file=file) print(" setp jogincr.suppress-no-input %s" % self.d.mpgignorefalse, file=file) for i in range(0,16): value = self.d["mpgincrvalue%d"% i] print(" setp jogincr.in%02d %f"% (i,value), file=file) print(file=file) else: print("sets selected-jog-incr %f"% (self.d.mpgincrvalue0), file=file) print(file=file) # check for dedicated feed override MPG pinname = self.a.make_pinname(self.a.findsignal("fo-mpg-a"), substitution = self.d.useinisubstitution) if pinname: ending = "" if "enc" in pinname: ending = ".count" print(_("# ---feed override signals to mesa encoder - mpg---"), file=file) print(file=file) print("net fo-count <= %s%s"% (pinname,ending), file=file) if 'encoder' in ending: print("setp %s.filter true" % pinname, file=file) print("setp %s.counter-mode true" % pinname, file=file) print(file=file) # was feed override option selected? MPG or switch selected? if self.d.externalfo: if self.d.fo_usempg: print(_("# connect feed override increments - MPG"), file=file) print(file=file) print(" setp halui.feed-override.direct-value false", file=file) print(" setp halui.feed-override.scale .01", file=file) if pinname: # dedicated MPG if self.a.findsignal("fo-enable"): # make it enable-able externally print("net fo-enable => halui.feed-override.count-enable", file=file) else: print(" setp halui.feed-override.count-enable true", file=file) print("net fo-count => halui.feed-override.counts", file=file) else: # shared MPG print("net fo-enable => halui.feed-override.count-enable", file=file) print("net axis-selected-count => halui.feed-override.counts", file=file) print(file=file) elif self.d.fo_useswitch: print(_("# connect feed override increments - switches"), file=file) print(file=file) print(" setp halui.feed-override.count-enable true", file=file) print(" setp halui.feed-override.direct-value true", file=file) print(" setp halui.feed-override.scale .01", file=file) print("net feedoverride-incr => halui.feed-override.counts", file=file) print("net fo-incr-a => foincr.sel0", file=file) print("net fo-incr-b => foincr.sel1", file=file) print("net fo-incr-c => foincr.sel2", file=file) print("net fo-incr-d => foincr.sel3", file=file) print("net feedoverride-incr <= foincr.out-s", file=file) if self.d.fodebounce: print(" setp foincr.debounce-time %f"% self.d.fodebouncetime, file=file) print(" setp foincr.use-graycode %s"% self.d.fograycode, file=file) print(" setp foincr.suppress-no-input %s" % self.d.foignorefalse, file=file) for i in range(0,16): value = self.d["foincrvalue%d"% i] print(" setp foincr.in%02d %f"% (i,value), file=file) print(file=file) # check for dedicated max velocity MPG pinname = self.a.make_pinname(self.a.findsignal("mvo-mpg-a"), substitution = self.d.useinisubstitution) if pinname: ending = "" if "enc" in pinname: ending = ".count" print(_("# ---max velocity override signals to mesa encoder - mpg---"), file=file) print(file=file) print("net mvo-count <= %s%s"% (pinname,ending), file=file) if 'encoder' in ending: print("setp %s.filter true" % pinname, file=file) print("setp %s.counter-mode true" % pinname, file=file) print(file=file) # was max velocity override option selected? MPG or switch selected? if self.d.externalmvo: temp=[] for i in self.d.available_axes: temp.append(float(self.d[i+"maxvel"])) scale = max(temp)/100 if self.d.mvo_usempg: print(_("# connect max velocity override increments - MPG"), file=file) print(file=file) print(" setp halui.max-velocity.direct-value false", file=file) print(" setp halui.max-velocity.scale %04f"% scale, file=file) if pinname: # dedicated MPG if self.a.findsignal("mvo-enable"): # make it enable-able externally print("net mvo-enable => halui.max-velocity.count-enable", file=file) else: print(" setp halui.max-velocity.count-enable true", file=file) print("net mvo-count => halui.max-velocity.counts", file=file) else: # shared MPG print("net mvo-enable => halui.max-velocity.count-enable", file=file) print("net axis-selected-count => halui.max-velocity.counts", file=file) print(file=file) elif self.d.mvo_useswitch: print(_("# connect max velocity override increments - switches"), file=file) print(file=file) print(" setp halui.max-velocity.count-enable true", file=file) print(" setp halui.max-velocity.direct-value true", file=file) print(" setp halui.max-velocity.scale %04f"% scale, file=file) print("net max-vel-override-incr => halui.max-velocity.counts", file=file) print("net mvo-incr-a => mvoincr.sel0", file=file) print("net mvo-incr-b => mvoincr.sel1", file=file) print("net mvo-incr-c => mvoincr.sel2", file=file) print("net mvo-incr-d => mvoincr.sel3", file=file) print("net max-vel-override-incr <= mvoincr.out-s", file=file) if self.d.mvodebounce: print(" setp mvoincr.debounce-time %f"% self.d.mvodebouncetime, file=file) print(" setp mvoincr.use-graycode %s"% self.d.mvograycode, file=file) print(" setp mvoincr.suppress-no-input %s" % self.d.mvoignorefalse, file=file) for i in range(0,16): value = self.d["mvoincrvalue%d"% i] print(" setp mvoincr.in%02d %f"% (i,value), file=file) print(file=file) # check for dedicated spindle override MPG pinname = self.a.make_pinname(self.a.findsignal("so-mpg-a"), substitution = self.d.useinisubstitution) if pinname: ending = "" if "enc" in pinname: ending = ".count" print(_("# ---spindle override signals to mesa encoder - mpg---"), file=file) print(file=file) print("net so-count <= %s%s"% (pinname,ending), file=file) if 'encoder' in ending: print("setp %s.filter true" % pinname, file=file) print("setp %s.counter-mode true" % pinname, file=file) print(file=file) if self.d.externalso: if self.d.so_usempg: print(_("# connect spindle override increments - MPG"), file=file) print(file=file) print(" setp halui.spindle.0.override.direct-value false", file=file) print(" setp halui.spindle.0.override.scale .01", file=file) if pinname: # dedicated MPG if self.a.findsignal("so-enable"): # make it enable-able externally print("net so-enable => halui.spindle.0.override.count-enable", file=file) else: print(" setp halui.spindle.0.override.count-enable true", file=file) print("net so-count => halui.spindle.0.override.counts", file=file) else: # shared MPG print("net so-enable => halui.spindle.0.override.count-enable", file=file) print("net axis-selected-count => halui.spindle.0.override.counts", file=file) print(file=file) elif self.d.so_useswitch: print(_("# connect spindle override increments "), file=file) print(file=file) print(" setp halui.spindle.0.override.count-enable true", file=file) print(" setp halui.spindle.0.override.direct-value true", file=file) print(" setp halui.spindle.0.override.scale .01", file=file) print("net spindleoverride-incr => halui.spindle.0.override.counts", file=file) print("net so-incr-a => soincr.sel0", file=file) print("net so-incr-b => soincr.sel1", file=file) print("net so-incr-c => soincr.sel2", file=file) print("net so-incr-d => soincr.sel3", file=file) print("net spindleoverride-incr <= soincr.out-s", file=file) if self.d.sodebounce: print(" setp soincr.debounce-time %f"% self.d.sodebouncetime, file=file) print(" setp soincr.use-graycode %s"% self.d.sograycode, file=file) print(" setp soincr.suppress-no-input %s" % self.d.soignorefalse, file=file) for i in range(0,16): value = self.d["soincrvalue%d"% i] print(" setp soincr.in%02d %f"% (i,value), file=file) print(file=file) print(_("# ---motion control signals---"), file=file) print(file=file) print("net in-position <= motion.in-position", file=file) print("net machine-is-enabled <= motion.motion-enabled", file=file) print(file=file) print(_("# ---digital in / out signals---"), file=file) print(file=file) for i in range(4): dout = "dout-%02d" % i if self.a.findsignal(dout): comment = "" if self.d.frontend == _PD._QTPLASMAC and dout in ['dout-01','dout-02','dout-03']: comment = "#qtplasmac uses digital output %s:\n#" % dout print("%snet %s <= motion.digital-out-%02d" % (comment, dout, i), file=file) for i in range(4): din = "din-%02d" % i if self.a.findsignal(din): print("net %s => motion.digital-in-%02d" % (din, i), file=file) print(_("# ---estop signals---"), file=file) print(file=file) print("net estop-out <= iocontrol.0.user-enable-out", file=file) if self.d.classicladder and self.d.ladderhaltype == 1 and self.d.ladderconnect: # external estop program print(file=file) print(_("# **** Setup for external estop ladder program -START ****"), file=file) print(file=file) print("net estop-out => classicladder.0.in-00", file=file) print("net estop-ext => classicladder.0.in-01", file=file) print("net estop-strobe classicladder.0.in-02 <= iocontrol.0.user-request-enable", file=file) print("net estop-outcl classicladder.0.out-00 => iocontrol.0.emc-enable-in", file=file) print(file=file) print(_("# **** Setup for external estop ladder program -END ****"), file=file) elif estop: print("net estop-ext => iocontrol.0.emc-enable-in", file=file) else: print("net estop-out => iocontrol.0.emc-enable-in", file=file) print(file=file) # qtplasmac doesn't require these: if self.d.frontend != _PD._QTPLASMAC: if self.d.toolchangeprompt: print(_("# ---manual tool change signals---"), file=file) print(file=file) print("net tool-change-request <= iocontrol.0.tool-change", file=file) print("net tool-change-confirmed => iocontrol.0.tool-changed", file=file) print("net tool-number <= iocontrol.0.tool-prep-number", file=file) print(file=file) if not self.d.frontend in (_PD._QTDRAGON,_PD._GMOCCAPY): print(_("# ---Use external manual tool change dialog---"), file=file) print(file=file) print("loadusr -W hal_manualtoolchange", file=file) print("net tool-change-request => hal_manualtoolchange.change", file=file) print("net tool-change-confirmed <= hal_manualtoolchange.changed", file=file) print("net tool-number => hal_manualtoolchange.number", file=file) print(file=file) if self.d.frontend == _PD._GMOCCAPY: gm = os.path.join(base, "gmoccapy_postgui.hal") if not os.path.exists(gm): f1 = open(gm, "w") print(_("# ---manual tool change signals to gmoccapy's dialog---"), file=f1) print(file=f1) print("net tool-change-request => gmoccapy.toolchange-change", file=f1) print("net tool-change-confirmed <= gmoccapy.toolchange-changed", file=f1) print("net tool-number => gmoccapy.toolchange-number", file=f1) f1.close() elif self.d.frontend == _PD._QTDRAGON: qt = os.path.join(base, "qtvcp_postgui.hal") if not os.path.exists(qt): f1 = open(qt, "w") print(_("# ---manual tool change signals to qtdragon's dialog---"), file=f1) print(file=f1) print("net tool-change-request => hal_manualtoolchange.change", file=f1) print("net tool-change-confirmed <= hal_manualtoolchange.changed", file=f1) print("net tool-number => hal_manualtoolchange.number", file=f1) f1.close() print(_("# ---ignore tool prepare requests---"), file=file) print("net tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared", file=file) print(file=file) else: print(_("# ---toolchange signals for custom tool changer---"), file=file) print(file=file) print("net tool-number <= iocontrol.0.tool-prep-number", file=file) print("net tool-change-request <= iocontrol.0.tool-change", file=file) print("net tool-change-confirmed => iocontrol.0.tool-changed", file=file) print("net tool-prepare-request <= iocontrol.0.tool-prepare", file=file) print("net tool-prepare-confirmed => iocontrol.0.tool-prepared", file=file) print(file=file) # qtplasmac tool change passthrough else: print(_("\n# ---QTPLASMAC TOOLCHANGE PASSTHROUGH---"), file=file) print("net tool:change iocontrol.0.tool-change => iocontrol.0.tool-changed", file=file) print("net tool:prep iocontrol.0.tool-prepare => iocontrol.0.tool-prepared", file=file) if self.d.classicladder: print(file=file) if self.d.modbus: print(_("# Load Classicladder with modbus master included (GUI must run for Modbus)"), file=file) print(file=file) print("loadusr classicladder --modmaster custom.clp", file=file) print(file=file) else: print(_("# Load Classicladder without GUI (can reload LADDER GUI in AXIS GUI"), file=file) print(file=file) print("loadusr classicladder --nogui custom.clp", file=file) print(file=file) if self.d.laddertouchz: othercmds = self.d.gladevcphaluicmds print(_("# --- Classicladder signals for Z axis Auto touch off program---"), file=file) print("net auto-touch-z => classicladder.0.in-00", file=file) print("net MDI-mode => classicladder.0.in-01", file=file) print("net in-position => classicladder.0.in-02", file=file) print("net z-touchoff-cmd classicladder.0.out-00 => halui.mdi-command-%02d"% (othercmds), file=file) print("net z-zero-cmd classicladder.0.out-01 => halui.mdi-command-%02d"% (othercmds +1), file=file) print("net rapid-away-cmd classicladder.0.out-02 => halui.mdi-command-%02d"% (othercmds +2), file=file) gvcp_options_filename = os.path.join(base, "gvcp_options.hal") gvcp_call_filename = os.path.join(base, "gvcp_call_list.hal") if self.d.gladevcp and self.d.frontend != _PD._QTPLASMAC: # write the call_list # the call_list allows multiple hal files to be loaded post gladevcp # this simplifies the problem of overwriting the users custom HAL code # when they change gvcp sample options # if the user asks for existing instead of sample then if the call_list file exists # don't overwrite it if (not self.d.gladesample and not os.path.exists(gvcp_call_filename)) or self.d.gladesample: f1 = open(gvcp_call_filename, "w") print(_("# These files are loaded post gladeVCP, in the order they appear"), file=f1) print(file=f1) if self.d.gladesample: print("source gvcp_options.hal", file=f1) print("source custom_gvcp.hal", file=f1) # write hal file for sample options selected if self.d.gladesample: # copy glade panel from temp file to config gvcp = os.path.join(base, "gvcp-panel.ui") if os.path.exists(gvcp): writebackup(gvcp) shutil.copy2('/tmp/gvcp-panel.ui', gvcp) # write gvcp options HAL file f1 = open(gvcp_options_filename, "w") print(_("# _DO NOT_ include your HAL commands here."), file=f1) print(_("# Put custom HAL commands in custom_gvcp.hal"), file=f1) print(file=f1) if self.d.spindlespeedbar: print(_("# **** Setup of spindle speed display using gladevcp ****"), file=f1) print(file=f1) if spindle_enc: print(("net spindle-fb-rpm-abs-filtered => gladevcp.spindle-speed"), file=f1) else: print(("net spindle-vel-cmd-rpm-abs => gladevcp.spindle-speed"), file=f1) if self.d.spindleatspeed: print(("net spindle-at-speed => gladevcp.spindle-at-speed-led"), file=f1) i = 0 print(_("# **** Setup GLADE MDI buttons ****"), file=f1) print(("net machine-is-on => gladevcp.button-box-active"), file=f1) for temp in(("zerox","zero-x","x"),("zeroy","zero-y","y"),("zeroz","zero-z","z"),("zeroa","zero-a","a")): if self.d[temp[0]]: print(("# **** MDI Command %d - %s-axis is specified in the machine named INI file under [HALUI] heading ****"%(i,temp[1])), file=f1) print(("net MDI-%s gladevcp.%s => halui.mdi-command-%02d")%(temp[0],temp[1],i), file=f1) if self.d.require_homing: print(("net %s-is-homed => gladevcp.%s-active"% (temp[2],temp[1])), file=f1) else: print(("net machine-is-on => gladevcp.%s-active"% (temp[1])), file=f1) print(file=f1) i += 1 if self.d.autotouchz: print(_("# **** Z axis touch-off button - requires the touch-off classicladder program ****"), file=f1) print(("net auto-touch-z <= gladevcp.auto-touch-z"), file=f1) print(("net MDI-mode => gladevcp.auto-touch-z-active"), file=f1) print(file=f1) else: # gvcp was not selected remove any existing related HAl files if os.path.exists(gvcp_options_filename): os.remove(gvcp_options_filename) if os.path.exists(gvcp_call_filename): os.remove(gvcp_call_filename) if self.d.pyvcp and self.d.frontend != _PD._QTPLASMAC: vcp = os.path.join(base, "pyvcp-panel.xml") if not os.path.exists(vcp): f1 = open(vcp, "w") print("", file=f1) print("", file=f1) print("", file=f1) print("", file=f1) # If the user asked for pyvcp sample panel add the HAL commands too pyfilename = os.path.join(base, "pyvcp_options.hal") if self.d.pyvcp and self.d.pyvcphaltype == 1 and self.d.pyvcpconnect and self.d.frontend != _PD._QTPLASMAC: # spindle speed display f1 = open(pyfilename, "w") print(_("# _DO NOT_ include your HAL commands here."), file=f1) print(_("# Put custom HAL commands in custom_postgui.hal"), file=f1) print(_("""# The commands in this file are run after the GUI loads"""), file=f1) print(file=f1) print(_("# **** Setup of spindle speed display using pyvcp -START ****"), file=f1) print(file=f1) if spindle_enc: print(("net spindle-fb-rpm-abs-filtered => pyvcp.spindle-speed"), file=f1) else: print(("net spindle-vel-cmd-rpm-abs => pyvcp.spindle-speed"), file=f1) print(("net spindle-at-speed => pyvcp.spindle-at-speed-led"), file=f1) print(file=f1) print(_("# **** Setup of spindle speed display using pyvcp -END ****"), file=f1) print(file=f1) else: if os.path.exists(pyfilename): os.remove(pyfilename) # pncconf adds a custom.hal and custom_postgui.hal file if one is not present if self.d.frontend != _PD._QTPLASMAC: customfiles = "custom","custom_postgui","shutdown","custom_gvcp" else: customfiles = "custom","custom_postgui","shutdown" for i in customfiles: custom = os.path.join(base, i+".hal") if not os.path.exists(custom): f1 = open(custom, "w") print(_("# Include your %s HAL commands here")%i, file=f1) print(_("# This file will not be overwritten when you run PNCconf again"), file=f1) if self.d.frontend == _PD._TOUCHY:# TOUCHY GUI touchyfile = os.path.join(base, "touchy.hal") #if not os.path.exists(touchyfile): f1 = open(touchyfile, "w") print(_("# These commands are required for Touchy GUI"), file=f1) print(("net cycle-start => touchy.cycle-start"), file=f1) print(("net abort => touchy.abort"), file=f1) print(("net single-step => touchy.single-block"), file=f1) print(("net selected-jog-incr <= touchy.jog.wheel.increment"), file=f1) print(("net axis-selected-count => touchy.wheel-counts"), file=f1) print(("net jog-x-pos => touchy.jog.continuous.x.positive"), file=f1) print(("net jog-x-neg => touchy.jog.continuous.x.negative"), file=f1) print(("net jog-y-pos => touchy.jog.continuous.y.positive"), file=f1) print(("net jog-y-neg => touchy.jog.continuous.y.negative"), file=f1) print(("net jog-z-pos => touchy.jog.continuous.z.positive"), file=f1) print(("net jog-z-neg => touchy.jog.continuous.z.negative"), file=f1) print(("net quillup => touchy.quill-up"), file=f1) for axletter in enumerate(axis_convert): if axletter in self.d.available_axes: print("net axis-select-%s <= touchy.jog.wheel.%s"% (axletter, axletter), file=f1) # include Automation Direct GS2 VFD HAL file fname = os.path.join(base, "gs2_vfd.hal") if self.d.serial_vfd and self.d.gs2_vfd: self.write_gs2_vfd(fname) else: if os.path.exists(fname): os.remove(fname) # include Mitsubishi FR VFD HAL file fname = os.path.join(base, "mitsub_vfd.hal") if self.d.serial_vfd and self.d.mitsub_vfd: self.write_mitsub_vfd(fname) else: if os.path.exists(fname): os.remove(fname) if self.d.classicladder: if not self.d.laddername == "custom.clp": filename = os.path.join(_PD.DISTDIR, "configurable_options/ladder/%s" % self.d.laddername) original = os.path.expanduser("~/linuxcnc/configs/%s/custom.clp" % self.d.machinename) if os.path.exists(filename): # check for the master file to copy from if os.path.exists(original): #print("custom file already exists") writebackup(original) #shutil.copy( original,os.path.expanduser("~/linuxcnc/configs/%s/backups/custom_backup.clp" % self.d.machinename) ) print("made backup of existing custom") shutil.copy( filename,original) #print("copied ladder program to usr directory") #print("%s" % filename) else: print("Master or temp ladder files missing from configurable_options dir") if self.d.pyvcp and not self.d.pyvcpexist and self.d.frontend != _PD._QTPLASMAC: panelname = os.path.join(_PD.DISTDIR, "configurable_options/pyvcp/%s" % self.d.pyvcpname) originalname = os.path.expanduser("~/linuxcnc/configs/%s/pyvcp-panel.xml" % self.d.machinename) if os.path.exists(panelname): if os.path.exists(originalname): #print("custom PYVCP file already exists") writebackup(originalname) #shutil.copy( originalname,os.path.expanduser("~/linuxcnc/configs/%s/backups/pyvcp-panel_backup.xml" % self.d.machinename) ) print("made backup of existing custom") shutil.copy( panelname,originalname) #print("copied PYVCP program to usr directory") #print("%s" % panelname) else: print("Master PYVCP file: %s missing from configurable_options dir"% self.d.pyvcpname) file.close() self.d.add_md5sum(filename) def write_gs2_vfd(self,filename): p = self.d.gs2_vfd_port b = self.d.gs2_vfd_baud s = int(self.d.gs2_vfd_slave) a = int(self.d.gs2_vfd_accel) d = int(self.d.gs2_vfd_deaccel) f1 = open(filename, "w") print(_("# Generated by PNCconf at %s") % time.asctime(), file=f1) print(file=f1) print(_("# Automation Direct GS2 VFD for spindle control"), file=f1) print(file=f1) print(_("# The communications switches must be set to RS-232C"), file=f1) print(_("# The motor parameters must be set to match the motor"), file=f1) print(_("# P3.00 (Source of Operation Command) must be set to Operation determined by RS-485 interface, 03 or 04"), file=f1) print(_("# P4.00 (Source of Frequency Command) must be set to Frequency determined by RS232C/RS485 communication interface, 05"), file=f1) print(_("# P9.01 (Transmission Speed) must be set to the specified baud, 9600 = 01"), file=f1) print(_("""# P9.02 (Communication Protocol) must be set to "Modbus RTU mode, 8 data bits, no parity, 2 stop bits", 03"""), file=f1) print(file=f1) print("loadusr -Wn spindle-vfd gs2_vfd -d %s -r %s -p none -s 2 -t %s -n spindle-vfd -A %s -D %s"%(p,b,s,a,d), file=f1) print("net spindle-cw => spindle-vfd.spindle-fwd", file=f1) print("net spindle-enable => spindle-vfd.spindle-on", file=f1) print("net spindle-at-speed <= spindle-vfd.at-speed", file=f1) print("net spindle-vel-cmd-rpm => spindle-vfd.speed-command", file=f1) f1.close() def write_mitsub_vfd(self,filename): f1 = open(filename, "w") print(_("# Generated by PNCconf at %s") % time.asctime(), file=f1) print(file=f1) print(_("# Misubishi FR VFD for spindle control"), file=f1) f1.close() def write_readme(self, base): filename = os.path.join(base, "README") file = open(filename, "w") print(_("Generated by PNCconf at %s") % time.asctime(), file=file) print(file=file) if self.d.units == _PD._IMPERIAL: unit = "an imperial" else: unit = "a metric" if self.d.frontend == _PD._AXIS: display = "AXIS" elif self.d.frontend == _PD._TKLINUXCNC: display = "Tklinuxcnc" elif self.d.frontend == _PD._GMOCCAPY: display = "TOUCHY" elif self.d.frontend == _PD._TOUCHY: display = "TOUCHY" else: display = "an unknown" if self.d.axes == 0:machinetype ="XYZ" elif self.d.axes == 1:machinetype ="XYZA" elif self.d.axes == 2:machinetype ="XZ-Lathe" print(self.d.machinename,_("configures LinuxCNC as:\n"), file=file) print(unit,machinetype,_("type CNC\n"), file=file) print(display,_("will be used as the frontend display"), file=file) print(file=file) if self.d.number_mesa != 0: for boardnum in range(0,int(self.d.number_mesa)): print("Mesa hardware I/O card - board %d is designated as\n"% boardnum,self.d["mesa%d_currentfirmwaredata"% boardnum][_PD._BOARDTITLE], file=file) print("with", self.d["mesa%d_currentfirmwaredata"% boardnum][_PD._MAXGPIO], "I/O pins and firmware is:", self.d["mesa%d_firmware"% boardnum], file=file) print(file=file) for boardnum in range(0,int(self.d.number_mesa)): for concount,connector in enumerate(self.d["mesa%d_currentfirmwaredata"% boardnum][_PD._NUMOFCNCTRS]) : print("** Mesa %s -> Board #"% self.d["mesa%d_boardtitle"% boardnum],boardnum,_(" connector")," %d **\n"% connector, file=file) print("connector board num component signal ", file=file) print("number position type name\n", file=file) conpin = 1 for pin in range (0,24): dummy,compnum = self.d["mesa%d_currentfirmwaredata"% (boardnum)][_PD._STARTOFDATA+pin+(concount*24)] temp = self.d["mesa%dc%dpin%d" % (boardnum,connector,pin) ] tempinv = self.d["mesa%dc%dpin%dinv" % (boardnum,connector,pin) ] temptype = self.d["mesa%dc%dpin%dtype" % (boardnum,connector,pin) ] if temptype in(_PD.GPIOI,_PD.GPIOO,_PD.GPIOD): compnum = pin+(concount*24) if tempinv: invmessage = _("invrt") else: invmessage ="" print(("P%d-%d %d (%d %s) %s %s\n"%(connector,conpin,pin,compnum,temptype,temp,invmessage)), file=file) #print((" connected to signal:'%(data)s'%(mess)s\n" %{'data':temp, 'mess':invmessage}), file=file) conpin +=2 print(file=file) templist = ("pp1","pp2","pp3") for j, k in enumerate(templist): if self.d.number_pports < (j+1): break print(_("%(name)s Parport" % { 'name':k}), file=file) for x in (2,3,4,5,6,7,8,9,10,11,12,13,15): temp = self.d["%sIpin%d" % (k, x)] tempinv = self.d["%sIpin%dinv" % (k, x)] if tempinv: invmessage = _("-> inverted") else: invmessage ="" print(_("pin# %(pinnum)d is connected to input signal:'%(data)s' %(mesag)s" %{ 'pinnum':x,'data':temp,'mesag':invmessage}), file=file) for x in (1,2,3,4,5,6,7,8,9,14,16,17): temp = self.d["%sOpin%d" % (k, x)] tempinv = self.d["%sOpin%dinv" % (k, x)] if tempinv: invmessage = _("-> inverted") else: invmessage ="" print(_("pin# %(pinnum)d is connected to output signal:'%(data)s' %(mesag)s" %{ 'pinnum':x,'data':temp,'mesag':invmessage}), file=file) print(file=file) file.close() self.d.add_md5sum(filename) #******************* # helper functions #******************* def build_pid(self, file, jnum, let, stepflag): title = 'JOINT' if let == 's': title = 'SPINDLE' print("setp pid.%s.Pgain [%s_%d]P" % (let, title, jnum), file=file) print("setp pid.%s.Igain [%s_%d]I" % (let, title, jnum), file=file) print("setp pid.%s.Dgain [%s_%d]D" % (let, title, jnum), file=file) print("setp pid.%s.bias [%s_%d]BIAS" % (let, title, jnum), file=file) print("setp pid.%s.FF0 [%s_%d]FF0" % (let, title, jnum), file=file) print("setp pid.%s.FF1 [%s_%d]FF1" % (let, title, jnum), file=file) print("setp pid.%s.FF2 [%s_%d]FF2" % (let, title, jnum), file=file) print("setp pid.%s.deadband [%s_%d]DEADBAND" % (let, title, jnum), file=file) if let =='s' and self.d.suseoutputrange2: print("net ratio_select.out pid.%s.maxoutput " % (let), file=file) else: print("setp pid.%s.maxoutput [%s_%d]MAX_OUTPUT" % (let, title, jnum), file=file) # steppers print("setp pid.%s.error-previous-target true" % let, file=file) # steppers if stepflag: if self.d.units == _PD._IMPERIAL: me = .0005 else: me = .0127 print('# This setting is to limit bogus stepgen',file=file) print('# velocity corrections caused by position',file=file) print('# feedback sample time jitter.',file=file) print("setp pid.%s.maxerror %f" % (let, me),file=file) print(file=file) if let == 's': name = "spindle" else: name = let print("net %s-index-enable => pid.%s.index-enable" % (name, let), file=file) print("net %s-enable => pid.%s.enable" % (name, let), file=file) if let == 's': if self.d.susenegativevoltage: signal = "spindle-vel-cmd-rpm" fbsignal= "spindle-vel-fb-rpm" else: signal = "spindle-vel-cmd-rpm-abs" fbsignal= "spindle-vel-fb-rpm-abs" print("net %s => pid.%s.command" % (signal, let), file=file) print("net %s => pid.%s.feedback"% (fbsignal, let), file=file) if self.d.suseoutputrange2: print("net spindle-pid-out pid.s.output => scale.gear.in", file=file) print("net gear-ratio ratio_select.out-f => scale.gear.gain", file=file) print("setp ratio_select.in00 %f" % (1/float(self.d.gsincrvalue0)), file=file) print("setp ratio_select.in01 %f" % (1/float(self.d.gsincrvalue1)), file=file) #print("setp ratio_select.in2 %f" % self.d.gsincrvalue2, file=file) #print("setp ratio_select.in4 %f" % self.d.gsincrvalue4, file=file) print("net gear-select-a => ratio_select.sel0", file=file) #print("net gear-select-b ratio_select.sel1", file=file) #print("net gear-select-c ratio_select.sel2", file=file) print("net spindle-output <= scale.gear.out", file=file) else: print("net spindle-output <= pid.%s.output"% (let), file=file) else: print("net %s-pos-cmd => pid.%s.command" % (name, let), file=file) #print("net %s-vel-cmd => pid.%s.command-deriv" % (name, let), file=file) # This must be connected to something print("net %s-pos-fb => pid.%s.feedback"% (name,let), file=file) print("net %s-output <= pid.%s.output"% (name, let), file=file) #print(file, "net %s-vel-fb => pid.%s.feedback-deriv"% (name, let), file=file) # This must be connected to something print(file=file) def connect_joint(self, file, jnum, let): def get(s): return self.d[let + s] title = 'JOINT' if let == 's': title = 'SPINDLE' closedloop = False pwmpin = self.a.pwmgen_sig(let) pwmpinname = self.a.make_pinname(pwmpin, substitution = self.d.useinisubstitution) if pwmpinname and not 'serial' in pwmpin: # TODO allow sserial PWM to be inverted pwminvertlist = self.a.pwmgen_invert_pins(pwmpin) if not pwmpin == None: pwmtype = self.a.pwmgen_sig(let)+"type" else: pwmtype = None tppwmpinname = self.a.make_pinname(self.a.tppwmgen_sig(let), substitution = self.d.useinisubstitution) tppwm_six = self.a.tppwmgen_has_6(let) steppinname = self.a.make_pinname(self.a.stepgen_sig(let), substitution = self.d.useinisubstitution) try: bldc_control = self.d[let+"bldc_option"] except: bldc_control = False if steppinname: stepinvertlist = self.a.stepgen_invert_pins(self.a.stepgen_sig(let)) encoderpinname = self.a.make_pinname(self.a.encoder_sig(let), substitution = self.d.useinisubstitution) amp8i20pinname = self.a.make_pinname(self.a.amp_8i20_sig(let), substitution = self.d.useinisubstitution) resolverpinname = self.a.make_pinname(self.a.resolver_sig(let), substitution = self.d.useinisubstitution) potpinname = self.a.make_pinname(self.a.potoutput_sig(let), substitution = self.d.useinisubstitution) if potpinname: potinvertlist = self.a.spindle_invert_pins(self.a.potoutput_sig(let)) if steppinname and encoderpinname and not let == 's': closedloop = True if (encoderpinname or resolverpinname) and (pwmpinname or tppwmpinname or amp8i20pinname): closedloop = True print(let + " is closedloop? "+ str(closedloop)) print(" ENCODER:",encoderpinname," RESOLVER:",resolverpinname) print(" PWM:",pwmpinname," 3PWM:",tppwmpinname," 8i20:",amp8i20pinname) print(" STEPPER:",steppinname) print(" POTENTIOMETER:",potpinname) lat = self.d.latency print("#*******************", file=file) if let.upper() == 'S': print(_("# SPINDLE"), file=file) elif len(let) >1: print("# Tandem AXIS %s %s %d" % (let.upper(), title, jnum ), file=file) else: print("# AXIS %s %s %d" % (let.upper(), title, jnum ), file=file) print("#*******************", file=file) print(file=file) if bldc_control: bldc = self.d[let+"bldc_config"] print(_("# -- BLDC setup --"), file=file) print("setp bldc.%d.drive-offset %d" % (jnum,self.d[let+"bldc_drive_offset"]), file=file) print("setp bldc.%s.rev %d" % (jnum,self.d[let+"bldc_reverse"]), file=file) if "q" in(bldc): print("setp bldc.%d.scale %d" % (jnum,self.d[let+"bldc_scale"]), file=file) print("setp bldc.%d.poles %d" % (jnum,self.d[let+"bldc_poles"]), file=file) if "i" in(bldc): print("setp bldc.%s.initvalue %d" % (jnum,self.d[let+"bldc_inital_value"]), file=file) if "i" in(bldc) or "a" in(bldc): print("setp bldc.%s.lead-angle %d" % (jnum,self.d[let+"bldc_lead_angle"]), file=file) print("setp bldc.%d.encoder-offset %d" % (jnum,self.d[let+"bldc_encoder_offset"]), file=file) if "h" in(bldc): print("setp bldc.%d.pattern %d" % (jnum,self.d[let+"bldc_pattern_in"]), file=file) print("net %s-hall1-in bldc.%d.hall1"% (let,jnum), file=file) print("net %s-hall2-in bldc.%d.hall2"% (let,jnum), file=file) print("net %s-hall3-in bldc.%d.hall3"% (let,jnum), file=file) if "f" in(bldc): print("net %s-c1-in bldc.%d.C1"% (let,jnum), file=file) print("net %s-c2-in bldc.%d.C2"% (let,jnum), file=file) print("net %s-c4-in bldc.%d.C4"% (let,jnum), file=file) print("net %s-c8-in bldc.%d.C8"% (let,jnum), file=file) if "H" in(bldc): print("setp bldc.%d.output-pattern %d" % (jnum,self.d[let+"bldc_pattern_out"]), file=file) print("net %s-hall1-out bldc.%d.hall1-out"% (let,jnum), file=file) print("net %s-hall2-out bldc.%d.hall2-out"% (let,jnum), file=file) print("net %s-hall3-out bldc.%d.hall3-out"% (let,jnum), file=file) if "6" in(bldc) : if "B" in(bldc): print("net %s-a-high-on bldc.%d.A-high-on"% (let,jnum), file=file) print("net %s-a-low-on bldc.%d.A-low-on"% (let,jnum), file=file) print("net %s-b-high-on bldc.%d.B-high-on"% (let,jnum), file=file) print("net %s-b-low-on bldc.%d.B-low-on"% (let,jnum), file=file) print("net %s-c-high-on bldc.%d.C-high-on"% (let,jnum), file=file) print("net %s-c-low-on bldc.%d.C-low-on"% (let,jnum), file=file) else: print("net %s-a-high-value bldc.%d.A-high"% (let,jnum), file=file) print("net %s-a-low-value bldc.%d.A-low"% (let,jnum), file=file) print("net %s-b-high-value bldc.%d.B-high"% (let,jnum), file=file) print("net %s-b-low-value bldc.%d.B-low"% (let,jnum), file=file) print("net %s-c-high-value bldc.%d.C-high"% (let,jnum), file=file) print("net %s-c-low-value bldc.%d.C-low"% (let,jnum), file=file) elif "B" in(bldc): print("net %s-a-on bldc.%d.A-on"% (let,jnum), file=file) print("net %s-b-on bldc.%d.B-on"% (let,jnum), file=file) print("net %s-c-on bldc.%d.C-on"% (let,jnum), file=file) elif "F" in(bldc): print("net %s-c1-out bldc.%d.C1-out"% (let,jnum), file=file) print("net %s-c2-out bldc.%d.C2-out"% (let,jnum), file=file) print("net %s-c4-out bldc.%d.C4-out"% (let,jnum), file=file) print("net %s-c8-out bldc.%d.C8-out"% (let,jnum), file=file) else: print("net %s-a-value bldc.%d.A-value"% (let,jnum), file=file) print("net %s-b-value bldc.%d.B-value"% (let,jnum), file=file) print("net %s-c-value bldc.%d.C-value"% (let,jnum), file=file) print(file=file) print("net %s-pos-rawcounts bldc.%d.rawcounts"% (let,jnum), file=file) print("net %s-index-enable bldc.%d.index-enable"% (let,jnum), file=file) print("net %s-bldc-current bldc.%d.out"% (let,jnum), file=file) print("net %s-meas-angle bldc.%d.phase-angle"% (let,jnum), file=file) print("net %s-output bldc.%d.value"% (let,jnum), file=file) print("net %s-enable bldc.%d.init"% (let,jnum), file=file) print("net %s-is-init bldc.%s.init-done"% (let,jnum), file=file) print(file=file) stepflag = bool(steppinname !=None) self.build_pid(file, jnum, let, stepflag) if tppwmpinname: print(_("# ---TPPWM Generator signals/setup---"), file=file) if tppwm_six: print(_("# six output 3pwg"), file=file) else:print(_("# three output 3pwg"), file=file) print(_("# TODO write some commands!"), file=file) print(file=file) if amp8i20pinname: print(_("# ---8i20 amplifier card signals/setup---"), file=file) print(file=file) print("setp %s.max_current %.3f"% (amp8i20pinname,self.d[let+"8i20maxcurrent"]), file=file) print("net %s-meas-angle => %s.angle"% (let,amp8i20pinname), file=file) print("net %s-bldc-current => %s.current"% (let,amp8i20pinname), file=file) print("net %s-enable => %s.amp_enable"% (let,amp8i20pinname), file=file) print(file=file) if potpinname: # sserial digital potentiometer outputs for spindle eg 7i76 board print(_("# ---digital potentiometer output signals/setup---"), file=file) print(file=file) print("setp "+potpinname+"spinout-minlim [%s_%d]OUTPUT_MIN_LIMIT"% (title, jnum), file=file) print("setp "+potpinname+"spinout-maxlim [%s_%d]OUTPUT_MAX_LIMIT"% (title, jnum), file=file) print("setp "+potpinname+"spinout-scalemax [%s_%d]OUTPUT_SCALE"% (title, jnum), file=file) for i in potinvertlist: if i == _PD.POTO: print("setp "+potpinname+"spindir-invert true", file=file) if i == _PD.POTE: print("setp "+potpinname+"spinena-invert true", file=file) print(file=file) print("net spindle-output => " + potpinname + "spinout", file=file) print("net spindle-enable => " + potpinname +"spinena", file=file) print("net spindle-ccw => " + potpinname +"spindir", file=file) print(file=file) if pwmpinname: print(_("# ---PWM Generator signals/setup---"), file=file) print(file=file) # sserial daughter board PWMGENS eg 7i77 if "analogout" in pwmpinname: rawpinname = self.a.make_pinname(pwmpin, gpionumber = False, prefixonly = True, substitution = self.d.useinisubstitution) # dont want the component name if let == 's': print("setp "+pwmpinname+"-scalemax [%s_%d]OUTPUT_SCALE"% (title, jnum), file=file) print("setp "+pwmpinname+"-minlim [%s_%d]OUTPUT_MIN_LIMIT"% (title, jnum), file=file) print("setp "+pwmpinname+"-maxlim [%s_%d]OUTPUT_MAX_LIMIT"% (title, jnum), file=file) print(file=file) print("net spindle-output => " + pwmpinname, file=file) if 'analogout5' in pwmpinname: # on the 7i77 analog out 5 has it's own enable print("net spindle-enable => " + rawpinname + "spinena", file=file) else: print("setp "+pwmpinname+"-scalemax [%s_%d]OUTPUT_SCALE"% (title, jnum), file=file) print("setp "+pwmpinname+"-minlim [%s_%d]OUTPUT_MIN_LIMIT"% (title, jnum), file=file) print("setp "+pwmpinname+"-maxlim [%s_%d]OUTPUT_MAX_LIMIT"% (title, jnum), file=file) print(file=file) print("net %s-output => "% (let) + pwmpinname, file=file) print("net %s-pos-cmd <= joint.%d.motor-pos-cmd" % (let, jnum ), file=file) print("net %s-enable <= joint.%d.amp-enable-out"% (let,jnum), file=file) if 'analogout5' in pwmpinname: # on the 7i77 analog out 5 has it's own enable print("net %s-enable %spinena"% (let,rawpinname), file=file) if let == "x": print(_("# enable _all_ sserial pwmgens"), file=file) print("net %s-enable => %sanalogena"% (let,rawpinname), file=file) print(file=file) else: # mainboard PWMGENS pulsetype = 1 if self.d[pwmtype] == _PD.PDMP: pulsetype = 3 if self.d[pwmtype] == _PD.UDMU: pulsetype = 2 print("setp "+pwmpinname+".output-type %d"% pulsetype, file=file) print("setp "+pwmpinname+".scale [%s_%d]OUTPUT_SCALE"% (title, jnum), file=file) for i in pwminvertlist: print("setp "+i+".invert_output true", file=file) print(file=file) if let == 's': print(file=file) if closedloop or self.d.suseoutputrange2: print("net spindle-output => " + pwmpinname + ".value", file=file) print("net spindle-enable => " + pwmpinname +".enable", file=file) else: print("net spindle-vel-cmd-rpm => " + pwmpinname + ".value", file=file) print("net spindle-enable => " + pwmpinname +".enable", file=file) else: print("net %s-output => "% (let) + pwmpinname + ".value", file=file) print("net %s-pos-cmd joint.%d.motor-pos-cmd" % (let, jnum ), file=file) print("net %s-enable joint.%d.amp-enable-out => "% (let,jnum) + pwmpinname +".enable", file=file) print(file=file) if steppinname: if len(let) >1: print(_("# Step Gen signals/setup for tandem axis"), file=file) else: print(_("# Step Gen signals/setup"), file=file) print(file=file) print("setp " + steppinname + ".dirsetup [%s_%d]DIRSETUP"% (title, jnum), file=file) print("setp " + steppinname + ".dirhold [%s_%d]DIRHOLD"% (title, jnum), file=file) print("setp " + steppinname + ".steplen [%s_%d]STEPLEN"% (title, jnum), file=file) print("setp " + steppinname + ".stepspace [%s_%d]STEPSPACE"% (title, jnum), file=file) print("setp " + steppinname + ".position-scale [%s_%d]STEP_SCALE"% (title, jnum), file=file) print("setp " + steppinname + ".step_type 0", file=file) print("setp " + steppinname + ".control-type 1", file=file) print("setp " + steppinname + ".maxaccel [%s_%d]STEPGEN_MAXACCEL"% (title, jnum), file=file) print("setp " + steppinname + ".maxvel [%s_%d]STEPGEN_MAXVEL"% (title, jnum), file=file) # invert step pins if requested # step does not have alias pin names so we invert it's GPIO pin for i in stepinvertlist[0]: print("setp " + steppinname + ".step.invert_output true", file=file) # step direction has an alias pin for i in stepinvertlist[1]: print("setp " + steppinname + ".direction.invert_output true", file=file) if let == "s": print(file=file) print("net spindle-enable => " + steppinname + ".enable", file=file) print("net spindle-vel-cmd-rps => "+ steppinname + ".velocity-cmd", file=file) if not encoderpinname and not resolverpinname: print("net spindle-vel-fb-rps <= "+ steppinname + ".velocity-fb", file=file) else: print(file=file) print(_("# ---closedloop stepper signals---"), file=file) print(file=file) print("net %s-pos-cmd <= joint.%d.motor-pos-cmd" % (let, jnum ), file=file) print("net %s-vel-cmd <= joint.%d.vel-cmd" % (let, jnum ), file=file) print("net %s-output => "% (let) + steppinname + ".velocity-cmd", file=file) print("net %s-pos-fb <= "% (let) + steppinname + ".position-fb", file=file) print("net %s-pos-fb => joint.%d.motor-pos-fb" % (let, jnum ), file=file) print("net %s-enable <= joint.%d.amp-enable-out"% (let,jnum), file=file) print("net %s-enable => %s.enable"% (let, steppinname), file=file) print(file=file) if encoderpinname: countmode = 0 if let == "s" and self.d.ssingleinputencoder: countmode = 1 print(_("# ---Encoder feedback signals/setup---"), file=file) print(file=file) print("setp "+encoderpinname+".counter-mode %d"% countmode, file=file) print("setp "+encoderpinname+".filter 1", file=file) print("setp "+encoderpinname+".index-invert 0", file=file) print("setp "+encoderpinname+".index-mask 0", file=file) print("setp "+encoderpinname+".index-mask-invert 0", file=file) print("setp "+encoderpinname+".scale [%s_%d]ENCODER_SCALE"% (title, jnum), file=file) print(file=file) if let == 's': print("net spindle-revs <= " + encoderpinname + ".position", file=file) print("net spindle-vel-fb-rps <= " + encoderpinname + ".velocity", file=file) print("net spindle-vel-fb-rpm <= " + encoderpinname + ".velocity-rpm", file=file) print("net spindle-index-enable <=> " + encoderpinname + ".index-enable", file=file) else: print("net %s-pos-fb <= "% (let) + encoderpinname+".position", file=file) print("net %s-vel-fb <= "% (let) + encoderpinname + ".velocity", file=file) print("net %s-pos-fb => joint.%d.motor-pos-fb" % (let, jnum), file=file) print("net %s-index-enable joint.%d.index-enable <=> "% (let, jnum) + encoderpinname + ".index-enable", file=file) print("net %s-pos-rawcounts <= "% (let) + encoderpinname + ".rawcounts", file=file) print(file=file) if resolverpinname: print(_("# ---Resolver feedback signals/setup---"), file=file) print(file=file) print("setp "+resolverpinname+".velocity-scale 1 # mptor speed in RPS", file=file) print("setp "+resolverpinname+".scale [%s_%d]RESOLVER_SCALE"% (title, jnum), file=file) print(file=file) print("net %s-pos-rawcounts <= "% (let) + resolverpinname + ".rawcounts", file=file) if let == 's': print("net spindle-revs <= " + resolverpinname + ".position", file=file) print("net spindle-vel-fb-rps <= " + resolverpinname + ".velocity", file=file) print("net spindle-vel-fb-rpm <= " + resolverpinname + ".velocity-rpm", file=file) print("net spindle-index-enable <=> " + resolverpinname + ".index-enable", file=file) else: print("net %s-pos-fb <= "% (let) + resolverpinname+".position", file=file) print("net %s-vel-fb <= "% (let) + resolverpinname + ".velocity", file=file) print("net %s-pos-fb => joint.%d.motor-pos-fb" % (let, jnum), file=file) print("net %s-index-enable joint.%d.index-enable <=> "% (let, jnum) + resolverpinname + ".index-enable", file=file) print(file=file) if let =='s': print(_("# ---setup spindle control signals---"), file=file) print(file=file) print("net spindle-vel-cmd-rps <= spindle.0.speed-out-rps", file=file) print("net spindle-vel-cmd-rps-abs <= spindle.0.speed-out-rps-abs", file=file) print("net spindle-vel-cmd-rpm <= spindle.0.speed-out", file=file) print("net spindle-vel-cmd-rpm-abs <= spindle.0.speed-out-abs", file=file) print("net spindle-enable <= spindle.0.on", file=file) print("net spindle-cw <= spindle.0.forward", file=file) print("net spindle-ccw <= spindle.0.reverse", file=file) print("net spindle-brake <= spindle.0.brake", file=file) print("net spindle-revs => spindle.0.revs", file=file) print("net spindle-at-speed => spindle.0.at-speed", file=file) print("net spindle-vel-fb-rps => spindle.0.speed-in", file=file) print("net spindle-index-enable <=> spindle.0.index-enable", file=file) print(file=file) if not self.a.findsignal("spindle-at-speed"): print(_("# ---Setup spindle at speed signals---"), file=file) print(file=file) if (encoderpinname or resolverpinname) and self.d.suseatspeed: if self.d.susenearrange: near_scale = 1 near_range = self.d.snearrange/60 else: near_scale = self.d.snearscale near_range = 0 print("net spindle-vel-cmd-rps => near.0.in1", file=file) print("net spindle-vel-fb-rps => near.0.in2", file=file) print("net spindle-at-speed <= near.0.out", file=file) print("setp near.0.scale %f"%near_scale, file=file) print("setp near.0.difference %f"% near_range, file=file) print(file=file) else: print("sets spindle-at-speed true", file=file) print(file=file) if encoderpinname or resolverpinname: if (self.d.pyvcp and self.d.pyvcpconnect == 1 and self.d.pyvcphaltype == 1) \ or self.d.gladevcp and self.d.spindlespeedbar: print(_("# Use ACTUAL spindle velocity from spindle encoder"), file=file) print(_("# spindle-velocity bounces around so we filter it with lowpass"), file=file) print(_("# spindle-velocity is signed so we use absolute component to remove sign"), file=file) print(_("# ACTUAL velocity is in RPS not RPM so we scale it."), file=file) print(file=file) print(("setp scale.spindle.gain 60"), file=file) print(("setp lowpass.spindle.gain %f"% self.d.sfiltergain), file=file) print(("net spindle-vel-fb-rps => scale.spindle.in"), file=file) print(("net spindle-fb-rpm scale.spindle.out => abs.spindle.in"), file=file) print(("net spindle-fb-rpm-abs abs.spindle.out => lowpass.spindle.in"), file=file) print(("net spindle-fb-rpm-abs-filtered lowpass.spindle.out "), file=file) return min_limsig = self.a.min_lim_sig(let) if not min_limsig: min_limsig = "%s-neg-limit" % let max_limsig = self.a.max_lim_sig(let) if not max_limsig: max_limsig = "%s-pos-limit" % let homesig = self.a.home_sig(let) if not homesig: homesig = "%s-home-sw" % let print(_("# ---setup home / limit switch signals---"), file=file) print(file=file) print("net %s => joint.%d.home-sw-in" % (homesig, jnum), file=file) print("net %s => joint.%d.neg-lim-sw-in" % (min_limsig, jnum), file=file) print("net %s => joint.%d.pos-lim-sw-in" % (max_limsig, jnum), file=file) print(file=file) def connect_input(self, file): print(_("# external input signals"), file=file) def write_pins(pname,p,i,t): # for input pins if t in (_PD.GPIOI, _PD.INM0): if not p == "unused-input": pinname = self.a.make_pinname(pname, substitution = self.d.useinisubstitution) print("\n# ---",p.upper(),"---", file=file) if "parport" in pinname: if i: print("net %s <= %s-not" % (p, pinname), file=file) else: print("net %s <= %s" % (p, pinname), file=file) elif "sserial" in pname or t == _PD.INM0: if i: print("net %s <= "% (p)+pinname +"-not", file=file) else: print("net %s <= "% (p)+pinname, file=file) else: if i: print("net %s <= "% (p)+pinname +".in_not", file=file) else: print("net %s <= "% (p)+pinname +".in", file=file) # for encoder pins elif t in (_PD.ENCA,_PD.MXE0,_PD.MXE1): if not p == "unused-encoder": for sig in (self.d.halencoderinputsignames): if p == sig+"-a": pinname = self.a.make_pinname(self.a.findsignal( p ), substitution = self.d.useinisubstitution) print("\n# ---",sig.upper(),"---", file=file) print("net %s <= "% (sig+"-position")+pinname +".position", file=file) print("net %s <= "% (sig+"-count")+pinname +".count", file=file) print("net %s <= "% (sig+"-velocity")+pinname +".velocity", file=file) print("net %s <= "% (sig+"-reset")+pinname +".reset", file=file) print("net %s <= "% (sig+"-index-enable")+pinname +".index-enable", file=file) for ending in ("counter-mode","filter","index-invert","indek-mask","index-mask-invert","scale","vel-timeout"): title = sig + "-%s"% ending name = pinname + ".%s"% ending self._substitution_list.append((title.upper(),name)) self._substitution_list.append(("","")) break elif t in (_PD.RES0,_PD.RES1,_PD.RES2,_PD.RES3,_PD.RES4,_PD.RES5): if not p == "unused-resolver": for sig in (self.d.halresolversignames): if p == sig: pinname = self.a.make_pinname(self.a.findsignal( p ), substitution = self.d.useinisubstitution) print("\n# ---",sig.upper(),"---", file=file) print("net %s <= "% (sig+"-position")+pinname +".position", file=file) print("net %s <= "% (sig+"-count")+pinname +".count", file=file) print("net %s <= "% (sig+"-angle")+pinname +".angle", file=file) print("net %s <= "% (sig+"-error")+pinname +".error", file=file) print("net %s <= "% (sig+"-velocity")+pinname +".velocity", file=file) print("net %s <= "% (sig+"-reset")+pinname +".reset", file=file) print("net %s <= "% (sig+"-index-enable")+pinname +".index-enable", file=file) for ending in ("scale","velocity-scale"): title = sig + "-%s"% ending name = pinname + ".%s"% ending self._substitution_list.append((title.upper(),name)) self._substitution_list.append(("","")) break # for analog in pins elif t == (_PD.ANALOGIN): if not p == "unused-analog-input": pinname = self.a.make_pinname(self.a.findsignal( p ), substitution = self.d.useinisubstitution) print("\n# ---",p.upper(),"---", file=file) print("net %s <= "% (p)+pinname, file=file) # mesa mainboards for boardnum in range(0,int(self.d.number_mesa)): for concount,connector in enumerate(self.d["mesa%d_currentfirmwaredata"% (boardnum)][_PD._NUMOFCNCTRS]) : for pin in range(0,24): pname = 'mesa%dc%dpin%d' % (boardnum,connector, pin) p = self.d['mesa%dc%dpin%d' % (boardnum,connector, pin)] i = self.d['mesa%dc%dpin%dinv' % (boardnum,connector, pin)] t = self.d['mesa%dc%dpin%dtype' % (boardnum,connector, pin)] write_pins(pname,p,i,t) # sserial if self.d["mesa%d_numof_sserialports"% (boardnum)]: # only check if we have sserialports print(file=file) port = 0 for channel in range (0,self.d["mesa%d_currentfirmwaredata"% boardnum][_PD._MAXSSERIALCHANNELS]): if channel > _PD._NUM_CHANNELS: break for pin in range (0,_PD._SSCOMBOLEN): pname = 'mesa%dsserial%d_%dpin%d' % (boardnum,port,channel,pin) p = self.d['mesa%dsserial%d_%dpin%d' % (boardnum,port,channel,pin)] i = self.d['mesa%dsserial%d_%dpin%dinv' % (boardnum,port,channel,pin)] t = self.d['mesa%dsserial%d_%dpin%dtype' % (boardnum,port,channel,pin)] write_pins(pname,p,i,t) # parports templist = ("pp1","pp2","pp3") for j, k in enumerate(templist): if self.d.number_pports < (j+1): break print(file=file) for x in (2,3,4,5,6,7,8,9,10,11,12,13,15): pname = "%s_Ipin%d" % (k, x) p = self.d[pname] i = self.d[pname+"_inv"] if not p == "unused-input": write_pins(pname,p,i,_PD.GPIOI) def connect_output(self, file): print(_("# external output signals"), file=file) def write_pins(pname,p,i,t,boardnum,connector,port,channel,pin): # for output /open drain pins if t in (_PD.GPIOO,_PD.GPIOD,_PD.SSR0,_PD.OUTM0): if not p == "unused-output": pinname = self.a.make_pinname(pname, substitution = self.d.useinisubstitution) print("\n# ---",p.upper(),"---", file=file) if "parport" in pinname: if p == "force-pin-true": print("setp %s true"% (pinname), file=file) else: print("net %s => %s"% (p,pinname), file=file) else: if "sserial" in pname: temp = pinname # mainboard GPIOO require extra setup commands else: if t not in (_PD.SSR0,_PD.OUTM0): print("setp %s true"% (pinname + ".is_output"), file=file) if t == _PD.GPIOD: print("setp "+pinname+".is_opendrain true", file=file) if t in (_PD.SSR0,_PD.OUTM0): temp = pinname else: temp = pinname + ".out" # set pin true if force-pin-true otherwise connect to a signal if p == "force-pin-true": print("setp %s true"% (temp), file=file) else: comment = "" if self.d.frontend == _PD._QTPLASMAC and p in ['dout-01','dout-02','dout-03']: comment = "#qtplasmac uses digital output %s:\n#" % p print("%snet %s => %s"% (comment,p,temp), file=file) if i: # invert pin if "sserial" in pname: ending = "-invert" elif "parport" in pinname: ending = "-invert" else: ending = ".invert_output" print("setp %s true"% (pinname + ending ), file=file) # for pwm pins elif t in (_PD.PWMP,_PD.PDMP,_PD.UDMU): if not p == "unused-pwm": for sig in (self.d.halpwmoutputsignames): if p == (sig+"-pulse"): pinname = self.a.make_pinname(pname, substitution = self.d.useinisubstitution) print("\n# ---",sig.upper(),"---", file=file) if t == _PD.PWMP: print("setp "+pinname +".output-type 1", file=file) if t == _PD.UDMU: print("setp "+pinname +".output-type 2", file=file) elif t == _PD.PDMP: print("setp "+pinname +".output-type 3", file=file) print("net %s <= "% (sig+"-enable")+pinname +".enable", file=file) print("net %s <= "% (sig+"-value")+pinname +".value", file=file) for ending in ("scale","output-type"): title = sig + "-%s"% ending name = pinname + ".%s"% ending self._substitution_list.append((title.upper(),name)) self._substitution_list.append(("","")) break # for TP pwm pins elif t == (_PD.TPPWMA): if not p == "unused-tppwmgen": for sig in (self.d.haltppwmoutputsignames): if p == (sig+"-a"): pinname = self.a.make_pinname(pname, substitution = self.d.useinisubstitution) print("\n# ---",sig.upper(),"---", file=file) print("net %s <= "% (sig+"-enable")+pinname +".enable", file=file) print("net %s <= "% (sig+"-a-value")+pinname +".A-value", file=file) print("net %s <= "% (sig+"-b-value")+pinname +".B-value", file=file) print("net %s <= "% (sig+"-c-value")+pinname +".C-value", file=file) print("net %s <= "% (sig+"-fault")+pinname +".fault", file=file) for ending in ("scale","deadtime","fault-invert","sample-time"): title = sig + "-%s"% ending name = pinname + ".%s"% ending self._substitution_list.append((title.upper(),name)) self._substitution_list.append(("","")) break # for stepper pins elif t == (_PD.STEPA): if not p == "unused-stepgen": for sig in (self.d.halsteppersignames): if p == (sig+"-step"): pinname = self.a.make_pinname(pname, substitution = self.d.useinisubstitution) print("\n# ---",sig.upper(),"---", file=file) print("net %s <= "% (sig+"-enable")+pinname +".enable", file=file) print("net %s <= "% (sig+"-count")+pinname +".counts", file=file) print("net %s <= "% (sig+"-cmd-position")+pinname +".position-cmd", file=file) print("net %s <= "% (sig+"-act-position")+pinname +".position-fb", file=file) print("net %s <= "% (sig+"-velocity")+pinname +".velocity-fb", file=file) pinlist = self.a.list_related_pins([_PD.STEPA,_PD.STEPB], boardnum, connector, channel, pin, 0) for i in pinlist: if self.d[i[0]+"inv"]: gpioname = self.a.make_pinname(i[0],gpionumber = True, substitution = self.d.useinisubstitution) print("setp "+gpioname+".invert_output true", file=file) for ending in ("position-scale","maxvel","maxaccel","steplen","stepspace","dirsetup","dirhold","step_type"): title = sig + "-%s"% ending name = pinname + ".%s"% ending self._substitution_list.append((title.upper(),name)) self._substitution_list.append(("","")) break # potentiometer outpot elif t == (_PD.POTO): print(pname) if not p == "unused-pot": for sig in (self.d.halpotsignames): print("looking",p,sig) if p == (sig+"-output"): pinname = self.a.make_pinname(pname, substitution = self.d.useinisubstitution) print("\n# ---",sig.upper(),"---", file=file) print("net %s => "% (sig+"-enable")+pinname +".spinena", file=file) print("net %s => "% (sig+"-output")+pinname +".spinout", file=file) print("net %s => "% (sig+"-direction")+pinname +".spindir", file=file) pinlist = self.a.list_related_pins([_PD.POTO,_PD.POTE], boardnum, port, channel, pin, 0) for i in pinlist: if self.d[i[0]+"inv"]: if self.d[i[0]+"type"] == _PD.POTO: print("setp "+pinname+".spindir-invert true", file=file) if self.d[i[0]+"type"] == _PD.POTE: print("setp "+pinname+".spinena-invert true", file=file) for ending in ("spindir-invert","spinena-invert","spinout-maxlim","spinout-minlim","spinout-scalemax"): title = sig + "-%s"% ending name = pinname + ".%s"% ending self._substitution_list.append((title.upper(),name)) self._substitution_list.append(("","")) break # mesa mainboards for boardnum in range(0,int(self.d.number_mesa)): for concount,connector in enumerate(self.d["mesa%d_currentfirmwaredata"% (boardnum)][_PD._NUMOFCNCTRS]) : for pin in range(0,24): pname = 'mesa%dc%dpin%d' % (boardnum,connector, pin) p = self.d['mesa%dc%dpin%d' % (boardnum,connector, pin)] i = self.d['mesa%dc%dpin%dinv' % (boardnum,connector, pin)] t = self.d['mesa%dc%dpin%dtype' % (boardnum,connector, pin)] write_pins(pname,p,i,t,boardnum,connector,None,None,pin) # mesa sserial if self.d["mesa%d_numof_sserialports"% (boardnum)]: # only check if we have sserialports print(file=file) port = 0 for channel in range (0,self.d["mesa%d_currentfirmwaredata"% boardnum][_PD._MAXSSERIALCHANNELS]): if channel > _PD._NUM_CHANNELS: break for pin in range (0,_PD._SSCOMBOLEN): pname = 'mesa%dsserial%d_%dpin%d' % (boardnum,port,channel,pin) p = self.d['mesa%dsserial%d_%dpin%d' % (boardnum,port,channel,pin)] i = self.d['mesa%dsserial%d_%dpin%dinv' % (boardnum,port,channel,pin)] t = self.d['mesa%dsserial%d_%dpin%dtype' % (boardnum,port,channel,pin)] write_pins(pname,p,i,t,boardnum,None,port,channel,pin) # parports templist = ("pp1","pp2","pp3") for j, k in enumerate(templist): if self.d.number_pports < (j+1): break print(file=file) for x in (1,2,3,4,5,6,7,8,9,14,16,17): pname = "%s_Opin%d" % (k, x) p = self.d[pname] i = self.d[pname+"_inv"] if not p == "unused-output": write_pins(pname,p,i,_PD.GPIOO,None,None,None,None,None) # qtplasmac hal connections def qtplasmac_connections(self, file, base): print(_("\n# ---PLASMA INPUT DEBOUNCE---"), file=file) print(_("#values for these are in custom.hal"), file=file) print("loadrt dbounce names=db_breakaway,db_float,db_ohmic,db_arc-ok", file=file) print("addf db_float servo-thread", file=file) print("addf db_ohmic servo-thread", file=file) print("addf db_breakaway servo-thread", file=file) print("addf db_arc-ok servo-thread", file=file) print(_("\n# ---JOINT ASSOCIATED WITH THE Z AXIS---"), file=file) jnum = 0 tandemjoint = self.a.tandem_check('x') if tandemjoint: jnum += 1 jnum += 1 tandemjoint = self.a.tandem_check('y') if tandemjoint: jnum += 1 jnum += 1 print("net plasmac:axis-position joint.{:d}.pos-fb => plasmac.axis-z-position".format(jnum), file=file) print(_("\n# ---PLASMA INPUTS---"), file=file) print(_("# ---all modes---"), file=file) print("net plasmac:float-switch => db_float.in", file=file) print("net plasmac:breakaway => db_breakaway.in", file=file) print("net plasmac:ohmic-probe => db_ohmic.in", file=file) print("net plasmac:ohmic-sense-in => plasmac.ohmic-sense-in", file=file) print(_("# ---modes 0 & 1"), file=file) print("net plasmac:arc-voltage-in => plasmac.arc-voltage-in", file=file) print(_("# ---modes 1 & 2"), file=file) print("net plasmac:arc-ok-in => db_arc-ok.in", file=file) print(_("# ---mode 2"), file=file) print("net plasmac:move-up <= plasmac.move-up", file=file) print("net plasmac:move-down <= plasmac.move-down", file=file) print(_("\n# ---PLASMA OUTPUTS---"), file=file) print(_("# ---all modes---"), file=file) print("net plasmac:ohmic-enable <= plasmac.ohmic-enable", file=file) print("net plasmac:scribe-arm <= plasmac.scribe-arm", file=file) print("net plasmac:scribe-on <= plasmac.scribe-on", file=file) # check for arc voltage encoder self.d.qtplasmacvscale = 1 self.d.qtplasmacvoffset = 0 pinname = self.a.make_pinname(self.a.findsignal("arc-volt-enc-a"), substitution = self.d.useinisubstitution) if pinname: ending = "" if "enc" in pinname: ending = ".velocity" if self.d.voltsrdiv < 150: dratio = self.d.voltsrdiv else: dratio = (self.d.voltsrdiv + 100000) / 100000 if self.d.voltsmodel.startswith("2"): if "(W1 down)" in self.d.voltsmodel: thcadvolts = 5 else: thcadvolts = 10 else: thcadvolts = int(self.d.voltsmodel) self.d.qtplasmacvscale = dratio / (((self.d.voltsfullf - self.d.voltszerof) * 1000) / int(self.d.voltsfjumper) / thcadvolts) self.d.qtplasmacvoffset = self.d.voltszerof * 1000 / int(self.d.voltsfjumper) # arc voltage in hal file print(_("\n# ---ARC VOLTAGE ENCODER---"), file=file) print("net plasmac:arc-voltage-in <= %s%s"% (pinname, ending), file=file) print("setp {}.counter-mode 1".format(pinname), file=file) print("setp {}.filter 1".format(pinname), file=file) print("setp {}.scale -1".format(pinname), file=file) # check for ohmic sensing with a relay contact or similar pinname = self.a.make_pinname(self.a.findsignal("plasmac:ohmic-sense-in"), substitution = self.d.useinisubstitution) if pinname: vscale = 1 voffset = 0 print(_("\n# ---OHMIC SENSE LINK---"), file=file) print("net plasmac:ohmic-probe <= plasmac.ohmic-sense-out", file=file) # write custom hal file chfile = os.path.join(base, "custom.hal") if not os.path.exists(chfile): f1 = open(chfile, "w") print(_("# Include your custom HAL commands here"), file=f1) print(_("# This file will not be overwritten when you run PNCconf again"), file=f1) print(_("\n# ---COMMON PLASMAC DEBOUNCE---"), file=f1) print(_("# for the float and ohmic inputs each increment in delay is"), file=f1) print(_("# is a 0.001mm (0.00004\") increase in any probed height result"), file=f1) print("setp db_float.delay 5", file=f1) if pinname: print(_("# set to zero if using internal ohmic sensing"), file=f1) print("setp db_ohmic.delay 0", file=f1) else: print("setp db_ohmic.delay 5", file=f1) print("setp db_breakaway.delay 5", file=f1) print("setp db_arc-ok.delay 5", file=f1) if pinname: self.plasmac_ohmic_sense(f1) # hints for fine tuning print(_("\n\n\n########################################"), file=f1) print(_("# The following variables are available for fine tuning some parameters."), file=f1) print(_("# To use any of these, uncomment the required setp line and set an appropriate value.\n"), file=f1) print(_("# Dampen excessive noise on the arc voltage input"), file=f1) print(_("# default = 0 (volts)"), file=f1) print("#setp plasmac.lowpass-frequency 0\n", file=f1) print(_("# The time delay from losing the arc ok signal until QtPlasmaC reacts to the arc loss."), file=f1) print(_("# default = 0.0 (seconds)"), file=f1) print("#setp plasmac.arc-lost-delay 0.0\n", file=f1) print(_("# For mode 0 Arc-OK only, the number of consecutive readings within the threshold that are required to set the Arc-OK signal."), file=f1) print(_("# default = 6"), file=f1) print("#setp plasmac.arc-ok-counts 6\n", file=f1) print(_("# For mode 0 Arc-OK only, the maximum voltage deviation that is allowed for a valid voltage to set the Arc OK signal."), file=f1) print(_("# default = 10 (volts)"), file=f1) print("#setp plasmac.arc-ok-threshold 10\n", file=f1) print(_("# The voltage above and below 0V that will display as 0V. Prevents small fluctuations from flickering the voltage display."), file=f1) print(_("# default = 0 (volts)"), file=f1) print("#setp plasmac.zero-window 0\n", file=f1) print(_("# The distance (in millimeters) away from the Z MAX_LIMIT that QtPlasmaC will allow the Z axis to travel while under machine control."), file=f1) print(_("# default = 5 (mm)"), file=f1) print("#setp plasmac.max-offset 5\n", file=f1) print(_("# The required number of consecutive times that the threshold has been exceeded before applying the void lock to the THC."), file=f1) print(_("# default = 2"), file=f1) print("#setp plasmac.kerf-error-max 2\n", file=f1) f1.close() else: f1 = open(chfile, "r") chdata = f1.readlines() f1.close() ohmics = False for line in chdata: if "plasmac.ohmic-sense" in line: return f1 = open(chfile, "w") for line in chdata: if "db_ohmic.delay" in line and line.split("delay")[1].strip() != '0': print(_("# set to zero if using internal ohmic sensing"), file=f1) line = "setp db_ohmic.delay 0" print(line.strip(), file=f1) self.plasmac_ohmic_sense(f1) def qtplasmac_prefs(self, prefsfile): def putPrefs(prefs, file, section, option, value): if prefs.has_section(section): prefs.set(section, option, str(value)) prefs.write(open(prefsfile, "w")) else: prefs.add_section(section) prefs.set(section, option, str(value)) prefs.write(open(prefsfile, "w")) from configparser import RawConfigParser prefs = RawConfigParser() prefs.optionxform = str putPrefs(prefs, prefsfile, 'PLASMA_PARAMETERS', 'Arc Voltage Offset', '{:.3f}'.format(self.d.qtplasmacvoffset)) putPrefs(prefs, prefsfile, 'PLASMA_PARAMETERS', 'Arc Voltage Scale', '{:.6f}'.format(self.d.qtplasmacvscale)) putPrefs(prefs, prefsfile, 'GUI_OPTIONS', 'Mode', self.d.qtplasmacmode) putPrefs(prefs, prefsfile, 'GUI_OPTIONS', 'Estop type', self.d.qtplasmacestop) dro = 'top' if self.d.qtplasmacdro else 'bottom' putPrefs(prefs, prefsfile, 'GUI_OPTIONS', 'DRO position', dro) putPrefs(prefs, prefsfile, 'GUI_OPTIONS', 'Flash error', self.d.qtplasmacerror) putPrefs(prefs, prefsfile, 'GUI_OPTIONS', 'Hide run', self.d.qtplasmacstart) putPrefs(prefs, prefsfile, 'GUI_OPTIONS', 'Hide pause', self.d.qtplasmacpause) putPrefs(prefs, prefsfile, 'GUI_OPTIONS', 'Hide abort', self.d.qtplasmacstop) for ub in range(1, 21): putPrefs(prefs, prefsfile, 'BUTTONS', '{} Name'.format(ub), self.d.qtplasmac_bnames[ub-1]) putPrefs(prefs, prefsfile, 'BUTTONS', '{} Code'.format(ub), self.d.qtplasmac_bcodes[ub-1]) putPrefs(prefs, prefsfile, 'POWERMAX', 'Port', self.d.qtplasmacpmx) def plasmac_ohmic_sense(self, f1): print(_("\n# ---OHMIC SENSE CONTACT DEBOUNCE---"), file=f1) print("setp plasmac.ohmic-sense-off-delay 3", file=f1) print("setp plasmac.ohmic-sense-on-delay 3", file=f1) # BOILER CODE def __getitem__(self, item): return getattr(self, item) def __setitem__(self, item, value): return setattr(self, item, value)