From 38a8c8484b33f77cf5aa82981254499aa6a453d2 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Thu, 29 Nov 2018 15:56:05 +0100 Subject: [PATCH] adding Q1 for triggering status --- Readme.md | 11 +++++++ evr_PCIe-300DC.subs | 4 +-- python/MXMotion.py | 45 ++++++++++++++------------ python/MXTuning.py | 74 +++++++++++++++++++++++++++++++++++++++++-- python/helicalscan.py | 3 +- python/shapepath.py | 14 ++++++-- 6 files changed, 122 insertions(+), 29 deletions(-) diff --git a/Readme.md b/Readme.md index fff3895..f8d7354 100644 --- a/Readme.md +++ b/Readme.md @@ -1159,3 +1159,14 @@ caput SAR-CVME-TIFALL5-EVG0:SoftEvt-EvtCode-SP 254 ``` + + +Try to find encoder count loss +------------------------------ +``` +//set incEncFrq to 25MHz, (default was to low: 3.125MHz) + +Gate3[0].EncClockDiv=2 +Gate3[1].EncClockDiv=2 + +``` diff --git a/evr_PCIe-300DC.subs b/evr_PCIe-300DC.subs index 4a3e9d7..10af1a9 100644 --- a/evr_PCIe-300DC.subs +++ b/evr_PCIe-300DC.subs @@ -69,8 +69,8 @@ file "$(mrfioc2_TEMPLATES=db)/evr-pcie-300DC.db" Pul1-Name-I.DESC="" #Secondary description of the pulser. Maximum 40 characters allowed! Pul1-Ena-Sel=1, #0 = Disabled, 1 = Enabled Pul1-Polarity-Sel=1, #0 = Active High, 1 = Active Low - Pul1-Delay-SP=0, #Pulser delay in us - Pul1-Width-SP=5000, #Pulser width in us + Pul1-Delay-SP=1992.8, #Pulser delay in us + Pul1-Width-SP=5000, #Pulser width in us Pul1-Prescaler-SP=1, #0-65535 : Pulser prescaler Pul2-Name-I="Pulser 2" #Description of the pulser. Maximum 40 characters allowed! diff --git a/python/MXMotion.py b/python/MXMotion.py index 249e08d..534474b 100644 --- a/python/MXMotion.py +++ b/python/MXMotion.py @@ -1,26 +1,27 @@ -#some further usefull PMAC commands: -# list pc , 10 //list program counter during motion exec -# buffer //list allocated buffers -#the rotary stuff only works from gpascii, not gpasciiCommander -#delete rotary -#define rotary 4096 //allocates mem -#open rotary //same as open prog 0 -# -# X100 Y100 -# X200 Y300 -# X600 Y500 -# adding lines alway are acknowledged with ACK, -# if not, it means that the buffer is full -# it will acknowlegde when there is again free space. -# close -# delete rotary +#!/usr/bin/env python +# *-----------------------------------------------------------------------* +# | | +# | Copyright (c) 2016 by Paul Scherrer Institute (http://www.psi.ch) | +# | | +# | Author Thierry Zamofing (thierry.zamofing@psi.ch) | +# *-----------------------------------------------------------------------* +''' +Coord[1].Q[0] : sync points when using setup_sync(mode=2) + 0: after setup_sync(mode=2) call + idx: index of position during run + -1: pvt motion is finished +Coord[1].Q[1] : sync trigger: when setup_sync(mode=1 or 2) + 0: idle + 1: waiting for trigger + 2: running -#from other gpascii -#list rotary -#rotfree -#size -#b0s //start the rotary buffer in single step mode +Gather.Enable : 1: after .setup_gather() called + 2: during data gathering + 0: when gather finished + +Gather.Samples : number af gathered data samples +''' import os, sys sys.path.insert(0,os.path.expanduser('~/Documents/prj/SwissFEL/PBTools/')) @@ -63,10 +64,12 @@ class MotionBase: prg = ''' //L0=Sys.PhaseCount //send 1"sync0 %d:%d\\n",Sys.PhaseCount,Sys.PhaseCount-L0 + Coord[1].Q[1]=1 while({flag0}){{}} //send 1"sync1 %d:%d\\n",Sys.PhaseCount,Sys.PhaseCount-L0 //L1=Sys.PhaseCount while({flag1}){{}} + Coord[1].Q[1]=2 //PowerBrick[0].GpioData[0].16.8=255 //send 1"sync2 %d:%d\\n",Sys.PhaseCount,Sys.PhaseCount-L1 '''.format(plcId=plcId, crdId=crdId, flag0=flag0, flag1=flag1) diff --git a/python/MXTuning.py b/python/MXTuning.py index 5eecd58..5e6b458 100755 --- a/python/MXTuning.py +++ b/python/MXTuning.py @@ -289,6 +289,75 @@ class MXTuning(Tuning): EXPORT_SYMBOL(obsvr_servo_ctrl_{motid});'''.format(motid=motid) return (hdr,prog) + def check_fast_stage(self,file='/tmp/gather.npz'): + if os.path.isfile(file): + f=np.load(file) + data=f['data'] + meta=f['meta'].item() + meta['file']=file + else: + #self.init_stage();time sleep + phase=False + motor=2 + gpascii = self.comm.gpascii + gt = self.gather + gt.set_phasemode(phase) + address=('Motor[2].ActPos','Motor[8].ActPos') + gt.set_address(*address) + gt.set_property(Period=1) + + tSrv=gpascii.servo_period + tSrv=2E-4 # seconds + phOsv = gpascii.get_variable('sys.PhaseOverServoPeriod', float) + + subs={'prgId':999,'mot':motor,'num':100,'phase':'Phase' if phase else ''} + + #the servoloop is called 2 times per servo cycle ?!? + #don't know why, but this is the reason why the value L10 is incremented by 0.5 + prog = ''' + &1 + open prog {prgId} + P1=Motor[{mot}].DesPos-Motor[{mot}].HomePos + Q2=10 + Gather.{phase}Enable=2 + Q1={num} + while (Q1>0) + {{ + jog{mot}=(P1-1000) + dwell 10 + jog{mot}=(P1) + dwell 10 + Q1=Q1-1 + }} + dwell 10 + Gather.{phase}Enable=0 + close + &1 + b{prgId}r + '''.format(**subs) + + gpascii.send_line(prog) + res=gpascii.sync() + res=res.replace(GpasciiChannel.ACK+'\r\n','') + print(res) + t=time.time() + gt.wait_stopped() + print('time %f'%(time.time()-t)) + self.data=data=gt.upload() + meta={'motor':motor,'date':time.asctime(),'ts':tSrv if not phase else tSrv*phOsv,'address':address} + np.savez_compressed(file, data=data, meta=meta) + meta['file'] = file + tSrv=meta['ts'] + t=tSrv*np.arange(data.shape[0]) + data=data-data[0,:] + plt.plot(t,data[:,0],t,data[:,1]) + plt.figure() + plt.plot(t,data[:,0]-data[:,1]) + plt.show() + + + + def bode(mdl): w,mag,phase = signal.bode(mdl,1000) f=w/(2*np.pi) @@ -337,7 +406,7 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n ' #plt.ion() #args.host='MOTTEST-CPPM-CRM0573' - args.host=None + #args.host=None if args.host is None: comm=gt=None else: @@ -490,7 +559,8 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n ' fn=os.path.join(base, 'scratch_%d.npz' % mot) if not init_stage and not os.path.isfile(fn):tune.init_stage();init_stage=True tune.custom_chirp(motor=mot,minFrq=1,maxFrq=20,amp=200,tSec=15,mode=2,file=fn) - + elif mode==10: # record stage x and probe encoder + tune.check_fast_stage() print('done') plt.show() #------------------ Main Code ---------------------------------- diff --git a/python/helicalscan.py b/python/helicalscan.py index 77240ac..58bb3f8 100755 --- a/python/helicalscan.py +++ b/python/helicalscan.py @@ -1070,7 +1070,8 @@ close else: prg.append(' dwell 1000') if sync_frq is not None: - prg.append('Coord[1].Q[0]=-1') + prg.append(' Coord[1].Q[0]=-1') + prg.append(' Coord[1].Q[1]=0') prg.append(' Gather.Enable=0') prg.append('close') #prg.append('&1\nb%dr\n'%prgId) diff --git a/python/shapepath.py b/python/shapepath.py index ac0ed1a..56a5460 100755 --- a/python/shapepath.py +++ b/python/shapepath.py @@ -113,14 +113,14 @@ class ShapePath(MotionBase): pts=np.random.rand(n,2)*scale self.points=pts - def gen_grid_points(self,w=10,h=10,pitch=100,rnd=.2): + def gen_grid_points(self,w=10,h=10,pitch=100,rnd=.2,ofs=(0,0)): 'generates points in a grid with a given pitch and a bit randomness' np.random.seed(0) xx,yy=np.meshgrid(range(w), range(h)) pts=np.array([xx.reshape(-1),yy.reshape(-1)],dtype=np.float).transpose()*pitch if rnd != 0: pts+=(np.random.rand(pts.shape[0],2)*(rnd*pitch)) - pts[:,0]+=500 + pts+=ofs self.points=pts def opt_pts(self,fn): @@ -277,6 +277,7 @@ class ShapePath(MotionBase): prg.append('dwell 1000') if sync_frq is not None: prg.append('Coord[1].Q[0]=-1') + prg.append('Coord[1].Q[1]=0') prg.append('Gather.Enable=0') elif mode==2: #### spline motion try: @@ -636,15 +637,21 @@ if __name__=='__main__': #sp.gen_grid_points(w=2,h=2,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) #sp.gen_swissmx_points(width=1000,ofs=(-500,0));sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40,acq_per=1) + + #sp.gen_grid_points(w=30,h=30,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) #sp.gen_grid_points(w=200,h=200,pitch=50,rnd=.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) #sp.gen_grid_points(w=2,h=20,pitch=50,rnd=0);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) #sp.gen_rand_points(n=500, scale=1000);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) - sp.gen_grid_points(w=30,h=30,pitch=50,rnd=0.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) + #sp.gen_grid_points(w=30,h=30,pitch=50,rnd=0.2);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) #sp.gen_rand_points(n=400, scale=1000);sp.sort_points(xy);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10) + #sp.gen_swissmx_points(width=500,flipx=True,flipy=True,ofs=(-380,3980));sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40,acq_per=1) + #sp.gen_grid_points(w=20,h=20,pitch=20,rnd=0,ofs=(-464,1754));sp.sort_points(True);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) + sp.gen_grid_points(w=20,h=20,pitch=20,rnd=0,ofs=(-160,3700));sp.sort_points(False);sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=40) + #>>>setup gather and sync<<< #sp.setup_gather() #sp.setup_sync() @@ -653,6 +660,7 @@ if __name__=='__main__': #sp.setup_motion(fnPrg=fn+'.prg',mode=1,pt2pt_time=10,acq_per=1) #>>>run gather and plot trajectory<<< + #return sp.run() trigger(0.5) sp.gather_upload(fnRec=fn+'.npz')