18 Commits

Author SHA1 Message Date
179bd6aa22 Use ecmc 11.0 2025-10-13 11:54:03 +02:00
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
53 changed files with 1005 additions and 923 deletions

8
.gitignore vendored
View File

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

View File

@@ -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.7 EXCLUDE_VERSIONS+=3 7.0.5 7.0.6 7.0.7
IGNORE_MODULES += asynMotor IGNORE_MODULES += asynMotor
IGNORE_MODULES += motorBase IGNORE_MODULES += motorBase
@@ -15,24 +17,32 @@ USR_CXXFLAGS += -std=c++17
OPT_CXXFLAGS_YES = -O3 OPT_CXXFLAGS_YES = -O3
# dependencies # dependencies
ECmasterECMC_VERSION = v1.1.0 ecmc_VERSION = 11.0
motorECMC_VERSION = 7.0.7-ESS
ecmc_VERSION = v9.0.1_RC1
################################################################################ # ethercat
# THIS RELATES TO THE EtherCAT MASTER LIBRARY # debian 12
# IT IS OF PARAMOUNT IMPORTANCE TO LOAD THE PROPER KERNEL MODULE EC_MASTER_VER = 1.6.3
# ################################################################################ EC_BASE_PATH = /ioc/NeedfulThings/EtherCAT/4epics/${EC_MASTER_VER}/
USR_LDFLAGS += -lethercat 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} LIB_SYS_LIBS += ethercat
USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB} USR_LDFLAGS_deb12-x86_64 += -Wl,-rpath=${EC_BASE_PATH}${T_A}/lib/
USR_LDFLAGS += -L ${EC_MASTER_LIB} USR_LDFLAGS_deb12-x86_64 += -L ${EC_BASE_PATH}${T_A}/lib/
BASE_DIR = ecmc_plugin_motion # 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 SRC_DIR = $(BASE_DIR)/src
DB_DIR = $(BASE_DIR)/Db DB_DIR = $(BASE_DIR)/Db
SCRIPTS_DIR = $(BASE_DIR)/scripts
SOURCES += $(SRC_DIR)/ecmcPluginMotion.c SOURCES += $(SRC_DIR)/ecmcPluginMotion.c
SOURCES += $(SRC_DIR)/ecmcMotionPlgWrap.cpp SOURCES += $(SRC_DIR)/ecmcMotionPlgWrap.cpp
SOURCES += $(SRC_DIR)/ecmcMotionPlg.cpp SOURCES += $(SRC_DIR)/ecmcMotionPlg.cpp
@@ -41,6 +51,5 @@ SOURCES += $(SRC_DIR)/ecmcMotionPlg.cpp
HEADERS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.h)) HEADERS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.h))
DBDS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.dbd)) DBDS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.dbd))
SCRIPTS += $(BASE_DIR)/startup.cmd SCRIPTS += $(BASE_DIR)/startup.cmd
SCRIPTS += $(BASE_DIR)/addMotionObj.cmd SCRIPTS += $(SCRIPTS_DIR)/addMotionObj.cmd
TEMPLATES += $(wildcard $(DB_DIR)/*.template) TEMPLATES += $(wildcard $(DB_DIR)/*.template)

View File

@@ -4,6 +4,7 @@ Plugin designed for commisioning and troubleshooting of motion axes.
Motion data are sampled, buffered and exposed to epics as waveforms. Motion data are sampled, buffered and exposed to epics as waveforms.
python3 ecmcMotionMainPyQtGraph.py c6025a-04 0

View File

@@ -1,99 +0,0 @@
#
# Copyright (c) 2023 Paul Scherrer Institute
#
# The program is free software: you can redistribute
# it and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 2 of the
# License, or any newer version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see https://www.gnu.org/licenses/gpl-2.0.txt
#
#
# Author : anderssandstrom
# email : anders.sandstroem@psi.ch
# Date : 2023 July 10
# version : 0.0.0
#
## The following lines are mandatory, please don't change them.
where_am_I := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
include $(E3_REQUIRE_TOOLS)/driver.makefile
include $(E3_REQUIRE_CONFIG)/DECOUPLE_FLAGS
ifneq ($(strip $(ASYN_DEP_VERSION)),)
asyn_VERSION=$(ASYN_DEP_VERSION)
endif
ifneq ($(strip $(ECMC_DEP_VERSION)),)
ecmc_VERSION=$(ECMC_DEP_VERSION)
endif
ifneq ($(strip $(RUCKIG_DEP_VERSION)),)
ruckig_VERSION=$(RUCKIG_DEP_VERSION)
endif
ifeq ($(T_A),linux-x86_64)
# Assume that the etherlab user library is done via
# https://github.com/icshwi/etherlabmaster
USR_INCLUDES += -I/opt/etherlab/include
USR_CFLAGS += -fPIC
USR_LDFLAGS += -L /opt/etherlab/lib
USR_LDFLAGS += -lethercat
USR_LDFLAGS += -Wl,-rpath=/opt/etherlab/lib
else
ifeq ($(T_A),linux-arm)
# Assume that the etherlab user library is done via
# https://github.com/icshwi/etherlabmaster
USR_INCLUDES += -I/opt/etherlab/include
USR_CFLAGS += -fPIC
USR_LDFLAGS += -L /opt/etherlab/lib
USR_LDFLAGS += -lethercat
USR_LDFLAGS += -Wl,-rpath=/opt/etherlab/lib
else
# Assume that the etherlab user library is done via
# Yocto ESS Linux bb recipe
USR_INCLUDES += -I$(SDKTARGETSYSROOT)/usr/include/etherlab
USR_CFLAGS += -fPIC
USR_LDFLAGS += -L $(SDKTARGETSYSROOT)/usr/lib/etherlab
USR_LDFLAGS += -lethercat
USR_LDFLAGS += -Wl,-rpath=$(SDKTARGETSYSROOT)/usr/lib/etherlab
USR_LDFLAGS += -lstdc++
endif
endif
APP:="."
#APPDB:=$(APP)/Db
#APPSRC:=$(APP)/src
APPSRC:=src
APPDB:=Db
USR_CFLAGS += -shared -fPIC -Wall -Wextra
USR_LDFLAGS += -lstdc++
USR_INCLUDES += -I$(where_am_I)$(APPSRC)
TEMPLATES += $(wildcard $(APPDB)/*.db)
TEMPLATES += $(wildcard $(APPDB)/*.template)
SOURCES += $(APPSRC)/ecmcPluginMotion.c
SOURCES += $(APPSRC)/ecmcMotionPlgWrap.cpp
SOURCES += $(APPSRC)/ecmcMotionPlg.cpp
#SOURCES += $(APPSRC)/ecmcDataBuffer.cpp
SCRIPTS += startup.cmd
SCRIPTS += addMotionObj.cmd
db:
.PHONY: db
vlibs:
.PHONY: vlibs
###

View File

@@ -1,298 +0,0 @@
/*************************************************************************\
* Copyright (c) 2023 Paul Scherrer Institute
* ecmc is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*
* ecmcPluginExample.cpp
*
* Created on: july 10, 2023
* Author: anderssandstrom
*
\*************************************************************************/
// Needed to get headers in ecmc right...
#define ECMC_IS_PLUGIN
#define ECMC_EXAMPLE_PLUGIN_VERSION 2
#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ecmcPluginDefs.h"
#include "ecmcMotionPlgDefs.h"
#include "ecmcMotionPlgWrap.h"
static int lastEcmcError = 0;
static char* lastConfStr = NULL;
/** Optional.
* Will be called once after successfull load into ecmc.
* Return value other than 0 will be considered error.
* configStr can be used for configuration parameters.
**/
int motionConstruct(char *configStr)
{
//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);
return createMotionObj(configStr);
}
/** Optional function.
* Will be called once at unload.
**/
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
* 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)
{
executeMotionObjs();
lastEcmcError = ecmcError;
return 0;
}
/** Link to data source here since all sources should be availabe at this stage
* (for example ecmc PLC variables are defined only at enter of realtime)
**/
int motionEnterRT(){
return linkDataTomotionObjs();
}
/** Optional function.
* Will be called once just before leaving realtime mode
* Return value other than 0 will be considered error.
**/
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 = {
// Allways use ECMC_PLUG_VERSION_MAGIC
.ifVersion = ECMC_PLUG_VERSION_MAGIC,
// Name
.name = "ecmcPlugin_Motion",
// Description
.desc = "Motion plugin for commissioning of ecmc motion axes.",
// Option description
.optionDesc = "\n "ECMC_PLUGIN_DBG_PRINT_OPTION_CMD"<1/0> : Enables/disables printouts from plugin, default = disabled.\n"
" "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> : 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.
.destructFnc = motionDestruct,
// Optional func that will be called each rt cycle. NULL if not definded.
.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..
};
ecmc_plugin_register(pluginDataDef);
# ifdef __cplusplus
}
# endif // ifdef __cplusplus

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

