diff --git a/ESB_MX.subs b/ESB_MX.subs index 6d8a8e1..c860410 100644 --- a/ESB_MX.subs +++ b/ESB_MX.subs @@ -20,9 +20,9 @@ file PPMACMotor.template { pattern {DESC ,P ,M ,PORT ,ADDR ,DIR,VMAX,VELO,JVEL,HVEL,ACCL,JAR,MRES ,PREC,EGU ,DHLM,DLLM} -{ "Rotation Y" ,"$(P_M)","MOTOR_ROT_Y1","$(PORT_M)","$(M1)",0 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"deg",0 ,0} -{ "Translation X","$(P_M)","MOTOR_X1" ,"$(PORT_M)","$(M2)",0 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} -{ "Translation Y","$(P_M)","MOTOR_Y1" ,"$(PORT_M)","$(M3)",0 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} -{ "TransBase X", "$(P_M)","MOTOR_AX" ,"$(PORT_M)","$(M7)",0 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} -{ "TransBase Z", "$(P_M)","MOTOR_AZ" ,"$(PORT_M)","$(M8)",0 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} +{ "Rotation Y" ,"$(P_M)","MOTOR_ROT_Y1","$(PORT_M)","$(M1)",1 ,50 ,50 ,50 ,1 ,0.1 ,20 ,-0.001,3 ,"deg",0 ,0} +{ "Translation X","$(P_M)","MOTOR_X1" ,"$(PORT_M)","$(M2)",1 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} +{ "Translation Y","$(P_M)","MOTOR_Y1" ,"$(PORT_M)","$(M3)",1 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} +{ "TransBase X", "$(P_M)","MOTOR_AX" ,"$(PORT_M)","$(M7)",1 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} +{ "TransBase Z", "$(P_M)","MOTOR_AZ" ,"$(PORT_M)","$(M8)",1 ,2 ,2 ,2 ,1 ,0.1 ,20 ,-0.001,3 ,"mm",0 ,0} } diff --git a/Makefile b/Makefile index 3da60c1..a11eb03 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ MODULE = $(notdir $(shell pwd)) BUILDCLASSES = Linux ARCH_FILTER = eldk42% SL6-x86_64 EXCLUDE_VERSIONS = 3.14.8 -SCRIPTS+=$(wildcard add_device*.cmd cfg/*.cfg cfg/*.py cfg/*.pbi qt/*.ui qt/*.jpg) +SCRIPTS+=$(wildcard add_device*.cmd cfg/*.cfg cfg/*.py cfg/*.pbi qt/*.ui qt/*.jpg python/*.py) #SOURCES+=src/DHVSaSub.cpp #DBDS+=src/DHVSaSub.dbd USR_CXXFLAGS+= -fno-operator-names diff --git a/Readme.md b/Readme.md index 960f037..385b901 100644 --- a/Readme.md +++ b/Readme.md @@ -4,6 +4,7 @@ Various motor documents Parker stage ------------ +``` - encoder is incremental encoder 25mm or 50mm travel stage Stall Current Continuous 0.8 @@ -14,7 +15,7 @@ Max.BuxVoltage V 80 Continous Force 4N -> assume 1kg load -> acceleration=a=F/m=4m/s^2 Weight top stage: 250g=2.5N - +``` Mecapion rot stage @@ -27,15 +28,16 @@ http://www.parkem.ch/medien/produkte/direktantriebstechnik/pdf/MDM_Rundtisch_kat http://www.goto.si/wp-content/uploads/2016/kat/L7%20Series%20catalog.pdf http://farasys.ir/wp-content/uploads/2015/Direct%20Drive%20Rotary%20Motors.pdf http://www.inmoco.co.uk/Upload/product/1037_DD_Series_Motors_79.pdf -``` - encoder is biss 20 bit - Rated Current 1.46 Arms - Max Current 4.38 Arms - 32 pole (16 einraster per rev) +``` Servo Test Motor QBL 4208-41-04-006 ----------------------------------- +``` 8 pole (4 lock position per rev) 24 V rated voltage 1.79 A rated phase current @@ -43,10 +45,12 @@ Servo Test Motor QBL 4208-41-04-006 4000 rpm rated speed 1.8 ohm line to line resistance 2.6 mH line to line inductance +``` + - 2Phase Stepper Test Motor Vextra PK244M --------------------------------------- +``` - 200 pole (100 einraster per rev) @@ -61,28 +65,31 @@ gpasciiCommander --host SAR-CPPM-EXPMX1 -i cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python ./shapepath.py -v255 - +``` Testing ServoFrq. ----------------- - +``` !common(PhaseFreq=20000,PhasePerServo=4) -> 25000points, 20um error leads the trajectory in x !common(PhaseFreq=20000,PhasePerServo=2) -> 25000points, 6.6um error !common(PhaseFreq=20000,PhasePerServo=1) -> 25000points, 6.1um error ossilates in y, x is quite good -> the servo loop has to be optimized! +``` Testing linear,pvt,spline moves ------------------------------- +``` Tested with shapepath.py: THE BEST TRAJECTORY RESULT IST WITH PVT MOTION +``` Optimize/Test Parameters with Parker Stage ------------------------------------------ - +``` cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/cfg gpasciiCommander --host SAR-CPPM-EXPMX1 -i !mx-stage() @@ -119,12 +126,12 @@ average error x 0.313575 um, y 0.461707 um, 0.629583 um ./shapepath.py average error x 0.371877 um, y 0.317152 um, 0.542073 um - +``` Start motion on external signal ------------------------------- - +``` open plc 1 Coord[1].DesTimeBase=0 // freezes timebase at boot while(1) @@ -144,3 +151,32 @@ close enable plc 1 -> run motion program. press gpio 0 to run at 100% +``` + +29.9.17 Testing in MX-LAB +------------------------- +``` +Start the powerbrick. ioc is started automatically +zamofing_t@ganymede:~$ ssh x06mx-cons-1 + +caget SAR-ESB_MX:MOTOR_AX +cd /net/slsfs-crtl/export/sf/common/config/qt/ +startDM -macro 'P=SAR-ESB_MX' ESB_MX_exp +press homing button +-> all axes can be moved. + +(on thierrys laptop only) +cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python +./shapepath.py +will execute the custom motion. No problems with EPICS + +(on other machines) +module is installed in: +ls /net/slsfs-crtl/export/sf/ioc/modules/ESB_MX/zamofing_t/R3.14.12/ +PATH=/net/slsfs-crtl/export/sf/controls/bin/:$PATH +source /opt/gfa/python-2.7/2.3.0/bin/activate xblpython > /dev/null 2>&1 +cd /net/slsfs-crtl/export/sf/ioc/modules/ESB_MX/zamofing_t/R3.14.12/ +./shapepath.py + +``` + diff --git a/cfg/torqueCtrl.cfg b/cfg/torqueCtrl.cfg index b72e6e3..b6658ce 100644 --- a/cfg/torqueCtrl.cfg +++ b/cfg/torqueCtrl.cfg @@ -41,7 +41,7 @@ Motor[1].pPhaseEnc=Acc84B[0].Chan[0].SerialEncDataA.a //Motor[1].pAbsPhasePos=Acc84B[0].Chan[0].SerialEncDataA.a !motor_servo(mot=1,ctrl='ServoCtrl',Kp=0.8,Kvfb=20,Ki=0.001,Kvff=40,Kaff=0,MaxInt=1000) -!motor(mot=1,dirCur=0,contCur=1000,peakCur=2000,timeAtPeak=1,IiGain=1.5,IpfGain=0,IpbGain=3,JogSpeed=180.,numPhase=3,invDir=True,servo=None,PhasePosSf=1./8192,PhaseFindingDac=100,PhaseFindingTime=50,SlipGain=0,AdvGain=0,PwmSf=10000,FatalFeLimit=3000,WarnFeLimit=1000,InPosBand=10) +!motor(mot=1,dirCur=0,contCur=1000,peakCur=2000,timeAtPeak=1,IiGain=1.5,IpfGain=0,IpbGain=3,JogSpeed=180.,numPhase=3,invDir=True,servo=None,PhasePosSf=1./8192,PhaseFindingDac=100,PhaseFindingTime=50,SlipGain=0,AdvGain=0,PwmSf=10000,FatalFeLimit=3000,WarnFeLimit=1000,InPosBand=10, HomeOffset=228987) //Stage Y Parker MX80L @@ -85,12 +85,14 @@ Motor[1].pPhaseEnc=Acc84B[0].Chan[0].SerialEncDataA.a !encoder_biss(enc=7,numBits=32,posSf=1./20) !encoder_biss(enc=8,numBits=32,posSf=1./20) -!motor(mot=7,current=200,JogSpeed=0.5,invDir=1,servoSf=204.8) -!motor(mot=8,current=200,JogSpeed=0.5,invDir=1,servoSf=204.8) +!motor(mot=7,current=200,JogSpeed=0.5,invDir=1,servoSf=204.8,InPosBand=1,HomeOffset=39278) +!motor(mot=8,current=200,JogSpeed=0.5,invDir=1,servoSf=204.8,InPosBand=1,HomeOffset=39736) //turn off servon and inpos below ... user units (here 1um) -Motor[7].InPosBand=1;Motor[7].Servo.BreakPosErr=Motor[7].InPosBand -Motor[8].InPosBand=1;Motor[8].Servo.BreakPosErr=Motor[8].InPosBand +//Motor[7].InPosBand=1;Motor[7].Servo.BreakPosErr=Motor[7].InPosBand +//Motor[8].InPosBand=1;Motor[8].Servo.BreakPosErr=Motor[8].InPosBand + +#1,7,8hmz //holding current !holding_current(m7=[0,200],m8=[0,200]) diff --git a/python/shapepath.py b/python/shapepath.py index 3d7c395..83aa6fb 100755 --- a/python/shapepath.py +++ b/python/shapepath.py @@ -64,7 +64,7 @@ class ShapePath: fh=open(args.cfg,'r') s=fh.read() cfg=json.loads(s, object_hook=ConvUtf8) - s=json.dumps(cfg, indent=2, separators=(',', ': '));print s + s=json.dumps(cfg, indent=2, separators=(',', ': '));print(s) else: fn='/tmp/shapepath4' #fn='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/data/'+time.strftime('%y-%m-%d-%H_%M_%S') @@ -88,9 +88,11 @@ class ShapePath: cfg = {"sequencer": ['gen_grid_points(w=5,h=5,pitch=100,rnd=0.4)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=10,cnt=1)', 'plot_gather("'+fn+'.npz")']} #cfg = {"sequencer":['gen_rand_points(n=400, scale=1000)','sort_points()','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=20,acq_per=10)','plot_gather("'+fn+'.npz")']} #cfg = {"sequencer": ['gen_swissfel_points(scale=300)','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=100,acq_per=10)', 'plot_gather("'+fn+'.npz")']} - cfg = {"sequencer": ['opt_pts("'+fn+'.npz")','gen_prog(file="'+fn+'_corr.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=10,cnt=1)', 'plot_gather("'+fn+'_corr.npz")']} + #cfg = {"sequencer": ['opt_pts("'+fn+'.npz")','gen_prog(file="'+fn+'_corr.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=10,cnt=1)', 'plot_gather("'+fn+'_corr.npz")']} #cfg = {"sequencer": ['opt_pts("'+fn+'.npz")','gen_prog(file="'+fn+'.prg",mode=1,pt2pt_time=10,cnt=1)']} + #cfg = {"sequencer": ['gen_grid_points(w=5,h=5,pitch=100,rnd=0.4)', 'sort_points()','gen_prog(file="'+fn+'.prg",mode=1,pt2pt_time=10,cnt=1)']} + self.cfg=dotdict(cfg) self.args=args @@ -108,7 +110,7 @@ class ShapePath: else: dryrun=self.args.dryrun for cmd in sequencer: - print '>'*5+' '+cmd+' '+'<'*5 + print('>'*5+' '+cmd+' '+'<'*5) if not dryrun: eval('self.' + cmd) @@ -164,7 +166,7 @@ class ShapePath: ptsCorr=(pts-recPts[:,1:3]+recPts[:,4:6]) self.points=pts self.ptsCorr=ptsCorr - print ptsCorr + print(ptsCorr) def gen_prog(self,prgId=2,file=None,host=None,mode=0,**kwargs): ''' @@ -221,7 +223,7 @@ class ShapePath: try: pt2pt_time=kwargs['pt2pt_time'] #how many ms to move to next point (pt2pt_time) except KeyError: - print 'missing pt2pt_time, use default=100ms' + print('missing pt2pt_time, use default=100ms') pt2pt_time=100. try: cnt=kwargs['cnt'] #move path multiple times @@ -273,7 +275,7 @@ class ShapePath: try: pt2pt_time=kwargs['pt2pt_time'] #how many ms to move to next point (pt2pt_time) except KeyError: - print 'missing pt2pt_time, use default=100ms' + print('missing pt2pt_time, use default=100ms') pt2pt_time=100. pos=self.points pcor=np.ndarray(pos.shape,dtype=pos.dtype);pcor[:]=np.NaN @@ -302,13 +304,13 @@ class ShapePath: fh.close() if host is not None: cmd ='gpasciiCommander --host '+host+' '+ file - print cmd + print(cmd) p = sprc.Popen(cmd, shell=True)#, stdout=sprc.PIPE, stderr=sprc.STDOUT) #res=p.stdout.readlines(); print res retval = p.wait() #gather -u /var/ftp/gather/out.txt cmd ='PBGatherPlot -m24 -v7 --host '+host - print cmd + print(cmd) p = sprc.Popen(cmd, shell=True)#, stdout=sprc.PIPE, stderr=sprc.STDOUT) retval = p.wait() self.prg=prg @@ -349,8 +351,8 @@ class ShapePath: @staticmethod def onclick(event): - print 'button=%s, x=%d, y=%d, xdata=%f, ydata=%f'%( - event.button, event.x, event.y, event.xdata, event.ydata) + print('button=%s, x=%d, y=%d, xdata=%f, ydata=%f'%( + event.button, event.x, event.y, event.xdata, event.ydata)) obj=event.canvas.figure.obj def plot_points(self,pts): diff --git a/qt/ESB_MX_motor.ui b/qt/ESB_MX_motor.ui index 9b7d533..e7c6941 100644 --- a/qt/ESB_MX_motor.ui +++ b/qt/ESB_MX_motor.ui @@ -13,7 +13,7 @@ Form - + 2 @@ -77,6 +77,26 @@ + + + + + 25 + 4 + + + + $(P):$(M).DMOV + + + + 0 + 85 + 255 + + + +