Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 104875d532 | |||
| 69fcd4da36 | |||
| 653d4aac02 | |||
| 0c19350ee5 | |||
| d47820b543 | |||
| 04ea63c8f4 | |||
| af297d71c4 | |||
| 1abf42ec4f | |||
| b1743a29b4 | |||
| 755ef8abe3 |
6
.gitignore
vendored
@@ -15,4 +15,8 @@ core.*
|
|||||||
*-loc/*.Makefile
|
*-loc/*.Makefile
|
||||||
ecmc_plugin_motion/*.Makefile
|
ecmc_plugin_motion/*.Makefile
|
||||||
*__*
|
*__*
|
||||||
O*
|
O*
|
||||||
|
tools/bin
|
||||||
|
tools/lib
|
||||||
|
tools/lib64
|
||||||
|
tools/pyvenv.cfg
|
||||||
|
|||||||
29
GNUmakefile
@@ -1,12 +1,14 @@
|
|||||||
include /ioc/tools/driver.makefile
|
include /ioc/tools/driver.makefile
|
||||||
|
|
||||||
MODULE = ecmc_plugin_motion
|
MODULE = ecmc_plugin_motion
|
||||||
|
# "Transfer" module name to plugin
|
||||||
|
USR_CFLAGS +=-DECMC_PLUGIN_MODULE_NAME=${MODULE}
|
||||||
|
|
||||||
BUILDCLASSES = Linux
|
BUILDCLASSES = Linux
|
||||||
ARCH_FILTER = deb10%
|
ARCH_FILTER = deb10% deb12%
|
||||||
|
|
||||||
# Run 7.0.6 for now
|
# 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 7.0.9
|
||||||
|
|
||||||
IGNORE_MODULES += asynMotor
|
IGNORE_MODULES += asynMotor
|
||||||
IGNORE_MODULES += motorBase
|
IGNORE_MODULES += motorBase
|
||||||
@@ -16,18 +18,23 @@ OPT_CXXFLAGS_YES = -O3
|
|||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
ECmasterECMC_VERSION = v1.1.0
|
ECmasterECMC_VERSION = v1.1.0
|
||||||
#motorECMC_VERSION = 7.0.7-ESS
|
ecmc_VERSION = 10.0
|
||||||
ecmc_VERSION = 9.5.0
|
|
||||||
|
|
||||||
################################################################################
|
# ethercat
|
||||||
# THIS RELATES TO THE EtherCAT MASTER LIBRARY
|
EC_BASE_PATH = /ioc/NeedfulThings/EtherCAT/4epics/
|
||||||
# IT IS OF PARAMOUNT IMPORTANCE TO LOAD THE PROPER KERNEL MODULE
|
USR_CXXFLAGS_deb12-x86_64 += -I${EC_BASE_PATH}${T_A}/include/
|
||||||
# ################################################################################
|
USR_CXXFLAGS_deb12-x86_64 += -L${EC_BASE_PATH}${T_A}/lib/
|
||||||
USR_LDFLAGS += -lethercat
|
|
||||||
|
|
||||||
|
OPT_CXXFLAGS_YES = -O3
|
||||||
|
|
||||||
|
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/
|
||||||
|
|
||||||
|
USR_LDFLAGS_deb10-x86_64 += -lethercat
|
||||||
EC_MASTER_LIB = ${EPICS_MODULES}/ECmasterECMC/${ECmasterECMC_VERSION}/R${EPICSVERSION}/lib/${T_A}
|
EC_MASTER_LIB = ${EPICS_MODULES}/ECmasterECMC/${ECmasterECMC_VERSION}/R${EPICSVERSION}/lib/${T_A}
|
||||||
USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB}
|
USR_LDFLAGS_deb10-x86_64 += -Wl,-rpath=${EC_MASTER_LIB}
|
||||||
USR_LDFLAGS += -L ${EC_MASTER_LIB}
|
USR_LDFLAGS_deb10-x86_64 += -L ${EC_MASTER_LIB}
|
||||||
|
|
||||||
BASE_DIR = .
|
BASE_DIR = .
|
||||||
SRC_DIR = $(BASE_DIR)/src
|
SRC_DIR = $(BASE_DIR)/src
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ 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_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};")
|
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}")
|
dbLoadRecords(${ecmc_plugin_motion_TEMPLATES}ecmcPluginMotion.template,"P=$(IOC):,INDEX=${ECMC_PLG_MOTION_OBJ_INDEX=0},NELM=${BUFF_SIZE=1000}")
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,16 @@
|
|||||||
* Created on: july 10, 2023
|
* Created on: july 10, 2023
|
||||||
* Author: anderssandstrom
|
* 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...
|
// Needed to get headers in ecmc right...
|
||||||
#define ECMC_IS_PLUGIN
|
#define ECMC_IS_PLUGIN
|
||||||
#define ECMC_EXAMPLE_PLUGIN_VERSION 2
|
#define ECMC_PLUGIN_VERSION 2
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -30,15 +35,13 @@ static int lastEcmcError = 0;
|
|||||||
static char* lastConfStr = NULL;
|
static char* lastConfStr = NULL;
|
||||||
|
|
||||||
/** Optional.
|
/** 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.
|
* Return value other than 0 will be considered error.
|
||||||
* configStr can be used for configuration parameters.
|
* 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
|
//This module is allowed to load several times so no need to check if loaded
|
||||||
|
|
||||||
// create FFT object and register data callback
|
|
||||||
lastConfStr = strdup(configStr);
|
lastConfStr = strdup(configStr);
|
||||||
return createMotionObj(configStr);
|
return createMotionObj(configStr);
|
||||||
}
|
}
|
||||||
@@ -46,31 +49,27 @@ int motionConstruct(char *configStr)
|
|||||||
/** Optional function.
|
/** Optional function.
|
||||||
* Will be called once at unload.
|
* Will be called once at unload.
|
||||||
**/
|
**/
|
||||||
void motionDestruct(void)
|
static void motionDestruct(void)
|
||||||
{
|
{
|
||||||
//deleteAllMotionObjs();
|
|
||||||
//if(lastConfStr){
|
|
||||||
// free(lastConfStr);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Optional function.
|
/** Optional function.
|
||||||
* Will be called each realtime cycle if definded
|
* Will be called each realtime cycle if defined
|
||||||
* ecmcError: Error code of ecmc. Makes it posible for
|
* ecmcError: Error code of ecmc. Makes it possible for
|
||||||
* this plugin to react on ecmc errors
|
* this plugin to react on ecmc errors
|
||||||
* Return value other than 0 will be considered to be an error code in ecmc.
|
* 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();
|
executeMotionObjs();
|
||||||
lastEcmcError = ecmcError;
|
lastEcmcError = ecmcError;
|
||||||
return 0;
|
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)
|
* (for example ecmc PLC variables are defined only at enter of realtime)
|
||||||
**/
|
**/
|
||||||
int motionEnterRT(){
|
static int motionEnterRT(){
|
||||||
return linkDataTomotionObjs();
|
return linkDataTomotionObjs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,41 +77,17 @@ int motionEnterRT(){
|
|||||||
* Will be called once just before leaving realtime mode
|
* Will be called once just before leaving realtime mode
|
||||||
* Return value other than 0 will be considered error.
|
* Return value other than 0 will be considered error.
|
||||||
**/
|
**/
|
||||||
int motionExitRT(void){
|
static int motionExitRT(void){
|
||||||
return 0;
|
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
|
// Register data for plugin so ecmc know what to use
|
||||||
struct ecmcPluginData pluginDataDef = {
|
static struct ecmcPluginData pluginDataDef = {
|
||||||
|
|
||||||
// Allways use ECMC_PLUG_VERSION_MAGIC
|
// Allways use ECMC_PLUG_VERSION_MAGIC
|
||||||
.ifVersion = ECMC_PLUG_VERSION_MAGIC,
|
.ifVersion = ECMC_PLUG_VERSION_MAGIC,
|
||||||
// Name
|
// Name
|
||||||
.name = "ecmcPlugin_Motion",
|
.name = "ecmc_plugin_motion",
|
||||||
// Description
|
// Description
|
||||||
.desc = "Motion plugin for commissioning of ecmc motion axes.",
|
.desc = "Motion plugin for commissioning of ecmc motion axes.",
|
||||||
// Option description
|
// Option description
|
||||||
@@ -123,171 +98,20 @@ struct ecmcPluginData pluginDataDef = {
|
|||||||
" "ECMC_PLUGIN_MODE_OPTION_CMD"<TRIGG/CONT> : Sampling rate in Hz"
|
" "ECMC_PLUGIN_MODE_OPTION_CMD"<TRIGG/CONT> : Sampling rate in Hz"
|
||||||
,
|
,
|
||||||
// Plugin version
|
// Plugin version
|
||||||
.version = ECMC_EXAMPLE_PLUGIN_VERSION,
|
.version = ECMC_PLUGIN_VERSION,
|
||||||
// Optional construct func, called once at load. NULL if not definded.
|
// Optional construct func, called once at load. NULL if not defined.
|
||||||
.constructFnc = motionConstruct,
|
.constructFnc = construct,
|
||||||
// Optional destruct func, called once at unload. NULL if not definded.
|
// Optional destruct func, called once at unload. NULL if not defined.
|
||||||
.destructFnc = motionDestruct,
|
.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,
|
.realtimeFnc = motionRealtime,
|
||||||
// Optional func that will be called once just before enter realtime mode
|
// Optional func that will be called once just before enter realtime mode
|
||||||
.realtimeEnterFnc = motionEnterRT,
|
.realtimeEnterFnc = motionEnterRT,
|
||||||
// Optional func that will be called once just before exit realtime mode
|
// Optional func that will be called once just before exit realtime mode
|
||||||
.realtimeExitFnc = motionExitRT,
|
.realtimeExitFnc = motionExitRT,
|
||||||
// PLC funcs
|
// 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..
|
.funcs[0] = {0}, // last element set all to zero..
|
||||||
// PLC consts
|
// 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..
|
.consts[0] = {0}, // last element set all to zero..
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,8 @@
|
|||||||
#-###############################################################################
|
#-###############################################################################
|
||||||
#-
|
#-
|
||||||
#- Arguments
|
#- Arguments
|
||||||
#- [mandatory]
|
|
||||||
#- PLUGIN_ID = Plugin instansiation index, must be unique for each call
|
|
||||||
#-
|
|
||||||
#- [optional]
|
#- [optional]
|
||||||
|
#- PLUGIN_ID = Plugin instansiation index, must be unique for each call defaults to 0
|
||||||
#- AX = Axis id, default 1
|
#- AX = Axis id, default 1
|
||||||
#- BUFF_SIZE = Buffer size, default 1000
|
#- BUFF_SIZE = Buffer size, default 1000
|
||||||
#- DBG = Debug mode, default 1
|
#- 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.
|
# 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
|
#- 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" ,"#")
|
epicsEnvSet("ECMC_PLG_MOTION_INIT" ,"#")
|
||||||
|
|||||||
BIN
tools/cos_ff_trq_test.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
tools/cos_ff_trq_test_2.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
tools/cos_ff_trq_test_adaptive.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
tools/cos_ff_trq_test_adaptive_2.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
tools/cos_ff_trq_test_adaptive_3.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
tools/cos_ff_trq_test_adaptive_4.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
tools/cos_ff_trq_test_adaptive_5.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
tools/delay0.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
tools/delay0_kx0.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
tools/delay10_kx0.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
tools/delay1_kx0.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
tools/delay2.5.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
tools/delay2.5_kx0.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
tools/delay2_kx0.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
tools/delay3_kx0.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
tools/delay4_kx0.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
@@ -2,12 +2,16 @@
|
|||||||
import sys
|
import sys
|
||||||
import epics
|
import epics
|
||||||
import numpy as np
|
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 import QtCore,QtWidgets, QtGui
|
||||||
from PyQt5.QtCore import *
|
#from PyQt5.QtWidgets import *
|
||||||
from PyQt5.QtCore import QObject
|
#from PyQt5.QtCore import *
|
||||||
from PyQt5.QtGui import *
|
#from PyQt5.QtCore import QObject
|
||||||
|
#from PyQt5.QtGui import *
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import ecmcTrend
|
import ecmcTrend
|
||||||
|
|||||||
@@ -1,852 +0,0 @@
|
|||||||
#*************************************************************************
|
|
||||||
# Copyright (c) 2020 European Spallation Source ERIC
|
|
||||||
# ecmc is distributed subject to a Software License Agreement found
|
|
||||||
# in file LICENSE that is included with this distribution.
|
|
||||||
#
|
|
||||||
# ecmcMtnMainGui.py
|
|
||||||
#
|
|
||||||
# Created on: October 6, 2020
|
|
||||||
# Author: Anders Sandström
|
|
||||||
#
|
|
||||||
# Plots two waveforms (x vs y) updates for each callback on the y-pv
|
|
||||||
#
|
|
||||||
#*************************************************************************
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import epics
|
|
||||||
from PyQt5.QtWidgets import *
|
|
||||||
from PyQt5 import QtWidgets
|
|
||||||
from PyQt5.QtCore import *
|
|
||||||
from PyQt5.QtGui import *
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib
|
|
||||||
matplotlib.use("Qt5Agg")
|
|
||||||
from matplotlib.figure import Figure
|
|
||||||
from matplotlib.animation import TimedAnimation
|
|
||||||
from matplotlib.lines import Line2D
|
|
||||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
||||||
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import threading
|
|
||||||
|
|
||||||
# Allow buffering of 10s data, need to add setting for this
|
|
||||||
xMaxTime = 10
|
|
||||||
|
|
||||||
# List of pv names
|
|
||||||
pvlist = [ 'BuffSze',
|
|
||||||
'ElmCnt',
|
|
||||||
'PosAct-Arr',
|
|
||||||
'PosSet-Arr',
|
|
||||||
'PosErr-Arr',
|
|
||||||
'Time-Arr',
|
|
||||||
'Ena-Arr',
|
|
||||||
'EnaAct-Arr',
|
|
||||||
'Bsy-Arr',
|
|
||||||
'Exe-Arr',
|
|
||||||
'TrjSrc-Arr',
|
|
||||||
'EncSrc-Arr',
|
|
||||||
'AtTrg-Arr',
|
|
||||||
'ErrId-Arr',
|
|
||||||
'Mde-RB',
|
|
||||||
'Cmd-RB',
|
|
||||||
'Stat',
|
|
||||||
'AxCmd-RB',
|
|
||||||
'SmpHz-RB',
|
|
||||||
'TrgCmd-RB',
|
|
||||||
'EnaCmd-RB' ]
|
|
||||||
|
|
||||||
pvAnalog = ['PosAct-Arr',
|
|
||||||
'PosSet-Arr',
|
|
||||||
'PosErr-Arr',
|
|
||||||
'ErrId-Arr']
|
|
||||||
|
|
||||||
pvBinary = ['Ena-Arr',
|
|
||||||
'EnaAct-Arr',
|
|
||||||
'Bsy-Arr',
|
|
||||||
'Exe-Arr',
|
|
||||||
'TrjSrc-Arr',
|
|
||||||
'EncSrc-Arr',
|
|
||||||
'AtTrg-Arr']
|
|
||||||
|
|
||||||
pvmiddlestring='Plg-Mtn'
|
|
||||||
|
|
||||||
class comSignal(QObject):
|
|
||||||
data_signal = pyqtSignal(object)
|
|
||||||
|
|
||||||
class ecmcMtnMainGui(QtWidgets.QDialog):
|
|
||||||
def __init__(self,prefix=None,mtnPluginId=None):
|
|
||||||
super(ecmcMtnMainGui, self).__init__()
|
|
||||||
|
|
||||||
self.pvnames = {}
|
|
||||||
self.pvs = {}
|
|
||||||
self.pv_signal_cbs = {}
|
|
||||||
self.data = {}
|
|
||||||
self.datalength = {}
|
|
||||||
self.plottedLineAnalog = {}
|
|
||||||
self.plottedLineBinary = {}
|
|
||||||
|
|
||||||
for pv in pvAnalog:
|
|
||||||
self.plottedLineAnalog[pv] = None
|
|
||||||
|
|
||||||
for pv in pvBinary:
|
|
||||||
self.plottedLineBinary[pv] = None
|
|
||||||
|
|
||||||
for pv in pvlist:
|
|
||||||
self.data[pv] = None
|
|
||||||
self.datalength[pv] = 0
|
|
||||||
|
|
||||||
#Set some default plot colours
|
|
||||||
self.plotColor={}
|
|
||||||
# Analog
|
|
||||||
self.plotColor['PosAct-Arr']='g'
|
|
||||||
self.plotColor['PosSet-Arr']='b'
|
|
||||||
self.plotColor['PosErr-Arr']='k'
|
|
||||||
self.plotColor['ErrId-Arr']='r'
|
|
||||||
|
|
||||||
# Binary
|
|
||||||
self.plotColor['Ena-Arr']='b'
|
|
||||||
self.plotColor['EnaAct-Arr']='c'
|
|
||||||
self.plotColor['Bsy-Arr']='r'
|
|
||||||
self.plotColor['Exe-Arr']='m'
|
|
||||||
self.plotColor['TrjSrc-Arr']='y'
|
|
||||||
self.plotColor['EncSrc-Arr']='k'
|
|
||||||
self.plotColor['AtTrg-Arr']='g'
|
|
||||||
|
|
||||||
self.offline = False
|
|
||||||
self.pvPrefixStr = prefix
|
|
||||||
self.pvPrefixOrigStr = prefix # save for restore after open datafile
|
|
||||||
self.mtnPluginId = mtnPluginId
|
|
||||||
self.mtnPluginOrigId = mtnPluginId
|
|
||||||
self.allowSave = False
|
|
||||||
self.path = '.'
|
|
||||||
self.unitAnalogY = "[]"
|
|
||||||
self.unitBinaryY = "[]"
|
|
||||||
self.labelBinaryY = "Binary"
|
|
||||||
self.labelAnalogY = "Analog"
|
|
||||||
self.title = ""
|
|
||||||
#self.NMtn = 1024
|
|
||||||
self.sampleRate = 1000
|
|
||||||
self.sampleRateValid = False
|
|
||||||
self.MtnYDataValid = False
|
|
||||||
self.MtnXDataValid = False
|
|
||||||
|
|
||||||
if prefix is None or mtnPluginId is None:
|
|
||||||
self.offline = True
|
|
||||||
self.pause = True
|
|
||||||
self.data['EnaCmd-RB'] = False
|
|
||||||
else:
|
|
||||||
#Check for connection else go offline
|
|
||||||
self.buildPvNames()
|
|
||||||
connected = self.pvs['BuffSze'].wait_for_connection(timeout=2)
|
|
||||||
if connected:
|
|
||||||
self.offline = False
|
|
||||||
self.pause = False
|
|
||||||
else:
|
|
||||||
self.offline = True
|
|
||||||
self.pause = True
|
|
||||||
self.data['EnaCmd-RB'] = False
|
|
||||||
|
|
||||||
self.startupDone=False
|
|
||||||
self.pause = 0
|
|
||||||
self.createWidgets()
|
|
||||||
self.setStatusOfWidgets()
|
|
||||||
self.resize(1000,850)
|
|
||||||
return
|
|
||||||
|
|
||||||
def createWidgets(self):
|
|
||||||
self.figure = plt.figure()
|
|
||||||
#self.plottedLineAnalog = None
|
|
||||||
#self.plottedLineBinary = None
|
|
||||||
self.axAnalog = None
|
|
||||||
self.axBinary = None
|
|
||||||
self.canvas = FigureCanvas(self.figure)
|
|
||||||
self.toolbar = NavigationToolbar(self.canvas, self)
|
|
||||||
self.pauseBtn = QPushButton(text = 'pause')
|
|
||||||
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.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)
|
|
||||||
self.triggBtn = QPushButton(text = 'trigg Mtn')
|
|
||||||
self.triggBtn.setFixedSize(100, 50)
|
|
||||||
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) # 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.setEnabled(False)) # Not yet supported
|
|
||||||
self.progressBar = QProgressBar()
|
|
||||||
self.progressBar.reset()
|
|
||||||
self.progressBar.setMinimum(0)
|
|
||||||
self.progressBar.setMaximum(100) #100%
|
|
||||||
self.progressBar.setValue(0)
|
|
||||||
self.progressBar.setFixedHeight(20)
|
|
||||||
|
|
||||||
# Fix layout
|
|
||||||
self.setGeometry(300, 300, 900, 700)
|
|
||||||
|
|
||||||
layoutVert = QVBoxLayout()
|
|
||||||
layoutVert.addWidget(self.toolbar)
|
|
||||||
layoutVert.addWidget(self.canvas)
|
|
||||||
|
|
||||||
layoutControl = QHBoxLayout()
|
|
||||||
layoutControl.addWidget(self.pauseBtn)
|
|
||||||
layoutControl.addWidget(self.enableBtn)
|
|
||||||
layoutControl.addWidget(self.triggBtn)
|
|
||||||
layoutControl.addWidget(self.modeCombo)
|
|
||||||
layoutControl.addWidget(self.zoomBtn)
|
|
||||||
layoutControl.addWidget(self.saveBtn)
|
|
||||||
layoutControl.addWidget(self.openBtn)
|
|
||||||
|
|
||||||
frameControl = QFrame(self)
|
|
||||||
frameControl.setFixedHeight(70)
|
|
||||||
frameControl.setLayout(layoutControl)
|
|
||||||
|
|
||||||
|
|
||||||
layoutVert.addWidget(frameControl)
|
|
||||||
layoutVert.addWidget(self.progressBar)
|
|
||||||
self.setLayout(layoutVert)
|
|
||||||
|
|
||||||
def setStatusOfWidgets(self):
|
|
||||||
self.saveBtn.setEnabled(self.allowSave)
|
|
||||||
if self.offline:
|
|
||||||
self.enableBtn.setStyleSheet("background-color: grey")
|
|
||||||
self.enableBtn.setEnabled(False)
|
|
||||||
self.pauseBtn.setStyleSheet("background-color: grey")
|
|
||||||
self.pauseBtn.setEnabled(False)
|
|
||||||
self.modeCombo.setEnabled(False)
|
|
||||||
self.triggBtn.setEnabled(False)
|
|
||||||
self.setWindowTitle("ecmc Mtn Main plot: Offline")
|
|
||||||
else:
|
|
||||||
self.modeCombo.setEnabled(True)
|
|
||||||
# Check actual value of pvs
|
|
||||||
enable = self.pvs['EnaCmd-RB'].get()
|
|
||||||
if enable is None:
|
|
||||||
print("pvs['EnaCmd-RB'].get() failed")
|
|
||||||
return
|
|
||||||
if(enable>0):
|
|
||||||
self.enableBtn.setStyleSheet("background-color: green")
|
|
||||||
self.data['EnaCmd-RB'] = True
|
|
||||||
else:
|
|
||||||
self.enableBtn.setStyleSheet("background-color: red")
|
|
||||||
self.data['EnaCmd-RB'] = False
|
|
||||||
|
|
||||||
#self.sourceStr = self.pvSource.get(as_string=True)
|
|
||||||
#if self.sourceStr is None:
|
|
||||||
# print("pvSource.get() failed")
|
|
||||||
# return
|
|
||||||
|
|
||||||
self.sampleRate = self.pvs['SmpHz-RB'].get()
|
|
||||||
if self.sampleRate is None:
|
|
||||||
print("pvs['SmpHz-RB'].get() failed")
|
|
||||||
return
|
|
||||||
self.sampleRateValid = True
|
|
||||||
|
|
||||||
# calc x Array
|
|
||||||
step=1/self.sampleRate
|
|
||||||
|
|
||||||
self.x = np.arange(-xMaxTime-step,0+step,step)
|
|
||||||
print('x')
|
|
||||||
print(self.x)
|
|
||||||
|
|
||||||
self.data['Mde-RB'] = self.pvs['Mde-RB'].get()
|
|
||||||
if self.data['Mde-RB'] is None:
|
|
||||||
print("pvs['Mde-RB'].get() failed")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.modeStr = "NO_MODE"
|
|
||||||
self.triggBtn.setEnabled(False) # Only enable if mode = TRIGG = 2
|
|
||||||
if self.data['Mde-RB'] == 1:
|
|
||||||
self.modeStr = "CONT"
|
|
||||||
self.modeCombo.setCurrentIndex(self.data['Mde-RB']-1) # Index starta t zero
|
|
||||||
|
|
||||||
if self.data['Mde-RB'] == 2:
|
|
||||||
self.modeStr = "TRIGG"
|
|
||||||
self.triggBtn.setEnabled(True)
|
|
||||||
self.modeCombo.setCurrentIndex(self.data['Mde-RB']-1) # Index starta t zero
|
|
||||||
|
|
||||||
self.setWindowTitle("ecmc Mtn Main plot: prefix=" + self.pvPrefixStr + " , mtnId=" + str(self.mtnPluginId) +
|
|
||||||
", rate=" + str(self.sampleRate))
|
|
||||||
|
|
||||||
def addData(self, pvName, values):
|
|
||||||
# Check if first assignment
|
|
||||||
if self.data[pvName] is None:
|
|
||||||
self.data[pvName] = values
|
|
||||||
return
|
|
||||||
|
|
||||||
self.data[pvName]=np.append(self.data[pvName],values)
|
|
||||||
# check if delete in beginning is needed
|
|
||||||
currcount = len(self.data[pvName])
|
|
||||||
if self.sampleRateValid:
|
|
||||||
allowedcount = int(xMaxTime * self.sampleRate)
|
|
||||||
else:
|
|
||||||
print('Warning sample rate not defined, fallback to max 10000 values')
|
|
||||||
allowedcount = 10000
|
|
||||||
|
|
||||||
# remove if needed
|
|
||||||
if currcount > allowedcount:
|
|
||||||
self.data[pvName]=self.data[pvName][currcount-allowedcount:]
|
|
||||||
|
|
||||||
self.datalength[pvName] = len(self.data[pvName])
|
|
||||||
|
|
||||||
|
|
||||||
def buildPvNames(self):
|
|
||||||
# Pv names based on structure: <prefix>Plugin-Mtn<mtnPluginId>-<suffixname>
|
|
||||||
for pv in pvlist:
|
|
||||||
self.pvnames[pv]=self.buildPvName(pv)
|
|
||||||
if self.pvnames[pv] is None:
|
|
||||||
raise RuntimeError("pvname must not be 'None'")
|
|
||||||
if len(self.pvnames[pv])==0:
|
|
||||||
raise RuntimeError("pvname must not be ''")
|
|
||||||
self.pvs[pv] = epics.PV(self.pvnames[pv])
|
|
||||||
self.pv_signal_cbs[pv] = comSignal()
|
|
||||||
|
|
||||||
# Signal callbacks (update gui)
|
|
||||||
# replace any '-' with '_' since '-' not allowed in funcion names
|
|
||||||
sig_cb_func=getattr(self,'sig_cb_' + pv.replace('-','_'))
|
|
||||||
self.pv_signal_cbs[pv].data_signal.connect(sig_cb_func)
|
|
||||||
|
|
||||||
# Pv monitor callbacks
|
|
||||||
mon_cb_func=getattr(self,'on_change_' + pv.replace('-','_'))
|
|
||||||
self.pvs[pv].add_callback(mon_cb_func)
|
|
||||||
|
|
||||||
QCoreApplication.processEvents()
|
|
||||||
|
|
||||||
def buildPvName(self, suffixname):
|
|
||||||
return self.pvPrefixStr + pvmiddlestring + str(self.mtnPluginId) + '-' + suffixname
|
|
||||||
|
|
||||||
###### Pv monitor callbacks
|
|
||||||
def on_change_BuffSze(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
self.pv_signal_cbs['BuffSze'].data_signal.emit(value)
|
|
||||||
|
|
||||||
def on_change_ElmCnt(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
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):
|
|
||||||
self.pv_signal_cbs['Mde-RB'].data_signal.emit(value)
|
|
||||||
|
|
||||||
def on_change_Cmd_RB(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
self.pv_signal_cbs['Cmd-RB'].data_signal.emit(value)
|
|
||||||
|
|
||||||
def on_change_Stat(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
self.pv_signal_cbs['Stat'].data_signal.emit(value)
|
|
||||||
|
|
||||||
def on_change_AxCmd_RB(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
self.pv_signal_cbs['AxCmd-RB'].data_signal.emit(value)
|
|
||||||
|
|
||||||
def on_change_SmpHz_RB(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
self.pv_signal_cbs['SmpHz-RB'].data_signal.emit(value)
|
|
||||||
|
|
||||||
def on_change_TrgCmd_RB(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
self.pv_signal_cbs['TrgCmd-RB'].data_signal.emit(value)
|
|
||||||
|
|
||||||
def on_change_EnaCmd_RB(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
self.pv_signal_cbs['EnaCmd-RB'].data_signal.emit(value)
|
|
||||||
|
|
||||||
# def onChangePvMode(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
# if self.pause:
|
|
||||||
# return
|
|
||||||
# self.comSignalMode.data_signal.emit(value)
|
|
||||||
#
|
|
||||||
# def onChangePvEnable(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
# if self.pause:
|
|
||||||
# return
|
|
||||||
# self.comSignalEnable.data_signal.emit(value)
|
|
||||||
#
|
|
||||||
# def onChangeX(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
# if self.pause:
|
|
||||||
# return
|
|
||||||
# self.comSignalX.data_signal.emit(value)
|
|
||||||
#
|
|
||||||
# def onChangePvSpectY(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
# if self.pause:
|
|
||||||
# return
|
|
||||||
# self.comSignalSpectY.data_signal.emit(value)
|
|
||||||
#
|
|
||||||
# def onChangePvrawData(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
# if self.pause:
|
|
||||||
# return
|
|
||||||
# self.comSignalRawData.data_signal.emit(value)
|
|
||||||
#
|
|
||||||
# def onChangePvBuffIdAct(self,pvname=None, value=None, char_value=None,timestamp=None, **kw):
|
|
||||||
# if self.pause:
|
|
||||||
# return
|
|
||||||
# self.comSignalBuffIdAct.data_signal.emit(value)
|
|
||||||
|
|
||||||
###### Signal callbacks
|
|
||||||
def sig_cb_BuffSze(self,value):
|
|
||||||
self.data['BuffSze'] = value
|
|
||||||
|
|
||||||
def sig_cb_ElmCnt(self,value):
|
|
||||||
self.data['ElmCnt'] = value
|
|
||||||
|
|
||||||
def sig_cb_PosAct_Arr(self,value):
|
|
||||||
if(np.size(value)) > 0:
|
|
||||||
self.MtnYDataValid = True
|
|
||||||
self.addData('PosAct-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_PosSet_Arr(self,value):
|
|
||||||
self.addData('PosSet-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_PosErr_Arr(self,value):
|
|
||||||
self.addData('PosErr-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_Time_Arr(self,value):
|
|
||||||
if(np.size(value)) > 0:
|
|
||||||
self.addData('Time-Arr', value)
|
|
||||||
self.MtnXDataValid = True
|
|
||||||
self.plotAll()
|
|
||||||
return
|
|
||||||
|
|
||||||
def sig_cb_Ena_Arr(self,value):
|
|
||||||
self.addData('Ena-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_EnaAct_Arr(self,value):
|
|
||||||
self.addData('EnaAct-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_Bsy_Arr(self,value):
|
|
||||||
self.addData('Bsy-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_Exe_Arr(self,value):
|
|
||||||
self.addData('Exe-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_TrjSrc_Arr(self,value):
|
|
||||||
self.addData('TrjSrc-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_EncSrc_Arr(self,value):
|
|
||||||
self.addData('EncSrc-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_AtTrg_Arr(self,value):
|
|
||||||
self.addData('AtTrg-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_ErrId_Arr(self,value):
|
|
||||||
self.addData('ErrId-Arr', value)
|
|
||||||
|
|
||||||
def sig_cb_Mde_RB(self,value):
|
|
||||||
if value < 1 or value> 2:
|
|
||||||
self.modeStr = "NO_MODE"
|
|
||||||
print('callbackFuncMode: Error Invalid mode.')
|
|
||||||
return
|
|
||||||
|
|
||||||
self.data['Mde-RB'] = value
|
|
||||||
self.modeCombo.setCurrentIndex(self.data['Mde-RB']-1) # Index starta t zero
|
|
||||||
|
|
||||||
if self.data['Mde-RB'] == 1:
|
|
||||||
self.modeStr = "CONT"
|
|
||||||
self.triggBtn.setEnabled(False) # Only enable if mode = TRIGG = 2
|
|
||||||
|
|
||||||
if self.data['Mde-RB'] == 2:
|
|
||||||
self.modeStr = "TRIGG"
|
|
||||||
self.triggBtn.setEnabled(True)
|
|
||||||
return
|
|
||||||
|
|
||||||
def sig_cb_Cmd_RB(self,value):
|
|
||||||
self.data['Cmd-RB'] = value
|
|
||||||
|
|
||||||
def sig_cb_Stat(self,value):
|
|
||||||
self.data['Stat'] = value
|
|
||||||
|
|
||||||
def sig_cb_AxCmd_RB(self,value):
|
|
||||||
self.data['AxCmd-RB'] = value
|
|
||||||
|
|
||||||
def sig_cb_SmpHz_RB(self,value):
|
|
||||||
self.data['SmpHz-RB'] = value
|
|
||||||
|
|
||||||
def sig_cb_TrgCmd_RB(self,value):
|
|
||||||
self.data['TrgCmd-RB'] = value
|
|
||||||
|
|
||||||
def sig_cb_EnaCmd_RB(self,value):
|
|
||||||
self.data['EnaCmd-RB'] = value
|
|
||||||
|
|
||||||
self.data['EnaCmd-RB'] = value
|
|
||||||
if self.data['EnaCmd-RB']:
|
|
||||||
self.enableBtn.setStyleSheet("background-color: green")
|
|
||||||
else:
|
|
||||||
self.enableBtn.setStyleSheet("background-color: red")
|
|
||||||
self.data['EnaCmd-RB'] = value
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# def callbackFuncSpectY(self, value):
|
|
||||||
# if(np.size(value)) > 0:
|
|
||||||
#
|
|
||||||
# self.spectY = value
|
|
||||||
# self.MtnYDataValid = self.RawXDataValid
|
|
||||||
# self.plotAll()
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# def callbackFuncrawData(self, value):
|
|
||||||
# if(np.size(value)) > 0:
|
|
||||||
# if (self.data['Time-Arr'] is None or np.size(value) != np.size(self.rawdataY)) and self.sampleRateValid:
|
|
||||||
# self.data['Time-Arr'] = np.arange(-np.size(value)/self.sampleRate, 0, 1/self.sampleRate)
|
|
||||||
# self.RawXDataValid = True
|
|
||||||
#
|
|
||||||
# self.rawdataY = value
|
|
||||||
# self.RawYDataValid = True
|
|
||||||
# self.plotAll()
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# def callbackFuncBuffIdAct(self, value):
|
|
||||||
# if self.NMtn is None:
|
|
||||||
# return
|
|
||||||
# if(self.NMtn>0):
|
|
||||||
# self.progressBar.setValue(value/self.NMtn*100)
|
|
||||||
# if value/self.NMtn*100 < 80 and value/self.NMtn*100 >1:
|
|
||||||
# self.MtnYDataValid = False
|
|
||||||
# self.RawYDataValid = False
|
|
||||||
# return
|
|
||||||
|
|
||||||
###### Widget callbacks
|
|
||||||
def pauseBtnAction(self):
|
|
||||||
self.pause = not self.pause
|
|
||||||
if self.pause:
|
|
||||||
self.pauseBtn.setStyleSheet("background-color: red")
|
|
||||||
else:
|
|
||||||
self.pvPrefixStr = self.pvPrefixOrigStr # Restore if dataset was opened
|
|
||||||
self.mtnPluginId = self.mtnPluginOrigId # Restore if dataset was opened
|
|
||||||
self.buildPvNames()
|
|
||||||
|
|
||||||
self.pauseBtn.setStyleSheet("background-color: green")
|
|
||||||
# Retrigger plots with newest values
|
|
||||||
#self.comSignalSpectY.data_signal.emit(self.spectY)
|
|
||||||
#self.comSignalRawData.data_signal.emit(self.rawdataY)
|
|
||||||
return
|
|
||||||
|
|
||||||
def enableBtnAction(self):
|
|
||||||
self.data['EnaCmd-RB'] = not self.data['EnaCmd-RB']
|
|
||||||
self.pvs['EnaCmd-RB'].put(self.data['EnaCmd-RB'])
|
|
||||||
if self.data['EnaCmd-RB']:
|
|
||||||
self.enableBtn.setStyleSheet("background-color: green")
|
|
||||||
else:
|
|
||||||
self.enableBtn.setStyleSheet("background-color: red")
|
|
||||||
return
|
|
||||||
|
|
||||||
def triggBtnAction(self):
|
|
||||||
self.pvTrigg.put(True)
|
|
||||||
return
|
|
||||||
|
|
||||||
def zoomBtnAction(self):
|
|
||||||
if self.data['Time-Arr'] is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.data['PosAct-Arr'] is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.plotAnalog(True)
|
|
||||||
self.plotBinary(True)
|
|
||||||
return
|
|
||||||
|
|
||||||
def newModeIndexChanged(self,index):
|
|
||||||
if index==0 or index==1:
|
|
||||||
if not self.offline and self.pvs['Mde-RB'] is not None:
|
|
||||||
self.pvs['Mde-RB'].put(index+1)
|
|
||||||
return
|
|
||||||
|
|
||||||
def openBtnAction(self):
|
|
||||||
#if not self.offline:
|
|
||||||
# self.pause = 1 # pause while open if online
|
|
||||||
# self.pauseBtn.setStyleSheet("background-color: red")
|
|
||||||
# QCoreApplication.processEvents()
|
|
||||||
#
|
|
||||||
#fname = QFileDialog.getOpenFileName(self, 'Open file', self.path, "Data files (*.npz)")
|
|
||||||
#if fname is None:
|
|
||||||
# return
|
|
||||||
#if np.size(fname) != 2:
|
|
||||||
# return
|
|
||||||
#if len(fname[0])<=0:
|
|
||||||
# return
|
|
||||||
#self.path = os.path.dirname(os.path.abspath(fname[0]))
|
|
||||||
#
|
|
||||||
#npzfile = np.load(fname[0])
|
|
||||||
#
|
|
||||||
## verify scope plugin
|
|
||||||
#if npzfile['plugin'] != "Mtn":
|
|
||||||
# print ("Invalid data type (wrong plugin type)")
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
## File valid
|
|
||||||
#self.data['Time-Arr'] = npzfile['rawdataX']
|
|
||||||
#self.rawdataY = npzfile['rawdataY']
|
|
||||||
#self.dataX = npzfile['spectX']
|
|
||||||
#self.spectY = npzfile['spectY']
|
|
||||||
#self.sampleRate = npzfile['sampleRate']
|
|
||||||
#self.NMtn = npzfile['NMtn']
|
|
||||||
#self.data['Mde-RB'] = npzfile['mode']
|
|
||||||
#self.pvPrefixStr = str(npzfile['pvPrefixStr'])
|
|
||||||
#self.mtnPluginId = npzfile['mtnPluginId']
|
|
||||||
#if 'unitRawY' in npzfile:
|
|
||||||
# self.unitAnalogY = str(npzfile['unitRawY'])
|
|
||||||
#if 'unitSpectY' in npzfile:
|
|
||||||
# self.unitSpectY = str(npzfile['unitSpectY'])
|
|
||||||
#if 'labelRawY' in npzfile:
|
|
||||||
# self.labelAnalogY = str(npzfile['labelRawY'])
|
|
||||||
#if 'labelSpectY' in npzfile:
|
|
||||||
# self.labelSpectY = str(npzfile['labelSpectY'])
|
|
||||||
#if 'title' in npzfile:
|
|
||||||
# self.title = str(npzfile['title'])
|
|
||||||
#
|
|
||||||
#self.buildPvNames()
|
|
||||||
#
|
|
||||||
## trigg draw
|
|
||||||
#self.MtnYDataValid = True
|
|
||||||
#self.MtnXDataValid = True
|
|
||||||
#self.RawYDataValid = True
|
|
||||||
#self.RawXDataValid = True
|
|
||||||
#self.sampleRateValid = True
|
|
||||||
|
|
||||||
|
|
||||||
#self.comSignalMode.data_signal.emit(self.data['Mde-RB'])
|
|
||||||
#self.comSignalX.data_signal.emit(self.dataX)
|
|
||||||
#self.comSignalSpectY.data_signal.emit(self.spectY)
|
|
||||||
#self.comSignalRawData.data_signal.emit(self.rawdataY)
|
|
||||||
|
|
||||||
#self.setStatusOfWidgets()
|
|
||||||
#
|
|
||||||
#self.startupDone=True
|
|
||||||
#self.zoomBtnAction()
|
|
||||||
return
|
|
||||||
|
|
||||||
def saveBtnAction(self):
|
|
||||||
#fname = QFileDialog.getSaveFileName(self, 'Save file', self.path, "Data files (*.npz)")
|
|
||||||
#if fname is None:
|
|
||||||
# return
|
|
||||||
#if np.size(fname) != 2:
|
|
||||||
# return
|
|
||||||
#if len(fname[0])<=0:
|
|
||||||
# return
|
|
||||||
## Save all relevant data
|
|
||||||
#np.savez(fname[0],
|
|
||||||
# plugin = "Mtn",
|
|
||||||
# rawdataX = self.data['Time-Arr'],
|
|
||||||
# rawdataY = self.rawdataY,
|
|
||||||
# spectX = self.dataX,
|
|
||||||
# spectY = self.spectY,
|
|
||||||
# sampleRate = self.sampleRate,
|
|
||||||
# NMtn = self.NMtn,
|
|
||||||
# mode = self.data['Mde-RB'],
|
|
||||||
# pvPrefixStr = self.pvPrefixStr,
|
|
||||||
# mtnPluginId = self.mtnPluginId,
|
|
||||||
# unitRawY = self.unitAnalogY,
|
|
||||||
# unitSpectY = self.unitSpectY,
|
|
||||||
# labelRawY = self.labelAnalogY,
|
|
||||||
# labelSpectY = self.labelSpectY,
|
|
||||||
# title = self.title
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
#self.path = os.path.dirname(os.path.abspath(fname[0]))
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def plotAll(self):
|
|
||||||
if self.MtnYDataValid and self.MtnXDataValid:
|
|
||||||
self.plotAnalog()
|
|
||||||
self.plotBinary()
|
|
||||||
self.MtnYDataValid = False
|
|
||||||
self.RawYDataValid = False
|
|
||||||
|
|
||||||
def plotAnalog(self, autozoom=False):
|
|
||||||
if self.data['Time-Arr'] is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.data['PosAct-Arr'] is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
# create an axis
|
|
||||||
if self.axAnalog is None:
|
|
||||||
self.axAnalog = self.figure.add_subplot(211)
|
|
||||||
self.axAnalog.set_xlim(-10,0)
|
|
||||||
|
|
||||||
minimum_x=0
|
|
||||||
# plot data
|
|
||||||
for pv in pvAnalog:
|
|
||||||
if self.plottedLineAnalog[pv] is not None:
|
|
||||||
self.plottedLineAnalog[pv].remove()
|
|
||||||
if self.data[pv] is not None:
|
|
||||||
y = self.data[pv]
|
|
||||||
y_len=len(y)
|
|
||||||
x_len=len(self.x)
|
|
||||||
self.plottedLineAnalog[pv], = self.axAnalog.plot(self.x[x_len-y_len:],y,self.plotColor[pv])
|
|
||||||
|
|
||||||
minimum_x_temp=-y_len/self.sampleRate
|
|
||||||
if minimum_x_temp < minimum_x:
|
|
||||||
minimum_x = minimum_x_temp
|
|
||||||
|
|
||||||
else:
|
|
||||||
print("Data null for pv: " + pv)
|
|
||||||
|
|
||||||
self.axAnalog.grid(True)
|
|
||||||
self.axAnalog.set_xlabel('Time [s]')
|
|
||||||
self.axAnalog.set_ylabel(self.labelAnalogY + ' ' + self.unitAnalogY)
|
|
||||||
self.axAnalog.set_title(self.title)
|
|
||||||
|
|
||||||
if autozoom:
|
|
||||||
ymin = np.min(self.data['PosAct-Arr'])
|
|
||||||
ymax = np.max(self.data['PosAct-Arr'])
|
|
||||||
# ensure different values
|
|
||||||
if ymin == ymax:
|
|
||||||
ymin=ymin-1
|
|
||||||
ymax=ymax+1
|
|
||||||
range = ymax - ymin
|
|
||||||
ymax += range * 0.1
|
|
||||||
ymin -= range * 0.1
|
|
||||||
#xmin = np.min(self.data['Time-Arr'])
|
|
||||||
xmin=minimum_x
|
|
||||||
#xmax = np.max(self.data['Time-Arr'])
|
|
||||||
xmax = 0
|
|
||||||
if xmin == xmax:
|
|
||||||
xmin = xmin - 1
|
|
||||||
xmax = xmax + 1
|
|
||||||
range = xmax - xmin
|
|
||||||
xmax += range * 0.02
|
|
||||||
xmin -= range * 0.02
|
|
||||||
self.axAnalog.set_ylim(ymin,ymax)
|
|
||||||
self.axAnalog.set_xlim(xmin,xmax)
|
|
||||||
|
|
||||||
# refresh canvas
|
|
||||||
self.canvas.draw()
|
|
||||||
self.allowSave = True
|
|
||||||
self.saveBtn.setEnabled(True)
|
|
||||||
self.axAnalog.autoscale(enable=False)
|
|
||||||
|
|
||||||
def plotBinary(self, autozoom=False):
|
|
||||||
if self.data['Time-Arr'] is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
#if self.data['PosAct-Arr'] is None:
|
|
||||||
# return
|
|
||||||
|
|
||||||
# create an axis
|
|
||||||
if self.axBinary is None:
|
|
||||||
self.axBinary = self.figure.add_subplot(212)
|
|
||||||
self.axBinary.set_xlim(-10,0)
|
|
||||||
|
|
||||||
|
|
||||||
# plot data
|
|
||||||
minimum_x = 0
|
|
||||||
for pv in pvBinary:
|
|
||||||
if self.plottedLineBinary[pv] is not None:
|
|
||||||
self.plottedLineBinary[pv].remove()
|
|
||||||
if self.data[pv] is not None:
|
|
||||||
y = self.data[pv]
|
|
||||||
y_len=len(y)
|
|
||||||
x_len=len(self.x)
|
|
||||||
self.plottedLineBinary[pv], = self.axBinary.plot(self.x[x_len-y_len:],y,self.plotColor[pv])
|
|
||||||
|
|
||||||
minimum_x_temp=-y_len/self.sampleRate
|
|
||||||
if minimum_x_temp < minimum_x:
|
|
||||||
minimum_x = minimum_x_temp
|
|
||||||
|
|
||||||
else:
|
|
||||||
print("Data null for pv: " + pv)
|
|
||||||
|
|
||||||
|
|
||||||
self.axBinary.grid(True)
|
|
||||||
self.axBinary.set_xlabel('Time [s]')
|
|
||||||
self.axBinary.set_ylabel(self.labelBinaryY + ' ' + self.unitBinaryY)
|
|
||||||
self.axBinary.set_title(self.title)
|
|
||||||
|
|
||||||
if autozoom:
|
|
||||||
ymin = -0.1
|
|
||||||
ymax = 1.1
|
|
||||||
# ensure different values
|
|
||||||
if ymin == ymax:
|
|
||||||
ymin=ymin-1
|
|
||||||
ymax=ymax+1
|
|
||||||
range = ymax - ymin
|
|
||||||
ymax += range * 0.1
|
|
||||||
ymin -= range * 0.1
|
|
||||||
#xmin = np.min(self.data['Time-Arr'])
|
|
||||||
xmin=minimum_x
|
|
||||||
#xmax = np.max(self.data['Time-Arr'])
|
|
||||||
xmax = 0
|
|
||||||
if xmin == xmax:
|
|
||||||
xmin = xmin - 1
|
|
||||||
xmax = xmax + 1
|
|
||||||
range = xmax - xmin
|
|
||||||
xmax += range * 0.02
|
|
||||||
xmin -= range * 0.02
|
|
||||||
self.axBinary.set_ylim(ymin,ymax)
|
|
||||||
self.axBinary.set_xlim(xmin,xmax)
|
|
||||||
|
|
||||||
# refresh canvas
|
|
||||||
self.canvas.draw()
|
|
||||||
self.allowSave = True
|
|
||||||
self.saveBtn.setEnabled(True)
|
|
||||||
self.axBinary.autoscale(enable=False)
|
|
||||||
|
|
||||||
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("<mtnId> : Id of mtn plugin ('0')")
|
|
||||||
print("example : python ecmcMotionMainGui.py 'IOC_TEST:' '0'")
|
|
||||||
print("Will connect to Pvs: <prefix>Plg-Mtn<mtnId>-*")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
import sys
|
|
||||||
prefix = None
|
|
||||||
mtnid = None
|
|
||||||
if len(sys.argv) == 1:
|
|
||||||
prefix = None
|
|
||||||
mtnid = None
|
|
||||||
elif len(sys.argv) == 3:
|
|
||||||
prefix = sys.argv[1]
|
|
||||||
mtnid = int(sys.argv[2])
|
|
||||||
else:
|
|
||||||
printOutHelp()
|
|
||||||
sys.exit()
|
|
||||||
app = QtWidgets.QApplication(sys.argv)
|
|
||||||
window=ecmcMtnMainGui(prefix=prefix,mtnPluginId=mtnid)
|
|
||||||
window.show()
|
|
||||||
sys.exit(app.exec_())
|
|
||||||
@@ -14,10 +14,15 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import epics
|
import epics
|
||||||
from PyQt5.QtWidgets import *
|
from PySide2 import QtCore, QtGui, QtWidgets
|
||||||
from PyQt5 import QtWidgets
|
from PySide2.QtWidgets import *
|
||||||
from PyQt5.QtCore import *
|
from PySide2.QtGui import *
|
||||||
from PyQt5.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
|
import numpy as np
|
||||||
from ecmcOneMotorGUI import *
|
from ecmcOneMotorGUI import *
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
#!/usr/bin/env python3.6
|
#!/usr/bin/env python3.6
|
||||||
import epics
|
import epics
|
||||||
import sys
|
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 *
|
from ecmcArrayStat import *
|
||||||
|
|
||||||
#Define pvs
|
#Define pvs
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ import epics
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import time
|
import time
|
||||||
import threading
|
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):
|
class comSignal(QObject):
|
||||||
data_signal = pyqtSignal(object)
|
data_signal = pyqtSignal(object)
|
||||||
|
|||||||
@@ -15,11 +15,13 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import epics
|
import epics
|
||||||
from PyQt5.QtWidgets import *
|
from PySide2 import QtCore, QtGui, QtWidgets
|
||||||
from PyQt5 import QtWidgets
|
|
||||||
|
|
||||||
from PyQt5.QtCore import *
|
#from PyQt5.QtWidgets import *
|
||||||
from PyQt5.QtGui import *
|
#from PyQt5 import QtWidgets
|
||||||
|
#
|
||||||
|
#from PyQt5.QtCore import *
|
||||||
|
#from PyQt5.QtGui import *
|
||||||
import functools
|
import functools
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import random as rd
|
import random as rd
|
||||||
|
|||||||
@@ -15,10 +15,15 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import ecmcRTCanvas
|
import ecmcRTCanvas
|
||||||
from PyQt5.QtWidgets import *
|
from PySide2 import QtCore, QtGui, QtWidgets
|
||||||
from PyQt5 import QtWidgets
|
from PySide2.QtWidgets import *
|
||||||
from PyQt5.QtCore import *
|
from PySide2.QtGui import *
|
||||||
from PyQt5.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 functools
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import random as rd
|
import random as rd
|
||||||
|
|||||||
@@ -18,10 +18,15 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import epics
|
import epics
|
||||||
import ecmcTrend
|
import ecmcTrend
|
||||||
from PyQt5.QtWidgets import *
|
from PySide2 import QtCore, QtGui, QtWidgets
|
||||||
from PyQt5 import QtWidgets
|
from PySide2.QtWidgets import *
|
||||||
from PyQt5.QtCore import *
|
from PySide2.QtGui import *
|
||||||
from PyQt5.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 functools
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import random as rd
|
import random as rd
|
||||||
|
|||||||
@@ -166,12 +166,14 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
|
|||||||
self.pauseBtn.setFixedSize(100, 50)
|
self.pauseBtn.setFixedSize(100, 50)
|
||||||
self.pauseBtn.clicked.connect(self.pauseBtnAction)
|
self.pauseBtn.clicked.connect(self.pauseBtnAction)
|
||||||
self.pauseBtn.setStyleSheet("background-color: green")
|
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.setFixedSize(100, 50)
|
||||||
|
self.openBtn.setEnabled(False) # Not yet supported
|
||||||
self.openBtn.clicked.connect(self.openBtnAction)
|
self.openBtn.clicked.connect(self.openBtnAction)
|
||||||
self.saveBtn = QPushButton(text = 'save data')
|
self.saveBtn = QPushButton(text = 'save data')
|
||||||
self.saveBtn.setFixedSize(100, 50)
|
self.saveBtn.setFixedSize(100, 50)
|
||||||
self.saveBtn.clicked.connect(self.saveBtnAction)
|
self.saveBtn.clicked.connect(self.saveBtnAction)
|
||||||
|
self.saveBtn.setEnabled(False) # Not yet supported
|
||||||
self.enableBtn = QPushButton(text = 'enable Mtn')
|
self.enableBtn = QPushButton(text = 'enable Mtn')
|
||||||
self.enableBtn.setFixedSize(100, 50)
|
self.enableBtn.setFixedSize(100, 50)
|
||||||
self.enableBtn.clicked.connect(self.enableBtnAction)
|
self.enableBtn.clicked.connect(self.enableBtnAction)
|
||||||
@@ -181,11 +183,13 @@ class ecmcMtnMainGui(QtWidgets.QDialog):
|
|||||||
self.zoomBtn = QPushButton(text = 'auto zoom')
|
self.zoomBtn = QPushButton(text = 'auto zoom')
|
||||||
self.zoomBtn.setFixedSize(100, 50)
|
self.zoomBtn.setFixedSize(100, 50)
|
||||||
self.zoomBtn.clicked.connect(self.zoomBtnAction)
|
self.zoomBtn.clicked.connect(self.zoomBtnAction)
|
||||||
|
self.zoomBtn.setEnabled(False) # Not yet supported
|
||||||
self.modeCombo = QComboBox()
|
self.modeCombo = QComboBox()
|
||||||
self.modeCombo.setFixedSize(100, 50)
|
self.modeCombo.setFixedSize(100, 50)
|
||||||
self.modeCombo.currentIndexChanged.connect(self.newModeIndexChanged)
|
self.modeCombo.currentIndexChanged.connect(self.newModeIndexChanged)
|
||||||
self.modeCombo.addItem("CONT")
|
self.modeCombo.addItem("CONT")
|
||||||
self.modeCombo.addItem("TRIGG")
|
self.modeCombo.addItem("TRIGG"
|
||||||
|
self.modeCombo.setEnabled(False)) # Not yet supported
|
||||||
self.progressBar = QProgressBar()
|
self.progressBar = QProgressBar()
|
||||||
self.progressBar.reset()
|
self.progressBar.reset()
|
||||||
self.progressBar.setMinimum(0)
|
self.progressBar.setMinimum(0)
|
||||||
|
|||||||
22
tools/startGui.sh
Executable 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}"
|
||||||
|
|
||||||
|
python ecmcMotionMainPyQtGraph.py ${P=c6025a-04} ${ID=0}
|
||||||