From 4b38db8405c45995dc3520dcae39feb9f1fc1494 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Thu, 31 Oct 2024 15:57:26 +0100 Subject: [PATCH] documentation triggerSync with mermaid --- Readme.md | 208 ++++++++++++++++++++++++---- python/MXMotion.py | 14 +- src/triggerSync/Readme.md | 22 ++- src/triggerSync/UnusedSeqDiag.md | 231 +++++++++++++++++++++++++++++++ 4 files changed, 429 insertions(+), 46 deletions(-) create mode 100644 src/triggerSync/UnusedSeqDiag.md diff --git a/Readme.md b/Readme.md index b04f1f3..c2b14f5 100644 --- a/Readme.md +++ b/Readme.md @@ -1,25 +1,23 @@ -Various motor documents ------------------------ -- /home/zamofing_t/Documents/doc-ext/SwissFEL/ESB-MX +PBSwissMX +========= +This repository is used by the SwissMX application.
+A complete list of SwissMX repositories dependencies is shown in [grp-sf_cristallina/SwissMX.git](https://git.psi.ch/grp-sf_cristallina/SwissMX). -Repository structure and dependency (update:23.09.24) ------------------------------------------------------ +PBSwissMX contains python application and executables to: + - generate trajectories and motion programs for SwissMX (`shapepath.py` and `helicalscan.py`[obsolete]) + - motion synchronization executables (`triggerSync`) for Deltatau + - analyse recorded trajectories on SwissMX (`ShapePathAnalyser`) + - motor tuning tools (`MXTuning`) + - documentation about the tuning results (`MXfastStageDoc`) + +motion start/framesynchronization (update31.10.24) +--------------------------------------------------- + +**For more details about triggerSync read: [src/triggerSync/Readme.md](src/triggerSync/Readme.md)** + +#### Important used vaiables: ``` -This repository contains PowerBrick documents and tool to generate trajectories and motion programs for SwissMX - -for more info about SwissMX read: -psigithub git@git.psi.ch:grp-sf_cristallina/SwissMX.git --> ~/Documents/prj/SwissFEL/apps/SwissMX/Readme.md - -For more details about triggerSync read: - ~/Documents/prj/SwissFEL/apps/PBSwissMX/src/triggerSync/Readme.md -``` - -motion/frame synchronization ----------------------------- -``` -s.a. ~/Documents/prj/SwissFEL/apps/PBSwissMX/src/triggerSync/Readme.md - Coord[1].Q[0] : sync points indicator: (at whick point is the motion program) val: desc set in code -3: waiting at start position motion code generated in MXMotion.py:setup_sync(mode=?) @@ -50,18 +48,165 @@ triggerSync.c mode: bit1:2: simulate start trigger bit2:4: simulate frame trigger bit3:8: verbose +``` -Acquisition start event: +### start/frame event system +``` +Start event: sim: Coord[1].Q[10] - EVR: Gate3[1].Chan[0].UserFlag == (gate3_1->Chan[0].Status&0x800) == FrontUnivOut4 -> Pulser0 -> (active Low, 5000us delay 0us) Map: 214 + EVR: Gate3[1].Chan[0].UserFlag == (gate3_1->Chan[0].Status&0x800) == FrontUnivOut4, EPICS MACRO: $(USR_FLAG_ID)=5 + -> Pulser0 -> (active Low, 5000us delay 0us) Map: 214 + -> event 214 is 'ESC multipurpose event. In this case used as: start motion' Frame event: sim: Coord[1].Q[11] - EVR: Gate3[1].Chan[1].UserFlag == (gate3_1->Chan[1].Status&0x800) == FrontUnivOut5 -> Pulser1 -> (active Low, 5000us delay 750us) Map: 40 + EVR: Gate3[1].Chan[1].UserFlag == (gate3_1->Chan[1].Status&0x800) == FrontUnivOut5, EPICS MACRO: $(USR_FLAG_ID)=5 + -> Pulser1 -> (active Low, 5000us delay 750us) Map: 40 + -> event 40 = 'ESA_detector 100 Hz' >>> should be 77='ESC detector' + +unused EVR input?: + EVR: Gate3[1].Chan[2].UserFlag == (gate3_1->Chan[2].Status&0x800) == FrontUnivOut6, EPICS MACRO: $(USR_FLAG_ID)=7 + +!!! Deltatau flags are inverted: FrontUnivOut6(Force Low) -> Gate3[1].Chan[2].UserFlag==1 +``` +|event |simulated |real | +|- |- |- | +|start |Coord[.].Q[10] | Gate3[1].Chan[0].UserFlag | +|frame |Coord[.].Q[11] | Gate3[1].Chan[1].UserFlag | + +**frequence jitter 50Hz Swissgrid:** https://www.swissgrid.ch/de/home/operation/grid-data/current-data.html + +### partial python class diagram of PBSwissMX + +```mermaid +classDiagram +MotionBase <|-- ShapePath +MotionBase <|-- HelicalScan + + class MotionBase { + @MXMotion.py + + setup_sync(self, crdId, prgId, verbose, timeOfs, timeCor) + + homing(self) + + run(self, crdId) + + wait_armed(self, crdId) + + progress(self) + + trigger(self, wait) + } + + class ShapePath { + @shapepath.py + %%- __init__(self, args) None + + setup_gather(self,acq_per=None,numPts=None) + + setup_coord_trf(self,fx='X',fy='Y',cz='0') + + setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs) + + gather_upload(self,fnRec=None) + } + + class HelicalScan { + @helicalscan.py [obsolete] + + setup_gather(self,acq_per=1) + + setup_coord_trf(self,fnCrdTrf='/tmp/coordTrf.cfg') + + setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs) + + gather_upload(self,fnRec=None) + } + + class GenPath { + @shapepath.py + + swissmx(self, flipx, flipy, ofs, width) + + swissfel(self, flipx, flipy, ofs, width) + %%+ rand(self, n, scale, ofs) + + grid(self, w, h, pitch, rnd, ofs) + %%+ spiral(self, rStart, rInc, numSeg, numCir, phase, ofs) + %%+ closed_shifted(self, pitch, shift, mult) + %%+ sort(self, mode, grp_sz) + } ``` -testing shapepath.py in different modes (tunneling) ---------------------------------------------------- +### Simplified Python sequence + +Source for the instance "start/frame event system" can be: + - python code + - timing system (EVR) + - motion code + - triggerSync executable running on Deltatau + +```mermaid +sequenceDiagram + participant es as start/frame
event system + participant py as Python + participant pb as PowerBrick + + Note over py: .setup_sync()
prepare code snipplets + activate py + opt needs triggerSync + Note over es,pb: triggerSync is needed in case of:
simulated start/frame triggers
and/or adjust DesTimeBase + py -) pb: sftp / ssh + Note over pb: sftp triggerSync
run triggerSync + pb ->> es: run triggerSync + end + + Note over py: .setup_coord_trf() + py -) pb: download code + Note over pb: setup coordinate transformation + Note over py: .setup_motion() + py -) pb: generate code
download code + Note over pb: setup motion program + Note over py: .setup_gather() + py -) pb: download code
set gather vars + Note over pb: set addresses to gather
Gather.Enable=1 + Note over py: .homing() + py -)+ pb: download code
run homing PLC + Note over py: wait(Motor[1].HomeComplete) + deactivate py + Note over pb: runs homing PLC [if needed]
enable plc 1 + pb ->>- py: Motor[1].HomeComplete + activate py + Note over py: .run() + py -)+ pb: run motion program + Note over pb: runs motion program 2 in coordSystem 1
&1br2 + Note over pb: move to first point
DesTimeBase=0 (wait motion)
Q[0]=-3 (motion program waiting at start position) + pb ->>- es: Q[0]=-3 + Note over es: Q[0]=-2 (event system armed)
[in motion code or
triggerSync exe] + Note over py: .wait_armed()
wait(Q[0]==-2) # wait until motors are at first position + deactivate py + es ->>+ py: Q[0]=-2 + Note over es: wait for start trigger + Note over py: .trigger() + alt sim start trig + Note over py: Q[10]=1 [send a simulated start trigger
after given time] + py ->> es: Q[10]=1 + else real start trig + es->> es: Gate3[1].Chan[0].UserFlag==1 + end + Note over es: DesTimeBase=Sys.ServoPeriod
[in motion code or
triggerSync exe] + es->>+pb: continue motion + opt adjust time base + Note over es: in thread trigger_sync_func()
of triggerSync exe + es->>es: adjust DesTimeBase + end + Note over pb: pvt10abs
move to all points + loop 10 ms + Note over pb: move to next point + end + opt triggerSync running + pb ->> es: Gather.Enable=0 + Note over es: exit triggerSync exe + end + Note over py: while .progress()
wait(Gather.Enable==0) + deactivate py + Note over pb: end motion program + pb ->>- py: Gather.Enable=0 + activate py + Note over py: .gather_upload() + deactivate py +``` + +------------------------------- +Work log +======== + +??10.24: testing shapepath.py in different modes (tunneling) +----------------------------------------------------------- ``` zamofing_t@ganymede:~$ >>> kill previous tunnels 127.0.0.1:100?? @@ -132,6 +277,19 @@ caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0 Debugging were the coordinate program counter is: &1 list pc,10 - ``` +??.10.24: mermaid tricks and links +--------------------------------- +- https://mermaid.live/ +- https://app.zenuml.com/ +- https://www.mermaidchart.com/ +- https://help.whimsical.com/article/732-sequence-diagrams +- https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-sequence-diagram/ +- https://www.geeksforgeeks.org/unified-modeling-language-uml-sequence-diagrams/ + +``` +pip install pymermaider --user +pymermaider ~/Documents/prj/SwissFEL/apps/PBSwissMX/python -o /tmp +subl /tmp/python.md +``` diff --git a/python/MXMotion.py b/python/MXMotion.py index 99935d0..7e0425b 100644 --- a/python/MXMotion.py +++ b/python/MXMotion.py @@ -99,13 +99,13 @@ class MotionBase: Coord[{crdId}].TimeBaseSlew=1 //1E-4 is default Coord[{crdId}].DesTimeBase=0 Coord[{crdId}].Q[0]=-3 // motion program waiting at start position -Coord[{crdId}].Q[0]=-2 // motion program started and armed -while({flag0}==0){{}} -Coord[{crdId}].Q[0]=-1 -Gather.Enable=2 -while({flag1}==0){{}} -Coord[1].DesTimeBase=Sys.ServoPeriod -Coord[{crdId}].Q[0]=0 // +Coord[{crdId}].Q[0]=-2 // 'start/frame event system' armed (triggerSync not used in these modes) +while({flag0}==0){{}} // wait start trigger +Coord[{crdId}].Q[0]=-1 // start trigger received +Gather.Enable=2 // start acquire date +while({flag1}==0){{}} // wait first frame trigger +Coord[1].DesTimeBase=Sys.ServoPeriod //run motion +Coord[{crdId}].Q[0]=0 // indicates that motion moves to first measurement point ''' else: #sync_mode==2: triggerSync:trigsync_func called prg = f''' diff --git a/src/triggerSync/Readme.md b/src/triggerSync/Readme.md index 73f9a5e..fbb8fed 100644 --- a/src/triggerSync/Readme.md +++ b/src/triggerSync/Readme.md @@ -1,5 +1,8 @@ triggerSync =========== + + + ``` samples: root@:/opt/ppmac# /tmp/triggerSync 40 11 trigger all 40 ms, simulated start, use real frame triggers, verbose @@ -8,37 +11,27 @@ samples: root@:/opt/ppmac# /tmp/triggerSync 40 7 trigger all 40 ms, simulated start and frame triggers, with sync, minimal verbose -For real triggers, deltatau is using flags from the EVR-card: - +//Simulated triggers uses Q variables #define SIMFLAG0 (pshm->Coord[1].Q[10]) #define SIMFLAG1 (pshm->Coord[1].Q[11]) - -//Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag +//real triggers, uses inputsfrom the EVR-card +// s.a. Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag #define FLAG0 (gate3_1->Chan[0].Status&0x800) #define FLAG1 (gate3_1->Chan[1].Status&0x800) - work of triggerSync program: - wait for [SIM]FLAG0 (arm trigger) - once armed, each [SIM]FLAG1 trigger is a frame trigger. -SIMFLAG[0|1] are vairables Coord[1].Q[10] and Coord[1].Q[11] - the EVR flags are set in; caqtdm -attach -macro SYS=SAR-EXPMX,DEVICE=EVR0,FF=PCIe G_EVR_main.ui -FLAG0 == Gate3[1].Chan[0].UserFlag == FrontUnivOut4 -> Pulser0 -> (active Low, 5000us delay 0us) Map: 214 -FLAG1 == Gate3[1].Chan[1].UserFlag == FrontUnivOut5 -> Pulser1 -> (active Low, 5000us delay 750us) Map: 40 - -Pulser 0: event 214 is 'ESC multipurpose event. In this case used as: start motion' -Pulser 1: maps event 40 = 'ESA_detector 100 Hz' >>> should be 77='ESC detector' - event 214 is set with the CTA. For tests one can set manually caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 9 # Force High(0) -> arm event, before start motion caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 8 # Force Low(1) -> trigger motion caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0 # set back to Pulser 0 -> reset for CTA usage -This are values how they should be: +Here values as they were set (??.10.24): caget SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-RB SAR-EXPMX-EVR0:FrontUnivOut5-Src-Pulse-RB \ SAR-EXPMX-EVR0:Pul0-Polarity-Sel SAR-EXPMX-EVR0:Pul0-Delay-RB SAR-EXPMX-EVR0:Pul0-Width-RB \ SAR-EXPMX-EVR0:Pul1-Polarity-Sel SAR-EXPMX-EVR0:Pul1-Delay-RB SAR-EXPMX-EVR0:Pul1-Width-RB \ @@ -108,3 +101,4 @@ caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0 Gather.Enable=0 # end triggerSync ``` + diff --git a/src/triggerSync/UnusedSeqDiag.md b/src/triggerSync/UnusedSeqDiag.md new file mode 100644 index 0000000..77773dc --- /dev/null +++ b/src/triggerSync/UnusedSeqDiag.md @@ -0,0 +1,231 @@ + +Detailed Python sequence +```mermaid +sequenceDiagram + participant ts as TimingSystem + participant py as Python + participant pb as PowerBrick + + activate py + Note over py: .setup_sync()
prepare code snipplets + py -)+ pb: sftp / ssh + Note over pb: sftp triggerSync
run triggerSync + pb --)- py: done + Note over py: .setup_coord_trf() + py -)+ pb: download code + Note over pb: setup coordinate transformation + pb --)- py: done + Note over py: .setup_motion() + py -)+ pb: generate code
download code + Note over pb: setup motion program + pb --)- py: done + Note over py: .setup_gather() + py -)+ pb: download code + Note over pb: set addresses to gather
Gather.Enable=1 + pb --)- py: done + Note over py: .homing() + py -)+ pb: download code + Note over pb: runs homing PLC [if needed]
enable plc 1 + pb --) py: done + Note over py: wait(Motor[1].HomeComplete) + deactivate py + pb ->>- py: HomeComplete + activate py + Note over py: .run() + py -)+ pb: .run() + Note over pb: runs motion program 2 in coordSystem 1
&1br2 + pb --) py: done + Note over py: .wait_armed()
wait(Q[0]==-2) # wait until motors are at first position + deactivate py + Note over pb: move to first point
DesTimeBase=0 (wait motion)
Q[0]=-2 (motion armed) + pb ->>- py: Q[0]=-2 done + activate py + Note over py: .trigger() #send a start trigger (if needed) after given time + Note over pb: wait for the start trigger + alt simulated trigger + Note over py:Q[10]=1 + py-)+pb: start trigger + Note over pb: DesTimeBase=Sys.ServoPeriod + else real trigger + ts-)pb: start trigger
triggerSync:DesTimeBase=Sys.ServoPeriod + end + Note over pb: pvt10abs
move to all points + Note over py: while .progress()
wait(Gather.Enable==0) + deactivate py + loop 10 ms + Note over pb: move to next point + end + Note over pb: Gather.Enable=0 + pb ->>- py: Gather.Enable=0 + activate py + Note over py: .gather_upload() + deactivate py +``` + +more detailed sequence trial 1 +```mermaid +sequenceDiagram + participant py as Python + participant pb as PowerBrick + + Note over py: .setup_sync() + create participant ts as TriggerSync + py -)+ ts: .setup_sync() + create participant tsync as triggersync_func() + ts -) tsync: start thread + create participant tsim as trig_sim_func() + ts -) tsim: ? if sync_mode&2 then start thread + deactivate ts + + Note over py: .setup_coord_trf()
shapepath.py + py -)+ pb: download code + pb --)- py: done + Note over py: .setup_motion()
shapepath.py + py -)+ pb: generate code
download code + pb --)- py: done + Note over py: .setup_gather() + Note over py, pb: calls set_address(*address)
that sets also Gather.Enable=1. + py -)+ pb: download code + Note over pb: Gather.Enable=1 + pb --)- py: done + Note over py: .homing() + py -)+ pb: download code + pb --) py: done + Note over pb: runs homing PLC if needed
enable plc 1 + Note over py: wait(Motor[1].HomeComplete) + pb ->>- py: HomeComplete + Note over py: .run() + py -)+ pb: .run() + pb --)- py: done + Note over pb: runs motion program 2 in coordSystem 1
&1br2
move to first point
DesTimeBase=0 (wait motion) + Note over tsync: wait(Q[0]==-3) + pb -)+ tsync: Q[0]=-3 + Note over py: MXMotion.py:.wait_armed()
wait(Q[0]==-2) + tsync -)+ py: Q[0]=-2 + Note over py: MXMotion.py:.trigger()
if sync_mode&1 then Q[10]=1 + deactivate py + + tsync -)+ pb: DesTimeBase=ServoPerion + loop aaa + tsync ->> tsync:adjust DesTimeBase
while Gather.Enable!=0 + end + activate tsim + loop bbb + tsim ->> tsim:simulate start and frame triggers + end + deactivate tsim + + Note over pb: pvt10abs
move to all points + Note over pb: Gather.Enable=0 + Note over py: while .progress()
wait(Gather.Enable==0) + pb -)+ py: Gather.Enable=0 + pb -)- tsync: Gather.Enable=0 + + Note over py: shapepath.py:.gather_upload() + Note over ts: wait threds finished + activate ts + + deactivate tsync + destroy tsync + tsync -x ts: thread finished + destroy tsim + tsim -x ts: thread finished + deactivate ts + deactivate py + + box rgba(196,196,224,.3) TriggerSync executable + participant ts + participant tsim + participant tsync + end +``` +more detailed sequence simulated trigger and speed adjustment +```mermaid +sequenceDiagram + participant py as Python + participant pb as PowerBrick + participant ts as TimingSystem + + activate py + Note over py: .setup_sync()
prepare code snipplets + py -)+ pb: sftp / ssh + Note over pb: sftp triggerSync
run triggerSync + pb --)- py: done + Note over py: .setup_sync() + create participant tgss as TriggerSync + py -)+ tgss: .setup_sync() + create participant tsync as triggersync_func() + tgss ->> tsync: start thread + opt if sync_mode&2 + create participant tsim as trig_sim_func() + tgss ->>- tsim: start thread + end +# deactivate tgss + + + + Note over py: .setup_coord_trf() + py -)+ pb: download code + Note over pb: setup coordinate transformation + pb --)- py: done + Note over py: .setup_motion() + py -)+ pb: generate code
download code + Note over pb: setup motion program + pb --)- py: done + Note over py: .setup_gather() + py -)+ pb: download code + Note over pb: set addresses to gather
Gather.Enable=1 + pb --)- py: done + Note over py: .homing() + py -)+ pb: download code + Note over pb: runs homing PLC [if needed]
enable plc 1 + pb --) py: done + Note over py: wait(Motor[1].HomeComplete) + deactivate py + pb -)- py: HomeComplete + activate py + Note over py: .run() + py -)+ pb: .run() + Note over pb: runs motion program 2 in coordSystem 1
&1br2 + pb --) py: done + Note over py: .wait_armed()
wait(Q[0]==-2) # wait until motors are at first position + deactivate py + Note over pb: move to first point
DesTimeBase=0 (wait motion)
Q[0]=-3 (motion program waiting at start position) + + pb -) tsync: Q[0]=-3 (motion program waiting at start position) + + pb -)- py: Q[0]=-2 done + activate py + Note over py: .trigger() #send a start trigger (if needed) after given time + Note over pb: wait for the start trigger + Note over py:Q[10]=1 + py-)+pb: start trigger + Note over pb: DesTimeBase=Sys.ServoPeriod + Note over pb: pvt10abs
move to all points + Note over py: while .progress()
wait(Gather.Enable==0) + deactivate py + loop 10 ms + Note over pb: move to next point + end + #activate tsync + #activate tsim + tgss->>tsync: Wait for tsync to Finish + tgss->>tsim: Wait for tsim to Finish + + Note over pb: Gather.Enable=0 + pb -) py: Gather.Enable=0 + pb -) tsync: Gather.Enable=0 + pb -)- tsim: Gather.Enable=0 + + destroy tsync + tsync-->>tgss: exit triggersync_func() thread + destroy tsim + tsim-->>tgss: exit triggersync_func() thread + destroy tgss + tsync-->tgss: Exit Main Thread + + activate py + Note over py: .gather_upload() + deactivate py + +```