diff --git a/Makefile b/Makefile index 7a4a1db..2ede947 100644 --- a/Makefile +++ b/Makefile @@ -9,3 +9,8 @@ EXCLUDE_VERSIONS+=3 7.0.5 7.0.6 SCRIPTS += axis_sm.plc_inc SCRIPTS += axis_kin_slit.plc_inc SCRIPTS += axis_kin_mirror.plc_inc +SCRIPTS += axis_kin_2DoF.plc_inc +SCRIPTS += axis_kin_3DoF.plc_inc +SCRIPTS += axis_kin_4DoF.plc_inc +SCRIPTS += axis_kin_5DoF.plc_inc +SCRIPTS += axis_kin_6DoF.plc_inc diff --git a/axis_kin_2DoF.plc_inc b/axis_kin_2DoF.plc_inc new file mode 100644 index 0000000..33ab335 --- /dev/null +++ b/axis_kin_2DoF.plc_inc @@ -0,0 +1,13 @@ +#- Slave axes (normally physical/real axes): AX_S1, AX_S2 +var SLAVE_AXES[2] := {ax${AX_S1}.enc.actpos, ax${AX_S2}.enc.actpos}; + +#- Master axes (normally virtual axes): AX_M1, AX_M2 +var MASTER_AXES[2] := {ax${AX_M1}.traj.setpos, ax${AX_M2}.traj.setpos}; + +#- forward kinematics +ax${AX_M1}.enc.actpos := dot(FWD1, SLAVE_AXES); +ax${AX_M2}.enc.actpos := dot(FWD2, SLAVE_AXES); + +#- inverse kinematics +ax${AX_S1}.traj.extsetpos := dot(INV1, MASTER_AXES); +ax${AX_S2}.traj.extsetpos := dot(INV2, MASTER_AXES); diff --git a/axis_kin_3DoF.plc_inc b/axis_kin_3DoF.plc_inc new file mode 100644 index 0000000..1b563f3 --- /dev/null +++ b/axis_kin_3DoF.plc_inc @@ -0,0 +1,16 @@ + +#- Slave axes (normally physical/real axes): AX_S1, AX_S2, AX_S3 +var SLAVE_AXES[3] := {ax${AX_S1}.enc.actpos, ax${AX_S2}.enc.actpos, ax${AX_S3}.enc.actpos}; + +#- Master axes (normally virtual axes): AX_M1, AX_M2, AX_M3 +var MASTER_AXES[3] := {ax${AX_M1}.traj.setpos, ax${AX_M2}.traj.setpos, ax${AX_M3}.traj.setpos}; + +#- forward kinematics +ax${AX_M1}.enc.actpos := dot(FWD1, SLAVE_AXES); +ax${AX_M2}.enc.actpos := dot(FWD2, SLAVE_AXES); +ax${AX_M3}.enc.actpos := dot(FWD3, SLAVE_AXES); + +#- inverse kinematics +ax${AX_S1}.traj.extsetpos := dot(INV1, MASTER_AXES); +ax${AX_S2}.traj.extsetpos := dot(INV2, MASTER_AXES); +ax${AX_S3}.traj.extsetpos := dot(INV3, MASTER_AXES); diff --git a/axis_kin_4DoF.plc_inc b/axis_kin_4DoF.plc_inc new file mode 100644 index 0000000..832b40d --- /dev/null +++ b/axis_kin_4DoF.plc_inc @@ -0,0 +1,18 @@ + +#- Slave axes (normally physical/real axes): AX_S1, AX_S2, AX_S3, AX_S4 +var SLAVE_AXES[4] := {ax${AX_S1}.enc.actpos, ax${AX_S2}.enc.actpos, ax${AX_S3}.enc.actpos, ax${AX_S4}.enc.actpos}; + +#- Master axes (normally virtual axes): AX_M1, AX_M2, AX_M3, AX_M4 +var MASTER_AXES[4] := {ax${AX_M1}.traj.setpos, ax${AX_M2}.traj.setpos, ax${AX_M3}.traj.setpos, ax${AX_M4}.traj.setpos}; + +#- forward kinematics +ax${AX_M1}.enc.actpos := dot(FWD1, SLAVE_AXES); +ax${AX_M2}.enc.actpos := dot(FWD2, SLAVE_AXES); +ax${AX_M3}.enc.actpos := dot(FWD3, SLAVE_AXES); +ax${AX_M4}.enc.actpos := dot(FWD4, SLAVE_AXES); + +#- inverse kinematics +ax${AX_S1}.traj.extsetpos := dot(INV1, MASTER_AXES); +ax${AX_S2}.traj.extsetpos := dot(INV2, MASTER_AXES); +ax${AX_S3}.traj.extsetpos := dot(INV3, MASTER_AXES); +ax${AX_S4}.traj.extsetpos := dot(INV4, MASTER_AXES); diff --git a/axis_kin_5DoF.plc_inc b/axis_kin_5DoF.plc_inc new file mode 100644 index 0000000..88e38fa --- /dev/null +++ b/axis_kin_5DoF.plc_inc @@ -0,0 +1,20 @@ + +#- Slave axes (normally physical/real axes): AX_S1, AX_S2, AX_S3, AX_S4, AX_S5 +var SLAVE_AXES[5] := {ax${AX_S1}.enc.actpos, ax${AX_S2}.enc.actpos, ax${AX_S3}.enc.actpos, ax${AX_S4}.enc.actpos, ax${AX_S5}.enc.actpos}; + +#- Master axes (normally virtual axes): AX_M1, AX_M2, AX_M3, AX_M4, AX_M5 +var MASTER_AXES[5] := {ax${AX_M1}.traj.setpos, ax${AX_M2}.traj.setpos, ax${AX_M3}.traj.setpos, ax${AX_M4}.traj.setpos, ax${AX_M5}.traj.setpos}; + +#- forward kinematics +ax${AX_M1}.enc.actpos := dot(FWD1, SLAVE_AXES); +ax${AX_M2}.enc.actpos := dot(FWD2, SLAVE_AXES); +ax${AX_M3}.enc.actpos := dot(FWD3, SLAVE_AXES); +ax${AX_M4}.enc.actpos := dot(FWD4, SLAVE_AXES); +ax${AX_M5}.enc.actpos := dot(FWD5, SLAVE_AXES); + +#- inverse kinematics +ax${AX_S1}.traj.extsetpos := dot(INV1, MASTER_AXES); +ax${AX_S2}.traj.extsetpos := dot(INV2, MASTER_AXES); +ax${AX_S3}.traj.extsetpos := dot(INV3, MASTER_AXES); +ax${AX_S4}.traj.extsetpos := dot(INV4, MASTER_AXES); +ax${AX_S5}.traj.extsetpos := dot(INV5, MASTER_AXES); diff --git a/axis_kin_6DoF.plc_inc b/axis_kin_6DoF.plc_inc new file mode 100644 index 0000000..94bc37b --- /dev/null +++ b/axis_kin_6DoF.plc_inc @@ -0,0 +1,22 @@ + +#- Slave axes (normally physical/real axes): AX_S1, AX_S2, AX_S3, AX_S4, AX_S5, AX_S6 +var SLAVE_AXES[6] := {ax${AX_S1}.enc.actpos, ax${AX_S2}.enc.actpos, ax${AX_S3}.enc.actpos, ax${AX_S4}.enc.actpos, ax${AX_S5}.enc.actpos, ax${AX_S6}.enc.actpos}; + +#- Master axes (normally virtual axes): AX_M1, AX_M2, AX_M3, AX_M4, AX_M5, AX_M6 +var MASTER_AXES[6] := {ax${AX_M1}.traj.setpos, ax${AX_M2}.traj.setpos, ax${AX_M3}.traj.setpos, ax${AX_M4}.traj.setpos, ax${AX_M5}.traj.setpos, ax${AX_M6}.traj.setpos}; + +#- forward kinematics +ax${AX_M1}.enc.actpos := dot(FWD1, SLAVE_AXES); +ax${AX_M2}.enc.actpos := dot(FWD2, SLAVE_AXES); +ax${AX_M3}.enc.actpos := dot(FWD3, SLAVE_AXES); +ax${AX_M4}.enc.actpos := dot(FWD4, SLAVE_AXES); +ax${AX_M5}.enc.actpos := dot(FWD5, SLAVE_AXES); +ax${AX_M6}.enc.actpos := dot(FWD6, SLAVE_AXES); + +#- inverse kinematics +ax${AX_S1}.traj.extsetpos := dot(INV1, MASTER_AXES); +ax${AX_S2}.traj.extsetpos := dot(INV2, MASTER_AXES); +ax${AX_S3}.traj.extsetpos := dot(INV3, MASTER_AXES); +ax${AX_S4}.traj.extsetpos := dot(INV4, MASTER_AXES); +ax${AX_S5}.traj.extsetpos := dot(INV5, MASTER_AXES); +ax${AX_S6}.traj.extsetpos := dot(INV6, MASTER_AXES); diff --git a/axis_kin_mirror.plc_inc b/axis_kin_mirror.plc_inc index 8897c6f..b7a0cbf 100644 --- a/axis_kin_mirror.plc_inc +++ b/axis_kin_mirror.plc_inc @@ -16,4 +16,4 @@ ax${AX_Y1}.traj.extsetpos := dot(INV1, VIRT_AXES); ax${AX_Y2}.traj.extsetpos := dot(INV2, VIRT_AXES); ax${AX_Y3}.traj.extsetpos := dot(INV3, VIRT_AXES); ax${AX_X1}.traj.extsetpos := dot(INV4, VIRT_AXES); -ax${AX_X2}.traj.extsetpos := dot(INV5, VIRT_AXES); \ No newline at end of file +ax${AX_X2}.traj.extsetpos := dot(INV5, VIRT_AXES); diff --git a/example/slit/cfg/EPICSVERSION b/example/slit_equations/cfg/EPICSVERSION similarity index 100% rename from example/slit/cfg/EPICSVERSION rename to example/slit_equations/cfg/EPICSVERSION diff --git a/example/slit/cfg/axis_ax5_LO.yaml b/example/slit_equations/cfg/axis_ax5_LO.yaml similarity index 100% rename from example/slit/cfg/axis_ax5_LO.yaml rename to example/slit_equations/cfg/axis_ax5_LO.yaml diff --git a/example/slit/cfg/axis_ax6_HI.yaml b/example/slit_equations/cfg/axis_ax6_HI.yaml similarity index 100% rename from example/slit/cfg/axis_ax6_HI.yaml rename to example/slit_equations/cfg/axis_ax6_HI.yaml diff --git a/example/slit/cfg/axis_main.plc b/example/slit_equations/cfg/axis_main.plc similarity index 100% rename from example/slit/cfg/axis_main.plc rename to example/slit_equations/cfg/axis_main.plc diff --git a/example/slit_equations/cfg/axis_main_matrix.plc b/example/slit_equations/cfg/axis_main_matrix.plc new file mode 100644 index 0000000..c503e95 --- /dev/null +++ b/example/slit_equations/cfg/axis_main_matrix.plc @@ -0,0 +1,31 @@ +/* Forward kinematics to calculate virtual axes from real axes + | CEN | = FWD * | S1_LO | + | GAP | | S2_HI | + + Equations: + ax${AX_CEN}.enc.actpos:=(ax${AX_LO}.enc.actpos+ax${AX_HI}.enc.actpos)/2; + ax${AX_GAP}.enc.actpos:=ax${AX_HI}.enc.actpos-ax${AX_LO}.enc.actpos; +*/ + +var FWD1[2] := {0.5, 0.5}; +var FWD2[2] := { -1, 1 }; + +/* Inverse kinematics to calculate real axes from virtal axes + | S1_LO | = INV * | CEN | + | S2_HI | | GAP | + + Equations: + ax${AX_LO}.traj.extsetpos:=ax${AX_CEN}.traj.setpos-ax${AX_GAP}.traj.setpos/2; + ax${AX_HI}.traj.extsetpos:=ax${AX_CEN}.traj.setpos+ax${AX_GAP}.traj.setpos/2; +*/ + +var INV1[2] := { 1, -0.5}; +var INV2[2] := { 1, 0.5}; + +####### Kinematics for slit system. +# Macros cannot be used in an include. In order to find files, the loadPLCFile.cmd parameter "INC" defines the dirs that MSI will look for the file) +include "axis_kin_2DoF.plc_inc" + +####### State machine +# Macros cannot be used in an include. In order to find files, the loadPLCFile.cmd parameter "INC" defines the dirs that MSI will look for the file) +include "axis_sm.plc_inc" diff --git a/example/slit/cfg/axis_vax5_YCEN.yaml b/example/slit_equations/cfg/axis_vax5_YCEN.yaml similarity index 100% rename from example/slit/cfg/axis_vax5_YCEN.yaml rename to example/slit_equations/cfg/axis_vax5_YCEN.yaml diff --git a/example/slit/cfg/axis_vax6_YGAP.yaml b/example/slit_equations/cfg/axis_vax6_YGAP.yaml similarity index 100% rename from example/slit/cfg/axis_vax6_YGAP.yaml rename to example/slit_equations/cfg/axis_vax6_YGAP.yaml diff --git a/example/slit/readme.md b/example/slit_equations/readme.md similarity index 100% rename from example/slit/readme.md rename to example/slit_equations/readme.md diff --git a/example/slit/startup.script b/example/slit_equations/startup.script similarity index 100% rename from example/slit/startup.script rename to example/slit_equations/startup.script diff --git a/example/slit/startup.script_ecmc b/example/slit_equations/startup.script_ecmc similarity index 100% rename from example/slit/startup.script_ecmc rename to example/slit_equations/startup.script_ecmc diff --git a/example/slit_equations/startup_matrix.script_ecmc b/example/slit_equations/startup_matrix.script_ecmc new file mode 100644 index 0000000..96d718b --- /dev/null +++ b/example/slit_equations/startup_matrix.script_ecmc @@ -0,0 +1,85 @@ +#- Configuration scripts +require ecmccfg,"ENG_MODE=1,EC_RATE=100" + +#- Components lib +require ecmccomp + +#- Syncronization configs +require ecmc_master_slave sandst_a + +#- Only output errors +asynSetTraceMask(${ECMC_ASYN_PORT}, -1, 0x01) + + +#- ############################################################################ +#- add slaves +#- list of slaves (4 axis test motion box) +# Master0 +# 0 0:0 PREOP + EK1100 EtherCAT-Koppler (2A E-Bus) +# 1 0:1 PREOP + EL9227-5500 �berstromschutz 24V DC, 2K., max. 10A (Summe), eins +# 2 0:2 PREOP + EL5042 2Ch. BiSS-C Encoder +# 3 0:3 PREOP + EL5042 2Ch. BiSS-C Encoder +# 4 0:4 PREOP + EL3204 4K. Ana. Eingang PT100 (RTD) +# 5 0:5 PREOP + EL2008 8K. Dig. Ausgang 24V, 0.5A +# 6 0:6 PREOP + EL1008 8K. Dig. Eingang 24V, 3ms +# 7 0:7 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 8 0:8 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 9 0:9 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 10 0:10 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# + +# 0:0 - EK1100 EtherCAT coupler +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EK1100" + +# 0:1 - EL9227-5500 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL9227-5500" + +# 0:2 - EL5042 2Ch BiSS-C Encoder +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL5042" + +# 0:3 - EL5042 2Ch BiSS-C Encoder +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL5042" + +# 0:4 - EL3204 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL3204" + +# 0:5 - EL2008 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL2008" + +# 0:6 - EL1008 8K. Dig. Eingang 24V, 3ms +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL1008" + +# 0:7 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" +${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper,MACROS='I_MAX_MA=1000,I_STDBY_MA=500,U_NOM_MV=48000,R_COIL_MOHM=1230'" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_ax5_LO.yaml, DRV_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_CHANNEL=01" + +# 0:8 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" +${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper,MACROS='I_MAX_MA=1000,I_STDBY_MA=500,U_NOM_MV=48000,R_COIL_MOHM=1230'" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_ax6_HI.yaml, DRV_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_CHANNEL=01" + +# 0:9 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" + +# 0:10 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" + +#- ################################################################# +#- Virtual axes +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_vax5_YCEN.yaml, AX_ID=${AX_NUM=12}" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_vax6_YGAP.yaml, AX_ID=${AX_NUM=13}" + +#- ################################################################# +#- PLCs with inverse kinematics (note the INC var including dirs to search for include files) +#- The group ID:s configured in yaml are stored in GRP__ID +${SCRIPTEXEC} ${ecmccfg_DIR}loadPLCFile.cmd, "FILE=./cfg/axis_main_matrix.plc, PLC_ID=1, INC=.:${ecmc_master_slave_DIR}, PLC_MACROS='PLC_ID=1, AX_M1=12, AX_M2=13, AX_S1=5, AX_S2=6, GRP_ID_RA=${GRP_realAxes_ID}, GRP_ID_VA=${GRP_virtualAxes_ID}'" + +#- ################################################################# +#- go active +${SCRIPTEXEC} ${ecmccfg_DIR}applyConfig.cmd +${SCRIPTEXEC} ${ecmccfg_DIR}setAppMode.cmd + +#- ############################################################################# +#- reset all errors +afterInit("ecmcConfigOrDie 'ControllerErrorReset()'") diff --git a/example/slit_matrix/cfg/EPICSVERSION b/example/slit_matrix/cfg/EPICSVERSION new file mode 100644 index 0000000..2f2974f --- /dev/null +++ b/example/slit_matrix/cfg/EPICSVERSION @@ -0,0 +1 @@ +7.0.7 diff --git a/example/slit_matrix/cfg/axis_ax5_LO.yaml b/example/slit_matrix/cfg/axis_ax5_LO.yaml new file mode 100644 index 0000000..423b75c --- /dev/null +++ b/example/slit_matrix/cfg/axis_ax5_LO.yaml @@ -0,0 +1,79 @@ +# https://paulscherrerinstitute.github.io/ecmccfg/manual/axis/axisyaml/ + +axis: + id: 5 + group: realAxes + mode: CSV + features: + allowSrcChangeWhenEnabled: true + +epics: + name: TR_LO + precision: 4 + unit: mm + motorRecord: + description: "Low" + fieldInit: "SPAM=0,RTRY=1,FOFF=Frozen,TWV=1" + +drive: + numerator: 10 # max velo in EGU/s + denominator: 32768 # MAX_INT for a 16-bit register, always this for this stepper drive! + type: 0 + control: ec0.s$(DRV_SLAVE).driveControl01 + status: ec0.s$(DRV_SLAVE).driveStatus01 + setpoint: ec0.s$(DRV_SLAVE).velocitySetpoint01 + +encoder: + numerator: 1 # 1egu = 1mm + denominator: 12800 # Number of ticks when motor moves numerator (=1mm): 1 mm / 50 nm = 20000 + type: 0 # Type: 0=Incremental, 1=Absolute + bits: 16 # Total bit count of encoder raw data + absBits: 0 # Absolute bit count (for abs enc) always least significant part of 'bits' + absOffset: 0.0000 # Encoder offset in eng units (for absolute encoders) + position: ec0.s$(ENC_SLAVE).positionActual$(ENC_CHANNEL) + +controller: + Kp: 10.00 + Ki: 0.001 + Kd: 0.000 + Kff: 1.00 + +trajectory: + axis: + velocity: 1.0 + acceleration: 1.0 + deceleration: 1.0 + +input: + limit: + forward: ec0.s$(DRV_SLAVE).driveStatus01.12 # 1119994 cnts // 55.9997 mm + backward: ec0.s$(DRV_SLAVE).driveStatus01.11 # 98010 cnts // 4.9005 mm + home: ec0.s$(DRV_SLAVE).ONE.0 # unused + interlock: ec0.s$(DRV_SLAVE).ONE.0 # unused + +softlimits: + enable: false + backwardEnable: true + forwardEnable: true + forward: 55.8 + backward: 5.1 + +monitoring: + lag: + enable: true + tolerance: 0.05 + time: 100 + target: + enable: true + tolerance: 0.05 + time: 100 + velocity: + enable: true + max: 5 + time: + trajectory: 100 + drive: 200 + +plc: + enable: true + externalCommands: true diff --git a/example/slit_matrix/cfg/axis_ax6_HI.yaml b/example/slit_matrix/cfg/axis_ax6_HI.yaml new file mode 100644 index 0000000..4e921f9 --- /dev/null +++ b/example/slit_matrix/cfg/axis_ax6_HI.yaml @@ -0,0 +1,79 @@ +# https://paulscherrerinstitute.github.io/ecmccfg/manual/axis/axisyaml/ + +axis: + id: 6 + group: realAxes + mode: CSV + features: + allowSrcChangeWhenEnabled: true + +epics: + name: TR_HI + precision: 4 + unit: mm + motorRecord: + description: "Hi" + fieldInit: "SPAM=0,RTRY=1,FOFF=Frozen,TWV=1" + +drive: + numerator: 10 # max velo in EGU/s + denominator: 32768 # MAX_INT for a 16-bit register, always this for this stepper drive! + type: 0 + control: ec0.s$(DRV_SLAVE).driveControl01 + status: ec0.s$(DRV_SLAVE).driveStatus01 + setpoint: ec0.s$(DRV_SLAVE).velocitySetpoint01 + +encoder: + numerator: 1 # 1egu = 1mm + denominator: 12800 # Number of ticks when motor moves numerator (=1mm): 1 mm / 50 nm = 20000 + type: 0 # Type: 0=Incremental, 1=Absolute + bits: 16 # Total bit count of encoder raw data + absBits: 0 # Absolute bit count (for abs enc) always least significant part of 'bits' + absOffset: 0.0000 # Encoder offset in eng units (for absolute encoders) + position: ec0.s$(ENC_SLAVE).positionActual$(ENC_CHANNEL) + +controller: + Kp: 2.000 + Ki: 0.001 + Kd: 0.000 + Kff: 1.00 + +trajectory: + axis: + velocity: 1.0 + acceleration: 1.0 + deceleration: 1.0 + +input: + limit: + forward: ec0.s$(DRV_SLAVE).driveStatus01.12 # 1111969 cnts // 55.5984 mm + backward: ec0.s$(DRV_SLAVE).driveStatus01.11 # 109007 cnts // 5.4504 mm + home: ec0.s$(DRV_SLAVE).ONE.0 # unused + interlock: ec0.s$(DRV_SLAVE).ONE.0 # unused + +softlimits: + enable: false + backwardEnable: true + forwardEnable: true + forward: 55.4 + backward: 5.7 + +monitoring: + lag: + enable: true + tolerance: 0.05 + time: 100 + target: + enable: true + tolerance: 0.05 + time: 100 + velocity: + enable: true + max: 5 + time: + trajectory: 100 + drive: 200 + +plc: + enable: true + externalCommands: true diff --git a/example/slit_matrix/cfg/axis_main.plc b/example/slit_matrix/cfg/axis_main.plc new file mode 100755 index 0000000..b241a07 --- /dev/null +++ b/example/slit_matrix/cfg/axis_main.plc @@ -0,0 +1,8 @@ + +####### Kinematics for slit system. +# Macros cannot be used in an include. In order to find files, the loadPLCFile.cmd parameter "INC" defines the dirs that MSI will look for the file) +include "axis_kin_slit.plc_inc" + +####### State machine +# Macros cannot be used in an include. In order to find files, the loadPLCFile.cmd parameter "INC" defines the dirs that MSI will look for the file) +include "axis_sm.plc_inc" diff --git a/example/slit_matrix/cfg/axis_main_matrix.plc b/example/slit_matrix/cfg/axis_main_matrix.plc new file mode 100644 index 0000000..c503e95 --- /dev/null +++ b/example/slit_matrix/cfg/axis_main_matrix.plc @@ -0,0 +1,31 @@ +/* Forward kinematics to calculate virtual axes from real axes + | CEN | = FWD * | S1_LO | + | GAP | | S2_HI | + + Equations: + ax${AX_CEN}.enc.actpos:=(ax${AX_LO}.enc.actpos+ax${AX_HI}.enc.actpos)/2; + ax${AX_GAP}.enc.actpos:=ax${AX_HI}.enc.actpos-ax${AX_LO}.enc.actpos; +*/ + +var FWD1[2] := {0.5, 0.5}; +var FWD2[2] := { -1, 1 }; + +/* Inverse kinematics to calculate real axes from virtal axes + | S1_LO | = INV * | CEN | + | S2_HI | | GAP | + + Equations: + ax${AX_LO}.traj.extsetpos:=ax${AX_CEN}.traj.setpos-ax${AX_GAP}.traj.setpos/2; + ax${AX_HI}.traj.extsetpos:=ax${AX_CEN}.traj.setpos+ax${AX_GAP}.traj.setpos/2; +*/ + +var INV1[2] := { 1, -0.5}; +var INV2[2] := { 1, 0.5}; + +####### Kinematics for slit system. +# Macros cannot be used in an include. In order to find files, the loadPLCFile.cmd parameter "INC" defines the dirs that MSI will look for the file) +include "axis_kin_2DoF.plc_inc" + +####### State machine +# Macros cannot be used in an include. In order to find files, the loadPLCFile.cmd parameter "INC" defines the dirs that MSI will look for the file) +include "axis_sm.plc_inc" diff --git a/example/slit_matrix/cfg/axis_vax5_YCEN.yaml b/example/slit_matrix/cfg/axis_vax5_YCEN.yaml new file mode 100644 index 0000000..b7f707c --- /dev/null +++ b/example/slit_matrix/cfg/axis_vax5_YCEN.yaml @@ -0,0 +1,65 @@ +axis: + id: ${AX_ID} + group: virtualAxes + type: end effector + +epics: + name: CENTERY + precision: 4 + unit: mm + motorRecord: + description: "Center (Virtual)" + fieldInit: "SPAM=0,RTRY=1,FOFF=Frozen,TWV=1" + +encoder: + type: 1 + source: 1 + numerator: 1 + bits: 32 + +trajectory: + axis: + velocity: 0.5 + acceleration: 0.25 + jerk: 0.25 + +input: + limit: + forward: ec0.s0.ONE.0 # unused + backward: ec0.s0.ONE.0 # unused + home: ec0.s0.ONE.0 # unused + interlock: ec0.s0.ONE.0 # unused + +softlimits: + enable: false + forwardEnable: true + backwardEnable: true + forward: 52 + backward: 8 + +monitoring: + lag: + enable: yes + tolerance: 0.02 + time: 100 + target: + enable: yes + tolerance: 0.02 + time: 100 + velocity: + enable: yes + max: 0.6 + time: + trajectory: 100 + drive: 100 + +plc: + enable: true + externalCommands: true + filter: + velocity: + enable: false + size: 10 + trajectory: + enable: false + size: 10 diff --git a/example/slit_matrix/cfg/axis_vax6_YGAP.yaml b/example/slit_matrix/cfg/axis_vax6_YGAP.yaml new file mode 100644 index 0000000..dc54160 --- /dev/null +++ b/example/slit_matrix/cfg/axis_vax6_YGAP.yaml @@ -0,0 +1,65 @@ +axis: + id: ${AX_ID} + group: virtualAxes + type: end effector + +epics: + name: GAPY + precision: 4 + unit: mm + motorRecord: + description: "Gap (Virtual)" + fieldInit: "SPAM=0,RTRY=1,FOFF=Frozen,TWV=1" + +encoder: + type: 1 + source: 1 + numerator: 1 + bits: 32 + +trajectory: + axis: + velocity: 0.5 + acceleration: 0.25 + jerk: 0.25 + +input: + limit: + forward: ec0.s0.ONE.0 # unused + backward: ec0.s0.ONE.0 # unused + home: ec0.s0.ONE.0 # unused + interlock: ec0.s0.ONE.0 # unused + +softlimits: + enable: false + forwardEnable: true + backwardEnable: true + forward: 20 + backward: -20 + +monitoring: + lag: + enable: yes + tolerance: 0.02 + time: 100 + target: + enable: yes + tolerance: 0.02 + time: 100 + velocity: + enable: yes + max: 0.6 + time: + trajectory: 100 + drive: 100 + +plc: + enable: true + externalCommands: true + filter: + velocity: + enable: false + size: 10 + trajectory: + enable: false + size: 10 diff --git a/example/slit_matrix/readme.md b/example/slit_matrix/readme.md new file mode 100644 index 0000000..79ac180 --- /dev/null +++ b/example/slit_matrix/readme.md @@ -0,0 +1,19 @@ +# Test ioc for a slit system +Note: Motor record disabled in this test system + +## Changes +1. Use ecmc/ecmccfg version 9.5.4 or newer. +2. Divide statemachine and kinematics into separate include files (add INC param to loadPLCFile.cmd needed) +3. Use extsetpos in kinematics +4. Use new axis group functions in statemachine to make it generic (no direct access to axes in statemachine) +5. Set allow source change when enabled in axis yaml cfg (remove in startup script) +6. Remove encoder.position in virtual axis (not needed anymore) +7. Remove filter cfgs in yaml files + +## Panel +``` +caqtdm -macro "IOC=c6025a" ecmcMain.ui +``` + +## TODO +Test with motor record. diff --git a/example/slit_matrix/startup.script b/example/slit_matrix/startup.script new file mode 100644 index 0000000..eeb970f --- /dev/null +++ b/example/slit_matrix/startup.script @@ -0,0 +1,11 @@ +# The following lines were generated by "ioc install" +# Generated at: 2024-08-07 16:32:41.171272 + +epicsEnvSet IOC c6025a +epicsEnvSet ENGINEER sandst_a +< /ioc/startup/startup.script_linux + +# ---- ioc/system specific startup script(s) +< startup.script_ecmc + +iocInit diff --git a/example/slit_matrix/startup.script_ecmc b/example/slit_matrix/startup.script_ecmc new file mode 100644 index 0000000..2c94811 --- /dev/null +++ b/example/slit_matrix/startup.script_ecmc @@ -0,0 +1,85 @@ +#- Configuration scripts +require ecmccfg,"ENG_MODE=1,EC_RATE=100" + +#- Components lib +require ecmccomp + +#- Syncronization configs +require ecmc_master_slave + +#- Only output errors +asynSetTraceMask(${ECMC_ASYN_PORT}, -1, 0x01) + + +#- ############################################################################ +#- add slaves +#- list of slaves (4 axis test motion box) +# Master0 +# 0 0:0 PREOP + EK1100 EtherCAT-Koppler (2A E-Bus) +# 1 0:1 PREOP + EL9227-5500 �berstromschutz 24V DC, 2K., max. 10A (Summe), eins +# 2 0:2 PREOP + EL5042 2Ch. BiSS-C Encoder +# 3 0:3 PREOP + EL5042 2Ch. BiSS-C Encoder +# 4 0:4 PREOP + EL3204 4K. Ana. Eingang PT100 (RTD) +# 5 0:5 PREOP + EL2008 8K. Dig. Ausgang 24V, 0.5A +# 6 0:6 PREOP + EL1008 8K. Dig. Eingang 24V, 3ms +# 7 0:7 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 8 0:8 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 9 0:9 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 10 0:10 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# + +# 0:0 - EK1100 EtherCAT coupler +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EK1100" + +# 0:1 - EL9227-5500 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL9227-5500" + +# 0:2 - EL5042 2Ch BiSS-C Encoder +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL5042" + +# 0:3 - EL5042 2Ch BiSS-C Encoder +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL5042" + +# 0:4 - EL3204 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL3204" + +# 0:5 - EL2008 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL2008" + +# 0:6 - EL1008 8K. Dig. Eingang 24V, 3ms +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL1008" + +# 0:7 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" +${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper,MACROS='I_MAX_MA=1000,I_STDBY_MA=500,U_NOM_MV=48000,R_COIL_MOHM=1230'" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_ax5_LO.yaml, DRV_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_CHANNEL=01" + +# 0:8 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" +${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper,MACROS='I_MAX_MA=1000,I_STDBY_MA=500,U_NOM_MV=48000,R_COIL_MOHM=1230'" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_ax6_HI.yaml, DRV_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_CHANNEL=01" + +# 0:9 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" + +# 0:10 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" + +#- ################################################################# +#- Virtual axes +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_vax5_YCEN.yaml, AX_ID=${AX_NUM=12}" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_vax6_YGAP.yaml, AX_ID=${AX_NUM=13}" + +#- ################################################################# +#- PLCs with inverse kinematics (note the INC var including dirs to search for include files) +#- The group ID:s configured in yaml are stored in GRP__ID +${SCRIPTEXEC} ${ecmccfg_DIR}loadPLCFile.cmd, "FILE=./cfg/axis_main.plc, PLC_ID=1, INC=.:${ecmc_master_slave_DIR}, PLC_MACROS='PLC_ID=1, AX_CEN=12, AX_GAP=13, AX_LO=5, AX_HI=6, GRP_ID_RA=${GRP_realAxes_ID}, GRP_ID_VA=${GRP_virtualAxes_ID}'" + +#- ################################################################# +#- go active +${SCRIPTEXEC} ${ecmccfg_DIR}applyConfig.cmd +${SCRIPTEXEC} ${ecmccfg_DIR}setAppMode.cmd + +#- ############################################################################# +#- reset all errors +afterInit("ecmcConfigOrDie 'ControllerErrorReset()'") diff --git a/example/slit_matrix/startup_matrix.script_ecmc b/example/slit_matrix/startup_matrix.script_ecmc new file mode 100644 index 0000000..96d718b --- /dev/null +++ b/example/slit_matrix/startup_matrix.script_ecmc @@ -0,0 +1,85 @@ +#- Configuration scripts +require ecmccfg,"ENG_MODE=1,EC_RATE=100" + +#- Components lib +require ecmccomp + +#- Syncronization configs +require ecmc_master_slave sandst_a + +#- Only output errors +asynSetTraceMask(${ECMC_ASYN_PORT}, -1, 0x01) + + +#- ############################################################################ +#- add slaves +#- list of slaves (4 axis test motion box) +# Master0 +# 0 0:0 PREOP + EK1100 EtherCAT-Koppler (2A E-Bus) +# 1 0:1 PREOP + EL9227-5500 �berstromschutz 24V DC, 2K., max. 10A (Summe), eins +# 2 0:2 PREOP + EL5042 2Ch. BiSS-C Encoder +# 3 0:3 PREOP + EL5042 2Ch. BiSS-C Encoder +# 4 0:4 PREOP + EL3204 4K. Ana. Eingang PT100 (RTD) +# 5 0:5 PREOP + EL2008 8K. Dig. Ausgang 24V, 0.5A +# 6 0:6 PREOP + EL1008 8K. Dig. Eingang 24V, 3ms +# 7 0:7 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 8 0:8 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 9 0:9 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# 10 0:10 PREOP + EL7041 1Ch. Stepper motor output stage (50V, 5A) +# + +# 0:0 - EK1100 EtherCAT coupler +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EK1100" + +# 0:1 - EL9227-5500 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL9227-5500" + +# 0:2 - EL5042 2Ch BiSS-C Encoder +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL5042" + +# 0:3 - EL5042 2Ch BiSS-C Encoder +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL5042" + +# 0:4 - EL3204 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL3204" + +# 0:5 - EL2008 +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL2008" + +# 0:6 - EL1008 8K. Dig. Eingang 24V, 3ms +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL1008" + +# 0:7 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" +${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper,MACROS='I_MAX_MA=1000,I_STDBY_MA=500,U_NOM_MV=48000,R_COIL_MOHM=1230'" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_ax5_LO.yaml, DRV_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_CHANNEL=01" + +# 0:8 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" +${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper,MACROS='I_MAX_MA=1000,I_STDBY_MA=500,U_NOM_MV=48000,R_COIL_MOHM=1230'" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_ax6_HI.yaml, DRV_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_SLAVE=${ECMC_EC_SLAVE_NUM}, ENC_CHANNEL=01" + +# 0:9 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" + +# 0:10 - EL7041 1Ch Stepper +${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL7041-0052" + +#- ################################################################# +#- Virtual axes +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_vax5_YCEN.yaml, AX_ID=${AX_NUM=12}" +${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=cfg/axis_vax6_YGAP.yaml, AX_ID=${AX_NUM=13}" + +#- ################################################################# +#- PLCs with inverse kinematics (note the INC var including dirs to search for include files) +#- The group ID:s configured in yaml are stored in GRP__ID +${SCRIPTEXEC} ${ecmccfg_DIR}loadPLCFile.cmd, "FILE=./cfg/axis_main_matrix.plc, PLC_ID=1, INC=.:${ecmc_master_slave_DIR}, PLC_MACROS='PLC_ID=1, AX_M1=12, AX_M2=13, AX_S1=5, AX_S2=6, GRP_ID_RA=${GRP_realAxes_ID}, GRP_ID_VA=${GRP_virtualAxes_ID}'" + +#- ################################################################# +#- go active +${SCRIPTEXEC} ${ecmccfg_DIR}applyConfig.cmd +${SCRIPTEXEC} ${ecmccfg_DIR}setAppMode.cmd + +#- ############################################################################# +#- reset all errors +afterInit("ecmcConfigOrDie 'ControllerErrorReset()'")