@@ -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,62 +0,0 @@
##############################################################################
## Example: Configuraftion for running ecmc motion plugin
##############################################################################
## Initiation:
epicsEnvSet("IOC" ,"$(IOC="IOC_TEST")")
epicsEnvSet("SCRIPTEXEC" ,"$(SCRIPTEXEC="iocshLoad")")
require ecmccfg "9.0.1_RC1"
# run module startup.cmd (only needed at ESS PSI auto call at require)
$(ECMCCFG_INIT="")$(SCRIPTEXEC) ${ecmccfg_DIR}startup.cmd, "IOC=$(IOC),ECMC_VER=v9.0.1_RC1, 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

View File

@@ -0,0 +1,543 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1420</width>
<height>893</height>
</rect>
</property>
<property name="windowTitle">
<string>ecmc expert axis</string>
</property>
<widget class="caStripPlot" name="castripplot">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>1200</width>
<height>500</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>4</pointsize>
</font>
</property>
<property name="Title" stdset="0">
<string notr="true">Analog</string>
</property>
<property name="TitleX">
<string notr="true"/>
</property>
<property name="TitleY">
<string notr="true">Position</string>
</property>
<property name="channels" stdset="0">
<string>$(SYS):Plg-Mtn$(MTN_ID=0)-PosAct-Arr;$(SYS):Plg-Mtn$(MTN_ID=0)-PosSet-Arr;</string>
</property>
<property name="period">
<double>30.000000000000000</double>
</property>
<property name="refreshRate" stdset="0">
<enum>caStripPlot::High</enum>
</property>
<property name="XaxisType">
<enum>caStripPlot::TimeScale</enum>
</property>
<property name="numberOfXticks" stdset="0">
<number>4</number>
</property>
<property name="YAxisScaling" stdset="0">
<enum>caStripPlot::autoScale</enum>
</property>
<property name="YaxisLimitsMax_1">
<double>600.000000000000000</double>
</property>
<property name="YaxisLimitsMin_1">
<double>200.000000000000000</double>
</property>
<property name="YaxisScalingMax_1" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_1" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_1">
<color>
<red>255</red>
<green>216</green>
<blue>217</blue>
</color>
</property>
<property name="YaxisLimitsMin_2">
<double>-100.000000000000000</double>
</property>
<property name="YaxisScalingMax_2" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_2" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_2">
<color>
<red>0</red>
<green>255</green>
<blue>0</blue>
</color>
</property>
<property name="YaxisLimitsMax_3">
<double>30.000000000000000</double>
</property>
<property name="YaxisLimitsMin_3">
<double>0.000000000000000</double>
</property>
<property name="YaxisScalingMax_3" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_3" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_3">
<color>
<red>159</red>
<green>207</green>
<blue>255</blue>
</color>
</property>
<property name="foreground">
<color alpha="0">
<red>133</red>
<green>190</green>
<blue>232</blue>
</color>
</property>
<property name="XaxisEnabled">
<bool>false</bool>
</property>
<property name="LegendEnabled">
<bool>true</bool>
</property>
<property name="XaxisSyncGroup">
<number>1</number>
</property>
</widget>
<widget class="caStripPlot" name="castripplot_2">
<property name="geometry">
<rect>
<x>10</x>
<y>680</y>
<width>1231</width>
<height>200</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>4</pointsize>
</font>
</property>
<property name="Title" stdset="0">
<string notr="true"/>
</property>
<property name="TitleX">
<string notr="true">Time</string>
</property>
<property name="TitleY">
<string notr="true">State</string>
</property>
<property name="channels" stdset="0">
<string>$(SYS):Plg-Mtn$(MTN_ID=0)-Ena-Arr;$(SYS):Plg-Mtn$(MTN_ID=0)-EnaAct-Arr;$(SYS):Plg-Mtn$(MTN_ID=0)-Bsy-Arr;$(SYS):Plg-Mtn$(MTN_ID=0)-Exe-Arr;$(SYS):Plg-Mtn$(MTN_ID=0)-TrjSrc-Arr;$(SYS):Plg-Mtn$(MTN_ID=0)-EncSrc-Arr;$(SYS):Plg-Mtn$(MTN_ID=0)-AtTrg-Arr;</string>
</property>
<property name="period">
<double>30.000000000000000</double>
</property>
<property name="refreshRate" stdset="0">
<enum>caStripPlot::High</enum>
</property>
<property name="XaxisType">
<enum>caStripPlot::TimeScaleFix</enum>
</property>
<property name="numberOfXticks" stdset="0">
<number>4</number>
</property>
<property name="YAxisScaling" stdset="0">
<enum>caStripPlot::fixedScale</enum>
</property>
<property name="YaxisLimitsMax_1">
<double>1.200000000000000</double>
</property>
<property name="YaxisLimitsMin_1">
<double>-0.200000000000000</double>
</property>
<property name="YaxisScalingMax_1" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_1" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_1">
<color>
<red>255</red>
<green>216</green>
<blue>217</blue>
</color>
</property>
<property name="YaxisLimitsMax_2">
<double>1.200000000000000</double>
</property>
<property name="YaxisLimitsMin_2">
<double>-0.200000000000000</double>
</property>
<property name="YaxisScalingMax_2" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_2" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_2">
<color>
<red>0</red>
<green>255</green>
<blue>0</blue>
</color>
</property>
<property name="YaxisLimitsMax_3">
<double>1.200000000000000</double>
</property>
<property name="YaxisLimitsMin_3">
<double>-0.200000000000000</double>
</property>
<property name="YaxisScalingMax_3" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_3" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_3">
<color>
<red>159</red>
<green>207</green>
<blue>255</blue>
</color>
</property>
<property name="YaxisLimitsMax_4">
<double>1.200000000000000</double>
</property>
<property name="YaxisLimitsMin_4">
<double>-0.200000000000000</double>
</property>
<property name="YaxisScalingMax_4" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_4" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisLimitsMax_5">
<double>1.200000000000000</double>
</property>
<property name="YaxisLimitsMin_5">
<double>-0.200000000000000</double>
</property>
<property name="YaxisScalingMax_5" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_5" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisLimitsMax_6">
<double>1.200000000000000</double>
</property>
<property name="YaxisLimitsMin_6">
<double>-0.200000000000000</double>
</property>
<property name="YaxisScalingMax_6" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_6" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisLimitsMax_7">
<double>1.200000000000000</double>
</property>
<property name="YaxisLimitsMin_7">
<double>-0.200000000000000</double>
</property>
<property name="YaxisScalingMax_7" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_7" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="foreground">
<color alpha="0">
<red>133</red>
<green>190</green>
<blue>232</blue>
</color>
</property>
<property name="LegendEnabled">
<bool>true</bool>
</property>
<property name="XaxisSyncGroup">
<number>1</number>
</property>
</widget>
<widget class="caStripPlot" name="castripplot_3">
<property name="geometry">
<rect>
<x>10</x>
<y>530</y>
<width>1200</width>
<height>151</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>4</pointsize>
</font>
</property>
<property name="Title" stdset="0">
<string notr="true"/>
</property>
<property name="TitleX">
<string notr="true"/>
</property>
<property name="TitleY">
<string notr="true">Position Error</string>
</property>
<property name="channels" stdset="0">
<string>$(SYS):Plg-Mtn$(MTN_ID=0)-PosErr-Arr;</string>
</property>
<property name="period">
<double>30.000000000000000</double>
</property>
<property name="refreshRate" stdset="0">
<enum>caStripPlot::High</enum>
</property>
<property name="XaxisType">
<enum>caStripPlot::TimeScale</enum>
</property>
<property name="numberOfXticks" stdset="0">
<number>4</number>
</property>
<property name="YAxisScaling" stdset="0">
<enum>caStripPlot::autoScale</enum>
</property>
<property name="YaxisLimitsMax_1">
<double>600.000000000000000</double>
</property>
<property name="YaxisLimitsMin_1">
<double>200.000000000000000</double>
</property>
<property name="YaxisScalingMax_1" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_1" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_1">
<color>
<red>255</red>
<green>216</green>
<blue>217</blue>
</color>
</property>
<property name="YaxisLimitsMin_2">
<double>-100.000000000000000</double>
</property>
<property name="YaxisScalingMax_2" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_2" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_2">
<color>
<red>0</red>
<green>255</green>
<blue>0</blue>
</color>
</property>
<property name="YaxisLimitsMax_3">
<double>30.000000000000000</double>
</property>
<property name="YaxisLimitsMin_3">
<double>0.000000000000000</double>
</property>
<property name="YaxisScalingMax_3" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="YaxisScalingMin_3" stdset="0">
<enum>caStripPlot::User</enum>
</property>
<property name="color_3">
<color>
<red>159</red>
<green>207</green>
<blue>255</blue>
</color>
</property>
<property name="foreground">
<color alpha="0">
<red>133</red>
<green>190</green>
<blue>232</blue>
</color>
</property>
<property name="XaxisEnabled">
<bool>false</bool>
</property>
<property name="LegendEnabled">
<bool>true</bool>
</property>
<property name="XaxisSyncGroup">
<number>1</number>
</property>
</widget>
<widget class="caToggleButton" name="catogglebutton">
<property name="geometry">
<rect>
<x>1270</x>
<y>80</y>
<width>100</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Enable</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(SYS):Plg-Mtn$(MTN_ID=0)-EnaCmd-RB</string>
</property>
</widget>
<widget class="caNumeric" name="canumeric">
<property name="geometry">
<rect>
<x>1300</x>
<y>120</y>
<width>100</width>
<height>50</height>
</rect>
</property>
<property name="integerDigits" stdset="0">
<number>1</number>
</property>
<property name="decimalDigits" stdset="0">
<number>0</number>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
<property name="channel" stdset="0">
<string notr="true">$(SYS):Plg-Mtn$(MTN_ID=0)-AxCmd-RB</string>
</property>
<property name="colorMode">
<enum>caNumeric::Alarm</enum>
</property>
<property name="precisionMode">
<enum>caNumeric::User</enum>
</property>
<property name="fixedFormat">
<bool>true</bool>
</property>
<property name="limitsMode">
<enum>caNumeric::User</enum>
</property>
<property name="maxValue">
<double>100.000000000000000</double>
</property>
<property name="minValue">
<double>0.000000000000000</double>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>1230</x>
<y>130</y>
<width>63</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Axis ID:</string>
</property>
</widget>
<widget class="caLineEdit" name="calineedit">
<property name="geometry">
<rect>
<x>1330</x>
<y>190</y>
<width>61</width>
<height>20</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(SYS):Plg-Mtn$(MTN_ID=0)-SmpHz</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>1230</x>
<y>190</y>
<width>63</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Rate [Hz]:</string>
</property>
</widget>
<widget class="caLabel" name="calabel">
<property name="geometry">
<rect>
<x>1310</x>
<y>290</y>
<width>90</width>
<height>28</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(SYS):Plg-Mtn$(MTN_ID=0)-SmpHz</string>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>caNumeric</class>
<extends>QFrame</extends>
<header>caNumeric</header>
</customwidget>
<customwidget>
<class>caToggleButton</class>
<extends>QCheckBox</extends>
<header>caToggleButton</header>
</customwidget>
<customwidget>
<class>caLabel</class>
<extends>QLabel</extends>
<header>caLabel</header>
</customwidget>
<customwidget>
<class>caLineEdit</class>
<extends>QLineEdit</extends>
<header>caLineEdit</header>
</customwidget>
<customwidget>
<class>caStripPlot</class>
<extends>QwtPlot</extends>
<header>caStripPlot</header>
</customwidget>
<customwidget>
<class>QwtPlot</class>
<extends>QFrame</extends>
<header>qwt_plot.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -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}")

