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
This commit is contained in:
190
Readme.md
190
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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 $@
|
||||
|
||||
Binary file not shown.
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user