17 Commits

Author SHA1 Message Date
377a28c95f Adapt to ecmc v11 2025-09-10 13:44:56 +02:00
8d4ea1e87c epics 7.0.9 2025-04-22 12:14:17 +02:00
5ec740b3b0 Update makefile 2025-03-28 09:23:06 +01:00
104875d532 Fix makefile for deb12 2025-03-21 10:47:05 +01:00
69fcd4da36 Default to PLUGIN_ID=0 2025-03-03 15:17:46 +01:00
653d4aac02 Default to PLUGIN_ID=0 2025-03-03 15:17:18 +01:00
0c19350ee5 Update makefile and add some pictures 2025-03-03 15:08:41 +01:00
d47820b543 Prep for ecmc v10 2024-12-16 10:41:02 +01:00
04ea63c8f4 New plugin concept 2024-12-13 16:03:50 +01:00
af297d71c4 depend on ecmc 9.6 2024-09-13 09:25:43 +02:00
1abf42ec4f Depend on ecmc 9 2024-09-13 09:04:33 +02:00
b1743a29b4 Set startGui.sh as executable 2024-05-07 16:45:53 +02:00
755ef8abe3 Convert tool to pyside2 2024-05-07 16:39:35 +02:00
f3413d2c96 Cleanup examples 2024-05-02 14:52:16 +02:00
fd41f95d84 Update makefile 2024-05-02 14:48:37 +02:00
1074a0c9e3 Restruct 2024-05-02 14:43:10 +02:00
a6a53ddfc0 WIP 2024-05-02 14:40:24 +02:00
43 changed files with 435 additions and 892 deletions

8
.gitignore vendored
View File

