From 20c6d690e8191d0d86eec468d0f708ca5d086dfe Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Tue, 4 Oct 2022 16:39:13 +0200 Subject: [PATCH] enhance syncronization -> parameters in setup_sync -> sp.setup_sync(verbose=args.verbose&0x40,timeOfs=0.03,timeCor=0.0005) - cleanup code - add motion markers - add debug data - rework triggerSync - BUT nothing should change in Sync --- Readme.md | 190 ++++++++++++++++++++++++ python/MXMotion.py | 50 ++++--- python/shapepath.py | 268 ++++++++++++++++------------------ src/triggerSync/Makefile | 18 ++- src/triggerSync/triggerSync | Bin 65686 -> 67398 bytes src/triggerSync/triggerSync.c | 114 +++++++++++---- 6 files changed, 438 insertions(+), 202 deletions(-) diff --git a/Readme.md b/Readme.md index 9443110..0d12a4f 100644 --- a/Readme.md +++ b/Readme.md @@ -1274,4 +1274,194 @@ Make z to move over the grid. ?? what are the PV for the camera, zoom etc ??? +``` + + +30.9.22 Debug Synchronization +============================= + +https://docs.google.com/document/d/1soSuCZYyfGf_ntcgG_Y1_WeGuo_687OuFn0s4sMj1uY/edit + + +remote ssh tunnel + start gather_server +--------------------------------------- +``` +PPMAC=SAR-CPPM-EXPMX1 +rsync -va ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/ +lsof -i -n | grep '127.0.0.1:1000' +ssh -L 10001:localhost:22 root@$PPMAC 'uname -a' +ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a' +ssh root@$PPMAC +LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server +``` + +cleanup /tmp/ +------------- +``` +PPMAC=SAR-CPPM-EXPMX1 +ssh root@$PPMAC rm /tmp/gather_server /tmp/triggerSync +ssh root@$PPMAC ls -l /tmp +``` + +start debug tools +----------------- +``` +PPMAC=SAR-CPPM-EXPMX1 +PBInspect --host=$PPMAC& +gpasciiCommander --host $PPMAC -i +ssh root@$PPMAC +ssh root@$PPMAC rm /tmp/gather_server /tmp/triggerSync +ssh root@$PPMAC ls -l /tmp +``` + +restart IOC +----------- +``` +ssh saresc-cons-03 +PPMAC=SAR-CPPM-EXPMX1 +telnet $PPMAC 50001 +Ctrl-X +dbgf SAR-CPPM-EXPMX1:MOD_VER + +caget SAR-CPPM-EXPMX1:MOD_VER + +``` + +checking versions +----------------- +``` +git: 7a968aac967 +asyn 427.0.2 +motorBase alpha_220518 +asynMotor alpha_220518 +powerPmac alpha_220518 +PB_COMMON 2.0.1 +gpasciiCommander 0.9.0 +ESB_MX 0.0.2 +``` + +zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX$ +git loggraph -10 +* 7a968aa 2022-09-20 (HEAD -> master, tag: latest, tag: 0.0.2, psigithub/master) change speeds and directions [Thierry Zamofing] +* 00588f8 2022-09-16 minor changes [Thierry Zamofing] +* d52a6ce 2022-08-30 minor changes [Thierry Zamofing] +* f47e111 2022-05-20 (tag: 0.0.1) add DET_Z motor [Thierry Zamofing] +* 8e5b15e 2022-05-20 wip [Thierry Zamofing] +* 399282c 2019-03-20 enhance triggering [Thierry Zamofing] +* eda8caf 2019-03-19 wip [Thierry Zamofing] +* 0c45705 2019-03-08 optimize [Thierry Zamofing] +* c962ebd 2019-03-06 documentation [Thierry Zamofing] + +git reset --hard 7a968aa +rmake -e LIBVERSION=42.42.42 uninstall install +-> restart IOC + +ssh root@$PPMAC rm /tmp/triggerSync +cd python +git dt latest -- shapepath.py +./shapepath.py --host=localhost:10001:10002 + +removing test verion +ssh sf-lc7 ls -l /ioc/modules/ESB_MX/ +ssh sf-lc7 rm -rf /ioc/modules/ESB_MX/42.42.42 + + +IOC locations +------------- +``` +~/Documents/prj/SwissFEL/epics_ioc_boot_sf/ESC_all/ESB_MX_PowerBrick +They are just using the new alphy driver. That should have no impact on the motion config. +``` + + +Current (old) Synchronization +----------------------------- +``` +default: +/ESB_MX/src/triggerSync/triggerSync.c -> read usage +simulate start trigger -> pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start\n\ +simulate frame trigger -> pshm->Coord[1].Q[11] +Coord[1].Q[0] is incremented at each trigger + +Coord[1].DesTimeBase is adjusted at each frame trigger + +Coord[1].pDesTimeBase=Coord[1].DesTimeBase.a + + +gpascii: set Gather.Enable=1 +PMAC: LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync 10 0 11 -> wait for start trigger +gpascii: set Start trigger: pshm->Coord[1].Q[10]=1 or set EVR that generates the trigger +PMAC: start Gather (Gather.Enable=2) + count and sync frames: + Coord[1].Q[0] = frame counter +gpascii: stop Gather -> Gather.Enable=0 +PMAC: triggerSync stops when Gather.Enable=0 + + +``` + +Enhanced Synchronization +------------------------ +``` +(to be tested) +Coord[1].pDesTimeBase=Coord[1].DesTimeBase.a +For “external time base”, in which the coordinate system’s time base value is proportional to the +frequency of an incoming encoder signal or pulse train, Coord[x].pDesTimeBase should be set +to EncTable[i].DeltaPos.a + +Setup EncTable: +EncTable[n].type = (3)Software 1/T encoder extension (5)Four-byte read 32 bit int (11) Float 32f or 64f + +The ERV are mapped to +//Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag +(gate3_1->Chan[0].Status&0x800) = Gate3[1].Chan[0].UserFlag Trigger start +(gate3_1->Chan[1].Status&0x800) = Gate3[1].Chan[1].UserFlag Trigger frame + + +Use EncTable 20 as Frame counter +Gate3[1].Chan[1].EncCtrl = $encctrl +EncTable[20].type = 3 +EncTable[20].pEnc = Gate3[1].Chan[1].UserFlag.a (is same as Gate3[1].Chan[1].Status) thus it will not work +EncTable[20].pEnc1 = Gate3[1].Chan[0].TimerA.a +EncTable[20].index1 = 0 +EncTable[20].index2 = 0 +EncTable[20].index3 = 0 +EncTable[20].index4 = 0 +EncTable[20].index5 = 0 +EncTable[20].ScaleFactor = 1/256 +-> THIS DOES NOT WORK WITH CURRENT CONNECTIONS ! +-> ONE PHYSICAL ENCODER WOULD NEED PULSE AND DIRECTION INPUT AND SET Gate3[1].Chan[1].EncCtrl TO 'pulse and direction' mode + + +> Sys.Ddata[0]=Sys.Ddata[0]+10 + +Use EncTable 20 as Frame counter +Gate3[1].Chan[1].EncCtrl = $encctrl +EncTable[20].type = 11 //loating point read +EncTable[20].pEnc = Sys.Ddata[0].a +EncTable[20].pEnc1 = Gate3[1].Chan[0].TimerA.a +EncTable[20].index1 = 0 +EncTable[20].index2 = 0 +EncTable[20].index3 = 0 +EncTable[20].index4 = 0 +EncTable[20].index5 = 99 //multiply with 100 +EncTable[20].index5 = 1 //float64 +EncTable[20].ScaleFactor = 1/256 +EncTable[20].ScaleFactor=1E-3 + + +Use EncTable 20 as Frame counter +EncTable[20].type = 1 //32 Bit uint +EncTable[20].pEnc = Sys.Udata[0].a +EncTable[20].index1 = 0 +EncTable[20].index2 = 0 +EncTable[20].index3 = 0 +EncTable[20].index4 = 0 +EncTable[20].index5 = 0 +EncTable[20].index5 = 0 +EncTable[20].ScaleFactor=1E-3 + + +2.1 trigger zu spät +1.9 trigger zu früh diff --git a/python/MXMotion.py b/python/MXMotion.py index 9d96634..26679db 100644 --- a/python/MXMotion.py +++ b/python/MXMotion.py @@ -7,6 +7,8 @@ # *-----------------------------------------------------------------------* ''' Coord[1].Q[0] : sync points when using setup_sync(mode=2) + -3: when armed (at start position) + -2: triggerSync waiting for start trigger 0: after setup_sync(mode=2) call idx: index of position during run -1: pvt motion is finished @@ -44,7 +46,7 @@ class MotionBase: self.meta={'srv_per':ServoPeriod,'pt2pt_time':40,'sync_flag':0,'sync_mode':2} self.meta.update(kwargs) - def setup_sync(self, crdId=1, prgId=2,verbose=False, timeOfs=0.): + def setup_sync(self, crdId=1, prgId=2,verbose=False, timeOfs=0.,timeCor=0.): '''setup the timing synchronization for the motion program kwargs: sync_mode : default=2 @@ -88,41 +90,43 @@ class MotionBase: flag0='Coord[{crdId}].Q[10]'.format(crdId=crdId) if sync_flag&1 else 'Gate3[1].Chan[0].UserFlag' flag1='Coord[{crdId}].Q[11]'.format(crdId=crdId) if sync_flag&2 else 'Gate3[1].Chan[1].UserFlag' if sync_mode==1: - prg = ''' - Coord[{crdId}].Q[0]=-2 - Coord[{crdId}].TimeBaseSlew=1 //1E-4 is default - Coord[{crdId}].DesTimeBase=0 - while({flag0}==0){{}} - Coord[{crdId}].Q[0]=-1 - Gather.Enable=2 - while({flag1}==0){{}} - Coord[1].DesTimeBase=Sys.ServoPeriod - '''.format(crdId=crdId, flag0=flag0, flag1=flag1) + prg = f'\n{flag0}=0\n' if sync_flag&1 else '' + prg += f''' +Coord[{crdId}].Q[0]=-2 motion program started and armed +Coord[{crdId}].TimeBaseSlew=1 //1E-4 is default +Coord[{crdId}].DesTimeBase=0 +while({flag0}==0){{}} +Coord[{crdId}].Q[0]=-1 +Gather.Enable=2 +while({flag1}==0){{}} +Coord[1].DesTimeBase=Sys.ServoPeriod +''' else: - prg = ''' - //Gather.Enable=2 is done in the sync program - Coord[1].TimeBaseSlew=1 //1E-4 is default - Coord[1].DesTimeBase=0 - //Coord[1].Q[0]=-1 is done in the sync program - '''.format(crdId=crdId, flag0=flag0, flag1=flag1) + prg = f''' +//Gather.Enable=2 is done in the triggerSync program +Coord[1].TimeBaseSlew=1 //1E-4 is default +Coord[1].DesTimeBase=0 +Coord[1].Q[0]=-3 //motion program started and waits. Arm(-2) is done in triggerSync program +''' self.sync_prg = prg #download and start triggerSync code comm=self.comm if comm is None: return - arg=0 #argument to pass to triggerSync program - if sync_mode==2:arg+=1 #synchronize - arg+=sync_flag*2 #simulated or real triggers - if verbose: arg+=8 - if sync_mode==2 or arg&4: + mode=0 #mode to pass to triggerSync program + if sync_mode==2:mode+=1 #synchronize + mode+=sync_flag*2 #simulated or real triggers + if verbose: mode+=8 + if sync_mode==2 or mode&4: sftp = comm.sftp dst = '/tmp/triggerSync' src = os.path.abspath(os.path.join(os.path.dirname(__file__), 'triggerSync')) sftp.put(src, dst) sftp.chmod(dst, 0o755) cmd = 'LD_LIBRARY_PATH=/opt/ppmac/libppmac/ ' + dst - cmd+=' %g %g %d'%(pt2pt_time,timeOfs,arg) + #cmd+=' %d %g %g %g'%(mode,pt2pt_time,timeOfs,timeCor) + cmd+=' %d %g %g'%(mode,pt2pt_time+timeCor,timeOfs) self.cmdSync = cmd print ('starting '+cmd) self.syncShell=comm.shell_channel(cmd) diff --git a/python/shapepath.py b/python/shapepath.py index fb97d59..9fd0563 100755 --- a/python/shapepath.py +++ b/python/shapepath.py @@ -17,63 +17,36 @@ verbose bits: 0x20 plot pvt trajectory (before motion) 0x40 print sync details -Gather motor order -idx 0 1 2 3 4 5 6 -OLD Motor[3].ActPos Motor[2].ActPos Motor[1].ActPos Motor[3].DesPos Motor[2].DesPos Motor[1].DesPos Gate3[1].Chan[1].UserFlag + if mode&1: + self.plot_trajectory() + + if mode&2: + self.plot_pos_error() + + if mode&4: + self.plot_bode(xy=(3,1),mode=31,db=True) # FX + self.plot_bode(xy=(2,0),mode=31,db=True) # FY + + if mode&8: + self.plot_trigger_jitter() + + +Gather motor order +idx 0 1 2 3 4 NEW Motor[1].ActPos Motor[2].ActPos Motor[1].DesPos Motor[2].DesPos Gate3[1].Chan[1].UserFlag NEW y.ActPos x.ActPos y.DesPos x.DesPos Gate3[1].Chan[1].UserFlag -OLD->NEW -0->none -1->1 -2->0 -3->none -4->3 -5->2 Mot 1: Stage Y Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step Mot 2: Stage X Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step Mot 3: Rotation stage LS Mecapion MDM-DC06DNC0H 32 poles = 1 rev = 16*2048=32768 phase_step Mot 4: Stage X Stada Stepper 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor) Mot 5: Stage Z Stada Stepper 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor) -Enc 6: Interferometer Y -Enc 7: Interferometer X - - -tunnel PowerBrick port locally ------------------------------- -Port 22 on PowerBrick is the ssh server port -Port 2332 on PowerBrick is the gather port of gather_server - -PPMAC=SAR-CPPM-EXPMX1 - -rsync -vai ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/ -ssh root@$PPMAC -LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server - - - -rsync -vai ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp - -ssh -L 10001:localhost:22 root@$PPMAC 'uname -a' -ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a' --> this tunnels port 22 and 2332 of $PPMAC to 10001 and 10002 of localhost -('uname -a' is just to execute a command and return, because the port remains open) - -Tests: -nc localhost 10001 -nc localhost 10002 - -list close ssh tunnel ---------------------- -lsof -i -n | egrep 'ssh' -lsof -i -n | grep '127.0.0.1:1000' - - +s.a. https://docs.google.com/document/d/1soSuCZYyfGf_ntcgG_Y1_WeGuo_687OuFn0s4sMj1uY/ ''' + from __future__ import print_function -#from __future__ import absolute_import,division,generators,nested_scopes,print_function,unicode_literals,with_statement try: raw_input;input=raw_input except NameError: pass @@ -305,7 +278,7 @@ class DebugPlot: hl = ax.plot(pts[:, 0], pts[:, 1], 'r.', label='points') hl += ax.plot(pts[:, 0], pts[:, 1], 'y--', label='direct') hl += ax.plot(rec[:, 3], rec[:, 2], 'b-', label='DesPos') # desired path - hl += ax.plot(rec[:, 1], rec[:, 0], 'g-', label='ActPos') # actual path + hl += ax.plot(rec[:, 1], rec[:, 0], 'g.', label='ActPos') # actual path try: pvt = self.pvt except AttributeError: @@ -333,6 +306,23 @@ class DebugPlot: ax2.legend(loc='best') plt.show(block=False) + def plot_dbg(self): + rec = self.rec # yA,xA,yD,xD,trig + ts=self.meta['srv_per']*self.meta['acq_per'] + fig = plt.figure('debug plot') + ax = fig.add_subplot(1, 1, 1) + t=np.arange(rec.shape[0],dtype=np.uint32) + #address=("Motor[1].ActPos", "Motor[2].ActPos", "Motor[1].DesPos", "Motor[2].DesPos", "Gate3[1].Chan[1].UserFlag","EncTable[20].DeltaPos") + + hl = [] + rec[0, 5]=rec[0, 6]=0 + hl += ax.plot(t, rec[:, 6], 'rx', label='EncTable[20].DeltaPos') + hl += ax.plot(t, rec[:, 5], 'b-', label='Coord[1].TimeBase') + hl += ax.plot(t, rec[:, 4], 'g.', label='Gate3[1].Chan[1].UserFlag') + ax.xaxis.set_label_text('ms (timebase: %g ms per data point)' % ts) + ax.legend(loc='best') + plt.show(block=False) + def plot_gather(self,mode=255): try: meta=self.meta @@ -355,6 +345,10 @@ class DebugPlot: if mode&8: self.plot_trigger_jitter() + #self.plot_dbg() + + + plt.show(block=False) def plot_bode(self,xy=(0,1),mode=25,db=True): @@ -445,8 +439,8 @@ class DebugPlot: plt.show(block=False) def load_npz(self,fn='/tmp/shapepath.npz'): - fh=np.load(fn) - for k,v in fh.iteritems(): + fh=np.load(fn,allow_pickle=True) + for k,v in fh.items(): setattr(self,k,v) self.meta=self.meta.item() @@ -571,15 +565,6 @@ class ShapePath(MotionBase): for x in np.arange(mult)*shift: stack.append(pts+(x,y)) pts=np.vstack(stack) - - - #xx,yy=np.meshgrid(range(w), range(h)) - #pts=np.array([xx.reshape(-1),yy.reshape(-1)],dtype=np.float).transpose()*pitch - #if xy: - #else: - - # smlpitch - #pts+=ofs self.points=pts @@ -654,36 +639,26 @@ class ShapePath(MotionBase): comm=self.comm gt=self.gather gt.set_phasemode(False) - if self.meta['sync_flag']&2: + meta=self.meta + if meta['sync_flag']&2: address=("Motor[1].ActPos","Motor[2].ActPos","Motor[1].DesPos","Motor[2].DesPos","Coord[1].Q[11]") else: address=("Motor[1].ActPos","Motor[2].ActPos","Motor[1].DesPos","Motor[2].DesPos","Gate3[1].Chan[1].UserFlag") - + #address=("Motor[1].ActPos","Motor[2].ActPos","Motor[1].DesPos","Motor[2].DesPos","Gate3[1].Chan[1].UserFlag","EncTable[20].PrevEnc") + #address=("Motor[1].ActPos", "Motor[2].ActPos", "Motor[1].DesPos", "Motor[2].DesPos", "Gate3[1].Chan[1].UserFlag","Coord[1].TimeBase","EncTable[20].DeltaPos") gtMaxLn=gt.set_address(*address) if acq_per is None: ovhdTime=100 - acq_per=int(np.ceil((self.meta['pt2pt_time']*self.points.shape[0]+ovhdTime)/(gtMaxLn*self.meta['srv_per']))) + acq_per=int(np.ceil((meta['pt2pt_time']*self.points.shape[0]+ovhdTime)/(gtMaxLn*meta['srv_per']))) gt.set_property(MaxSamples=1000000, Period=acq_per) #gt.set_property(Period=acq_per) - self.meta.update({'acq_per':acq_per,'address':address}) + meta.update({'acq_per':acq_per,'address':address}) def setup_coord_trf(self,fx='X',fy='Y',cz='0'): # FY:1, FX:2, ROT_Y:3, CX:4, CZ:5, if self.comm is None: return comm = self.comm gpascii = comm.gpascii - prg = '''&1a -#1-> Y -#2-> X -#3-> A -&0#4->0 -&0#5->0 -&0#6->0 -&0#7->0 -#1..3j/ -//#8->0 -//#1..8j/ -''' prg=f'''&1a &1#3->0 &1#4->0 @@ -699,7 +674,6 @@ class ShapePath(MotionBase): #5->{cz} #1,2,5j/ ''' - gpascii.send_block(prg) def setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs): @@ -719,6 +693,22 @@ class ShapePath(MotionBase): numPad : number of padding points to reduce aliasing (default=16) ''' prg=['close all buffers','open prog %d'%(prgId)] + + #Use EncTable 20 as Frame counter + #dont use Coord[1].DesTimeBase as the time base but use the virtual encoder: + # Coord[1].pDesTimeBase=Coord[1].DesTimeBase.a #(default) + prg.append('''\ +EncTable[20].type = 1 //32 Bit uint +EncTable[20].pEnc = Sys.Udata[0].a +EncTable[20].index1 = 0 +EncTable[20].index2 = 0 +EncTable[20].index3 = 0 +EncTable[20].index4 = 0 +EncTable[20].index5 = 0 +EncTable[20].index5 = 0 +EncTable[20].ScaleFactor=1E-3 +//Coord[1].pDesTimeBase=EncTable[20].DeltaPos.a +''') verb=self.verbose comm=self.comm if comm is not None: @@ -768,7 +758,8 @@ class ShapePath(MotionBase): plt.show(block=False) pv[1:-1, (2, 3)]*=CoordFeedTime #scaling for Deltatau - prg.append(' linear abs') + prg.append('linear abs') + #prg.append('X%g Y%g' % tuple(pv[0, (0,1)]-(120,120))) prg.append('X%g Y%g' % tuple(pv[0, (0,1)])) prg.append('dwell 10') try: prg.extend(self.sync_prg.split('\n')) @@ -781,6 +772,10 @@ class ShapePath(MotionBase): prg.append(' pvt%g abs'%pt2pt_time) #100ms to next position for idx in range(1,pv.shape[0]): prg.append('X%g:%g Y%g:%g'%tuple(pv[idx,(0,2,1,3)])) + #if idx%78==10: #sync data all 256 points + # prg.append('Coord[1].Q[12]=Sys.ServoCount') + # #prg.append(f'Coord[1].Q[13]={idx}') + # prg.append(f'Coord[1].Q[13]=Motor[1].DesPos') prg.append('X%g Y%g' % tuple(pv[-1, (0,1)])) if cnt>1: prg.append('dwell 10') @@ -813,6 +808,7 @@ class ShapePath(MotionBase): def gather_upload(self,fnRec=None): gt=self.gather + comm=self.comm gt.wait_stopped(verbose=True) self.rec=rec=gt.upload() @@ -824,23 +820,24 @@ class ShapePath(MotionBase): del self.syncShell pts=self.points - ofsy=-rec[0,2]+pts[0,1] - ofsx=-rec[0,3]+pts[0,0] - rec[:,(1,3)]+=ofsx - rec[:,(0,2)]+=ofsy + + ofsy=comm.gpascii.get_variable("Motor[1].HomePos", type_=float) + ofsx=comm.gpascii.get_variable("Motor[2].HomePos", type_=float) + rec[:,(0,2)]-=ofsy + rec[:,(1,3)]-=ofsx if fnRec: np.savez_compressed(fnRec, rec=rec, pts=pts, meta=self.meta) if __name__=='__main__': - #import logging - #logger = logging.getLogger(__name__) - #logger = logging.getLogger('pbtools.misc.pp_comm') - #logger.setLevel(logging.DEBUG) - #logging.basicConfig(format=('%(asctime)s %(name)-12s ' - # '%(levelname)-8s %(message)s'), - # datefmt='%m-%d %H:%M', - # ) + import logging + _log=logging.getLogger(__name__) + logging.getLogger('pbtools.misc.pp_comm').setLevel(logging.INFO) + logging.getLogger('paramiko').setLevel(logging.WARNING) + logging.getLogger('matplotlib').setLevel(logging.INFO) + #https://docs.python.org/3/library/logging.html#logging.Formatter add %(name)s to identify the logger + logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ') + import argparse def unique_filename(fnBase): i = 0; @@ -854,20 +851,6 @@ if __name__=='__main__': def run_test(args): - #dp=DebugPlot();dp.plot_gather();return - #import socket - #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # create an INET, STREAMing socket - #s.settimeout(.1) - #try: - # port=22 #ssh port - # s.connect((args.host, port)) # try to connect to port - # s.close() - #except (socket.error, socket.gaierror) as e: - # comm=gather=None - #else: - # comm = PPComm(host=args.host) - # gather = Gather(comm) - hpp=args.host.split(':') param={'host':hpp[0]} if len(hpp)>1: @@ -885,7 +868,7 @@ if __name__=='__main__': #sp = ShapePath(comm, gather, args.verbose,sync_mode=0,pt2pt_time=10) #simulated start and frame trigger no sync - sp = ShapePath(comm, gather, args.verbose,sync_mode=1,sync_flag=3) + #sp = ShapePath(comm, gather, args.verbose,sync_mode=1,sync_flag=3) #simulated start and frame trigger with sync #sp = ShapePath(comm, gather, args.verbose,sync_mode=2,sync_flag=3) @@ -894,7 +877,7 @@ if __name__=='__main__': #sp = ShapePath(comm, gather, args.verbose,sync_mode=1,sync_flag=1) #simulated start real frame trigger with sync - #sp = ShapePath(comm, gather, args.verbose,sync_mode=2,sync_flag=1) + sp = ShapePath(comm, gather, args.verbose,sync_mode=2,sync_flag=1) fn='/tmp/shapepath' #fn =unique_filename('ShapePathAnalyser/records/19_01_24/spiral') @@ -927,18 +910,36 @@ if __name__=='__main__': #sp.gen_spiral_points(rStart=100,rInc=130,numSeg=4,numCir=2, ofs=(0, 0)) #sp.gen_grid_points(w=20,h=20,pitch=100,rnd=0,ofs=(0,+2000));sp.sort_points(False); #sp.gen_grid_points(w=5,h=10,pitch=100,rnd=0,ofs=(0,+2000));sp.sort_points(False,10); - sp.gen_grid_points(w=125,h=125,pitch=3,rnd=0,ofs=(0,+2000));sp.sort_points(False,125); sp.meta['pt2pt_time']=5 - + + #sp.gen_grid_points(w=50,h=50,pitch=120,rnd=0,ofs=(0,+2000));sp.sort_points(False,50); sp.meta['pt2pt_time']=10 + #sp.gen_grid_points(w=16,h=16,pitch=120,rnd=0,ofs=(0,+2000));sp.sort_points(False,16); sp.meta['pt2pt_time']=10 + #12.5x12.5 + sp.gen_grid_points(w=78,h=78,pitch=120,rnd=0,ofs=(-10000,-12000));sp.sort_points(False,78); sp.meta['pt2pt_time']=10 + #23.0x23.0 -> only 3 data points from shot to shot: 6,9,12,14,17,20... + #sp.gen_grid_points(w=162,h=162,pitch=120,rnd=0,ofs=(-10000,-12000));sp.sort_points(False,162); sp.meta['pt2pt_time']=10 + #sp.gen_grid_points(w=1,h=10,pitch=100,rnd=0,ofs=(0,0)) #sp.gen_spiral_points(rStart=100,rInc=20,numSeg=8,numCir=32, ofs=(0, 0)) #sp.gen_spiral_points(rStart=100,rInc=10,numSeg=2,numCir=32, phase=45, ofs=(0, 0)) #sp.gen_spiral_points(rStart=100,rInc=10,numSeg=4,numCir=32, ofs=(0, 0)) #sp.gen_closed_shifted() - gtMaxLn=116508;ovhdTime=100 + gtMaxLn=int(sp.comm.gpascii.get_variable('Gather.MaxLines')) # 116508 + if gtMaxLn==0: + sp.setup_gather(acq_per=1) + gtMaxLn=int(sp.comm.gpascii.get_variable('Gather.MaxLines')) # 116508 + + ovhdTime=100 acq_per=int(np.ceil((sp.meta['pt2pt_time']*sp.points.shape[0]+ovhdTime)/(gtMaxLn*sp.meta['srv_per']))) + if args.verbose&0x01: + print(f'''\ +Gather.MaxLines:{gtMaxLn} +Gather.Period: {acq_per} +meta: {sp.meta} +Filename: {fn}.[prg|npz] +''') sp.setup_gather(acq_per=acq_per) - sp.setup_sync(verbose=args.verbose&32,timeOfs=0.05) + sp.setup_sync(verbose=args.verbose&0x40,timeOfs=0.03,timeCor=0.0005) sp.setup_coord_trf() # reset to shape path system #sp.meta['pt2pt_time']=10 #put between setup_sync and setup_motion to have more motion points than FEL syncs sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1.,dwell=10) @@ -946,8 +947,11 @@ if __name__=='__main__': #sp.setup_motion(fnPrg=fn + '.prg', mode=1, scale=0,dwell=10) sp.homing() #homing if needed sp.run() #start motion program + print('wait_armed') sp.wait_armed() # wait until motors are at first position + print('trigger') sp.trigger(0.5) #send a start trigger (if needed) ater given time + print('progress..') if not comm is None: while True: p=sp.progress() @@ -955,55 +959,31 @@ if __name__=='__main__': print('progress %d/%d'%(p,sp.points.shape[0]));time.sleep(.1) sp.gather_upload(fnRec=fn+'.npz') dp=DebugPlot(sp);dp.plot_gather(mode=11) - print('done') plt.show(block=False) input('press return') - - #sp.plot_points(sp.points);plt.show() - - - - #>>>run gather and plot trajectory<<< - #return - - - from optparse import OptionParser, IndentedHelpFormatter - class MyFormatter(IndentedHelpFormatter): - 'helper class for formating the OptionParser' - - def __init__(self): - IndentedHelpFormatter.__init__(self) - - def format_epilog(self, epilog): - if epilog: - return epilog - else: - return "" - def parse_args(): 'main command line interpreter function' - #usage: gpasciiCommunicator.py --host=PPMACZT84 myPowerBRICK.cfg (h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>3 else sys.argv[0])+' ' exampleCmd=('-v15', - '--host=localhost:10001:10002' - ) - epilog=__doc__+''' -Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n ' - - fmt=MyFormatter() - parser=OptionParser(epilog=epilog, formatter=fmt) - - parser.add_option('-v', '--verbose', type="int", dest='verbose', help='verbosity bits (see below)', default=0) - parser.add_option('--host', help='hostname', default='SAR-CPPM-EXPMX1') + '--host=localhost:10001:10002 -v 0x5d', + '--host=localhost:10001:10002 -v 0x59' + ) + epilog=__doc__+'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n ' + parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("-m", "--mode", type=lambda x:int(x, 0), help="mode (see bitmasks) default=0x%(default)x", default=0xff) + parser.add_argument('-v', '--verbose', type=lambda x:int(x, 0), dest='verbose', help='verbosity bits (see below) default=0x%(default)x', default=0x00) + parser.add_argument('--host', help='hostname', default='SAR-CPPM-EXPMX1') #parser.add_option('--host', help='hostname', default='localhost:10001:10002') - #parser.add_option('--host', help='hostname') - (args, other)=parser.parse_args() - args.other=other + args=parser.parse_args() + _log.info('Arguments:{}'.format(args.__dict__)) run_test(args) #------------------ Main Code ---------------------------------- + + #dp=DebugPlot('/tmp/shapepath.npz');dp.plot_gather(mode=11);plt.show() + #exit(0) #ssh_test() ret=parse_args() exit(ret) diff --git a/src/triggerSync/Makefile b/src/triggerSync/Makefile index 4494a19..b8e35fe 100644 --- a/src/triggerSync/Makefile +++ b/src/triggerSync/Makefile @@ -1,12 +1,13 @@ #HOST=MOTTEST-CPPM-CRM0573 HOST=SAR-CPPM-EXPMX1 -XENOMAI_INC_DIR=/opt/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/include -XENOMAI_LIB_DIR=/opt/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/lib +#XENOMAI_INC_DIR=/opt/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/include +#XENOMAI_LIB_DIR=/opt/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/lib + +XENOMAI_INC_DIR=/tmp/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/include +XENOMAI_LIB_DIR=/tmp/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/lib INC=-I/opt/eldk-4.2/PPMAC_rootfs-7-wheezy/opt/ppmac/libppmac -I/opt/eldk-4.2/PPMAC_rootfs-7-wheezy/opt/ppmac/rtpmac -I$(XENOMAI_INC_DIR) - - LIB=-L/opt/eldk-4.2/PPMAC_rootfs-7-wheezy/opt/ppmac/libppmac -lppmac -L/opt/eldk-4.2/PPMAC_rootfs-7-wheezy/usr/local/xenomai-2.6.2.1/lib -lnative -lxenomai -lpthread_rt -lpthread -lrt -ldl CC=/opt/eldk-4.2/usr/bin/ppc_4xxFP-g++ @@ -14,8 +15,15 @@ LD=$(CC) all: triggerSync +triggerSync.o: $(XENOMAI_INC_DIR) + +$(XENOMAI_INC_DIR): + mkdir -p /tmp/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/ + rsync -vai root@$(HOST):/usr/local/xenomai-2.6.2.1/ /tmp/powerpc-465-rootfs/usr/local/xenomai-2.6.2.1/ + + %.o: %.c - $(CC) -g $(INC) -c $^ -o $@ + $(CC) -g $(INC) -c $< -o $@ triggerSync: triggerSync.o $(LD) -g $(LIB) $^ -o $@ diff --git a/src/triggerSync/triggerSync b/src/triggerSync/triggerSync index 1fff13556536e412f4395d469617227bc6493881..0eb681fc829564dd00958f97b2cb570c2f693be6 100755 GIT binary patch delta 12101 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 Ef2X#Jx&QzG delta 10410 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 E1B*u`umAu6 diff --git a/src/triggerSync/triggerSync.c b/src/triggerSync/triggerSync.c index 097b626..9944c36 100644 --- a/src/triggerSync/triggerSync.c +++ b/src/triggerSync/triggerSync.c @@ -33,11 +33,23 @@ extern struct SHM *pshm; static char mode=0; static float mtPt2Pt=40.f; //motion point to point time -static float timeOfs=0.f; //time ofset +static float timeOfs=0.f; //time ofset (start time adjustment) +static float timeCor=0.f; //time correction (frame to frame time adjustment) + #define CLOCK_RES 1e-9 //Clock resolution is 1 ns by default #define SIMFLAG0 (pshm->Coord[1].Q[10]) #define SIMFLAG1 (pshm->Coord[1].Q[11]) + +//EncTable[20].pEnc= Coord[1].Q[12].a does not work +//EncTable[20].pEnc= Sys.Udata[0].a works uint32 +//EncTable[20].pEnc= Sys.Idata[0].a works int32 +//EncTable[20].pEnc= Sys.Fdata[0].a works float32 +//EncTable[20].pEnc= Sys.Ddata[0].a works float64 +//#define ENCVAL (*((double *)pushm+0)) +#define ENCVAL (*((unsigned int *)pushm+0)) + + //#define SIMFLAG0 (pshm->P[10]) //#define SIMFLAG1 (pshm->P[11]) //Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag @@ -76,6 +88,14 @@ void trigsync_func(void *arg) printf("ending trigsync_func because Gather.Enable==0\n"); return; } + + //unsigned int lastQ12=0; //Q12 value for further sync + double mxActPos,mxDesPos,mxHomePos=pshm->Motor[2].HomePos; + double myActPos,myDesPos,myHomePos=pshm->Motor[1].HomePos; + + printf("Wait motion program arrived at start position...\n"); + while(pshm->Coord[1].Q[0]!=-3) + rt_task_wait_period(NULL); pshm->Coord[1].Q[0]=-2; srvPer=pshm->ServoPeriod; @@ -93,29 +113,30 @@ void trigsync_func(void *arg) } printf("Flag 0: %.5f ms\n", (rt_timer_read() - rtStart)/1E6); - pshm->Gather.Enable=2; //start gathering data - pshm->Coord[1].Q[0]=-1; if(mode&4) { + while(SIMFLAG1) + rt_task_wait_period(NULL); while(!SIMFLAG1) rt_task_wait_period(NULL); } else { + while(FLAG1) + rt_task_wait_period(NULL); while(!FLAG1) rt_task_wait_period(NULL); } -//puts("waitFlag1"); -//gate3_1->Chan[1].Status f057f77f -//gate3_1->Chan[1].Status f057ff7f -//printf("gate3_1->Chan[1].Status %x\n",gate3_1->Chan[1].Status); + //FEL shot arrived FLAG1 0->1: first frame trigger before first cristall + pshm->Gather.Enable=2; //start gathering data + pshm->Coord[1].Q[0]=-1; + ENCVAL=0; printf("Flag 1: %.5f ms\n", (rt_timer_read() - rtStart)/1E6); rtStart=rtLast=rt_timer_read(); scStart=scLast=pshm->ServoCount; mtAct=0.f; pshm->Coord[1].Q[0]=0; - srvPer=0.2f; //pshm->Coord[1].DesTimeBase=srvPer; //start motion at default speed pshm->Coord[1].DesTimeBase=srvPer*(mtPt2Pt+timeOfs)/mtPt2Pt; //start motion at default speed if(mode&8) @@ -134,24 +155,53 @@ void trigsync_func(void *arg) else { while(FLAG1) + { rt_task_wait_period(NULL); + ENCVAL=( (i-1)*mtPt2Pt + (pshm->ServoCount-scLast)*srvPer )*1000; + } while(!FLAG1) + { rt_task_wait_period(NULL); + ENCVAL=( (i-1)*mtPt2Pt + (pshm->ServoCount-scLast)*srvPer )*1000; + } } - //FEL shot arrived + //FEL shot arrived FLAG1 0->1 + //ENCVAL+=mtPt2Pt*1000; //ENCVAL in us + ENCVAL=i*mtPt2Pt*1000; //ENCVAL in us rtCur = rt_timer_read(); scCur=pshm->ServoCount; + //if (lastQ12!=(unsigned int)pshm->Coord[1].Q[12]) + //{ + // //'Coord[1].Q[12]=Sys.ServoCount' + // //'Coord[1].Q[13]={idxOfPoint}' + // //type of pshm->Coord[1].Q[12] is double + // lastQ12=(unsigned int)pshm->Coord[1].Q[12]; //saved ServoCount in program code + + // //mxActPos=pshm->Motor[2].ActPos;mxDesPos=pshm->Motor[2].DesPos; + // //myActPos=pshm->Motor[1].ActPos;myDesPos=pshm->Motor[1].DesPos; + + // //printf("*** SYNC *** Trigger count:%d, ProgIdx:%d, ServoCount diff:%d-%d=%d", i, (unsigned int)pshm->Coord[1].Q[13], lastQ12,scCur, lastQ12-scCur); + // printf("*** SYNC *** Trigger count:%d, myDesPos:%.2f, ServoCount diff:%d-%d=%d\n", i, pshm->Coord[1].Q[13]-myHomePos, lastQ12,scCur, lastQ12-scCur); + // //printf(" X,Y ActPos:(%.5g %.5g) DesPos:(%.5g %.5g)\n", mxActPos-mxHomePos, myActPos-myHomePos, mxDesPos-mxHomePos, myDesPos-myHomePos); + //} + rtDiff=rtCur-rtLast; scDiff=scCur-scLast; - mtAct+=scDiff*srvPer; + mtAct+=scDiff*srvPer+timeCor; mtDes=i*mtPt2Pt+timeOfs; srvPer=(mtPt2Pt+mtDes-mtAct)/scDiff; + //srvPer=pshm->ServoPeriod; //default speed pshm->Coord[1].DesTimeBase=srvPer; pshm->Coord[1].Q[0]++; if(mode&8) - printf("Trigger count:%d, rtDiff:%.3fms scDiff:%d mtAct:%.3f mtDes:%.3f srvPer:%.6f\n", i, rtDiff/1E6,scDiff, mtAct,mtDes,srvPer); + { + mxActPos=pshm->Motor[2].ActPos;mxDesPos=pshm->Motor[2].DesPos; + myActPos=pshm->Motor[1].ActPos;myDesPos=pshm->Motor[1].DesPos; + printf(" X,Y ActPos:(%.5g %.5g) DesPos:(%.5g %.5g) ", mxActPos-mxHomePos, myActPos-myHomePos, mxDesPos-mxHomePos, myDesPos-myHomePos); + printf("Trigger count:%d, rtDiff:%.3fms scDiff:%d mtAct:%.3f mtDes:%.3f srvPer:%.6f ENCVAL:%u \n", i, rtDiff/1E6,scDiff, mtAct,mtDes,srvPer,ENCVAL); + } rtLast=rtCur; scLast=scCur; } @@ -163,12 +213,13 @@ void trigsim_func(void *arg) RT_TASK *curtask; RT_TASK_INFO curtaskinfo; int iret = 0; + int loopPeriod=1e7;//Expressed in ticks (this is the default task period) curtask = rt_task_self(); rt_task_inquire(curtask, &curtaskinfo); //Print the info - //printf("Starting task %s with period of %f ms ....\n", curtaskinfo.name,10*1E6/1E6); + printf("Starting task %s with period of %f ms ....\n", curtaskinfo.name,loopPeriod/1E6); //Make the task periodic with a specified loop period - //rt_task_set_periodic(NULL, TM_NOW, 10*1E6); + //rt_task_set_periodic(NULL, TM_NOW, loopPeriod); //not critical here because not polling but rt_task_sleep_until ... printf("Starting task %s \n", curtaskinfo.name); int i,j=0; @@ -180,9 +231,8 @@ void trigsim_func(void *arg) for(i=0,rtSlice=rtStart;;i++) { - rtSlice=rtStart+i*40*1E6; // a slice is 40 ms - //rtSlice=rtStart+i*40.2*1E6; // a slice is 40 ms - //rtSlice+=(rand()%(int)(1*1E6)); //0.1ms jitter + rtSlice=rtStart+i*mtPt2Pt*1E6; // a slice is mtPt2Pt ms + //rtSlice+=(rand()%(int)(1*1E6)); //0.1ms jitter to test sync rt_task_sleep_until(rtSlice); //in ns if(mode&4) { @@ -275,6 +325,11 @@ mode:\n\ bit2:4: simulate frame trigger\n\ bit3:8: verbose\n\ \n\ +pt2ptTime: point to point time in ms (default=10, float value)\n\ +timeOfs: once added time offset in ms (default=0, float value)\n\ +scl: scale factor (so far unused, default=1, float value)\n\ +\n\ +\n\ simulate start trigger:\n\ set pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start\n\ \n\ @@ -297,7 +352,7 @@ Coord[1].Q[0]= 0 : got frame trigger 0\n\ Coord[1].Q[0] is incremented at each trigger\n\ sync task ends when Gather.Enable==0\n\ "; - printf("usage:\n%s pt2ptTime timeOfs mode\n",cmd); + printf("usage:\n%s mode pt2ptTime timeOfs(default=0) scl(default=1)\n",cmd); puts(s); return -1; } @@ -308,22 +363,21 @@ int main(int argc, char *argv[]) int initialized=0; int i; char *s; - if(argc!=4) - return usage(argv[0]); - mtPt2Pt=strtof(argv[1], &s); - if (argv[1]==s) - return usage(argv[0]); - timeOfs=strtof(argv[2], &s); - if (argv[2]==s) - return usage(argv[0]); - mode=(int)strtol(argv[3], &s, 10); - if (argv[3]==s) + if(argc<2) return usage(argv[0]); + mode=(int)strtol(argv[1], &s, 10); + if (argc>2) + mtPt2Pt=strtof(argv[2], &s); + if (argc>3) + timeOfs=strtof(argv[3], &s); + if (argc>4) + timeCor=strtof(argv[4], &s); puts(argv[0]); puts(argv[1]); - puts(argv[2]); - puts(argv[3]); - printf("mtPt2Pt:%g timeOfs:%g mode:%d\n",mtPt2Pt,timeOfs,mode); + //puts(argv[2]); + //puts(argv[3]); + //puts(argv[4]); + printf("mode:%d mtPt2Pt:%3.8gms timeOfs:%3.8gms timeCor:%3.8gms\n",mode,mtPt2Pt,timeOfs,timeCor); if ((err = InitLibrary()) != 0) { abort(); }