View File

@@ -839,22 +839,22 @@ void ecmcMotionPlg::executeMotionObject() {
// protect axis_ if axis object id is changed over asyn // protect axis_ if axis object id is changed over asyn
epicsMutexLock(axisMutex_); epicsMutexLock(axisMutex_);
ecmcAxisStatusType *tempAxisStat = axis_->getDebugInfoDataPointer(); ecmcAxisDataStatus *tempAxisStat = axis_->getAxisStatusStruct();
// Fill the buffers // Fill the buffers
actPosBuffer_->addData(tempAxisStat->onChangeData.positionActual); actPosBuffer_->addData(tempAxisStat->currentPositionActual);
setPosBuffer_->addData(tempAxisStat->onChangeData.positionSetpoint); setPosBuffer_->addData(tempAxisStat->currentPositionSetpoint);
diffPosBuffer_->addData(tempAxisStat->onChangeData.positionError); diffPosBuffer_->addData(tempAxisStat->cntrlError);
enableBuffer_->addData(tempAxisStat->onChangeData.statusWd.enable); enableBuffer_->addData(tempAxisStat->statusWord_.enable);
enabledBuffer_->addData(tempAxisStat->onChangeData.statusWd.enabled); enabledBuffer_->addData(tempAxisStat->statusWord_.enabled);
busyBuffer_->addData(tempAxisStat->onChangeData.statusWd.busy); busyBuffer_->addData(tempAxisStat->statusWord_.busy);
executeBuffer_->addData(tempAxisStat->onChangeData.statusWd.execute); executeBuffer_->addData(tempAxisStat->statusWord_.execute);
trajSourceBuffer_->addData(tempAxisStat->onChangeData.statusWd.trajsource); trajSourceBuffer_->addData(tempAxisStat->statusWord_.trajsource);
encSourceBuffer_->addData(tempAxisStat->onChangeData.statusWd.encsource); encSourceBuffer_->addData(tempAxisStat->statusWord_.encsource);
atTargetBuffer_->addData(tempAxisStat->onChangeData.statusWd.attarget); atTargetBuffer_->addData(tempAxisStat->statusWord_.attarget);
errorIdBuffer_->addData(tempAxisStat->onChangeData.error); errorIdBuffer_->addData(tempAxisStat->errorCode);
epicsInt32 *temp=(epicsInt32*)&(tempAxisStat->onChangeData.statusWd); // A bit nasty epicsInt32 *temp=(epicsInt32*)&(tempAxisStat->statusWord_); // A bit nasty
statusWdBuffer_->addData(*temp); statusWdBuffer_->addData(*temp);
xTime_+=xdt_; xTime_+=xdt_;
@@ -870,24 +870,6 @@ void ecmcMotionPlg::executeMotionObject() {
epicsMutexUnlock(axisMutex_); 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) { asynStatus ecmcMotionPlg::writeInt32(asynUser *pasynUser, epicsInt32 value) {
int function = pasynUser->reason; int function = pasynUser->reason;
if( function == asynEnableId_ ) { if( function == asynEnableId_ ) {
@@ -906,7 +888,7 @@ asynStatus ecmcMotionPlg::writeInt32(asynUser *pasynUser, epicsInt32 value) {
} else if( function == asynAxisId_){ } else if( function == asynAxisId_){
return setAxis(value) > 0 ? asynSuccess : asynError; return setAxis(value) > 0 ? asynSuccess : asynError;
} else if( function == asynModeId_){ } else if( function == asynModeId_){
return setMode((TRIGG_MODE)value) > 0 ? asynSuccess : asynError; return setMode((TRIGG_MODE)value) == 0 ? asynSuccess : asynError;
} else if( function == asynModeId_){ } else if( function == asynModeId_){
return setTrigg(value) ? asynSuccess :asynError; return setTrigg(value) ? asynSuccess :asynError;
} }

122
src/ecmcPluginMotion.c Normal file
View File

@@ -0,0 +1,122 @@
/*************************************************************************\
* Copyright (c) 2023 Paul Scherrer Institute
* ecmc is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*
* ecmcPluginExample.cpp
*
* 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_PLUGIN_VERSION 2
#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ecmcPluginDefs.h"
#include "ecmcMotionPlgDefs.h"
#include "ecmcMotionPlgWrap.h"
static int lastEcmcError = 0;
static char* lastConfStr = NULL;
/** Optional.
* 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.
**/
static int construct(char *configStr)
{
//This module is allowed to load several times so no need to check if loaded
lastConfStr = strdup(configStr);
return createMotionObj(configStr);
}
/** Optional function.
* Will be called once at unload.
**/
static void motionDestruct(void)
{
}
/** Optional function.
* 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.
**/
static int motionRealtime(int ecmcError)
{
executeMotionObjs();
lastEcmcError = ecmcError;
return 0;
}
/** 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)
**/
static int motionEnterRT(){
return linkDataTomotionObjs();
}
/** Optional function.
* Will be called once just before leaving realtime mode
* Return value other than 0 will be considered error.
**/
static int motionExitRT(void){
return 0;
}
// Register data for plugin so ecmc know what to use
static struct ecmcPluginData pluginDataDef = {
// Allways use ECMC_PLUG_VERSION_MAGIC
.ifVersion = ECMC_PLUG_VERSION_MAGIC,
// Name
.name = "ecmc_plugin_motion",
// Description
.desc = "Motion plugin for commissioning of ecmc motion axes.",
// Option description
.optionDesc = "\n "ECMC_PLUGIN_DBG_PRINT_OPTION_CMD"<1/0> : Enables/disables printouts from plugin, default = disabled.\n"
" "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> : Sampling rate in Hz"
,
// Plugin version
.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 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] = {0}, // last element set all to zero..
// PLC consts
.consts[0] = {0}, // last element set all to zero..
};
ecmc_plugin_register(pluginDataDef);
# ifdef __cplusplus
}
# endif // ifdef __cplusplus

View File

@@ -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" ,"#")

View File

@@ -1,8 +1,2 @@
# FFT tools # Tool for visualization
python3 ecmcMotionMainPyQtGraph.py c6025a-04 0
## 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)

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 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

View File

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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
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