@@ -15,4 +15,10 @@ core.*
*-loc/*.Makefile
ecmc_plugin_motion/*.Makefile
*__*
O*
O*
tools/bin
tools/lib
tools/lib64
tools/pyvenv.cfg
tools/.*

View File

@@ -2,7 +2,7 @@
record(waveform,"$(P)Plg-Mtn${INDEX}-PosAct-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Pos Act")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynFloat64ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.actpos_arr")
field(FTVL, "DOUBLE")
@@ -10,14 +10,13 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-PosAct-Arr"){
field(SCAN, "I/O Intr")
field(TSE, "0")
field(EGU, "${RAW_EGU= }")
field(PREC, "${PREC=3 }")
}
# Set pos
record(waveform,"$(P)Plg-Mtn${INDEX}-PosSet-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Pos Set")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynFloat64ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.setpos_arr")
field(FTVL, "DOUBLE")
@@ -25,14 +24,13 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-PosSet-Arr"){
field(SCAN, "I/O Intr")
field(TSE, "0")
field(EGU, "${RAW_EGU= }")
field(PREC, "${PREC=3 }")
}
# Position Error
record(waveform,"$(P)Plg-Mtn${INDEX}-PosErr-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Pos Error (diff)")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynFloat64ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.diffpos_arr")
field(FTVL, "DOUBLE")
@@ -40,28 +38,26 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-PosErr-Arr"){
field(SCAN, "I/O Intr")
field(TSE, "0")
field(EGU, "${RAW_EGU= }")
field(PREC, "${PREC=3 }")
}
# X axis time (reltive within buffer)
record(waveform,"$(P)Plg-Mtn${INDEX}-Time-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Rel. time within buffer")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynFloat64ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.x_arr")
field(FTVL, "DOUBLE")
field(NELM, "$(NELM)")
field(SCAN, "I/O Intr")
field(TSE, "0")
field(PREC, "${PREC=3 }")
}
# Axis Enable
record(waveform,"$(P)Plg-Mtn${INDEX}-Ena-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Enable")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt8ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enable_arr")
field(FTVL, "CHAR")
@@ -74,7 +70,7 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-Ena-Arr"){
record(waveform,"$(P)Plg-Mtn${INDEX}-EnaAct-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Enabled")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt8ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enabled_arr")
field(FTVL, "CHAR")
@@ -87,7 +83,7 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-EnaAct-Arr"){
record(waveform,"$(P)Plg-Mtn${INDEX}-Bsy-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Busy")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt8ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.busy_arr")
field(FTVL, "CHAR")
@@ -100,7 +96,7 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-Bsy-Arr"){
record(waveform,"$(P)Plg-Mtn${INDEX}-Exe-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Execute")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt8ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.execute_arr")
field(FTVL, "CHAR")
@@ -113,7 +109,7 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-Exe-Arr"){
record(waveform,"$(P)Plg-Mtn${INDEX}-TrjSrc-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Traj source")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt8ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.trajsrc_arr")
field(FTVL, "CHAR")
@@ -126,7 +122,7 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-TrjSrc-Arr"){
record(waveform,"$(P)Plg-Mtn${INDEX}-EncSrc-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Enc source")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt8ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.encsrc_arr")
field(FTVL, "CHAR")
@@ -139,7 +135,7 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-EncSrc-Arr"){
record(waveform,"$(P)Plg-Mtn${INDEX}-AtTrg-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "At target")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt8ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.attarget_arr")
field(FTVL, "CHAR")
@@ -152,7 +148,7 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-AtTrg-Arr"){
record(waveform,"$(P)Plg-Mtn${INDEX}-ErrId-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Error Id")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt32ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.error_arr")
field(FTVL, "LONG")
@@ -161,11 +157,11 @@ record(waveform,"$(P)Plg-Mtn${INDEX}-ErrId-Arr"){
field(TSE, "0")
}
# Axis status word
# Axis Error Id
record(waveform,"$(P)Plg-Mtn${INDEX}-Stat-Arr"){
info(asyn:FIFO, "1000")
field(DESC, "Status wd")
#field(PINI, "1")
field(PINI, "1")
field(DTYP, "asynInt32ArrayIn")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.statuswd_arr")
field(FTVL, "LONG")
@@ -191,13 +187,10 @@ record(ao,"$(P)Plg-Mtn${INDEX}-AxCmd-RB"){
field(DTYP,"asynInt32")
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.axis_id")
field(DOL, "0")
field(PREC,"0")
field(DRVL,"0")
field(DRVH,"100")
field(VAL, "1")
}
record(ai,"$(P)Plg-Mtn${INDEX}-SmpHz"){
record(ai,"$(P)Plg-Mtn${INDEX}-SmpHz-RB"){
info(asyn:READBACK,"1")
field(DESC, "Sample rate")
field(DTYP,"asynFloat64")
@@ -207,63 +200,52 @@ record(ai,"$(P)Plg-Mtn${INDEX}-SmpHz"){
field(SCAN, "I/O Intr")
}
# Future use
#record(ai,"$(P)Plg-Mtn${INDEX}-BuffSze"){
# info(asyn:READBACK,"1")
# field(DESC, "Buffer Size")
# field(DTYP,"asynInt32")
# field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.buff_size")
# field(VAL, "1")
#}
record(ai,"$(P)Plg-Mtn${INDEX}-BuffSze"){
info(asyn:READBACK,"1")
field(DESC, "Buffer Size")
field(DTYP,"asynInt32")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.buff_size")
field(VAL, "1")
}
# Future use
#record(ai,"$(P)Plg-Mtn${INDEX}-ElmCnt"){
# info(asyn:READBACK,"1")
# field(DESC, "Elements in buffer count")
# field(DTYP,"asynInt32")
# field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.elem_count")
# field(VAL, "1")
#}
record(ai,"$(P)Plg-Mtn${INDEX}-ElmCnt"){
info(asyn:READBACK,"1")
field(DESC, "Elements in buffer count")
field(DTYP,"asynInt32")
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.elem_count")
field(VAL, "1")
}
# Future use
#record(bo,"$(P)Plg-Mtn${INDEX}-TrgCmd-RB"){
# info(asyn:READBACK,"1")
# field(DESC, "Trigg command")
# field(DTYP,"asynInt32")
# field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.trigg")
# field(ZNAM,"IDLE")
# field(ONAM,"TRIGG")
# field(VAL, "0")
# field(HIGH, 0.001)
#}
record(bo,"$(P)Plg-Mtn${INDEX}-TrgCmd-RB"){
info(asyn:READBACK,"1")
field(DESC, "Trigg command")
field(DTYP,"asynInt32")
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.trigg")
field(ZNAM,"IDLE")
field(ONAM,"TRIGG")
field(VAL, "0")
field(HIGH, 0.001)
}
# Future use
#record(mbbo, "$(P)Plg-Mtn${INDEX}-Mde-RB"){
# info(asyn:READBACK,"1")
# field(DESC, "Mode selection")
# field(PINI, "1")
# field(TSE, "0")
# field(DTYP, "asynInt32")
# field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.mode")
# field(ZRST, "NO_COMMAND")
# field(ZRVL, 0)
# field(ONST, "CONT")
# field(ONVL, 1)
# field(TWST, "TRIGG")
# field(TWVL, 2)
# field(VAL, 1)
#}
record(longout,"$(P)Plg-Mtn${INDEX}-Mde-RB"){
info(asyn:READBACK,"1")
field(DESC, "Mode selection")
field(PINI, "1")
field(TSE, "0")
field(DTYP, "asynInt32")
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.mode")
field(SCAN, "Passive")
}
# Future use
# record(longout,"$(P)Plg-Mtn${INDEX}-Cmd-RB"){
# info(asyn:READBACK,"1")
# field(DESC, "Command")
# field(PINI, "1")
# field(TSE, "0")
# field(DTYP, "asynInt32")
# field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.cmd")
# field(SCAN, "Passive")
# }
record(longout,"$(P)Plg-Mtn${INDEX}-Cmd-RB"){
info(asyn:READBACK,"1")
field(DESC, "Command")
field(PINI, "1")
field(TSE, "0")
field(DTYP, "asynInt32")
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.cmd")
field(SCAN, "Passive")
}
record(longin,"$(P)Plg-Mtn${INDEX}-Stat"){
info(asyn:READBACK,"1")

View File

@@ -1,12 +1,14 @@
include /ioc/tools/driver.makefile
MODULE = ecmc_plugin_motion
# "Transfer" module name to plugin
USR_CFLAGS +=-DECMC_PLUGIN_MODULE_NAME=${MODULE}
BUILDCLASSES = Linux
ARCH_FILTER = deb10%
ARCH_FILTER = deb10% deb12%
# Run 7.0.6 for now
EXCLUDE_VERSIONS+=3 7.0.5 7.0.6
EXCLUDE_VERSIONS+=3 7.0.5 7.0.6 7.0.7
IGNORE_MODULES += asynMotor
IGNORE_MODULES += motorBase
@@ -15,25 +17,32 @@ USR_CXXFLAGS += -std=c++17
OPT_CXXFLAGS_YES = -O3
# dependencies
ECmasterECMC_VERSION = v1.1.0
motorECMC_VERSION = 7.0.9-ESS
ecmc_VERSION = 9.5.0
ecmc_VERSION = v11.0.0_RC1
################################################################################
# THIS RELATES TO THE EtherCAT MASTER LIBRARY
# IT IS OF PARAMOUNT IMPORTANCE TO LOAD THE PROPER KERNEL MODULE
# ################################################################################
USR_LDFLAGS += -lethercat
# ethercat
# debian 12
EC_MASTER_VER = 1.6.3
EC_BASE_PATH = /ioc/NeedfulThings/EtherCAT/4epics/${EC_MASTER_VER}/
USR_CXXFLAGS_deb12-x86_64 += -I${EC_BASE_PATH}${T_A}/include/
USR_CXXFLAGS_deb12-x86_64 += -L${EC_BASE_PATH}${T_A}/lib/
EC_MASTER_LIB = ${EPICS_MODULES}/ECmasterECMC/${ECmasterECMC_VERSION}/R${EPICSVERSION}/lib/${T_A}
USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB}
USR_LDFLAGS += -L ${EC_MASTER_LIB}
LIB_SYS_LIBS += ethercat
USR_LDFLAGS_deb12-x86_64 += -Wl,-rpath=${EC_BASE_PATH}${T_A}/lib/
USR_LDFLAGS_deb12-x86_64 += -L ${EC_BASE_PATH}${T_A}/lib/
# debian 10
# note: EC_MASTER LIB does not depend on epics version hence use the 7.0.8 build..
USR_LDFLAGS_deb10-x86_64 += -lethercat
EC_MASTER_LIB = /ioc/NeedfulThings/EtherCAT/4epics/v1.1.0/R7.0.8/
USR_LDFLAGS_deb10-x86_64 += -Wl,-rpath=${EC_MASTER_LIB}lib/${T_A}
USR_LDFLAGS_deb10-x86_64 += -L ${EC_MASTER_LIB}lib/${T_A}
USR_CXXFLAGS_deb10-x86_64 += -I${EC_MASTER_LIB}/include/
OPT_CXXFLAGS_YES = -O3
BASE_DIR = .
SRC_DIR = $(BASE_DIR)/src
DB_DIR = $(BASE_DIR)/Db
SCRIPTS_DIR = $(BASE_DIR)/scripts
SOURCES += $(SRC_DIR)/ecmcPluginMotion.c
SOURCES += $(SRC_DIR)/ecmcMotionPlgWrap.cpp
SOURCES += $(SRC_DIR)/ecmcMotionPlg.cpp

View File

@@ -1,76 +1,11 @@
ecmc_plugin_motion
======
Plugin designed for commisioning and troubleshooting of motion axes.
Motion data are sampled, buffered and exposed as epics as waveforms.
Motion data are sampled, buffered and exposed to epics as waveforms.
# Panel
```
# Plugin loaded once (MTN_ID defaults to 0)
caqtdm -macro "SYS=c6025a" ecmc_plugin_motion_main.ui
# If loaded more times
caqtdm -macro "SYS=c6025a,MTN_ID=1" ecmc_plugin_motion_main.ui
```
# Python panels
In tools directory.. WIP...
python3 ecmcMotionMainPyQtGraph.py c6025a-04 0
# PVs
The following PVs are created:
```
c6025a> dbgrep *Plg*
c6025a:Plg-Mtn0-SmpHz
c6025a:Plg-Mtn0-AxCmd-RB
c6025a:Plg-Mtn0-EnaCmd-RB
c6025a:Plg-Mtn0-Stat
c6025a:Plg-Mtn0-PosAct-Arr
c6025a:Plg-Mtn0-PosSet-Arr
c6025a:Plg-Mtn0-PosErr-Arr
c6025a:Plg-Mtn0-Time-Arr
c6025a:Plg-Mtn0-Ena-Arr
c6025a:Plg-Mtn0-EnaAct-Arr
c6025a:Plg-Mtn0-Bsy-Arr
c6025a:Plg-Mtn0-Exe-Arr
c6025a:Plg-Mtn0-TrjSrc-Arr
c6025a:Plg-Mtn0-EncSrc-Arr
c6025a:Plg-Mtn0-AtTrg-Arr
c6025a:Plg-Mtn0-ErrId-Arr
c6025a:Plg-Mtn0-Stat-Arr
```
# Plugin Report
```
Plugin info:
Index = 1
Name = ecmc_plugin_motion
Description = Motion plugin for commissioning of ecmc motion axes.
Option description =
DBG_PRINT=<1/0> : Enables/disables printouts from plugin, default = disabled.
AXIS=<axis id> : Sets default source axis id.
BUFFER_SIZE=<size> : Data points to collect, default = 4096.
RATE=<rate hz> : Sampling rate in Hz
Filename = /gfa/.mounts/sls_ioc/modules/ecmc_plugin_motion/test/R7.0.7//lib/deb10-x86_64/libecmc_plugin_motion.so
Config string = AXIS=1;BUFFER_SIZE=2000;DBG_PRINT=0;ENABLE=1;
Version = 2
Interface version = 65536 (ecmc = 65536)
max plc funcs = 64
max plc func args = 10
max plc consts = 64
Construct func = @0x7f0badafb780
Enter realtime func = @0x7f0badafb7c0
Exit realtime func = @0x7f0badafb770
Realtime func = @0x7f0badafb7a0
Destruct func = @0x7f0badafb760
dlhandle = @0x563c3aba7d00
Plc functions:
Plc constants:
```
# TODO
* Triggered mode
* Add control functionalities (step response)
* Fix python gui (and venv)

View File

@@ -1,9 +0,0 @@
###############################################################################################
# For help on syntax, variables and functions, please read the file: "plcSyntaxHelp.plc"
#
# PLC Functionality Demo:
# No hardware related variables
#
static.time:=ec_get_time()/1E9;
static.sineval:=sin(2*pi*${FREQ=10}*static.time);

View File

@@ -1,345 +0,0 @@
IOC_TEST:m0s001-Drv01-Cmd-RB
IOC_TEST:m0s001-Drv01-Spd-RB
IOC_TEST:m0s001-Enc01-PosAct
IOC_TEST:m0s001-Enc01-LtchPosAct
IOC_TEST:m0s001-Enc01-Cmd-RB
IOC_TEST:m0s001-Enc01-PosCmd-RB
IOC_TEST:Axis1-Vel-RB
IOC_TEST:Axis1-Acc-RB
IOC_TEST:Axis1-EncAct
IOC_TEST:Axis1-CfgSREV-RB
IOC_TEST:Axis1-CfgUREV-RB
IOC_TEST:Axis1-CfgPMIN-RB
IOC_TEST:Axis1-CfgPMAX-RB
IOC_TEST:Axis1-CfgSPDB-RB
IOC_TEST:Axis1-CfgRDBD-RB
IOC_TEST:Axis1-CfgRDBD-Tim-RB
IOC_TEST:Axis1-CfgPOSLAG-RB
IOC_TEST:Axis1-CfgPOSLAG-Tim-RB
IOC_TEST:Axis1-CfgDHLM-RB
IOC_TEST:Axis1-CfgDLLM-RB
IOC_TEST:Axis1-CfgVELO-RB
IOC_TEST:Axis1-CfgVMAX-RB
IOC_TEST:Axis1-CfgJVEL-RB
IOC_TEST:Axis1-CfgACCS-RB
IOC_TEST:Axis1-HomPos-RB
IOC_TEST:Axis1-PosAct
IOC_TEST:Axis1-VelAct
IOC_TEST:Axis1-PosSet
IOC_TEST:Axis1-PosErr
IOC_TEST:Axis1-PLC-Err
IOC_TEST:Plg-Mtn0-SmpHz-RB
IOC_TEST:Plg-Mtn0-BuffSze
IOC_TEST:Plg-Mtn0-ElmCnt
IOC_TEST:MCU-AppMode
IOC_TEST:MCU-ErrId
IOC_TEST:MCU-ThdLatMin
IOC_TEST:MCU-ThdLatMax
IOC_TEST:MCU-ThdPrdMin
IOC_TEST:MCU-ThdPrdMax
IOC_TEST:MCU-ThdExeMin
IOC_TEST:MCU-ThdExeMax
IOC_TEST:MCU-ThdSndMin
IOC_TEST:MCU-ThdSndMax
IOC_TEST:m0s001-Drv01-WrnAlrm
IOC_TEST:m0s001-Drv01-ErrAlrm
IOC_TEST:m0s001-Drv01-StlAlrm
IOC_TEST:m0s001-Drv01-SyncErrAlrm
IOC_TEST:m0s001-Enc01-ExtLtchOK
IOC_TEST:m0s001-Enc01-OpnCrctAlrm
IOC_TEST:m0s001-Enc01-WrnAlrm
IOC_TEST:m0s001-Enc01-SyncErrAlrm
IOC_TEST:m0s001-Online
IOC_TEST:m0s001-Operational
IOC_TEST:m0s001-Alstate-Init
IOC_TEST:m0s001-Alstate-Preop
IOC_TEST:m0s001-Alstate-Safeop
IOC_TEST:m0s001-Alstate-Op
IOC_TEST:m0s002-BO01-RB
IOC_TEST:m0s002-BO02-RB
IOC_TEST:m0s002-BO03-RB
IOC_TEST:m0s002-BO04-RB
IOC_TEST:m0s002-BO05-RB
IOC_TEST:m0s002-BO06-RB
IOC_TEST:m0s002-BO07-RB
IOC_TEST:m0s002-BO08-RB
IOC_TEST:m0s002-BO09-RB
IOC_TEST:m0s002-BO10-RB
IOC_TEST:m0s002-BO11-RB
IOC_TEST:m0s002-BO12-RB
IOC_TEST:m0s002-BO13-RB
IOC_TEST:m0s002-BO14-RB
IOC_TEST:m0s002-BO15-RB
IOC_TEST:m0s002-BO16-RB
IOC_TEST:m0s002-BO01-OvrTmpAlrm
IOC_TEST:m0s002-BO01-OpnLdAlrm
IOC_TEST:m0s002-BO01-OvrCurrAlrm
IOC_TEST:m0s002-BO01-ShrtCircAlrm
IOC_TEST:m0s002-BO02-OvrTmpAlrm
IOC_TEST:m0s002-BO02-OpnLdAlrm
IOC_TEST:m0s002-BO02-OvrCurrAlrm
IOC_TEST:m0s002-BO02-ShrtCircAlrm
IOC_TEST:m0s002-BO03-OvrTmpAlrm
IOC_TEST:m0s002-BO03-OpnLdAlrm
IOC_TEST:m0s002-BO03-OvrCurrAlrm
IOC_TEST:m0s002-BO03-ShrtCircAlrm
IOC_TEST:m0s002-BO04-OvrTmpAlrm
IOC_TEST:m0s002-BO04-OpnLdAlrm
IOC_TEST:m0s002-BO04-OvrCurrAlrm
IOC_TEST:m0s002-BO04-ShrtCircAlrm
IOC_TEST:m0s002-BO05-OvrTmpAlrm
IOC_TEST:m0s002-BO05-OpnLdAlrm
IOC_TEST:m0s002-BO05-OvrCurrAlrm
IOC_TEST:m0s002-BO05-ShrtCircAlrm
IOC_TEST:m0s002-BO06-OvrTmpAlrm
IOC_TEST:m0s002-BO06-OpnLdAlrm
IOC_TEST:m0s002-BO06-OvrCurrAlrm
IOC_TEST:m0s002-BO06-ShrtCircAlrm
IOC_TEST:m0s002-BO07-OvrTmpAlrm
IOC_TEST:m0s002-BO07-OpnLdAlrm
IOC_TEST:m0s002-BO07-OvrCurrAlrm
IOC_TEST:m0s002-BO07-ShrtCircAlrm
IOC_TEST:m0s002-BO08-OvrTmpAlrm
IOC_TEST:m0s002-BO08-OpnLdAlrm
IOC_TEST:m0s002-BO08-OvrCurrAlrm
IOC_TEST:m0s002-BO08-ShrtCircAlrm
IOC_TEST:m0s002-BO09-OvrTmpAlrm
IOC_TEST:m0s002-BO09-OpnLdAlrm
IOC_TEST:m0s002-BO09-OvrCurrAlrm
IOC_TEST:m0s002-BO09-ShrtCircAlrm
IOC_TEST:m0s002-BO10-OvrTmpAlrm
IOC_TEST:m0s002-BO10-OpnLdAlrm
IOC_TEST:m0s002-BO10-OvrCurrAlrm
IOC_TEST:m0s002-BO10-ShrtCircAlrm
IOC_TEST:m0s002-BO11-OvrTmpAlrm
IOC_TEST:m0s002-BO11-OpnLdAlrm
IOC_TEST:m0s002-BO11-OvrCurrAlrm
IOC_TEST:m0s002-BO11-ShrtCircAlrm
IOC_TEST:m0s002-BO12-OvrTmpAlrm
IOC_TEST:m0s002-BO12-OpnLdAlrm
IOC_TEST:m0s002-BO12-OvrCurrAlrm
IOC_TEST:m0s002-BO12-ShrtCircAlrm
IOC_TEST:m0s002-BO13-OvrTmpAlrm
IOC_TEST:m0s002-BO13-OpnLdAlrm
IOC_TEST:m0s002-BO13-OvrCurrAlrm
IOC_TEST:m0s002-BO13-ShrtCircAlrm
IOC_TEST:m0s002-BO14-OvrTmpAlrm
IOC_TEST:m0s002-BO14-OpnLdAlrm
IOC_TEST:m0s002-BO14-OvrCurrAlrm
IOC_TEST:m0s002-BO14-ShrtCircAlrm
IOC_TEST:m0s002-BO15-OvrTmpAlrm
IOC_TEST:m0s002-BO15-OpnLdAlrm
IOC_TEST:m0s002-BO15-OvrCurrAlrm
IOC_TEST:m0s002-BO15-ShrtCircAlrm
IOC_TEST:m0s002-BO16-OvrTmpAlrm
IOC_TEST:m0s002-BO16-OpnLdAlrm
IOC_TEST:m0s002-BO16-OvrCurrAlrm
IOC_TEST:m0s002-BO16-ShrtCircAlrm
IOC_TEST:m0s002-Online
IOC_TEST:m0s002-Operational
IOC_TEST:m0s002-Alstate-Init
IOC_TEST:m0s002-Alstate-Preop
IOC_TEST:m0s002-Alstate-Safeop
IOC_TEST:m0s002-Alstate-Op
IOC_TEST:Axis1-EnaCmd-RB
IOC_TEST:Axis1-EnaAct
IOC_TEST:Axis1-ExeCmd-RB
IOC_TEST:Axis1-Busy
IOC_TEST:Axis1-AtTarget
IOC_TEST:Axis1-Moving
IOC_TEST:Axis1-LimFwd
IOC_TEST:Axis1-LimBwd
IOC_TEST:Axis1-HomeSwitch
IOC_TEST:Axis1-Homed
IOC_TEST:Axis1-InRT
IOC_TEST:Axis1-TrjSrcTyp-RB
IOC_TEST:Axis1-EncSrcTyp-RB
IOC_TEST:Axis1-CmdFrmPLCCmd-RB
IOC_TEST:Axis1-SftLimFwdEna-RB
IOC_TEST:Axis1-SftLimBwdEna-RB
IOC_TEST:Axis1-PLC-EnaCmd-RB
IOC_TEST:Axis1-PLC-FirstScan
IOC_TEST:Axis1-Err
IOC_TEST:Axis1-Wrn
IOC_TEST:MCU-ThdRTPrioOK
IOC_TEST:MCU-ThdMemLocked
IOC_TEST:m0-LinkUp
IOC_TEST:m0-AlStates-Init
IOC_TEST:m0-AlStates-Preop
IOC_TEST:m0-AlStates-Safeop
IOC_TEST:m0-AlStates-Op
IOC_TEST:m0-Dom-RedunActive
IOC_TEST:m0-Dom-WC-Zero
IOC_TEST:m0-Dom-WC-Incomplete
IOC_TEST:m0-Dom-WC-Complete
IOC_TEST:m0-Stat-OK
REQMOD:raspberrypi-10406:exit
REQMOD:raspberrypi-10406:MODULES
REQMOD:raspberrypi-10406:VERSIONS
REQMOD:raspberrypi-10406:MOD_VER
IOC_TEST:Axis1-Arr-Stat
IOC_TEST:Axis1-PLC-Expr-RB
IOC_TEST:Plg-Mtn0-PosAct-Arr
IOC_TEST:Plg-Mtn0-PosSet-Arr
IOC_TEST:Plg-Mtn0-PosErr-Arr
IOC_TEST:Plg-Mtn0-Time-Arr
IOC_TEST:Plg-Mtn0-Ena-Arr
IOC_TEST:Plg-Mtn0-EnaAct-Arr
IOC_TEST:Plg-Mtn0-Bsy-Arr
IOC_TEST:Plg-Mtn0-Exe-Arr
IOC_TEST:Plg-Mtn0-TrjSrc-Arr
IOC_TEST:Plg-Mtn0-EncSrc-Arr
IOC_TEST:Plg-Mtn0-AtTrg-Arr
IOC_TEST:Plg-Mtn0-ErrId-Arr
IOC_TEST:MCU-ErrMsg
IOC_TEST:MCU-Updated
IOC_TEST:m0s001-Enc01-LtchCmd
IOC_TEST:Axis1-MtnCmd
IOC_TEST:Axis1-movVelCmd
IOC_TEST:Axis1-movRelCmd
IOC_TEST:Axis1-movAbsCmd
IOC_TEST:Axis1-movHomCmd
IOC_TEST:Axis1-HomProc-RB
IOC_TEST:Axis1-Type
IOC_TEST:Axis1-DrvType
IOC_TEST:Axis1-TrajType
IOC_TEST:m0s001-One
IOC_TEST:m0s001-Zero
IOC_TEST:m0s002-One
IOC_TEST:m0s002-Zero
IOC_TEST:Axis1-DIR_
IOC_TEST:Axis1-ErrRst
IOC_TEST:Axis1-HomProc
IOC_TEST:Axis1-MtnCmdData
IOC_TEST:Plg-Mtn0-Mde-RB
IOC_TEST:Plg-Mtn0-Cmd-RB
IOC_TEST:m0s001-Stat
IOC_TEST:m0s002-Stat
IOC_TEST:Axis1-MR-ErrId
IOC_TEST:Axis1-CfgRDBD-En-RB
IOC_TEST:Axis1-CfgPOSLAG-En-RB
IOC_TEST:Axis1-CfgDHLM-En-RB
IOC_TEST:Axis1-CfgDLLM-En-RB
IOC_TEST:Axis1-Stat
IOC_TEST:Axis1-ErrId
IOC_TEST:Axis1-WrnId
IOC_TEST:Plg-Mtn0-Stat
IOC_TEST:m0-Stat
IOC_TEST:m0-SlvCntr
IOC_TEST:m0-MemmapCntr
IOC_TEST:m0-DomFailCntrTot
IOC_TEST:m0-EntryCntr
IOC_TEST:m0-Dom-Stat
IOC_TEST:MCU-Cfg-Info
IOC_TEST:MCU-Cfg-Naming
IOC_TEST:MCU-Cfg-Mode
IOC_TEST:MCU-Cfg-PVA
IOC_TEST:Axis1-DbgStrToLOG
IOC_TEST:MCU-Cfg-AX1-Pfx
IOC_TEST:MCU-Cfg-AX1-Nam
IOC_TEST:MCU-Cfg-AX1-PfxNam
IOC_TEST:m0s001-EntryCntr
IOC_TEST:m0s002-EntryCntr
IOC_TEST:Axis1-SeqState
IOC_TEST:Axis1-LastIlock
IOC_TEST:m0-SlvRsp
IOC_TEST:m0-Dom-WC
IOC_TEST:m0s001-Enc01-LtchRst
IOC_TEST:Axis1-Cmd_
REQMOD:raspberrypi-10406:BaseVersion
REQMOD:raspberrypi-10406:require_VER
REQMOD:raspberrypi-10406:ecmccfg_VER
REQMOD:raspberrypi-10406:asyn_VER
REQMOD:raspberrypi-10406:exprtk_VER
REQMOD:raspberrypi-10406:motor_VER
REQMOD:raspberrypi-10406:ruckig_VER
REQMOD:raspberrypi-10406:ecmc_VER
IOC_TEST:m0s001-HWType
IOC_TEST:m0s002-HWType
IOC_TEST:Axis1-MsgTxt
REQMOD:raspberrypi-10406:ecmc_plugin_motion_VER
IOC_TEST:m0s001-Drv01-Stat
IOC_TEST:m0s001-Enc01-Stat
IOC_TEST:m0s001-Stat_
IOC_TEST:m0s002-BO01-Stat
IOC_TEST:m0s002-BO02-Stat
IOC_TEST:m0s002-BO03-Stat
IOC_TEST:m0s002-BO04-Stat
IOC_TEST:m0s002-BO05-Stat
IOC_TEST:m0s002-BO06-Stat
IOC_TEST:m0s002-BO07-Stat
IOC_TEST:m0s002-BO08-Stat
IOC_TEST:m0s002-BO09-Stat
IOC_TEST:m0s002-BO10-Stat
IOC_TEST:m0s002-BO11-Stat
IOC_TEST:m0s002-BO12-Stat
IOC_TEST:m0s002-BO13-Stat
IOC_TEST:m0s002-BO14-Stat
IOC_TEST:m0s002-BO15-Stat
IOC_TEST:m0s002-BO16-Stat
IOC_TEST:m0s002-Stat_
IOC_TEST:Axis1-Stat_
IOC_TEST:ThdRTStat_
IOC_TEST:m0-Stat_
IOC_TEST:m0-Dom-Stat_
IOC_TEST:m0s001-Enc01-LtchAutRst
IOC_TEST:Axis1-MtnCmd_
IOC_TEST:MCU-Cfg-EC-Mst
IOC_TEST:MCU-Cfg-Rate
IOC_TEST:MCU-Cfg-Time
IOC_TEST:MCU-Cfg-PV-Time
IOC_TEST:m0s001-Drv01-Cmd
IOC_TEST:m0s001-Drv01-Spd
IOC_TEST:m0s001-Enc01-Cmd
IOC_TEST:m0s001-Enc01-PosCmd
IOC_TEST:m0s001-NxtObjId
IOC_TEST:MCU-Cfg-EC-FrstObjId
IOC_TEST:m0s002-NxtObjId
IOC_TEST:Axis1-OFF_
IOC_TEST:Axis1-MRES_
IOC_TEST:Axis1-HomPos
IOC_TEST:Axis1-VelToHom
IOC_TEST:Axis1-VelFrmHom
IOC_TEST:Axis1-AccHom
IOC_TEST:Axis1-TgtPosCmd
IOC_TEST:Axis1-TgtVelCmd
IOC_TEST:Axis1-Id
IOC_TEST:MCU-Cfg-AX1-NxtObjId
IOC_TEST:MCU-Cfg-AX-FrstObjId
IOC_TEST:MCU-Cfg-PLG{Index}-NxtObjId
IOC_TEST:MCU-Cfg-PLG-FrstObjId
IOC_TEST:Plg-Mtn0-AxCmd-RB
IOC_TEST:MCU-Cfg-Eng-Mode
IOC_TEST:m0s001-Enc01-LchAutRstSp
IOC_TEST:m0s002-BO01
IOC_TEST:m0s002-BO02
IOC_TEST:m0s002-BO03
IOC_TEST:m0s002-BO04
IOC_TEST:m0s002-BO05
IOC_TEST:m0s002-BO06
IOC_TEST:m0s002-BO07
IOC_TEST:m0s002-BO08
IOC_TEST:m0s002-BO09
IOC_TEST:m0s002-BO10
IOC_TEST:m0s002-BO11
IOC_TEST:m0s002-BO12
IOC_TEST:m0s002-BO13
IOC_TEST:m0s002-BO14
IOC_TEST:m0s002-BO15
IOC_TEST:m0s002-BO16
IOC_TEST:Axis1-EnaCmd
IOC_TEST:Axis1-ExeCmd
IOC_TEST:Axis1-StpCmd
IOC_TEST:Axis1-RstCmd
IOC_TEST:Axis1-EncSrcTyp-Cmd
IOC_TEST:Axis1-TrjSrcTyp-Cmd
IOC_TEST:Axis1-PLC-EnaCmd
IOC_TEST:Axis1-CmdFrmPLCCmd
IOC_TEST:Axis1-SftLimBwdEna
IOC_TEST:Axis1-SftLimFwdEna
IOC_TEST:Plg-Mtn0-EnaCmd-RB
IOC_TEST:Plg-Mtn0-TrgCmd-RB
IOC_TEST:MCU-ErrRst
IOC_TEST:Axis1-MCU1-asyn
IOC_TEST:MCU-Cmd
IOC_TEST:Axis1

View File

@@ -2,9 +2,15 @@
## Example: Configuraftion for running ecmc motion plugin
##############################################################################
require ecmccfg "9.4.0" "ECMC_VER=9.4.0"
## Initiation:
epicsEnvSet("IOC" ,"$(IOC="IOC_TEST")")
epicsEnvSet("ECMCCFG_INIT" ,"") #Only run startup once (auto at PSI, need call at ESS), variable set to "#" in startup.cmd
epicsEnvSet("SCRIPTEXEC" ,"$(SCRIPTEXEC="iocshLoad")")
require ecmccfg "sandst_a_v9.0.1_RC1" "ECMC_VER=v9.0.1_RC1"
##############################################################################
## Configue
## Configure hardware
epicsEnvSet("ECMC_EC_SLAVE_NUM", "4")
${SCRIPTEXEC} ${ecmccfg_DIR}configureSlave.cmd, "SLAVE_ID=$(ECMC_EC_SLAVE_NUM), HW_DESC=EL7031, CONFIG=-Motor-Trinamic-QMot-QSH4218-41-10-035"
@@ -27,6 +33,8 @@ $(SCRIPTEXEC) ($(ecmccfg_DIR)configureAxis.cmd, CONFIG=./cfg/el7031.ax)
#
epicsEnvSet(ECMC_PLUGIN_CONFIG,"PLUGIN_ID=1,AX=1,BUFF_SIZE=200,DBG=0,ENA=1")
require ecmc_plugin_motion sandst_a "${ECMC_PLUGIN_CONFIG}"
# below needed at ESS but not PSI:
#${SCRIPTEXEC} ${ecmc_plugin_motion_DIR}startup.cmd "${ECMC_PLUGIN_CONFIG}"
##############################################################################
############# Configure diagnostics:

View File

@@ -0,0 +1,92 @@
# Macros:
# AX_ID : This axis id
# AX_NAME : This axis name
# DRV_ID : Slave id of drive
# OFFSET : Offset
axis:
id: ${AX_ID=1}
mode: CSV
# parameters: powerAutoOnOff=2;powerOnDelay=6.0;powerOffDelay=1.0;
epics:
name: ${AX_NAME=Axis1}
precision: 4
unit: revs
motorRecord:
enable: true
description: ""
fieldInit: "RTRY=0,FOFF=Frozen"
# Max scale is 8000Hz
drive:
numerator: 8000 #rev/s, Max speed is 8000 rev/sec for drive
denominator: 2147483648
type: 1 # Stepper: 0, DS402: 1 (servos)
control: ec0.s$(DRV_ID).driveControl01
status: ec0.s$(DRV_ID).driveStatus01
setpoint: ec0.s$(DRV_ID).velocitySetpoint01
reset: 7
# 0.02mm/rev (0.4mm pitch and gr of 20).
# in data sheet it states 0.364mm pitch and gr of 20 (which is not true)
encoder:
type: 1
position: ec0.s$(DRV_ID).positionActual01
numerator: 1
denominator: 1048576
bits: 32
absBits: 32
absOffset: $(OFFSET=0)
status: ec0.s$(DRV_ID).ONE
# error:
# - 7
# ready: 6
controller:
Kp: 140.0
Ki: 0.1
Kd: 0.0
deadband:
tol: 0.0 # Stop control if within this distance from target for the below time
time: 100
trajectory:
source: 0
type: 1
axis:
velocity: 50
acceleration: 50000
decceleration: 50000
input:
limit:
# forward: ec0.s$(DRV_ID).infoData02.1
# backward: ec0.s$(DRV_ID).infoData02.0
forward: ec0.s$(DRV_ID).ONE.1
backward: ec0.s$(DRV_ID).ONE.0
home: ec0.s$(DRV_ID).ONE.0
interlock: ec0.s$(DRV_ID).ONE.0
softlimits:
enable: no
backwardEnable: yes
forwardEnable: yes
forward: 10
backward: -10
monitoring:
lag:
enable: no
tolerance: 0.01
time: 100
target:
enable: yes
tolerance: 0.1
time: 100
velocity:
enable: no
max: 10000
time:
trajectory: 100
drive: 200

View File

@@ -0,0 +1,43 @@
##############################################################################
## Example config for ep7211-0010.. Why power cycle sometimes needed??? SDO 8000:17 (enc offset) gives error
##############################################################################
## Initiation:
require ecmccfg "ECMC_VER=EC_RATE=1000,ENG_MODE=1,MASTER_ID=1"
require ecmccomp
epicsEnvSet("ECMC_EC_SLAVE_NUM_DRIVE", "0")
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=$(ECMC_EC_SLAVE_NUM_DRIVE), HW_DESC=EP7211-0034_ALL_FB"
${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP= Motor-Beckhoff-AM8121-XFX0"
#Apply hardware configuration
ecmcConfigOrDie "Cfg.EcApplyConfig(1)"
#epicsEnvSet("ECMC_SAMPLE_RATE_MS", "${RATE="1"}")
##############################################################################
## AXIS 1
#
epicsEnvSet("DEV", "$(IOC)")
$(SCRIPTEXEC) $(ecmccfg_DIR)loadYamlAxis.cmd "FILE=./cfg/el7201_hipa.yaml,DRV_ID=$(ECMC_EC_SLAVE_NUM_DRIVE),AX_NAME='Axis1',AX_ID=1"
#epicsEnvSet("ECMC_SAMPLE_RATE_MS", "${RATE="10"}")
##############################################################################
## Load plugin: MOTION
#
epicsEnvSet(ECMC_PLUGIN_CONFIG,"PLUGIN_ID=1,AX=1,BUFF_SIZE=200,DBG=0,ENA=1")
require ecmc_plugin_motion sandst_a "${ECMC_PLUGIN_CONFIG}"
##############################################################################
############# Configure diagnostics:
ecmcConfigOrDie "Cfg.EcSetDiagnostics(1)"
ecmcConfigOrDie "Cfg.EcEnablePrintouts(0)"
ecmcConfigOrDie "Cfg.SetDiagAxisEnable(0)"
# go active
$(SCRIPTEXEC) ($(ecmccfg_DIR)setAppMode.cmd)

View File

@@ -1,57 +0,0 @@
##############################################################################
## Example: Configuraftion for running ecmc motion plugin
##############################################################################
require ecmccfg "9.4.0" "ECMC_VER=9.4.0,EC_RATE=500"
# run module startup.cmd (only needed at ESS PSI auto call at require)
$(ECMCCFG_INIT="")$(SCRIPTEXEC) ${ecmccfg_DIR}startup.cmd, "IOC=$(IOC),ECMC_VER=9.4.0, EC_RATE=500"
##############################################################################
## Configure hardware
epicsEnvSet("ECMC_EC_SLAVE_NUM", "1")
${SCRIPTEXEC} ${ecmccfg_DIR}configureSlave.cmd, "SLAVE_ID=$(ECMC_EC_SLAVE_NUM), HW_DESC=EL7031, CONFIG=-Motor-Trinamic-QMot-QSH4218-41-10-035"
epicsEnvSet("DRV_ID", "${ECMC_EC_SLAVE_NUM}")
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL2819"
epicsEnvSet("DO_ID", "${ECMC_EC_SLAVE_NUM}")
# Configure drv input 1 as drv enable
ecmcConfigOrDie "Cfg.EcAddSdo(${DRV_ID},0x8012,0x32,1,1)"
OK
# Control external drv enable
ecmcConfigOrDie "Cfg.WriteEcEntryIDString(${DO_ID},binaryOutput02,1)"
#Apply hardware configuration
ecmcConfigOrDie "Cfg.EcApplyConfig(1)"
##############################################################################
## AXIS 1
#
epicsEnvSet("DEV", "$(IOC)")
$(SCRIPTEXEC) ($(ecmccfg_DIR)configureAxis.cmd, CONFIG=./cfg/el7031.ax)
##############################################################################
## Load plugin: MOTION
#
epicsEnvSet(ECMC_PLUGIN_CONFIG,"PLUGIN_ID=1,AX=1,BUFF_SIZE=200,DBG=0,ENA=1")
require ecmc_plugin_motion master ${ECMC_PLUGIN_CONFIG}
# below needed at ESS but not PSI:
${SCRIPTEXEC} ${ecmc_plugin_motion_DIR}startup.cmd "${ECMC_PLUGIN_CONFIG}"
##############################################################################
############# Configure diagnostics:
ecmcConfigOrDie "Cfg.EcSetDiagnostics(1)"
ecmcConfigOrDie "Cfg.EcEnablePrintouts(0)"
ecmcConfigOrDie "Cfg.EcSetDomainFailedCyclesLimit(100)"
ecmcConfigOrDie "Cfg.SetDiagAxisIndex(1)"
ecmcConfigOrDie "Cfg.SetDiagAxisFreq(2)"
ecmcConfigOrDie "Cfg.SetDiagAxisEnable(0)"
##############################################################################
############# go active:
$(SCRIPTEXEC) ($(ecmccfg_DIR)setAppMode.cmd)
iocInit
dbl > pvs.log

0
qt/.keep Normal file
View File

View File

@@ -28,10 +28,10 @@
#- First loaded object will therefore have index
epicsEnvSet(ECMC_PLG_MOTION_OBJ_INDEX,${ECMC_PLG_MOTION_OBJ_INDEX=0})
#- Might need differet paths for PSI and ESS.. must check
# Might need differet paths for PSI and ESS.. must check
epicsEnvSet(ECMC_PLUGIN_FILNAME,"$(ecmc_plugin_motion_DIR)/lib/${EPICS_HOST_ARCH=linux-x86_64}/libecmc_plugin_motion.so")
epicsEnvSet(ECMC_PLUGIN_CONFIG,"AXIS=${AX};BUFFER_SIZE=${BUFF_SIZE};DBG_PRINT=${DBG=1};ENABLE=${ENA=1};")
${SCRIPTEXEC} ${ecmccfg_DIR}loadPlugin.cmd, "PLUGIN_ID=${PLUGIN_ID},FILE=${ECMC_PLUGIN_FILNAME},CONFIG='${ECMC_PLUGIN_CONFIG}', REPORT=${REPORT=1}"
${SCRIPTEXEC} ${ecmccfg_DIR}loadPlugin.cmd, "PLUGIN_ID=${PLUGIN_ID=0},FILE=${ECMC_PLUGIN_FILNAME},CONFIG='${ECMC_PLUGIN_CONFIG}', REPORT=${REPORT=1}"
dbLoadRecords(${ecmc_plugin_motion_TEMPLATES}ecmcPluginMotion.template,"P=$(IOC):,INDEX=${ECMC_PLG_MOTION_OBJ_INDEX=0},NELM=${BUFF_SIZE=1000}")

View File

@@ -833,28 +833,28 @@ void ecmcMotionPlg::executeMotionObject() {
return;
}
//if(cfgMode_==TRIGG && !bTriggInProgress_) {
// return;
//}
if(cfgMode_==TRIGG && !bTriggInProgress_) {
return;
}
// protect axis_ if axis object id is changed over asyn
epicsMutexLock(axisMutex_);
ecmcAxisStatusType *tempAxisStat = axis_->getDebugInfoDataPointer();
ecmcAxisDataStatus *tempAxisStat = axis_->getAxisStatusStruct();
// Fill the buffers
actPosBuffer_->addData(tempAxisStat->onChangeData.positionActual);
setPosBuffer_->addData(tempAxisStat->onChangeData.positionSetpoint);
diffPosBuffer_->addData(tempAxisStat->onChangeData.positionError);
enableBuffer_->addData(tempAxisStat->onChangeData.statusWd.enable);
enabledBuffer_->addData(tempAxisStat->onChangeData.statusWd.enabled);
busyBuffer_->addData(tempAxisStat->onChangeData.statusWd.busy);
executeBuffer_->addData(tempAxisStat->onChangeData.statusWd.execute);
trajSourceBuffer_->addData(tempAxisStat->onChangeData.statusWd.trajsource);
encSourceBuffer_->addData(tempAxisStat->onChangeData.statusWd.encsource);
atTargetBuffer_->addData(tempAxisStat->onChangeData.statusWd.attarget);
errorIdBuffer_->addData(tempAxisStat->onChangeData.error);
actPosBuffer_->addData(tempAxisStat->currentPositionActual);
setPosBuffer_->addData(tempAxisStat->currentPositionSetpoint);
diffPosBuffer_->addData(tempAxisStat->cntrlError);
enableBuffer_->addData(tempAxisStat->statusWord_.enable);
enabledBuffer_->addData(tempAxisStat->statusWord_.enabled);
busyBuffer_->addData(tempAxisStat->statusWord_.busy);
executeBuffer_->addData(tempAxisStat->statusWord_.execute);
trajSourceBuffer_->addData(tempAxisStat->statusWord_.trajsource);
encSourceBuffer_->addData(tempAxisStat->statusWord_.encsource);
atTargetBuffer_->addData(tempAxisStat->statusWord_.attarget);
errorIdBuffer_->addData(tempAxisStat->errorCode);
epicsInt32 *temp=(epicsInt32*)&(tempAxisStat->onChangeData.statusWd); // A bit nasty
epicsInt32 *temp=(epicsInt32*)&(tempAxisStat->statusWord_); // A bit nasty
statusWdBuffer_->addData(*temp);
xTime_+=xdt_;
@@ -870,24 +870,6 @@ void ecmcMotionPlg::executeMotionObject() {
epicsMutexUnlock(axisMutex_);
}
//void ecmcMotionPlg::setModeFFT(FFT_MODE mode) {
// cfgMode_ = mode;
// setIntegerParam(asynFFTModeId_,(epicsInt32)mode);
//}
//
//FFT_STATUS ecmcMotionPlg::getStatusFFT() {
// return status_;
//}
//void ecmcMotionPlg::updateStatus(FFT_STATUS status) {
// status_ = status;
// setIntegerParam(asynFFTStatId_,(epicsInt32) status);
//
// setIntegerParam(asynElementsInBuffer_, (epicsInt32)elementsInBuffer_);
//
// callParamCallbacks();
//}
asynStatus ecmcMotionPlg::writeInt32(asynUser *pasynUser, epicsInt32 value) {
int function = pasynUser->reason;
if( function == asynEnableId_ ) {
@@ -906,7 +888,7 @@ asynStatus ecmcMotionPlg::writeInt32(asynUser *pasynUser, epicsInt32 value) {
} else if( function == asynAxisId_){
return setAxis(value) > 0 ? asynSuccess : asynError;
} else if( function == asynModeId_){
return setMode((TRIGG_MODE)value) > 0 ? asynSuccess : asynError;
return setMode((TRIGG_MODE)value) == 0 ? asynSuccess : asynError;
} else if( function == asynModeId_){
return setTrigg(value) ? asynSuccess :asynError;
}
@@ -966,7 +948,7 @@ int ecmcMotionPlg::setAxis(int axisId) {
//set old value again
setParamAlarmStatus(asynAxisId_,1);
setParamAlarmSeverity(asynAxisId_,1);
setIntegerParam(asynAxisId_, (epicsInt32)axisId); // Set anyway to make alarms colors valid for correct index
setIntegerParam(asynAxisId_, (epicsInt32)cfgAxisIndex_);
callParamCallbacks();
return ECMC_PLUGIN_MOTION_ERROR_AXIS_OUT_OF_RANGE;
}

View File

@@ -8,11 +8,16 @@
* Created on: july 10, 2023
* Author: anderssandstrom
*
* Instructions:
* - IMPORTANT: Add "USR_CFLAGS +=-DECMC_PLUGIN_MODULE_NAME=${MODULE}" to GNUMakefile
* - All functions and ecmcPluginData struct must be declared static
*
\*************************************************************************/
// Needed to get headers in ecmc right...
#define ECMC_IS_PLUGIN
#define ECMC_EXAMPLE_PLUGIN_VERSION 2
#define ECMC_PLUGIN_VERSION 2
#ifdef __cplusplus
extern "C" {
@@ -27,18 +32,16 @@ extern "C" {
#include "ecmcMotionPlgWrap.h"
static int lastEcmcError = 0;
static char* lastConfStr = NULL;
static char* lastConfStr = NULL;
/** Optional.
* Will be called once after successfull load into ecmc.
* Will be called once after successful load into ecmc.
* Return value other than 0 will be considered error.
* configStr can be used for configuration parameters.
**/
int motionConstruct(char *configStr)
static int construct(char *configStr)
{
//This module is allowed to load several times so no need to check if loaded
// create object and register data callback
lastConfStr = strdup(configStr);
return createMotionObj(configStr);
}
@@ -46,31 +49,27 @@ int motionConstruct(char *configStr)
/** Optional function.
* Will be called once at unload.
**/
void motionDestruct(void)
static void motionDestruct(void)
{
//deleteAllMotionObjs();
//if(lastConfStr){
// free(lastConfStr);
//}
}
/** Optional function.
* Will be called each realtime cycle if definded
* ecmcError: Error code of ecmc. Makes it posible for
* Will be called each realtime cycle if defined
* ecmcError: Error code of ecmc. Makes it possible for
* this plugin to react on ecmc errors
* Return value other than 0 will be considered to be an error code in ecmc.
**/
int motionRealtime(int ecmcError)
static int motionRealtime(int ecmcError)
{
executeMotionObjs();
lastEcmcError = ecmcError;
return 0;
}
/** Link to data source here since all sources should be availabe at this stage
/** Link to data source here since all sources should be available at this stage
* (for example ecmc PLC variables are defined only at enter of realtime)
**/
int motionEnterRT(){
static int motionEnterRT(){
return linkDataTomotionObjs();
}
@@ -78,37 +77,13 @@ int motionEnterRT(){
* Will be called once just before leaving realtime mode
* Return value other than 0 will be considered error.
**/
int motionExitRT(void){
static int motionExitRT(void){
return 0;
}
//// Plc function for clear of buffers
//double fft_clear(double index) {
// return (double)clearFFT((int)index);
//}
//
//// Plc function for enable
//double fft_enable(double index, double enable) {
// return (double)enableFFT((int)index, (int)enable);
//}
//
//// Plc function for trigg new measurement (will clear buffers)
//double fft_trigg(double index) {
// return (double)triggFFT((int)index);
//}
//
//// Plc function for enable
//double fft_mode(double index, double mode) {
// return (double)modeFFT((int)index, (FFT_MODE)((int)mode));
//}
//
//// Plc function for enable
//double fft_stat(double index) {
// return (double)statFFT((int)index);
//}
// Register data for plugin so ecmc know what to use
struct ecmcPluginData pluginDataDef = {
static struct ecmcPluginData pluginDataDef = {
// Allways use ECMC_PLUG_VERSION_MAGIC
.ifVersion = ECMC_PLUG_VERSION_MAGIC,
// Name
@@ -120,174 +95,23 @@ struct ecmcPluginData pluginDataDef = {
" "ECMC_PLUGIN_AXIS_OPTION_CMD"<axis id> : Sets default source axis id.\n"
" "ECMC_PLUGIN_BUFFER_SIZE_OPTION_CMD"<size> : Data points to collect, default = 4096.\n"
" "ECMC_PLUGIN_RATE_OPTION_CMD"<rate hz> : Sampling rate in Hz"
// " "ECMC_PLUGIN_MODE_OPTION_CMD"<TRIGG/CONT> : Cont or triggered mode"
" "ECMC_PLUGIN_MODE_OPTION_CMD"<TRIGG/CONT> : Sampling rate in Hz"
,
// Plugin version
.version = ECMC_EXAMPLE_PLUGIN_VERSION,
// Optional construct func, called once at load. NULL if not definded.
.constructFnc = motionConstruct,
// Optional destruct func, called once at unload. NULL if not definded.
.version = ECMC_PLUGIN_VERSION,
// Optional construct func, called once at load. NULL if not defined.
.constructFnc = construct,
// Optional destruct func, called once at unload. NULL if not defined.
.destructFnc = motionDestruct,
// Optional func that will be called each rt cycle. NULL if not definded.
// Optional func that will be called each rt cycle. NULL if not defined.
.realtimeFnc = motionRealtime,
// Optional func that will be called once just before enter realtime mode
.realtimeEnterFnc = motionEnterRT,
// Optional func that will be called once just before exit realtime mode
.realtimeExitFnc = motionExitRT,
// PLC funcs
// .funcs[0] =
// { /*----fft_clear----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_clear",
// // Function description
// .funcDesc = "double fft_clear(index) : Clear/reset fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = fft_clear,
// .funcArg2 = NULL,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[1] =
// { /*----fft_enable----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_enable",
// // Function description
// .funcDesc = "double fft_enable(index, enable) : Set enable for fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = NULL,
// .funcArg2 = fft_enable,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[2] =
// { /*----fft_trigg----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_trigg",
// // Function description
// .funcDesc = "double fft_trigg(index) : Trigg new measurement for fft[index]. Will clear buffers.",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = fft_trigg,
// .funcArg2 = NULL,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[3] =
// { /*----fft_mode----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_mode",
// // Function description
// .funcDesc = "double fft_mode(index, mode) : Set mode Cont(1)/Trigg(2) for fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = NULL,
// .funcArg2 = fft_mode,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[4] =
// { /*----fft_stat----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_stat",
// // Function description
// .funcDesc = "double fft_stat(index) : Get status of fft (NO_STAT, IDLE, ACQ, CALC) for fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = fft_stat,
// .funcArg2 = NULL,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
.funcs[0] = {0}, // last element set all to zero..
// PLC consts
/* CONTINIOUS MODE = 1 */
// .consts[0] = {
// .constName = "fft_CONT",
// .constDesc = "FFT Mode: Continious",
// .constValue = CONT
// },
// /* TRIGGERED MODE = 2 */
// .consts[1] = {
// .constName = "fft_TRIGG",
// .constDesc = "FFT Mode :Triggered",
// .constValue = TRIGG
// },
// /* TRIGGERED MODE = 2 */
// .consts[2] = {
// .constName = "fft_NO_STAT",
// .constDesc = "FFT Status: Invalid state",
// .constValue = NO_STAT,
// },
// /* TRIGGERED MODE = 2 */
// .consts[3] = {
// .constName = "fft_IDLE",
// .constDesc = "FFT Status: Idle state (waiting for trigger)",
// .constValue = IDLE
// },
// /* TRIGGERED MODE = 2 */
// .consts[4] = {
// .constName = "fft_ACQ",
// .constDesc = "FFT Status: Acquiring data",
// .constValue = ACQ
// },
// /* TRIGGERED MODE = 2 */
// .consts[5] = {
// .constName = "fft_CALC",
// .constDesc = "FFT Status: Calculating result",
// .constValue = CALC
// },
.consts[0] = {0}, // last element set all to zero..
};

View File

@@ -10,10 +10,8 @@
#-###############################################################################
#-
#- Arguments
#- [mandatory]
#- PLUGIN_ID = Plugin instansiation index, must be unique for each call
#-
#- [optional]
#- PLUGIN_ID = Plugin instansiation index, must be unique for each call defaults to 0
#- AX = Axis id, default 1
#- BUFF_SIZE = Buffer size, default 1000
#- DBG = Debug mode, default 1
@@ -27,6 +25,6 @@
# Only allow call startup.cmd once. if more objects are needed then use addMotionObj.cmd directlly.
#- add One motion plugin object, only run startup once
${ECMC_PLG_MOTION_INIT=""}${SCRIPTEXEC} $(ecmc_plugin_motion_DIR)addMotionObj.cmd "PLUGIN_ID=${PLUGIN_ID},AX=${AX=1},BUFF_SIZE=${BUFF_SIZE=1000},DBG=${DBG=1},ENA=${ENA=1},REPORT=${REPORT=1}"
${ECMC_PLG_MOTION_INIT=""}${SCRIPTEXEC} $(ecmc_plugin_motion_DIR)addMotionObj.cmd "PLUGIN_ID=${PLUGIN_ID=0},AX=${AX=1},BUFF_SIZE=${BUFF_SIZE=1000},DBG=${DBG=1},ENA=${ENA=1},REPORT=${REPORT=1}"
epicsEnvSet("ECMC_PLG_MOTION_INIT" ,"#")

View File

@@ -1,8 +1,2 @@
# FFT tools
## GUI
A python gui for vizualization and control of the FFT plugin can be found in the ecmccomgui repo:
https://github.com/anderssandstrom/ecmccomgui
![ecmcFFTMainGui.py](docs/gui/ecmcFFTMainGui.png)
# Tool for visualization
python3 ecmcMotionMainPyQtGraph.py c6025a-04 0

BIN
tools/cos_ff_trq_test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
tools/cos_ff_trq_test_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
tools/delay0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
tools/delay0_kx0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
tools/delay10_kx0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
tools/delay1_kx0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
tools/delay2.5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
tools/delay2.5_kx0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
tools/delay2_kx0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
tools/delay3_kx0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
tools/delay4_kx0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -2,12 +2,16 @@
import sys
import epics
import numpy as np
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import QObject
from PySide2.QtCore import Signal as pyqtSignal, Slot as pyqtSlot
from PyQt5 import QtCore,QtWidgets, QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtCore import QObject
from PyQt5.QtGui import *
#from PyQt5 import QtCore,QtWidgets, QtGui
#from PyQt5.QtWidgets import *
#from PyQt5.QtCore import *
#from PyQt5.QtCore import QObject
#from PyQt5.QtGui import *
import random
import ecmcTrend

View File

@@ -14,18 +14,27 @@
import sys
import epics
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
#from PyQt5.QtWidgets import *
#from PyQt5 import QtWidgets
#from PyQt5.QtCore import *
#from PyQt5.QtGui import *
import numpy as np
from ecmcOneMotorGUI import *
import pyqtgraph as pg
from ecmcPvDataItem import *
from ecmcParseAxisStatusWord import *
import os
# Allow buffering of 10s data, need to add setting for this
xMaxTime = 10
caqtdmAxisExpertPanelName = "ecmcAxisExpert_v1.ui"
caqtdmExe ="/usr/local/bin/caqtdm"
# List of pv names
pvlist = [ 'BuffSze',
@@ -58,14 +67,12 @@ pvAnalog = ['PosAct-Arr',
'Stat-Arr']
pvAnaPLotsDefaultEnabled = ['PosAct-Arr',
'PosSet-Arr',
'PosErr-Arr']
'PosSet-Arr']
pvBinPLotsDefaultEnabled = ['enable',
'enabled',
'busy',
'attarget',
'moving']
'attarget']
pvBinBlock = ['instartup',
'inrealtime',
'axisType',
@@ -83,7 +90,7 @@ pvFistAxisIndexName = 'MCU-Cfg-AX-FrstObjId'
pvNextAxisIndexNamePart1 = 'MCU-Cfg-AX'
pvNextAxisIndexNamePart2 = '-NxtObjId'
pvmiddlestring='Plg-Mtn'
pvmiddlestring=':Plg-Mtn'
class ecmcMtnMainGui(QtWidgets.QDialog):
def __init__(self,prefix="IOC_TEST:",mtnPluginId=0):
@@ -188,7 +195,8 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
# Check connection and read sample rate
pvSampleRate = epics.PV(self.pvPrefixStr + pvmiddlestring + str(int(self.mtnPluginId))+ '-SmpHz-RB')
connected = pvSampleRate.wait_for_connection(timeout = 2)
print(self.pvPrefixStr + pvmiddlestring + str(int(self.mtnPluginId))+ '-SmpHz-RB')
connected = pvSampleRate.wait_for_connection(timeout = 3)
if connected:
print('Connected to ecmc')
self.offline = False
@@ -200,7 +208,8 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
else:
print('Not Connected')
self.offline = True
self.pause = True
self.pause = True
self.sampleRate = 1000
self.sampleRateValid = True
@@ -242,37 +251,58 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
self.plotItemBinary.setFixedHeight(150)
self.plotItemBinary.setMouseEnabled(y=False)
self.plotItemBinary.setLabel('bottom', 'Time [s]')
self.pauseBtn = QPushButton(text = 'pause')
self.pauseBtn.setFixedSize(100, 50)
self.pauseBtn.clicked.connect(self.pauseBtnAction)
self.pauseBtn.setStyleSheet("background-color: green")
#self.pauseBtn.setEnabled(False)
#self.pauseBtn.setVisible(False)
self.openBtn = QPushButton(text = 'open data')
self.openBtn.setFixedSize(100, 50)
self.openBtn.clicked.connect(self.openBtnAction)
self.openBtn.setEnabled(False)
self.openBtn.setVisible(False)
self.saveBtn = QPushButton(text = 'save data')
self.saveBtn.setFixedSize(100, 50)
self.saveBtn.clicked.connect(self.saveBtnAction)
self.saveBtn.setEnabled(False)
self.saveBtn.setVisible(False)
self.enableBtn = QPushButton(text = 'enable Mtn')
self.enableBtn.setFixedSize(100, 50)
self.enableBtn.clicked.connect(self.enableBtnAction)
self.triggBtn = QPushButton(text = 'trigg Mtn')
self.triggBtn.setFixedSize(100, 50)
self.triggBtn.setEnabled(False)
self.triggBtn.setVisible(False)
self.triggBtn.clicked.connect(self.triggBtnAction)
self.zoomBtn = QPushButton(text = 'auto zoom')
self.zoomBtn.setFixedSize(100, 50)
self.zoomBtn.clicked.connect(self.zoomBtnAction)
self.zoomBtn.setEnabled(False)
self.zoomBtn.setVisible(False)
self.modeCombo = QComboBox()
self.modeCombo.setFixedSize(100, 50)
self.modeCombo.currentIndexChanged.connect(self.newModeIndexChanged)
self.modeCombo.addItem("CONT")
self.modeCombo.addItem("TRIGG")
self.modeCombo.setEnabled(False)
self.modeCombo.setVisible(False)
self.progressBar = QProgressBar()
self.progressBar.reset()
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(100) #100%
self.progressBar.setValue(0)
self.progressBar.setFixedHeight(20)
self.progressBar.setEnabled(False)
self.progressBar.setVisible(False)
# Fix layout
self.setGeometry(300, 300, 1200, 900)
@@ -367,17 +397,23 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
frameMotion = QFrame(self)
layoutMotionGrid = QGridLayout()
frameMotion.setLayout(layoutMotionGrid)
self.btnMotorRecord = QPushButton(text = 'Motor Record')
self.btnMotorRecord.clicked.connect(self.openMotorRecordPanel)
self.btnMotorRecord.setFixedSize(100, 50)
self.btnMotorRecord.setFixedSize(150, 50)
layoutMotionGrid.addWidget(self.btnMotorRecord,0,0)
self.btnCaQTDmAxisExpert = QPushButton(text = 'caqtdm ecmc Axis')
self.btnCaQTDmAxisExpert.clicked.connect(self.openCaQTDmAxisExpert)
self.btnCaQTDmAxisExpert.setFixedSize(150, 50)
layoutMotionGrid.addWidget(self.btnCaQTDmAxisExpert,1,0)
label = QLabel('Axis id:')
self.cmbBxSelectAxis = QComboBox()
self.cmbBxSelectAxis.currentIndexChanged.connect(self.changeAxisIndex)
layoutMotionGrid.addWidget(label,1,0)
layoutMotionGrid.addWidget(self.cmbBxSelectAxis,1,1)
layoutMotionGrid.addWidget(label,2,0)
layoutMotionGrid.addWidget(self.cmbBxSelectAxis,2,1)
layoutVertMain.addWidget(frameMotion)
@@ -432,10 +468,14 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
QCoreApplication.processEvents()
def sig_cb_PosAct_Arr(self,value):
if self.pause:
return
if(np.size(value)) > 0:
self.MtnYDataValid = True
def sig_cb_Time_Arr(self,value):
if self.pause:
return
if(np.size(value)) > 0:
self.MtnXDataValid = True
self.plotAll()
@@ -467,13 +507,13 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
if id >= 0:
self.cmbBxSelectAxis.setCurrentIndex(id)
axisPrefixPvName = self.pvPrefixStr + pvAxisPrefixNamePart1 + str(int(value)) + pvAxisPrefixNamePart2
axisPrefixPvName = self.pvPrefixStr + ":" + pvAxisPrefixNamePart1 + str(int(value)) + pvAxisPrefixNamePart2
prefixPV = epics.PV(axisPrefixPvName)
axisPrefix = prefixPV.get()
if axisPrefix is not None:
self.axisPrefix = axisPrefix
self.axisPrefix = axisPrefix.rstrip(':')
axisNamePvName = self.pvPrefixStr + pvAxisNamePart1 + str(int(value)) + pvAxisNamePart2
axisNamePvName = self.pvPrefixStr + ":" + pvAxisNamePart1 + str(int(value)) + pvAxisNamePart2
namePV = epics.PV(axisNamePvName)
axisName = namePV.get()
if axisName is not None:
@@ -488,6 +528,8 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
return
def sig_cb_Stat_Arr(self,value):
if self.pause:
return
data = self.parseAxisStatWd.convert(value)
self.addStatWdData(data)
@@ -521,7 +563,7 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
self.plotBinary()
def readAxisList(self):
axIdPV = epics.PV(self.pvPrefixStr + pvFistAxisIndexName)
axIdPV = epics.PV(self.pvPrefixStr + ":" + pvFistAxisIndexName)
axId = axIdPV.get()
if axId is None:
print('ERROR: First Axis Index PV not found.')
@@ -532,22 +574,34 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
while axId >= 0:
# Get next axis id
pvName = self.pvPrefixStr + pvNextAxisIndexNamePart1 + str(int(axId)) + pvNextAxisIndexNamePart2
pvName = self.pvPrefixStr + ":" + pvNextAxisIndexNamePart1 + str(int(axId)) + pvNextAxisIndexNamePart2
axIdPV = epics.PV(pvName)
axId = axIdPV.get()
if axId > 0:
self.cmbBxSelectAxis.addItem(str(int(ax)))
self.cmbBxSelectAxis.addItem(str(int(axId)))
def changeAxisIndex(self,xxx):
if self.cmbBxSelectAxis.currentData() is not None:
self.pvItems['AxCmd-RB'].pvPut(self.cmbBxSelectAxis.currentData(), use_complete=True)
def openMotorRecordPanel(self,xxx):
self.dialog = MotorPanel(self,self.axisPrefix ,self.axisName)
self.dialog.resize(500, 900)
self.dialog = MotorPanel(self,self.axisPrefix + ':' ,self.axisName)
self.dialog.resize(500, 900)
self.dialog.show()
def openCaQTDmAxisExpert(self,xxx):
# caqtdm -macro "IOC=$I,SYS=$S,Axis=$A" ecmcAxisExpert_v1.ui
caqtdmString = caqtdmExe + " -macro "
caqtdmMacros = "SYS=" + self.axisPrefix
caqtdmMacros += ",IOC=" + self.axisPrefix
caqtdmMacros += ",Axis=" + self.axisName
caqtdmString+= "\"" + caqtdmMacros + "\"" + " " + caqtdmAxisExpertPanelName
print(caqtdmString)
#subprocess.call(caqtdmString)
os.system(caqtdmString)
###### Widget callbacks
def pauseBtnAction(self):
self.pause = not self.pause
@@ -815,9 +869,9 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
def printOutHelp():
print("ecmcMtnMainGui: Plots waveforms of Mtn data (updates on Y data callback). ")
print("python ecmcMtnMainGui.py <prefix> <mtnId>")
print("<prefix>: Ioc prefix ('IOC_TEST:')")
print("<prefix>: Ioc prefix ('IOC_TEST')")
print("<mtnId> : Id of mtn plugin ('0')")
print("example : python ecmcMotionMainGui.py 'IOC_TEST:' '0'")
print("example : python ecmcMotionMainGui.py 'IOC_TEST' '0'")
print("Will connect to Pvs: <prefix>Plg-Mtn<mtnId>-*")
if __name__ == "__main__":

View File

@@ -1,7 +1,12 @@
#!/usr/bin/env python3.6
import epics
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
#from PyQt5 import QtWidgets, QtGui, QtCore
from ecmcArrayStat import *
#Define pvs

View File

@@ -4,7 +4,11 @@ import epics
import numpy as np
import time
import threading
from PyQt5.QtCore import *
#from PyQt5.QtCore import *
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import QObject
from PySide2.QtCore import Signal as pyqtSignal, Slot as pyqtSlot
class comSignal(QObject):
data_signal = pyqtSignal(object)

View File

@@ -15,11 +15,13 @@
import sys
import os
import epics
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
from PySide2 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
#from PyQt5.QtWidgets import *
#from PyQt5 import QtWidgets
#
#from PyQt5.QtCore import *
#from PyQt5.QtGui import *
import functools
import numpy as np
import random as rd

View File

@@ -15,10 +15,15 @@
import sys
import os
import ecmcRTCanvas
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
#from PyQt5.QtWidgets import *
#from PyQt5 import QtWidgets
#from PyQt5.QtCore import *
#from PyQt5.QtGui import *
import functools
import numpy as np
import random as rd

View File

@@ -18,10 +18,15 @@ import sys
import os
import epics
import ecmcTrend
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
#from PyQt5.QtWidgets import *
#from PyQt5 import QtWidgets
#from PyQt5.QtCore import *
#from PyQt5.QtGui import *
import functools
import numpy as np
import random as rd

View File

@@ -166,12 +166,14 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
self.pauseBtn.setFixedSize(100, 50)
self.pauseBtn.clicked.connect(self.pauseBtnAction)
self.pauseBtn.setStyleSheet("background-color: green")
self.openBtn = QPushButton(text = 'open data')
self.openBtn = QPushButton(text = 'open data')
self.openBtn.setFixedSize(100, 50)
self.openBtn.setEnabled(False) # Not yet supported
self.openBtn.clicked.connect(self.openBtnAction)
self.saveBtn = QPushButton(text = 'save data')
self.saveBtn.setFixedSize(100, 50)
self.saveBtn.clicked.connect(self.saveBtnAction)
self.saveBtn.setEnabled(False) # Not yet supported
self.enableBtn = QPushButton(text = 'enable Mtn')
self.enableBtn.setFixedSize(100, 50)
self.enableBtn.clicked.connect(self.enableBtnAction)
@@ -181,11 +183,13 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
self.zoomBtn = QPushButton(text = 'auto zoom')
self.zoomBtn.setFixedSize(100, 50)
self.zoomBtn.clicked.connect(self.zoomBtnAction)
self.zoomBtn.setEnabled(False) # Not yet supported
self.modeCombo = QComboBox()
self.modeCombo.setFixedSize(100, 50)
self.modeCombo.currentIndexChanged.connect(self.newModeIndexChanged)
self.modeCombo.addItem("CONT")
self.modeCombo.addItem("TRIGG")
self.modeCombo.addItem("TRIGG"
self.modeCombo.setEnabled(False)) # Not yet supported
self.progressBar = QProgressBar()
self.progressBar.reset()
self.progressBar.setMinimum(0)
@@ -334,63 +338,39 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
self.pv_signal_cbs['ElmCnt'].data_signal.emit(value)
def on_change_PosAct_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['PosAct-Arr'].data_signal.emit(value)
def on_change_PosSet_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
def on_change_PosSet_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
self.pv_signal_cbs['PosSet-Arr'].data_signal.emit(value)
def on_change_PosErr_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['PosErr-Arr'].data_signal.emit(value)
def on_change_Time_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['Time-Arr'].data_signal.emit(value)
def on_change_Ena_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['Ena-Arr'].data_signal.emit(value)
def on_change_EnaAct_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['EnaAct-Arr'].data_signal.emit(value)
def on_change_Bsy_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['Bsy-Arr'].data_signal.emit(value)
def on_change_Exe_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['Exe-Arr'].data_signal.emit(value)
def on_change_TrjSrc_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['TrjSrc-Arr'].data_signal.emit(value)
def on_change_EncSrc_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['EncSrc-Arr'].data_signal.emit(value)
def on_change_AtTrg_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['AtTrg-Arr'].data_signal.emit(value)
def on_change_ErrId_Arr(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
if self.pause:
return
self.pv_signal_cbs['ErrId-Arr'].data_signal.emit(value)
def on_change_Mde_RB(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):

22
tools/startGui.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/bash
# Install virt env and execute python GUI
P=$1
ID=$2
DIR=$3
ENV_DIR="${DIR=/tmp}"/.venv
if [ -d "${ENV_DIR}" ]; then
. "${ENV_DIR}"/bin/activate
else
python3 -m venv "${ENV_DIR}"
. "${ENV_DIR}"/bin/activate
pip3 install wheel
pip3 install matplotlib==3.
pip3 install PySide2 pyepics pyqtgraph numpy
fi
echo "Prefix=${P=c6025a-04}"
echo "plugin id=${ID=0}"
python3 ecmcMotionMainPyQtGraph.py ${P=c6025a-04} ${ID=0}

BIN
tools/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB