67 Commits
0.2.0 ... 3.0.0

Author SHA1 Message Date
5125c4a861 use ecmc 11.0 2025-10-13 11:56:58 +02:00
7782df0049 epics 7.0.9 2025-04-22 12:20:57 +02:00
93648e1e02 update makefile 2025-03-28 09:17:41 +01:00
4b97b5a53c Fix makefiel for deb12 2025-03-21 10:49:47 +01:00
81b0013a57 Use ecmc 10.0 2025-03-03 14:34:29 +01:00
e43935510e Update panels 2025-02-26 17:15:38 +01:00
bddba4be91 Add more data to db 2025-02-26 14:51:27 +01:00
4df2642299 Add axis template 2025-02-26 09:54:39 +01:00
261f93ed43 WIP 2025-02-25 12:34:35 +01:00
8f68bc021d Calc emerg decelartion depending on actual traj velo 2025-02-25 09:18:12 +01:00
07acbe990e Cleanup panels 2025-02-24 16:53:44 +01:00
ece0240a5d Update readme 2025-02-24 16:43:14 +01:00
7583975ab2 Update readme 2025-02-24 16:41:32 +01:00
6e4d9e2933 Merge branch 'new_plg_concept' of git.psi.ch:motion/ecmc_plugin_safety into new_plg_concept 2025-02-24 16:39:39 +01:00
3d0896a290 WIP 2025-02-24 16:37:43 +01:00
0b9d22b327 Add simple panles 2025-02-24 16:37:10 +01:00
9f0147c83e WIP 2025-02-24 16:20:41 +01:00
f85f010d06 Merge branch 'new_plg_concept' of git.psi.ch:motion/ecmc_plugin_safety into new_plg_concept 2025-02-24 14:05:05 +01:00
fa77ffb099 Merge branch 'master' of git.psi.ch:motion/ecmc_plugin_safety into new_plg_concept 2025-02-24 14:03:29 +01:00
7893207cb6 Merge branch 'test' into 'master'
Test

See merge request motion/ecmc_plugin_safety!1
2025-02-24 14:02:20 +01:00
7431834bd3 Test 2025-02-24 14:02:20 +01:00
980aeeecdc WIP 2025-02-11 16:55:21 +01:00
9042a39a1b WIP 2025-02-11 16:42:26 +01:00
1fb017ac64 Add test script 2025-02-11 16:40:58 +01:00
e0d93179a8 Update test script 2025-02-11 15:50:43 +01:00
18e4821a83 Prep for ecmc v10 2024-12-16 10:43:29 +01:00
eeaffaad96 Update naming in scripts 2024-12-16 09:45:06 +01:00
31fd9d8851 New plugin concept and cleanup 2024-12-13 16:06:19 +01:00
adc421ba42 depend on ecmc 9.6 2024-09-13 09:20:12 +02:00
a1110a3aa4 depend on ecmc 9 2024-09-13 09:02:15 +02:00
4930b2bfeb Use ecmc 9.5.0 2024-05-01 10:32:16 +02:00
eea8ea48e9 Update test script 2024-03-20 09:54:37 +01:00
817b1a2b8d Update test script 2024-03-20 09:51:21 +01:00
876ddb1d4a Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-03-20 09:50:18 +01:00
7550551cc4 Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-03-20 09:29:59 +01:00
0c5f9a4091 Add check of bit id 2024-03-20 09:29:40 +01:00
28c25a4345 Update test script 2024-03-18 09:40:26 +01:00
5d1ff4fc99 Valdiate bit index of ethercat entries 2024-03-18 09:38:55 +01:00
a1b4ec01b8 Cleanup 2024-03-18 09:26:32 +01:00
05654f8917 Update testscript 2024-03-18 09:23:25 +01:00
694be265d0 Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-03-13 08:58:01 +01:00
aade802526 Update test script 2024-03-13 08:57:49 +01:00
ae7697bd08 Update readme 2024-03-13 08:57:03 +01:00
bedf777537 Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-03-13 08:55:40 +01:00
ad8dd2cc36 Added and tested velo limitation 2024-03-13 08:55:22 +01:00
50ce0d45ca Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-03-12 16:47:55 +01:00
b8da66f0a5 Use test versions safety3 2024-03-12 16:47:38 +01:00
d6f04bfa4d Remove obsolete test script 2024-03-12 16:24:58 +01:00
4bc5bf475f Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-03-12 16:23:12 +01:00
940d2c5a71 Update etst scripts 2024-03-12 16:23:03 +01:00
de10cade0f Add max velo feature 2024-03-12 16:22:13 +01:00
3272fd62ed Start add velo lim cmd 2024-03-12 11:02:50 +01:00
a5c2b5a4b3 Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety into safety 2024-03-11 10:03:20 +01:00
fec9293520 Use ecmc 9.2.0 2024-03-11 10:02:27 +01:00
1c051995c3 Update testscript 2024-03-11 09:38:31 +01:00
c02541c711 Update max velo in test script 2024-03-07 14:20:21 +01:00
67f6c739e0 Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-03-07 14:18:14 +01:00
ea4d26fd31 Update testscript 2024-03-07 14:17:53 +01:00
9bd3a2b124 Test safety branch of ecmc 2024-03-06 19:17:19 +01:00
48c6070a62 Fix paths to pics 2024-02-28 14:06:14 +01:00
dd1b229322 Add comment 2024-02-28 14:04:48 +01:00
10d5b1deb7 Add test pics to REDAME.md 2024-02-28 14:03:31 +01:00
f68a2602d5 Rename addAxisToGroup.cmd to addAxisToSafetyGroup.cmd 2024-02-28 13:54:40 +01:00
ed84fa26e3 Rename addAxisToGroup.cmd to addAxisToSafetyGroup.cmd WIP 2024-02-28 13:47:17 +01:00
8f3a9d5b59 Adapt emerg decelration to ensure ramp down before the 500ms sto delay 2024-02-28 12:24:27 +01:00
0eb4a8032e Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety 2024-02-28 12:21:37 +01:00
f9cf3e1fe2 Use default version of plugin 2024-02-28 12:21:15 +01:00
31 changed files with 1770 additions and 1250 deletions

View File

@@ -2,6 +2,7 @@
"files.associations": {
"string_view": "cpp",
"stdexcept": "cpp",
"iosfwd": "cpp"
"iosfwd": "cpp",
"typeinfo": "cpp"
}
}

25
Db/ecmcSS1Axis.template Normal file
View File

@@ -0,0 +1,25 @@
#- Will be a sub record to the axis object, example:
#- AXIS_PREFIX=c6015a-02:M1
record(stringin,"$(AXIS_PREFIX)-SS1-GrpNam") {
field(DESC, "Name of Saftey Grp ")
field(VAL, "${NAME}")
}
record(bi,"${AXIS_PREFIX}-SS1-EnaAct"){
field(DESC, "Safety PLG active for this axis")
field(VAL, 1)
field(ONAM, "1")
field(ZNAM, "0")
}
record(ai,"${AXIS_PREFIX}-SS1-VelMaxLim"){
field(DESC, "Velocity max limit (not safety...)")
field(VAL, ${VEL_MAX_LIM=-1})
field(PREC, 3)
}
record(ai,"${AXIS_PREFIX}-SS1-VelRestLim"){
field(DESC, "Velocity rest limit (not safety...)")
field(VAL, ${VEL_REST_LIM=-1})
field(PREC, 3)
}

View File

@@ -51,4 +51,33 @@ record(bi,"${P}SS1-${NAME}-AxsStndStllAct"){
field(ONAM, "Standstill")
field(ZSV, "NO_ALARM")
field(OSV, "NO_ALARM")
field(FLNK, "${P}SS1-${NAME}-RedVeloCmdAct.PROC")
}
# // bit 3 reduce velo active
record(bi,"${P}SS1-${NAME}-RedVeloCmdAct"){
field(DESC, "SS1-${NAME}: Reduce velo active")
field(INP, "${P}SS1-${NAME}-Stat_.B3")
field(ZNAM, "Not Active")
field(ONAM, "Active")
field(ZSV, "NO_ALARM")
field(OSV, "NO_ALARM")
}
record(ai,"$(P)SS1-${NAME}-Dly") {
field(DESC, "Power off delay [ms]")
field(EGU, "ms")
field(VAL, "$(DELAY=0)")
field(PREC, "0")
}
record(stringin,"$(P)SS1-Grp${ID=0}-Nam") {
field(DESC, "Name of Grp ${ID=0}")
field(VAL, "${NAME}")
}
record(ai,"$(P)SS1-GrpCnt") {
field(DESC, "Group Count")
field(VAL, "$(COUNT=0)")
}

11
Db/ecmcSS1Main.template Normal file
View File

@@ -0,0 +1,11 @@
record(stringin,"$(P)SS1-PnlTyp") {
field(DESC, "Panel name")
field(VAL, "ecmc_plugin_safety_main.ui")
}
record(bi,"${P}SS1-Loaded"){
field(DESC, "Plugin loaded")
field(VAL, 1)
field(ONAM, "1")
field(ZNAM, "0")
}

View File

@@ -2,11 +2,14 @@ include /ioc/tools/driver.makefile
MODULE = ecmc_plugin_safety
# "Transfer" module name to plugin
USR_CFLAGS +=-DECMC_PLUGIN_MODULE_NAME=${MODULE}
BUILDCLASSES = Linux
ARCH_FILTER = deb10%
ARCH_FILTER = deb10% deb12%
# Run 7.0.6 for now
EXCLUDE_VERSIONS+=3 7.0.5 7.0.6
EXCLUDE_VERSIONS+=3 7.0.5 7.0.6 7.0.7
IGNORE_MODULES += asynMotor
IGNORE_MODULES += motorBase
@@ -15,20 +18,29 @@ USR_CXXFLAGS += -std=c++17
OPT_CXXFLAGS_YES = -O3
# dependencies
ECmasterECMC_VERSION = v1.1.0
# motorECMC_VERSION = 7.0.7-ESS
#ecmc_VERSION = v9.0.1_RC4
ecmc_VERSION = 9.1.0
ecmc_VERSION = 11.0
################################################################################
# THIS RELATES TO THE EtherCAT MASTER LIBRARY
# IT IS OF PARAMOUNT IMPORTANCE TO LOAD THE PROPER KERNEL MODULE
# ################################################################################
USR_LDFLAGS += -lethercat
# ethercat
# debian 12
EC_MASTER_VER = 1.6.3
EC_BASE_PATH = /ioc/NeedfulThings/EtherCAT/4epics/${EC_MASTER_VER}/
USR_CXXFLAGS_deb12-x86_64 += -I${EC_BASE_PATH}${T_A}/include/
USR_CXXFLAGS_deb12-x86_64 += -L${EC_BASE_PATH}${T_A}/lib/
LIB_SYS_LIBS += ethercat
USR_LDFLAGS_deb12-x86_64 += -Wl,-rpath=${EC_BASE_PATH}${T_A}/lib/
USR_LDFLAGS_deb12-x86_64 += -L ${EC_BASE_PATH}${T_A}/lib/
# debian 10
# note: EC_MASTER LIB does not depend on epics version hence use the 7.0.8 build..
USR_LDFLAGS_deb10-x86_64 += -lethercat
EC_MASTER_LIB = /ioc/NeedfulThings/EtherCAT/4epics/v1.1.0/R7.0.8/
USR_LDFLAGS_deb10-x86_64 += -Wl,-rpath=${EC_MASTER_LIB}lib/${T_A}
USR_LDFLAGS_deb10-x86_64 += -L ${EC_MASTER_LIB}lib/${T_A}
USR_CXXFLAGS_deb10-x86_64 += -I${EC_MASTER_LIB}/include/
OPT_CXXFLAGS_YES = -O3
EC_MASTER_LIB = ${EPICS_MODULES}/ECmasterECMC/${ECmasterECMC_VERSION}/R${EPICSVERSION}/lib/${T_A}
USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB}
USR_LDFLAGS += -L ${EC_MASTER_LIB}
BASE_DIR = .
SRC_DIR = $(BASE_DIR)/src
@@ -43,5 +55,5 @@ HEADERS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.h))
DBDS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.dbd))
SCRIPTS += $(BASE_DIR)/startup.cmd
SCRIPTS += $(BASE_DIR)/scripts/addSS1Group.cmd
SCRIPTS += $(BASE_DIR)/scripts/addAxisToGroup.cmd
SCRIPTS += $(BASE_DIR)/scripts/addAxisToSafetyGroup.cmd
TEMPLATES += $(wildcard $(DB_DIR)/*.template)

711
README.md
View File

@@ -10,38 +10,61 @@ This plugin is designed for interfacing safety systems, see example in below pic
# SS1-t
The plugin supports stopping axes according to a concept described as SS1-t, see below picture. In SS1-t the STO (or removal of power) from the axes are delayed for a certain defined time allowing a controlled rampdown of velocity. The rampdown of the axis is handled by the non-safe motion controller while the removal of power (or triggering of STO) after the time delay is handled by a safety system, . This makes it possible to stop moving axes in a controlled way and disable the drives before the power is interrupted (or STO triggered). This will result in a safer system and less harware failures and error messages.
After the time delay expires, hopfully all axes are at standstill and power is already removed from the drives.
After the time delay expires, hopfully all axes are at standstill and power is already removed from the drives.
![SS1-t](docs/SS1-t.png)
## Velocity limit
An additional optional feature of this plugin is limiting of axis velocity based on an the state of an ethercat I/O (this is not a safety certified fucntionality).
Axes that are configured with a max velocity will be monitored by this plugin and if exceeding the configured max velocity, the axis will be disabled.
For initiation of new movements, the target velocity will be limited to 95% of the configured maximum velocity. The reason for this is toi allow small fluctuations in actual velocity without disablaing the axes.
## Interface
Basically the safey system is interfaced with two binary signals (ethercat I/O):
* Ramp down command (from safety system to ecmc)
* Axis stand still status (to safety system from ecmc)
Basically the safey system is interfaced with three binary signals (ethercat I/O):
* Ramp down command (from safety system to ecmc). 0 means ramp down command is active.
* Axis stand still status (to safety system from ecmc). 1 means that all axes are at rest _AND_ disabled
* Limitation of velocity (optional). 0 means limitation of velocity is acrive
If, for instance, an safety event is triggerd by the safety system, it will immediately command this plugin to rampdown velocity of all axes (that a configured to stop). When all axes, that are configured to rampdown, have stopped then this plugin will disable the axes and set an ethercat output informing the safety system that the axes are standstill. After a certain timout the safety system will make sure power is removed from the motion axes by triggering an STO or removing power. The removal of power or triggering of STO will made regardless if the axes are at rest or not. A reset of the safety system, allowing power to the drives, will only be possible once the safety system gets a confirmation that all axes are at rest.
The configuration is made by two commands:
1. ecmcAddSS1SafetyGroup()
2. ecmcAddAxisToSafetyGroup()
1. ecmcAddSS1SafetyGroup() wrapped into addSS1Group.cmd
2. ecmcAddAxisToSafetyGroup() wrapped in snippet addAxisToSafetyGroup.cmd
## ecmcAddSS1SafetyGroup()
The ecmcAddSS1SafetyGroup() adds a SS1 safety group. The command takes the following parameters:
```
ecmcAddSS1SafetyGroup(<name>, <ec_rampdown_cmd>, <ec_standstill_status>,<time_delay_ms>)
<name> : Name of group.
<ec_rampdown> : Ethercat entry input for rampdown cmd.
<ec_axes_at_rest> : Ethercat entry output for group standstill status.
<time_delay_ms> : Time delay of STO [ms].
ecmcAddSS1SafetyGroup(<name>, <ec_rampdown_cmd>, <ec_standstill_status>,<ec_max_velo_cmd>,<time_delay_ms>)
<name> : Name of group
<ec_rampdown_cmd> : Ethercat entry input for rampdown cmd
<ec_standstill_status> : Ethercat entry output for group standstill status
<ec_max_velo_cmd> : Ethercat entry input for activation of maximum velo limitation (set to "empty" to disable)
<time_delay_ms> : Time delay of STO [ms]
```
Each group is interfacing the safety system through the same I/O (ethercat).
Axes that needs the SS1 fucntionality can be added to this group with the ecmcAddAxisToSafetyGroup() command.
This command is also wrapped in a snippet:
* addSS1Group.cmd
This command is also wrapped in a snippet addSS1Group.cmd with the follwoing parameters:
* NAME : Name of group
* EC_RAMP_DOWN : Ethercat input of ramp down signal from safety PLC
* EC_AXES_REST : Ethercat entry for signaling that all axes in group are at rest, output from ecmc (feedback to safety PLC/system)
* EC_AXES_MAX_VELO : Ethercat entry for reducing velocity, input to ecmc (command from safety PLC/system), put 0 to disable
* DELAY_MS : Safety system delay time of STO or removal of power
Example:
```
# Create SS1 group
epicsEnvSet(EC_RAMP_DOWN,"ec${ECMC_EC_MASTER_ID}.s${BI_SLAVE}.binaryInput08.0")
epicsEnvSet(EC_AXES_REST,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.binaryOutput07.0")
epicsEnvSet(SAFETY_TIMEOUT,500)
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addSS1Group.cmd "NAME=first,EC_RAMP_DOWN=${EC_RAMP_DOWN},EC_AXES_REST=${EC_AXES_REST},DELAY_MS=${SAFETY_TIMEOUT}"
```
## ecmcAddAxisToSafetyGroup()
With the "ecmcAddAxisToSafetyGroup()" command an ecmc axis can be added to a safety group.
All axes linked to a certain group will act on command from the safety system (initiation of velocity rampdown).
@@ -50,632 +73,76 @@ The ecmcAddAxisToSafetyGroup() command takes the following parameters:
ecmcAddAxisToSafetyGroup(<group_name>, <axis_index>, <velo_limit>, <filter_time>)
<name> : Name of safety group to add axis to.
<Axis id> : Axis index to add (ecmc axis index).
<velo limit> : Axis standstill velo limit [unit of axis].
<velo_rest_limit> : Axis at rest velo limit [unit of axis].
<velo_max_limit> : Axis max velo limit [unit of axis].
<filter_time> : NOT USED (for future implemenation). Time for axis to be below velo limit [ms].
```
Note: The "filter_time" parameter is not used right now. As soon as the axis is below teh velo_limit it will be considered to stand still and will then be disabled.
Note: The plugin checks the trajectory generated velocity setpoint and not the actual velocity.
This command is also wrapped in a snippet:
* addAxisToGroup.cmd
This command is also wrapped in a snippet addAxisToSafetyGroup.cmd with the following parameters:
* NAME : Name of group to add axis to (group must be created first with addSS1Group.cmd)
* AX_ID : ecmc axis index of axis to add
* VELO_REST_LIM : Velocity at rest limit [unit same as EGU of axis]
* VELO_MAX_LIM : Velocity maximum limit, -1 to disable [unit same as EGU of axis]
Example:
```
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToSafetyGroup.cmd "NAME=first,AX_ID=1,VELO_REST_LIM=1,VELO_MAX_LIM=100"
```
# Example of startup script:
```
##############################################################################
## Load safety plugin
#
require ecmc_plugin_safety sandst_a
# Create SS1 group
epicsEnvSet(RAMP_DOWN_CMD,"ec${ECMC_EC_MASTER_ID}.s${DRV_SLAVE}.ZERO.0")
epicsEnvSet(STANDSTILL_STAT,"ec${ECMC_EC_MASTER_ID}.s${DRV_SLAVE}.ZERO.1")
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addSS1Group.cmd "NAME=first,EC_RAMP_DOWN_CMD=${RAMP_DOWN_CMD},EC_STANDSTILL_STAT=${STANDSTILL_STAT},DELAY_MS=500"
# Add axes to group "first"
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToGroup.cmd "NAME=first,AX_ID=1,VELO_LIM=1"
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToGroup.cmd "NAME=first,AX_ID=2,VELO_LIM=1"
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToGroup.cmd "NAME=first,AX_ID=3,VELO_LIM=1"
# Create SS1 group
#- EC_RAMP_DOWN : Ethercat entry for ramp down command, input to ecmc (command from safety PLC/system)
#- EC_AXES_REST : Ethercat entry for signaling that all axes in group are at rest, output from ecmc (feedback to safety PLC/system)
#- EC_AXES_MAX_VELO : Ethercat entry for reducing velocity, input to ecmc (command from safety PLC/system), set to "empty" to disable
#- DELAY_MS : Time between rampdown command and STO
epicsEnvSet(EC_RAMP_DOWN,"ec${ECMC_EC_MASTER_ID}.s${BI_SLAVE}.binaryInput08.0")
epicsEnvSet(EC_AXES_REST,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.binaryOutput07.0")
epicsEnvSet(EC_AXES_MAX_VELO,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.ONE.0")
epicsEnvSet(SAFETY_TIMEOUT,500)
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addSS1Group.cmd "NAME=first,EC_RAMP_DOWN=${EC_RAMP_DOWN},EC_AXES_REST=${EC_AXES_REST},EC_AXES_MAX_VELO=${EC_AXES_MAX_VELO},DELAY_MS=${SAFETY_TIMEOUT}"
#- Add axis
#- AX_ID : Axis ID
#- VELO_REST_LIM : Velocity at rest limit [unit same as EGU of axis]
#- VELO_MAX_LIM : Velocity maximum limit, -1 to disable [unit same as EGU of axis]
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToSafetyGroup.cmd "NAME=first,AX_ID=1,VELO_REST_LIM=1,VELO_MAX_LIM=100"
....
```
# Test
Triggering of e-stop:
* Velo 500mm/s
* Stop ramp 1200mm/s/s
# Test data:
[sandst_a@pc15846 ~]$ camon -time c6025a:m0s006-BI08 c6025a:m0s005-BO07 c6025a:Axis1-EnaAct c6025a:Axis1-VelAct
11:44:41.998324 c6025a:m0s006-BI08 "True"
11:44:30.378340 c6025a:m0s005-BO07 "One"
11:44:42.008324 c6025a:Axis1-EnaAct "Disabled"
11:44:30.388326 c6025a:Axis1-VelAct 0.000 mm/s
11:44:55.428324 c6025a:Axis1-EnaAct "Enabled"
11:45:00.958339 c6025a:Axis1-VelAct 0.281 mm/s
11:45:00.958365 c6025a:m0s005-BO07 "Zero"
11:45:00.978335 c6025a:Axis1-VelAct 0.844 mm/s
11:45:00.988344 c6025a:Axis1-VelAct 1.406 mm/s
11:45:00.998338 c6025a:Axis1-VelAct 2.250 mm/s
11:45:01.008337 c6025a:Axis1-VelAct 3.375 mm/s
11:45:01.018341 c6025a:Axis1-VelAct 4.500 mm/s
11:45:01.028338 c6025a:Axis1-VelAct 5.906 mm/s
11:45:01.038340 c6025a:Axis1-VelAct 7.594 mm/s
11:45:01.048338 c6025a:Axis1-VelAct 9.562 mm/s
11:45:01.058340 c6025a:Axis1-VelAct 11.250 mm/s
11:45:01.068337 c6025a:Axis1-VelAct 13.500 mm/s
11:45:01.078336 c6025a:Axis1-VelAct 15.469 mm/s
11:45:01.088338 c6025a:Axis1-VelAct 17.438 mm/s
11:45:01.098339 c6025a:Axis1-VelAct 19.406 mm/s
11:45:01.108341 c6025a:Axis1-VelAct 21.375 mm/s
11:45:01.118338 c6025a:Axis1-VelAct 23.625 mm/s
11:45:01.128339 c6025a:Axis1-VelAct 25.594 mm/s
11:45:01.138339 c6025a:Axis1-VelAct 27.562 mm/s
11:45:01.148337 c6025a:Axis1-VelAct 29.531 mm/s
11:45:01.158345 c6025a:Axis1-VelAct 31.500 mm/s
11:45:01.168338 c6025a:Axis1-VelAct 33.469 mm/s
11:45:01.178339 c6025a:Axis1-VelAct 35.437 mm/s
11:45:01.188338 c6025a:Axis1-VelAct 37.687 mm/s
11:45:01.198337 c6025a:Axis1-VelAct 39.656 mm/s
11:45:01.208338 c6025a:Axis1-VelAct 41.625 mm/s
11:45:01.218334 c6025a:Axis1-VelAct 43.594 mm/s
11:45:01.228342 c6025a:Axis1-VelAct 45.844 mm/s
11:45:01.238335 c6025a:Axis1-VelAct 47.812 mm/s
11:45:01.248352 c6025a:Axis1-VelAct 49.781 mm/s
11:45:01.258338 c6025a:Axis1-VelAct 51.750 mm/s
11:45:01.268342 c6025a:Axis1-VelAct 54.000 mm/s
11:45:01.278336 c6025a:Axis1-VelAct 55.969 mm/s
11:45:01.288340 c6025a:Axis1-VelAct 57.938 mm/s
11:45:01.298338 c6025a:Axis1-VelAct 59.906 mm/s
11:45:01.308337 c6025a:Axis1-VelAct 62.156 mm/s
11:45:01.318335 c6025a:Axis1-VelAct 63.844 mm/s
11:45:01.328344 c6025a:Axis1-VelAct 65.812 mm/s
11:45:01.338346 c6025a:Axis1-VelAct 68.063 mm/s
11:45:01.348341 c6025a:Axis1-VelAct 70.031 mm/s
11:45:01.358338 c6025a:Axis1-VelAct 72.281 mm/s
11:45:01.368343 c6025a:Axis1-VelAct 74.250 mm/s
11:45:01.378345 c6025a:Axis1-VelAct 76.219 mm/s
11:45:01.388342 c6025a:Axis1-VelAct 78.187 mm/s
11:45:01.398341 c6025a:Axis1-VelAct 80.438 mm/s
11:45:01.408339 c6025a:Axis1-VelAct 82.125 mm/s
11:45:01.418338 c6025a:Axis1-VelAct 84.375 mm/s
11:45:01.428338 c6025a:Axis1-VelAct 86.344 mm/s
11:45:01.438337 c6025a:Axis1-VelAct 88.312 mm/s
11:45:01.448338 c6025a:Axis1-VelAct 90.281 mm/s
11:45:01.458339 c6025a:Axis1-VelAct 92.250 mm/s
11:45:01.468344 c6025a:Axis1-VelAct 94.219 mm/s
11:45:01.478343 c6025a:Axis1-VelAct 96.469 mm/s
11:45:01.488347 c6025a:Axis1-VelAct 98.438 mm/s
11:45:01.498339 c6025a:Axis1-VelAct 100.406 mm/s
11:45:01.508340 c6025a:Axis1-VelAct 102.656 mm/s
11:45:01.518340 c6025a:Axis1-VelAct 104.625 mm/s
11:45:01.528338 c6025a:Axis1-VelAct 106.594 mm/s
11:45:01.538341 c6025a:Axis1-VelAct 108.563 mm/s
11:45:01.548337 c6025a:Axis1-VelAct 110.813 mm/s
11:45:01.558339 c6025a:Axis1-VelAct 112.781 mm/s
11:45:01.568337 c6025a:Axis1-VelAct 114.750 mm/s
11:45:01.578338 c6025a:Axis1-VelAct 116.437 mm/s
11:45:01.588338 c6025a:Axis1-VelAct 118.688 mm/s
11:45:01.598336 c6025a:Axis1-VelAct 120.656 mm/s
11:45:01.608339 c6025a:Axis1-VelAct 122.625 mm/s
11:45:01.618339 c6025a:Axis1-VelAct 124.594 mm/s
11:45:01.628337 c6025a:Axis1-VelAct 126.562 mm/s
11:45:01.638348 c6025a:Axis1-VelAct 128.531 mm/s
11:45:01.648346 c6025a:Axis1-VelAct 130.500 mm/s
11:45:01.658339 c6025a:Axis1-VelAct 132.469 mm/s
11:45:01.668338 c6025a:Axis1-VelAct 134.437 mm/s
11:45:01.678341 c6025a:Axis1-VelAct 136.688 mm/s
11:45:01.688346 c6025a:Axis1-VelAct 138.656 mm/s
11:45:01.698339 c6025a:Axis1-VelAct 140.625 mm/s
11:45:01.708350 c6025a:Axis1-VelAct 142.594 mm/s
11:45:01.718339 c6025a:Axis1-VelAct 144.844 mm/s
11:45:01.728339 c6025a:Axis1-VelAct 146.813 mm/s
11:45:01.738342 c6025a:Axis1-VelAct 148.781 mm/s
11:45:01.748340 c6025a:Axis1-VelAct 150.469 mm/s
11:45:01.758342 c6025a:Axis1-VelAct 152.719 mm/s
11:45:01.768344 c6025a:Axis1-VelAct 154.688 mm/s
11:45:01.778338 c6025a:Axis1-VelAct 156.656 mm/s
11:45:01.788341 c6025a:Axis1-VelAct 158.625 mm/s
11:45:01.798339 c6025a:Axis1-VelAct 160.594 mm/s
11:45:01.808344 c6025a:Axis1-VelAct 162.562 mm/s
11:45:01.818340 c6025a:Axis1-VelAct 164.531 mm/s
11:45:01.828337 c6025a:Axis1-VelAct 166.500 mm/s
11:45:01.838341 c6025a:Axis1-VelAct 168.187 mm/s
11:45:01.848342 c6025a:Axis1-VelAct 170.438 mm/s
11:45:01.858343 c6025a:Axis1-VelAct 172.406 mm/s
11:45:01.868336 c6025a:Axis1-VelAct 174.375 mm/s
11:45:01.878344 c6025a:Axis1-VelAct 176.344 mm/s
11:45:01.888347 c6025a:Axis1-VelAct 178.313 mm/s
11:45:01.898343 c6025a:Axis1-VelAct 180.281 mm/s
11:45:01.908343 c6025a:Axis1-VelAct 182.250 mm/s
11:45:01.918337 c6025a:Axis1-VelAct 183.937 mm/s
11:45:01.928340 c6025a:Axis1-VelAct 186.188 mm/s
11:45:01.938341 c6025a:Axis1-VelAct 188.438 mm/s
11:45:01.948339 c6025a:Axis1-VelAct 190.406 mm/s
11:45:01.958338 c6025a:Axis1-VelAct 192.094 mm/s
11:45:01.968337 c6025a:Axis1-VelAct 194.344 mm/s
11:45:01.978338 c6025a:Axis1-VelAct 196.312 mm/s
11:45:01.988340 c6025a:Axis1-VelAct 198.281 mm/s
11:45:01.998339 c6025a:Axis1-VelAct 200.250 mm/s
11:45:02.008339 c6025a:Axis1-VelAct 202.219 mm/s
11:45:02.018339 c6025a:Axis1-VelAct 204.469 mm/s
11:45:02.028341 c6025a:Axis1-VelAct 206.156 mm/s
11:45:02.038341 c6025a:Axis1-VelAct 208.406 mm/s
11:45:02.048342 c6025a:Axis1-VelAct 210.094 mm/s
11:45:02.058338 c6025a:Axis1-VelAct 212.344 mm/s
11:45:02.068337 c6025a:Axis1-VelAct 214.313 mm/s
11:45:02.078341 c6025a:Axis1-VelAct 216.000 mm/s
11:45:02.088339 c6025a:Axis1-VelAct 217.969 mm/s
11:45:02.098339 c6025a:Axis1-VelAct 219.937 mm/s
11:45:02.108341 c6025a:Axis1-VelAct 222.188 mm/s
11:45:02.118345 c6025a:Axis1-VelAct 224.156 mm/s
11:45:02.128344 c6025a:Axis1-VelAct 226.406 mm/s
11:45:02.138340 c6025a:Axis1-VelAct 227.812 mm/s
11:45:02.148344 c6025a:Axis1-VelAct 230.344 mm/s
11:45:02.158337 c6025a:Axis1-VelAct 232.031 mm/s
11:45:02.168339 c6025a:Axis1-VelAct 233.719 mm/s
11:45:02.178349 c6025a:Axis1-VelAct 236.250 mm/s
11:45:02.188339 c6025a:Axis1-VelAct 238.219 mm/s
11:45:02.198337 c6025a:Axis1-VelAct 240.188 mm/s
11:45:02.208340 c6025a:Axis1-VelAct 241.875 mm/s
11:45:02.218339 c6025a:Axis1-VelAct 243.844 mm/s
11:45:02.228343 c6025a:Axis1-VelAct 245.531 mm/s
11:45:02.238338 c6025a:Axis1-VelAct 248.062 mm/s
11:45:02.248339 c6025a:Axis1-VelAct 249.750 mm/s
11:45:02.258338 c6025a:Axis1-VelAct 251.719 mm/s
11:45:02.268338 c6025a:Axis1-VelAct 253.969 mm/s
11:45:02.278338 c6025a:Axis1-VelAct 255.937 mm/s
11:45:02.288343 c6025a:Axis1-VelAct 257.625 mm/s
11:45:02.298343 c6025a:Axis1-VelAct 259.594 mm/s
11:45:02.308340 c6025a:Axis1-VelAct 261.844 mm/s
11:45:02.318337 c6025a:Axis1-VelAct 263.812 mm/s
11:45:02.328342 c6025a:Axis1-VelAct 265.781 mm/s
11:45:02.338352 c6025a:Axis1-VelAct 267.750 mm/s
11:45:02.348340 c6025a:Axis1-VelAct 269.719 mm/s
11:45:02.358341 c6025a:Axis1-VelAct 271.969 mm/s
11:45:02.368340 c6025a:Axis1-VelAct 273.656 mm/s
11:45:02.378341 c6025a:Axis1-VelAct 275.625 mm/s
11:45:02.388340 c6025a:Axis1-VelAct 277.594 mm/s
11:45:02.398344 c6025a:Axis1-VelAct 279.844 mm/s
11:45:02.408340 c6025a:Axis1-VelAct 281.531 mm/s
11:45:02.418341 c6025a:Axis1-VelAct 283.500 mm/s
11:45:02.428344 c6025a:Axis1-VelAct 285.750 mm/s
11:45:02.438351 c6025a:Axis1-VelAct 288.000 mm/s
11:45:02.448342 c6025a:Axis1-VelAct 289.688 mm/s
11:45:02.458345 c6025a:Axis1-VelAct 291.656 mm/s
11:45:02.468351 c6025a:Axis1-VelAct 293.906 mm/s
11:45:02.478339 c6025a:Axis1-VelAct 295.312 mm/s
11:45:02.488339 c6025a:Axis1-VelAct 297.844 mm/s
11:45:02.498340 c6025a:Axis1-VelAct 299.531 mm/s
11:45:02.508340 c6025a:Axis1-VelAct 302.063 mm/s
11:45:02.518351 c6025a:Axis1-VelAct 304.031 mm/s
11:45:02.528340 c6025a:Axis1-VelAct 305.719 mm/s
11:45:02.538344 c6025a:Axis1-VelAct 307.406 mm/s
11:45:02.548338 c6025a:Axis1-VelAct 309.938 mm/s
11:45:02.558343 c6025a:Axis1-VelAct 311.906 mm/s
11:45:02.568340 c6025a:Axis1-VelAct 313.594 mm/s
11:45:02.578338 c6025a:Axis1-VelAct 316.125 mm/s
11:45:02.588339 c6025a:Axis1-VelAct 317.812 mm/s
11:45:02.598336 c6025a:Axis1-VelAct 320.062 mm/s
11:45:02.608346 c6025a:Axis1-VelAct 321.750 mm/s
11:45:02.618339 c6025a:Axis1-VelAct 323.719 mm/s
11:45:02.628345 c6025a:Axis1-VelAct 325.969 mm/s
11:45:02.638337 c6025a:Axis1-VelAct 327.937 mm/s
11:45:02.648337 c6025a:Axis1-VelAct 329.625 mm/s
11:45:02.658338 c6025a:Axis1-VelAct 331.875 mm/s
11:45:02.668340 c6025a:Axis1-VelAct 334.125 mm/s
11:45:02.678340 c6025a:Axis1-VelAct 336.094 mm/s
11:45:02.688345 c6025a:Axis1-VelAct 338.062 mm/s
11:45:02.698340 c6025a:Axis1-VelAct 339.750 mm/s
11:45:02.708339 c6025a:Axis1-VelAct 341.719 mm/s
11:45:02.718338 c6025a:Axis1-VelAct 343.969 mm/s
11:45:02.728337 c6025a:Axis1-VelAct 346.219 mm/s
11:45:02.738337 c6025a:Axis1-VelAct 348.188 mm/s
11:45:02.748340 c6025a:Axis1-VelAct 350.156 mm/s
11:45:02.758339 c6025a:Axis1-VelAct 351.844 mm/s
11:45:02.768342 c6025a:Axis1-VelAct 354.094 mm/s
11:45:02.778337 c6025a:Axis1-VelAct 355.781 mm/s
11:45:02.788340 c6025a:Axis1-VelAct 358.031 mm/s
11:45:02.798344 c6025a:Axis1-VelAct 360.281 mm/s
11:45:02.808336 c6025a:Axis1-VelAct 362.531 mm/s
11:45:02.818336 c6025a:Axis1-VelAct 363.938 mm/s
11:45:02.828338 c6025a:Axis1-VelAct 365.906 mm/s
11:45:02.838336 c6025a:Axis1-VelAct 367.875 mm/s
11:45:02.848338 c6025a:Axis1-VelAct 370.406 mm/s
11:45:02.858342 c6025a:Axis1-VelAct 372.094 mm/s
11:45:02.868341 c6025a:Axis1-VelAct 374.062 mm/s
11:45:02.878344 c6025a:Axis1-VelAct 376.312 mm/s
11:45:02.888336 c6025a:Axis1-VelAct 378.000 mm/s
11:45:02.898336 c6025a:Axis1-VelAct 380.250 mm/s
11:45:02.908340 c6025a:Axis1-VelAct 382.219 mm/s
11:45:02.918340 c6025a:Axis1-VelAct 384.469 mm/s
11:45:02.928337 c6025a:Axis1-VelAct 386.156 mm/s
11:45:02.938341 c6025a:Axis1-VelAct 388.406 mm/s
11:45:02.948338 c6025a:Axis1-VelAct 390.094 mm/s
11:45:02.958344 c6025a:Axis1-VelAct 392.344 mm/s
11:45:02.968342 c6025a:Axis1-VelAct 394.312 mm/s
11:45:02.978339 c6025a:Axis1-VelAct 396.281 mm/s
11:45:02.988337 c6025a:Axis1-VelAct 398.531 mm/s
11:45:02.998338 c6025a:Axis1-VelAct 400.219 mm/s
11:45:03.008341 c6025a:Axis1-VelAct 401.906 mm/s
11:45:03.018337 c6025a:Axis1-VelAct 404.156 mm/s
11:45:03.028343 c6025a:Axis1-VelAct 406.406 mm/s
11:45:03.038338 c6025a:Axis1-VelAct 408.094 mm/s
11:45:03.048342 c6025a:Axis1-VelAct 410.625 mm/s
11:45:03.058336 c6025a:Axis1-VelAct 412.312 mm/s
11:45:03.068338 c6025a:Axis1-VelAct 414.281 mm/s
11:45:03.078344 c6025a:Axis1-VelAct 416.250 mm/s
11:45:03.088342 c6025a:Axis1-VelAct 418.219 mm/s
11:45:03.098337 c6025a:Axis1-VelAct 420.188 mm/s
11:45:03.108343 c6025a:Axis1-VelAct 422.438 mm/s
11:45:03.118338 c6025a:Axis1-VelAct 424.406 mm/s
11:45:03.128345 c6025a:Axis1-VelAct 426.094 mm/s
11:45:03.138337 c6025a:Axis1-VelAct 428.625 mm/s
11:45:03.148340 c6025a:Axis1-VelAct 430.031 mm/s
11:45:03.158348 c6025a:Axis1-VelAct 432.562 mm/s
11:45:03.168340 c6025a:Axis1-VelAct 434.250 mm/s
11:45:03.178344 c6025a:Axis1-VelAct 436.500 mm/s
11:45:03.188340 c6025a:Axis1-VelAct 438.187 mm/s
11:45:03.198342 c6025a:Axis1-VelAct 440.437 mm/s
11:45:03.208341 c6025a:Axis1-VelAct 442.406 mm/s
11:45:03.218336 c6025a:Axis1-VelAct 444.375 mm/s
11:45:03.228338 c6025a:Axis1-VelAct 446.344 mm/s
11:45:03.238339 c6025a:Axis1-VelAct 448.313 mm/s
11:45:03.248344 c6025a:Axis1-VelAct 450.281 mm/s
11:45:03.258341 c6025a:Axis1-VelAct 452.250 mm/s
11:45:03.268340 c6025a:Axis1-VelAct 454.500 mm/s
11:45:03.278345 c6025a:Axis1-VelAct 455.906 mm/s
11:45:03.288342 c6025a:Axis1-VelAct 458.719 mm/s
11:45:03.298340 c6025a:Axis1-VelAct 460.406 mm/s
11:45:03.308345 c6025a:Axis1-VelAct 462.094 mm/s
11:45:03.318339 c6025a:Axis1-VelAct 464.062 mm/s
11:45:03.328338 c6025a:Axis1-VelAct 466.594 mm/s
11:45:03.338343 c6025a:Axis1-VelAct 468.000 mm/s
11:45:03.348339 c6025a:Axis1-VelAct 470.250 mm/s
11:45:03.358338 c6025a:Axis1-VelAct 472.500 mm/s
11:45:03.368340 c6025a:Axis1-VelAct 473.906 mm/s
11:45:03.378343 c6025a:Axis1-VelAct 476.719 mm/s
11:45:03.388343 c6025a:Axis1-VelAct 478.125 mm/s
11:45:03.398336 c6025a:Axis1-VelAct 480.094 mm/s
11:45:03.408338 c6025a:Axis1-VelAct 482.344 mm/s
11:45:03.418343 c6025a:Axis1-VelAct 484.313 mm/s
11:45:03.428343 c6025a:Axis1-VelAct 486.281 mm/s
11:45:03.438343 c6025a:Axis1-VelAct 488.250 mm/s
11:45:03.448340 c6025a:Axis1-VelAct 490.219 mm/s
11:45:03.458350 c6025a:Axis1-VelAct 491.906 mm/s
11:45:03.468345 c6025a:Axis1-VelAct 493.875 mm/s
11:45:03.478342 c6025a:Axis1-VelAct 495.000 mm/s
11:45:03.488338 c6025a:Axis1-VelAct 496.688 mm/s
11:45:03.498342 c6025a:Axis1-VelAct 498.375 mm/s
11:45:03.508339 c6025a:Axis1-VelAct 499.219 mm/s
11:45:03.518336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.528338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:03.538336 c6025a:Axis1-VelAct 500.625 mm/s
11:45:03.558342 c6025a:Axis1-VelAct 500.906 mm/s
11:45:03.568338 c6025a:Axis1-VelAct 501.187 mm/s
11:45:03.578337 c6025a:Axis1-VelAct 501.188 mm/s
11:45:03.588338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:03.628341 c6025a:Axis1-VelAct 500.062 mm/s
11:45:03.638338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:03.648338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:03.658337 c6025a:Axis1-VelAct 500.063 mm/s
11:45:03.678341 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.688335 c6025a:Axis1-VelAct 500.344 mm/s
11:45:03.698338 c6025a:Axis1-VelAct 500.062 mm/s
11:45:03.708336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:03.718337 c6025a:Axis1-VelAct 500.344 mm/s
11:45:03.728334 c6025a:Axis1-VelAct 500.063 mm/s
11:45:03.738336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:03.748334 c6025a:Axis1-VelAct 500.063 mm/s
11:45:03.768337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.778338 c6025a:Axis1-VelAct 500.063 mm/s
11:45:03.788335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:03.798338 c6025a:Axis1-VelAct 500.063 mm/s
11:45:03.808335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.818340 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.828351 c6025a:Axis1-VelAct 500.062 mm/s
11:45:03.838343 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.848336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.868336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:03.918336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.928334 c6025a:Axis1-VelAct 499.500 mm/s
11:45:03.938338 c6025a:Axis1-VelAct 500.062 mm/s
11:45:03.948336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:03.958338 c6025a:Axis1-VelAct 499.219 mm/s
11:45:03.968341 c6025a:Axis1-VelAct 500.063 mm/s
11:45:03.978335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.988336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:03.998334 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.008335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.018335 c6025a:Axis1-VelAct 499.219 mm/s
11:45:04.028338 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.038335 c6025a:Axis1-VelAct 498.656 mm/s
11:45:04.048344 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.058337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.068335 c6025a:Axis1-VelAct 498.938 mm/s
11:45:04.078335 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.088339 c6025a:Axis1-VelAct 499.219 mm/s
11:45:04.098342 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.138336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.148342 c6025a:Axis1-VelAct 499.219 mm/s
11:45:04.158337 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.168336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.178343 c6025a:Axis1-VelAct 499.219 mm/s
11:45:04.228342 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.238336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.248337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.258342 c6025a:Axis1-VelAct 499.219 mm/s
11:45:04.268339 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.278338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.288342 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.298335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.308334 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.318343 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.338337 c6025a:Axis1-VelAct 499.219 mm/s
11:45:04.348336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.358335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.368335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.378337 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.388339 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.398338 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.408338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.418341 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.428334 c6025a:Axis1-VelAct 499.500 mm/s
11:45:04.438338 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.448336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.468338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.478337 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.488338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.498334 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.508338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:04.518336 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.528335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.538335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.558336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.568336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.578336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.588336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.598344 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.608337 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.618335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.628346 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.638336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.648336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.658339 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.698335 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.708335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.718338 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.728340 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.738337 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.748342 c6025a:Axis1-VelAct 500.906 mm/s
11:45:04.758340 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.768337 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.778339 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.788336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.798339 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.808338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.828341 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.838338 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.848336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.858336 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.878335 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.888339 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.898336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.908342 c6025a:Axis1-VelAct 500.906 mm/s
11:45:04.918337 c6025a:Axis1-VelAct 500.625 mm/s
11:45:04.928342 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.938334 c6025a:Axis1-VelAct 500.906 mm/s
11:45:04.948340 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.968337 c6025a:Axis1-VelAct 500.063 mm/s
11:45:04.978334 c6025a:Axis1-VelAct 500.344 mm/s
11:45:04.988336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:04.998342 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.008338 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.018337 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.028336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.038336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.048336 c6025a:Axis1-VelAct 500.625 mm/s
11:45:05.058339 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.068337 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.078336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.088335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.098335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.108336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.128336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.148336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.158341 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.168341 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.178335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.188335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.198336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.208339 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.228337 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.238337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.248335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.258335 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.278335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.288342 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.298336 c6025a:Axis1-VelAct 499.219 mm/s
11:45:05.308338 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.318336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.328336 c6025a:Axis1-VelAct 499.219 mm/s
11:45:05.338336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.348337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.378335 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.388335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.398336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.408342 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.418335 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.428345 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.438336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.448340 c6025a:Axis1-VelAct 499.219 mm/s
11:45:05.458337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.478335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.488335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.498337 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.508337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.518335 c6025a:Axis1-VelAct 499.219 mm/s
11:45:05.528340 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.538338 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.548336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.558337 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.568338 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.578335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.588337 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.598335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.608335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.618338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.638336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.648340 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.658338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.668343 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.678337 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.688340 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.698336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.718335 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.728339 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.748335 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.758341 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.768337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.778337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.788335 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.798336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.808335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.818336 c6025a:Axis1-VelAct 499.500 mm/s
11:45:05.828338 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.848341 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.858337 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.868337 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.878339 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.888336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.898343 c6025a:Axis1-VelAct 499.781 mm/s
11:45:05.908337 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.918336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.938337 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.948341 c6025a:Axis1-VelAct 500.344 mm/s
11:45:05.958337 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.968345 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.978335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:05.988338 c6025a:Axis1-VelAct 500.063 mm/s
11:45:05.998336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.028337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.038336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.048341 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.058338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.068342 c6025a:Axis1-VelAct 500.062 mm/s
11:45:06.078339 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.088336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.098336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:06.108335 c6025a:Axis1-VelAct 499.500 mm/s
11:45:06.128336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.138337 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.148340 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.158335 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.168337 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.178335 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.188340 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.198335 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.218335 c6025a:Axis1-VelAct 500.906 mm/s
11:45:06.228340 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.238339 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.248335 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.258336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.268341 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.278335 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.288340 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.298336 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.308334 c6025a:Axis1-VelAct 500.906 mm/s
11:45:06.318341 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.328339 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.338340 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.348341 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.358344 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.378342 c6025a:Axis1-VelAct 500.062 mm/s
11:45:06.388337 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.398346 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.418339 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.428338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.448336 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.458336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.468335 c6025a:Axis1-VelAct 500.062 mm/s
11:45:06.478338 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.488336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.498338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.508341 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.518337 c6025a:Axis1-VelAct 500.625 mm/s
11:45:06.528336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.538337 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.548336 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.558337 c6025a:Axis1-VelAct 500.062 mm/s
11:45:06.568338 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.578338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.588338 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.598340 c6025a:Axis1-VelAct 500.344 mm/s
11:45:06.608335 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.618338 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.628336 c6025a:Axis1-VelAct 500.062 mm/s
11:45:06.638336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.658339 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.668336 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.678342 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.688342 c6025a:Axis1-VelAct 500.063 mm/s
11:45:06.698330 c6025a:m0s006-BI08 "False"
11:45:06.698343 c6025a:Axis1-VelAct 499.781 mm/s
11:45:06.708341 c6025a:Axis1-VelAct 499.500 mm/s
11:45:06.718341 c6025a:Axis1-VelAct 497.531 mm/s
11:45:06.728341 c6025a:Axis1-VelAct 495.563 mm/s
11:45:06.738345 c6025a:Axis1-VelAct 492.188 mm/s
11:45:06.748339 c6025a:Axis1-VelAct 487.969 mm/s
11:45:06.758344 c6025a:Axis1-VelAct 482.625 mm/s
11:45:06.768339 c6025a:Axis1-VelAct 476.156 mm/s
11:45:06.778343 c6025a:Axis1-VelAct 468.562 mm/s
11:45:06.788337 c6025a:Axis1-VelAct 460.125 mm/s
11:45:06.798343 c6025a:Axis1-VelAct 450.844 mm/s
11:45:06.808345 c6025a:Axis1-VelAct 440.719 mm/s
11:45:06.818337 c6025a:Axis1-VelAct 430.875 mm/s
11:45:06.828340 c6025a:Axis1-VelAct 420.750 mm/s
11:45:06.838345 c6025a:Axis1-VelAct 410.625 mm/s
11:45:06.848340 c6025a:Axis1-VelAct 400.500 mm/s
11:45:06.858337 c6025a:Axis1-VelAct 390.094 mm/s
11:45:06.868339 c6025a:Axis1-VelAct 379.969 mm/s
11:45:06.878343 c6025a:Axis1-VelAct 370.406 mm/s
11:45:06.888341 c6025a:Axis1-VelAct 360.000 mm/s
11:45:06.898345 c6025a:Axis1-VelAct 349.875 mm/s
11:45:06.908343 c6025a:Axis1-VelAct 339.750 mm/s
11:45:06.918337 c6025a:Axis1-VelAct 329.625 mm/s
11:45:06.928339 c6025a:Axis1-VelAct 319.219 mm/s
11:45:06.938336 c6025a:Axis1-VelAct 309.094 mm/s
11:45:06.948342 c6025a:Axis1-VelAct 298.969 mm/s
11:45:06.958339 c6025a:Axis1-VelAct 289.125 mm/s
11:45:06.968348 c6025a:Axis1-VelAct 279.000 mm/s
11:45:06.978337 c6025a:Axis1-VelAct 268.594 mm/s
11:45:06.988338 c6025a:Axis1-VelAct 258.750 mm/s
11:45:06.998340 c6025a:Axis1-VelAct 248.344 mm/s
11:45:07.008347 c6025a:Axis1-VelAct 238.219 mm/s
11:45:07.018340 c6025a:Axis1-VelAct 228.094 mm/s
11:45:07.028341 c6025a:Axis1-VelAct 218.250 mm/s
11:45:07.038341 c6025a:Axis1-VelAct 207.844 mm/s
11:45:07.048345 c6025a:Axis1-VelAct 197.719 mm/s
11:45:07.058341 c6025a:Axis1-VelAct 187.594 mm/s
11:45:07.068342 c6025a:Axis1-VelAct 177.469 mm/s
11:45:07.078337 c6025a:Axis1-VelAct 167.344 mm/s
11:45:07.088339 c6025a:Axis1-VelAct 156.937 mm/s
11:45:07.098337 c6025a:Axis1-VelAct 146.813 mm/s
11:45:07.108338 c6025a:Axis1-VelAct 136.969 mm/s
11:45:07.118338 c6025a:Axis1-VelAct 126.844 mm/s
11:45:07.128345 c6025a:Axis1-VelAct 116.438 mm/s
11:45:07.138338 c6025a:Axis1-VelAct 106.594 mm/s
11:45:07.148346 c6025a:Axis1-VelAct 96.469 mm/s
11:45:07.158336 c6025a:Axis1-VelAct 86.062 mm/s
11:45:07.168337 c6025a:Axis1-VelAct 75.938 mm/s
11:45:07.178344 c6025a:Axis1-VelAct 66.094 mm/s
11:45:07.188342 c6025a:Axis1-VelAct 55.969 mm/s
11:45:07.198335 c6025a:Axis1-VelAct 45.844 mm/s
11:45:07.208334 c6025a:Axis1-VelAct 36.000 mm/s
11:45:07.218331 c6025a:Axis1-VelAct 27.844 mm/s
11:45:07.228327 c6025a:Axis1-VelAct 20.813 mm/s
11:45:07.238326 c6025a:Axis1-VelAct 14.625 mm/s
11:45:07.248327 c6025a:Axis1-VelAct 9.563 mm/s
11:45:07.258326 c6025a:Axis1-VelAct 5.625 mm/s
11:45:07.268326 c6025a:Axis1-VelAct 2.531 mm/s
11:45:07.278327 c6025a:Axis1-VelAct 0.281 mm/s
11:45:07.278336 c6025a:Axis1-EnaAct "Disabled"
11:45:07.278368 c6025a:m0s005-BO07 "One"
11:45:07.288333 c6025a:Axis1-VelAct -0.562 mm/s
11:45:07.308329 c6025a:Axis1-VelAct 0.000 mm/s
[Test data](docs/data_log.txt)
![Velocity](docs/velo.png)
![Digital](docs/digital.png)
# Test at Debye
```
libversionShow
require 3.3.1 /gfa/.mounts/sls_ioc/modules/require/3.3.1/R7.0.7/
misc 2.15.0 /gfa/.mounts/sls_ioc/modules/misc/2.15.0/R7.0.7/
ecmccfg safety3 /gfa/.mounts/sls_ioc/modules/ecmccfg/safety3/R7.0.7/
ECmasterECMC v1.1.0 /gfa/.mounts/sls_ioc/modules/ECmasterECMC/v1.1.0/R7.0.7/
calc 3.7.6 /gfa/.mounts/sls_ioc/modules/calc/3.7.6/R7.0.7/
asyn 4.42.2 /gfa/.mounts/sls_ioc/modules/asyn/4.42.2/R7.0.7/
motorECMC 7.0.9-ESS /gfa/.mounts/sls_ioc/modules/motorECMC/7.0.9-ESS/R7.0.7/
ruckig 0.6.3 /gfa/.mounts/sls_ioc/modules/ruckig/0.6.3/R7.0.7/
ecmc safety3 /gfa/.mounts/sls_ioc/modules/ecmc/safety3/R7.0.7/
ecmccomp 0.1.0 /gfa/.mounts/sls_ioc/modules/ecmccomp/0.1.0/R7.0.7/
ecmc_plugin_safety safety3 /gfa/.mounts/sls_ioc/modules/ecmc_plugin_safety/safety3/R7.0.7/
```

View File

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 141 KiB

View File

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -1,204 +1,94 @@
macros: LIMIT=10000,TYPE=0,DRV_SLAVE=${DRV_SLAVE} # Macros for all below (evaluated before jinja linter)
axis:
id: 1 # Axis id
type: joint # this is for future selection of axis type
# mode: CSV # supported mode, CSV and CSP, defaults CSV
# parameters: 'axisPar' # additional parameters # Additional params to motor record driver
#healthOutput: ec0... # Ethercat entry for health output
# autoMode: # Switch drive modes automaticaly for normal motion and homing (smaract for instance)
# modeSet: ec0.. # Ethercat entry drive mode write (set CSV,CSP,homing)
# modeAct: ec0.. # Ethercat entry drive mode reading (set CSV,CSP,homing)
# modeCmdMotion: 9 # Drive mode value for normal motion (written to axis.drvMode.modeSet when normal motion)
# modeCmdHome: 10 # Drive mode value for when homing (written to axis.drvMode.modeSet when homing)
# features:
# blockCom: false # Block communication to axis
# allowedFunctions:
# homing: true # Allow homing
# constantVelocity: true # Allow constant velocity
# positioning: true # Allow positioning
id: ${AXIS_ID=1} # Axis id
parameters: 'powerAutoOnOff=2;powerOffDelay=-1;'
# feedSwitchesOutput: ec0.s${BO_SID}.binaryOutput${BO_CH=01} # Ethercat entry for feed switches
epics:
name: Axis1 # Axis anme
name: ${AX_NAME=M1} # Axis anme
precision: 3 # Decimal count
description: very important motor axis # Axis description
description: Test cfg # Axis description
unit: mm # Unit
# motorRecord:
# enable: true
# description: This is MR
# fieldInit: 'RRES=1.0,RTRY=2,RMOD=1,UEIP=0,RDBD=0.1,URIP=1,RDBL=$(IOC):$(ECMC_MOTOR_NAME)-PosActSim' # Extra config for Motor record
motorRecord:
fieldInit: 'RTRY=0,FOFF=Frozen' # Extra config for Motor record
drive:
numerator: 3600 # Fastest speed in engineering units
denominator: 32768 # I/O range for ECMC_EC_ALIAS_DRV_VELO_SET
# type: 0 # Stepper: 0. DS402: 1 (DS402 = servos and advanced stepper drives)
control: ec0.s$(DRV_SLAVE).driveControl01 # Control word ethercat entry
numerator: 10 # Fastest speed in eng. units (2000 Fullsteps/s==10mm/s)
denominator: 32768 # I/O range for ECMC_EC_ALIAS_DRV_VELO_SET (normally +-16bit)
type: 0 # Stepper: 0. DS402: 1 (DS402 = servos and advanced stepper drives)
setpoint: ec0.s$(DRV_SID).velocitySetpoint01 # Velocity setpoint if CSV. Position setpoint if CSP
control: ec0.s$(DRV_SID).driveControl01 # Control word ethercat entry
enable: 0 # Enable bit index in control word (not used if DS402)
enabled: 1 # Enabled bit index in status word (not used if DS402)
status: ec0.s$(DRV_SLAVE).driveStatus01 # Status word ethercat entry
setpoint: ec0.s$(DRV_SLAVE).velocitySetpoint01 # Velocity setpoint if CSV. Position setpoint if CSP
# reduceTorque: 2 # Reduce torque bit in drive control word
# reduceTorqueEnable: True # Enable reduce torque functionality
# brake:
# enable: true # Enable brake
# output: ec0... # Ethercat link to brake output
# openDelay: 0 # Brake timing parameter in cycles (default 1kHz)
# closeAhead: 0 # Brake timing parameter in cycles (default 1kHz)
# reset: 1 # Reset (if no drive reset bit then leave empty)
# warning: 2 # Warning (if no drive warning bit then leave empty)
# error: # max 3
# - 3 # Error 0 (if no drive error bit then leave empty)
# - 7 # Error 1 (if no drive error bit then leave empty)
# - 14 # Error 2 (if no drive error bit then leave empty)
reset: 1 # Reset bit in control word (if no drive reset bit then leave empty)
reduceTorque: 2 # Reduce torque bit in drive control word
reduceTorqueEnable: True # Enable reduce torque functionality
status: ec0.s$(DRV_SID).driveStatus01 # Status word ethercat entry
enabled: 1 # Enabled bit index in status word (not used if DS402)
warning: 2 # Warning bit in status word (if no drive warning bit then leave empty)
error: # max 3 error bits in status word
- 3 # Error 0 (if no drive error bit then leave empty)
- 7 # Error 1 (if no drive error bit then leave empty)
- 14 # Error 2 (if no drive error bit then leave empty)
encoder:
numerator: 360 # Scaling numerator example 360 deg/rev
denominator: 12800 # Scaling denominator example 4096 ticks per 360 degree
# type: 0 # Type: 0=Incremental, 1=Absolute
bits: 16 # Total bit count of encoder raw data
# absBits: 0 # Absolute bit count (for absolute encoders) always least significant part of 'bits'
# absOffset: 0 # Encoder offset in eng units (for absolute encoders)
# mask: '0xFFF00' # Mask applied to raw encoder value
position: ec0.s$(DRV_SLAVE).positionActual01 # Ethercat entry for actual position input (encoder)
control: ec0.s$(DRV_SLAVE).encoderControl01 # mandatory only if 'reset' is used
status: ec0.s$(DRV_SLAVE).encoderStatus01 # mandatory only if 'warning' or 'error' are used
# ready: 10 # Bit in encoder status word for encoder ready
# source: 0 # 0 = Encoder value from etehrcat hardware, 1 = Encoder value from PLC
# reset: 1 # Reset (optional)
# warning: 2 # Warning (optional)
# error: # max 3 (optional)
# - 5 # Error 0
# - 9 # Error 1
# - 11 # Error 2
# filter:
# velocity:
# size: 100 # Filter size for velocity
# enable: true # enable velocity filter
# position:
# size: 100 # Filter size for encoder value
# enable: true # enable encoder value filter
# latch:
# position: '' # Link to latched value. Used for some homing seqs
# control: 0 # Bit in encoder control word to arm latch. Used for some homing seqs
# status: 0 # Bit in encoder status word for latch triggered status. Used for some homing seqs
# primary: 1 # Use this encoder as primary (for control)
# homing:
# type: 3 # Homing sequence type
# position: -30 # Position to reference encoder to
# velocity:
# to: 10 # Velocity to cam/sensor (used for some homing seqs)
# from: 5 # Velocity from cam/sensor (used for some homing seqs)
# acceleration: 20 # Acceleration during homing
# deceleration: 100 # Deceleration during homing
# refToEncIDAtStartup: 1 # At startup then set the start value of this encoder to actpos of this encoder id
# refAtHome: 1 # If homing is executed then set position of this encoder
# tolToPrim: 0 # If set then this is the max allowed tolerance between prim encoder and this encoder
# postMoveEnable: yes # Enable move after successfull homing
# postMovePosition: 10 # Position to move to after successfull homing
# trigg: ec0.. # Ethercat entry for triggering drive internal homing seq (seq id 26)
# ready: ec0.. # Ethercat entry for readinf drive internal homing seq ready (seq id 26)
desc: BISS-C
numerator: 1 # Scaling numerator example 1 mm/rev
denominator: 4096 # Scaling denominator example 4096 ticks per 360 degree
type: 1 # Type: 0=Incremental, 1=Absolute
bits: 32 # Total bit count of encoder raw data
absBits: 26 # Absolute bit count (for absolute encoders) always least significant part of 'bits'
absOffset: -15615 # Encoder offset in eng units (for absolute encoders)
position: ec0.s$(ENC_SID).positionActual${ENC_CH=01} # Ethercat entry for actual position input (encoder)
status: ec0.s$(ENC_SID).encoderStatus${ENC_CH=01} # mandatory only if 'warning' or 'error' are used
ready: 2 # Bit in encoder status word for encoder ready
warning: 0 # Warning (optional)
error: # max 3 (optional)
- 1 # Error 0
delayComp: # Delay compensation for time between application of setpoint to reading of encoder (normally atleast 2 cycles)
time: 0 # Delay time between set and act [cycles]
enable: true # enable (defaults to 1 if not set)
controller:
Kp: 1 # Kp proportinal gain
Ki: 0.02 # Ki integral gain
Kd: 0 # Kd derivative gain
# Kff: 1 # Feed forward gain
# deadband:
# tol: 0.01 # Stop control if within this distance from target for the below time
# time: 100
# limits:
# minOutput: -100 # Minimum controller output
# maxOutput: 100 # Maximum controller output
# minIntegral: -100 # Minimum integral output
# maxIntegral: 100 # Maximum integral output
# inner:
# Kp: 0.1 # Kp for when close to target
# Ki: 0.1 # Ki for when close to target
# Kd: 0.1 # Kd for when close to target
# tol: 0.1 # Distance from target for when inner PID params will be used, defaults to atTarget tol
Kp: 10 # Kp proportinal gain
Ki: 0 # Ki integral gain
Kd: 0 # Kd derivative gain
trajectory:
# type: 1 # Default 0 = trapetz, 1 = S-curve (ruckig)
axis:
velocity: 500 # Default velo for axis
acceleration: 200 # Default acc for axis
deceleration: 200 # Default dec for axis
emergencyDeceleration: 1000 # Deceleration when axis in error state
velocity: 2 # Default velo for axis
acceleration: 2 # Default acc for axis
deceleration: 2 # Default dec for axis
emergencyDeceleration: 5 # Deceleration when axis in error state
jerk: 10 # Default jerk for axis
jog:
velocity: 5 # Default velo fro JOG (motor record)
# modulo:
# range: 360 # Modulo range 0..360
# type: 0 # Modulo type
velocity: 1 # Default velo fro JOG (motor record)
input:
limit:
forward: ec0.s$(DRV_SLAVE).driveStatus01.12 # Ethercat entry for low limit switch input
# forwardPolarity: 0 # Polarity of forward limit switch
backward: ec0.s$(DRV_SLAVE).driveStatus01.11 # Ethercat entry for high limit switch input
# backwardPolarity: 0 # Polarity of forward limit switch
home: 'ec0.s$(DRV_SLAVE).ONE.0' # Ethercat entry for home switch
# homePolarity: 0 # Polarity of home switch
interlock: 'ec0.s$(DRV_SLAVE).ONE.0' # Ethercat entry for interlock switch input
# interlockPolarity: 0 # Polarity of interlock switch
# homing:
# type: 3 # Homing sequence type
# position: -30 # Position to reference encoder to
# velocity:
# to: 10 # Velocity to cam/sensor (used for some homing seqs)
# from: 5 # Velocity from cam/sensor (used for some homing seqs)
# acc: 20 # Acceleration during homing
# dec: 100 # Deceleration during homing
# refToEncIDAtStartup: 1 # At startup then set the start value of this encoder to actpos of this encoder id
# refAtHome: 1 # If homing is executed then set position of this encoder
# tolToPrim: 0 # If set then this is the max allowed tolerance between prim encoder and this encoder
# postMoveEnable: yes # Enable move after successfull homing
# postMovePosition: 10 # Position to move to after successfull homing
# timeout: 100 # Sequence timeout
forward: ec0.s$(DRV_SID).driveStatus01.12 # Ethercat entry for low limit switch input
backward: ec0.s$(DRV_SID).driveStatus01.11 # Ethercat entry for high limit switch input
home: 'ec0.s$(DRV_SID).ONE.0' # Ethercat entry for home switch
interlock: 'ec0.s-1.ONE.0' # Ethercat entry for interlock switch input
softlimits:
enable: false # Enable soft limits
forward: 100 # Soft limit position fwd
forwardEnable: false # Soft limit position fwd enable
backward: -100 # Soft limit position bwd
backwardEnable: false # Soft limit position bwd enable
enable: true # Enable soft limits
forward: 30 # Soft limit position fwd
forwardEnable: true # Soft limit position fwd enable
backward: -30 # Soft limit position bwd
backwardEnable: true # Soft limit position bwd enable
monitoring:
lag:
enable: true # Enable position lag monitoring (following error)
tolerance: 2 # Allowed tolerance
tolerance: 0.1 # Allowed tolerance
time: 10 # Allowed time outside tolerance target:
target:
enable: true # Enable at target monitoring (needs to be enabled if using motor record)
tolerance: 0.5 # Allowed tolerance
time: 10 # Filter time inside tolerance to be at target
velocity:
enable: false # Enable velocity monitoring
max: 100 # Allowed max velocity
max: 8 # Allowed max velocity
time:
trajectory: 100 # Time allowed outside max velo before system init halt
drive: 200 # Time allowed outside max velo before system disables drive
# velocityDifference:
# enable: true # Enable velocity diff monitoring (velo set vs velo act)
# max: 100 # Allowed max difference
# time:
# trajectory: 100 # Time allowed outside max diff velo before system init halt
# drive: 200 # Time allowed outside max diff velo before system disables drive
#plc:
# enable: true # Enable axis plc
# externalCommands: true # Allow axis to inputs from PLC
# file: ${PLC_PATH}test.plc
# code: # Sync code
# - "if(static.counter % ${LIMIT} == 0){println('AX PLC: Appended');static.counter:=0;};" # calculate set pos for physical axis
# - "if(not(static.plc_code_loaded)) {static.counter:=static.counter+1;};"
# - ec0.s$(DRV_SLAVE).ONE > 1; # Enable axis if one of master axes is enabled
# - ec0.s$(DRV_SLAVE).ZERO > 1; # calculate set pos for physical axis
# velocity_filter: # Filter used to smother velocity feedforward
# encoder: # Filter plc enc velo
# enable: false # Filter enable
# size: 100 # Filter size
# trajectory: # Filter plc traj velo
# enable: false # Filter enable
# size: 100 # Filter size
target:
enable: true # Enable at target monitoring (needs to be enabled if using motor record)
tolerance: 0.01 # Allowed tolerance
time: 10 # Filter time inside tolerance to be at target

View File

@@ -0,0 +1,12 @@
encoder:
desc: 'Open loop'
unit: mm
numerator: 1 # Scaling numerator
denominator: 12800 # Scaling denominator
type: 0 # Type: 0=Incremental, 1=Absolute
bits: 16 # Total bit count of encoder raw data
absBits: 0 # Absolute bit count (for absolute encoders)
absOffset: 0 # Encoder offset in eng units (for absolute encoders)
position: ec0.s$(ENC_SID).positionActual01 # Ethercat entry for actual position input (encoder)
homing:
refToEncIDAtStartup: 1 # Ref encoder at startup (to BISS value)

View File

@@ -1,9 +0,0 @@
macros: LIMIT=1000,TYPE=1 # Macros to pass to this file (also plc.file)
plc:
id: 1
enable: yes
rateMilliseconds: 1
file: ${PLC_PATH}test.plc
code:
- "if(static.counter % ${LIMIT} == 0){println('PLC: Appended');static.counter:=0;};" # calculate set pos for physical axis
- "if(not(static.plc_code_loaded)) {static.counter:=static.counter+1;};"

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,9 +0,0 @@
static.counter:=static.counter+1;
static.plc_code_loaded:=1;
if(static.counter % ${LIMIT} == 0) {
if(${TYPE}=0) {
println('AX PLC: File');
} else {
println('PLC : File');
};
};

View File

@@ -7,10 +7,13 @@ sudo iocsh test_4ax_box.script
```
camon -d -t -nostat -nounit -int c6025a:m0s006-BI08 c6025a:m0s005-BO07 c6025a:Axis1-EnaAct c6025a:Axis1-VelAct
# for classic camonitor format:
/usr/local/epics/base-7.0.7/bin/RHEL8-x86_64/camonitor -n c6025a:m0s006-BI08 c6025a:m0s005-BO07 c6025a:Axis1-EnaAct c6025a:Axis1-VelAct
```
# Plot
```
Must be in "classic" camonitor format to use plotCaMonitor.py
Velo:
cat data_log.txt | grep Vel | python3 ~/myhome/sources/ecmccomgui/pyDataManip/plotCaMonitor.py

View File

@@ -1,74 +0,0 @@
##############################################################################
## test config for ecmc_plugin_safety
##
## In this config the interface to safety system is liked to simulated ethercat entries:
## * To allow motion:
## caput c6025a:m0s013-Zero 3
## * To simulate interlock from safety system:
## caput c6025a:m0s013-Zero 0
##
## Monitor status with:
## camon c6025a:SS1-first-Err c6025a:SS1-first-RmpDwnCmdAct c6025a:SS1-first-AxsStndStllAct
##
epicsEnvSet(IOC,c6025a)
require ecmccfg "ENG_MODE=1"
##############################################################################
## Load components lib
#
require ecmccomp
##############################################################################
## Configure hardware
epicsEnvSet("DRV_SLAVE", "13")
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=$(DRV_SLAVE), HW_DESC=EL7041-0052"
${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper,MACROS='I_STDBY_MA=200,I_MAX_MA=1000,R_COIL_MOHM=1700'"
epicsEnvSet("ENC_SLAVE", "14")
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=$(ENC_SLAVE), HW_DESC=EL5042"
${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Encoder-RLS-LA11-24bit-BISS-C"
#Apply hardware configuration
ecmcConfigOrDie "Cfg.EcApplyConfig(1)"
##############################################################################
## AXIS 1
#
epicsEnvSet("DEV", "$(IOC)")
epicsEnvSet("PLC_PATH", "/ioc/c6025a5a/ecmccfg/examples/test/ecmccomp/plc/")
${SCRIPTEXEC} ${ECMC_CONFIG_ROOT}loadYamlAxis.cmd, "FILE=./cfg/axis.yaml,LIMIT=1000,TYPE=0"
##############################################################################
## PLC 1
#
#-${SCRIPTEXEC} ${ECMC_CONFIG_ROOT}loadYamlPlc.cmd, "FILE=./plc/plc_cfg.yaml,LIMIT=5000,TYPE=1"
##############################################################################
## Load safety plugin
#
require ecmc_plugin_safety
# Create SS1 group
epicsEnvSet(EC_RAMP_DOWN,"ec${ECMC_EC_MASTER_ID}.s${DRV_SLAVE}.ZERO.0")
epicsEnvSet(EC_AXES_STANDSTILL,"ec${ECMC_EC_MASTER_ID}.s${DRV_SLAVE}.ZERO.1")
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addSS1Group.cmd "NAME=first,EC_RAMP_DOWN=${EC_RAMP_DOWN},EC_AXES_STANDSTILL=${EC_AXES_STANDSTILL},DELAY_MS=500"
#- Add axis
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToGroup.cmd "NAME=first,AX_ID=1,VELO_LIM=1"
##############################################################################
## 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)

View File

@@ -11,8 +11,7 @@
## camon c6025a:SS1-first-Err c6025a:SS1-first-RmpDwnCmdAct c6025a:SS1-first-AxsStndStllAct
##
epicsEnvSet(IOC,c6025a)
require ecmccfg "ENG_MODE=1"
require ecmccfg "ENG_MODE=1,MASTER_ID=0"
##############################################################################
## Load components lib
@@ -28,7 +27,8 @@ ${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepp
epicsEnvSet("ENC_SLAVE", "2")
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=$(ENC_SLAVE), HW_DESC=EL5042"
${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Encoder-RLS-LA11-24bit-BISS-C"
${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Encoder-RLS-LA11-26bit-BISS-C,CH_ID=1"
${SCRIPTEXEC} ${ecmccomp_DIR}applyComponent.cmd "COMP=Encoder-RLS-LA11-26bit-SSI,CH_ID=2"
epicsEnvSet("BO_SLAVE", "5")
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=$(BO_SLAVE), HW_DESC=EL2008"
@@ -45,22 +45,29 @@ ecmcConfigOrDie "Cfg.EcApplyConfig(1)"
## AXIS 1
#
epicsEnvSet("DEV", "$(IOC)")
epicsEnvSet("PLC_PATH", "/ioc/c6025a5a/ecmccfg/examples/test/ecmccomp/plc/")
${SCRIPTEXEC} ${ECMC_CONFIG_ROOT}loadYamlAxis.cmd, "FILE=./cfg/axis.yaml"
##############################################################################
## Load safety plugin
#
require ecmc_plugin_safety sandst_a
require ecmc_plugin_safety
# Create SS1 group
epicsEnvSet(EC_RAMP_DOWN,"ec${ECMC_EC_MASTER_ID}.s${BI_SLAVE}.binaryInput08.0")
epicsEnvSet(EC_AXES_STANDSTILL,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.binaryOutput07.0")
#- EC_RAMP_DOWN_CMD : EtherCAT entry for ramp down command, input to ecmc (command from safety PLC/system)
#- EC_REST_STAT : EtherCAT entry for signaling that all axes in group are at rest, output from ecmc (feedback to safety PLC/system)
#- EC_RED_VEL_CMD : EtherCAT entry for reducing velocity, input to ecmc (command from safety PLC/system)
#- DELAY_MS : Time between rampdown command and STO
epicsEnvSet(EC_RAMP_DOWN_CMD,"ec${ECMC_EC_MASTER_ID}.s${BI_SLAVE}.binaryInput08.0")
epicsEnvSet(EC_REST_STAT,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.binaryOutput07.0")
epicsEnvSet(EC_RED_VEL_CMD,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.ONE.0")
epicsEnvSet(SAFETY_TIMEOUT,500)
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addSS1Group.cmd "NAME=first,EC_RAMP_DOWN=${EC_RAMP_DOWN},EC_AXES_STANDSTILL=${EC_AXES_STANDSTILL},DELAY_MS=${SAFETY_TIMEOUT}"
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addSS1Group.cmd "NAME=first,EC_RAMP_DOWN_CMD=${EC_RAMP_DOWN_CMD},EC_REST_STAT=${EC_REST_STAT},EC_RED_VEL_CMD=${EC_RED_VEL_CMD=empty},DELAY_MS=${SAFETY_TIMEOUT}"
#- Add axis
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToGroup.cmd "NAME=first,AX_ID=1,VELO_LIM=1"
#- AX_ID : Axis ID
#- VELO_REST_LIM : Velocity at rest limit [unit same as EGU of axis]
#- VELO_MAX_LIM : Velocity maximum limit when EC_RED_VEL_CMD, set to -1 to disable [unit same as EGU of axis]
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToSafetyGroup.cmd "NAME=first,AX_ID=1,VELO_REST_LIM=1,VELO_MAX_LIM=100"
##############################################################################
## Configure diagnostics:

View File

@@ -0,0 +1,77 @@
##############################################################################
#- test config for ecmc_plugin_safety
#-
#- In this config the interface to safety system is liked to simulated ethercat entries:
#- * To allow motion:
#- caput c6025a:m0s013-Zero 3
#- * To simulate interlock from safety system:
#- caput c6025a:m0s013-Zero 0
#-
#- Monitor status with:
#- camon c6025a:SS1-first-Err c6025a:SS1-first-RmpDwnCmdAct c6025a:SS1-first-AxsStndStllAct
#-
#- ethercat slaves
#- 0 0:0 PREOP + EK1100 EtherCAT Coupler (2A E-Bus)
#- 1 0:1 PREOP + EL2068 8Ch. Dig Output 24V, 0.5A
#- 2 0:2 PREOP + EL2819 16K. Dig. Ausgang 24V, 0,5A, Diagnose
#- 3 0:3 PREOP + EL5001 1K. SSI Encoder
#- 4 0:4 PREOP + EL6224 (IO Link Master)
#- 5 0:5 PREOP + EL2008 8K. Dig. Ausgang 24V, 0.5A
#- 6 0:6 PREOP + EL2522 2K. Pulse Train Ausgang
#- 7 0:7 PREOP + EL5072 2Ch. Inductive sensor interface (LVDT, Half Bridge)
#- 8 0:8 PREOP + EL1008 8K. Dig. Eingang 24V, 3ms
#- 9 0:9 PREOP + EL5042 2Ch. BiSS-C Encoder
#- 10 0:10 PREOP + EL6692 EtherCAT Bridge-Klemme (Prim<69>r)
#- 11 0:11 PREOP + EK1100 EtherCAT-Koppler (2A E-Bus)
#- 12 0:12 PREOP + EL7031 1K. Schrittmotor-Endstufe (24V, 1.5A)
#- 13 0:13 PREOP + EL7201 1K. MDP742 Servo-Motor-Endstufe (50V, 4A)
#- 14 0:14 PREOP + EL7041-0052 1Ch. Stepper motor output stage (50V, 5A)
#- 15 0:15 PREOP + EL7342 2Ch. DC motor output stage (50V, 3.5A)
#- 16 0:16 PREOP + EL7411 BLDC Terminal with incremental encoder/Hall, 50 V DC, 4.
#- 17 0:17 PREOP + EL7211-9014 1K. MDP742 Servo-Motor-Endstufe mit OCT (50V, 4,5A
#- 18 0:18 PREOP + EL9576 Bremschopper Klemme
require ecmccfg v10.0.0_RC1 "ENG_MODE=1,MASTER_ID=0,ECMC_VER=v10.0.0_RC1"
# 0:14 - EL7041 1Ch Stepper
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=14,HW_DESC=EL7041-0052"
${SCRIPTEXEC} ${ecmccfg_DIR}applyComponent.cmd "COMP=Motor-Generic-2Phase-Stepper, MACROS='I_MAX_MA=1500, I_STDBY_MA=1000, U_NOM_MV=48000, R_COIL_MOHM=1230'"
epicsEnvSet(DRV_SID,${ECMC_EC_SLAVE_NUM})
# 0:9 - EL5042 2Ch BiSS-C Encoder, RLS-LA11
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "SLAVE_ID=9,HW_DESC=EL5042"
${SCRIPTEXEC} ${ecmccfg_DIR}applyComponent.cmd "COMP=Encoder-RLS-LA11-26bit-BISS-C,CH_ID=1"
${SCRIPTEXEC} ${ecmccfg_DIR}applyComponent.cmd "COMP=Encoder-RLS-LA11-26bit-BISS-C,CH_ID=2"
epicsEnvSet(ENC_SID,${ECMC_EC_SLAVE_NUM})
${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlAxis.cmd, "FILE=./cfg/axis.yaml, DEV=${IOC}, AX_NAME=M1, AXIS_ID=1, DRV_SID=${DRV_SID}, ENC_SID=${ENC_SID}, ENC_CH=01"
${SCRIPTEXEC} ${ecmccfg_DIR}loadYamlEnc.cmd, "FILE=./cfg/enc_open_loop.yaml, DEV=${IOC}, ENC_SID=${DRV_SID}"
##############################################################################
## Load safety plugin
require ecmc_plugin_safety v10.0.0_RC1
# simulate inputs and outputs in drive "ZERO" and ONE dummy-entry
epicsEnvSet(BI_SLAVE,${DRV_SID})
epicsEnvSet(BO_SLAVE,${DRV_SID})
# Create SS1 group
#- EC_RAMP_DOWN_CMD : Digital Input: Ethercat entry for ramp down command, input to ecmc (command from safety PLC/system)
#- EC_AXES_AT_REST_STAT : Digital Output: Ethercat entry for signaling that all axes in group are at rest, output from ecmc (feedback to safety PLC/system)
#- EC_AXES_LIM_VELO_CMD : Digital Input: Ethercat entry for reducing velocity, input to ecmc (command from safety PLC/system)
#- DELAY_MS : Time between rampdown command and STO
epicsEnvSet(EC_RAMP_DOWN_CMD,"ec${ECMC_EC_MASTER_ID}.s${BI_SLAVE}.ONE.0")
epicsEnvSet(EC_AXES_AT_REST_STAT,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.ZERO.0")
epicsEnvSet(EC_AXES_LIM_VELO_CMD,"ec${ECMC_EC_MASTER_ID}.s${BO_SLAVE}.ONE.1")
epicsEnvSet(SAFETY_TIMEOUT,500)
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addSS1Group.cmd "NAME=first,EC_RAMP_DOWN_CMD=${EC_RAMP_DOWN_CMD},EC_AXES_AT_REST_STAT=${EC_AXES_AT_REST_STAT},EC_AXES_LIM_VELO_CMD=${EC_AXES_LIM_VELO_CMD=empty},DELAY_MS=${SAFETY_TIMEOUT}"
#- Add axis
#- AX_ID : Axis ID
#- VELO_REST_LIM : Velocity at rest limit [unit same as EGU of axis]
#- VELO_MAX_LIM : Velocity maximum limit, -1 to disable [unit same as EGU of axis]
${SCRIPTEXEC} ${ecmc_plugin_safety_DIR}addAxisToSafetyGroup.cmd "NAME=first,AX_ID=1,VELO_REST_LIM=0.01,VELO_MAX_LIM=1"
ecmcEpicsEnvSetCalc(S_ID, "${DRV_SID}", "%03d")
afterInit "dbpf ${IOC}:m${ECMC_EC_MASTER_ID=0}s${S_ID}-One 0"

View File

@@ -0,0 +1,271 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>311</width>
<height>269</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>5</x>
<y>35</y>
<width>296</width>
<height>151</height>
</rect>
</property>
<property name="title">
<string>Diagnostics</string>
</property>
<widget class="caLabel" name="calabel_6">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>206</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Reduced velo cmd active:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caLed" name="caled_2">
<property name="geometry">
<rect>
<x>245</x>
<y>30</y>
<width>30</width>
<height>30</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-$(SAFETY_GRP)-RmpDwnCmdAct</string>
</property>
<property name="falseColor">
<color>
<red>0</red>
<green>85</green>
<blue>0</blue>
</color>
</property>
<property name="trueColor">
<color>
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
</widget>
<widget class="caLed" name="caled_3">
<property name="geometry">
<rect>
<x>245</x>
<y>60</y>
<width>30</width>
<height>30</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-$(SAFETY_GRP)-RedVeloCmdAct</string>
</property>
<property name="falseColor">
<color>
<red>0</red>
<green>85</green>
<blue>0</blue>
</color>
</property>
<property name="trueColor">
<color>
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
</widget>
<widget class="caLabel" name="calabel_5">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>246</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>E-Stop (rampdown cmd active):</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caLabel" name="calabel_4">
<property name="geometry">
<rect>
<x>10</x>
<y>85</y>
<width>251</width>
<height>26</height>
</rect>
</property>
<property name="text">
<string>Axes at rest:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caLed" name="caled">
<property name="geometry">
<rect>
<x>245</x>
<y>88</y>
<width>30</width>
<height>30</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-$(SAFETY_GRP)-AxsStndStllAct</string>
</property>
<property name="falseColor">
<color>
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
<property name="trueColor">
<color>
<red>0</red>
<green>85</green>
<blue>0</blue>
</color>
</property>
</widget>
<widget class="caLineEdit" name="calineedit_47">
<property name="geometry">
<rect>
<x>225</x>
<y>120</y>
<width>61</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-$(SAFETY_GRP)-Dly</string>
</property>
<property name="colorMode">
<enum>caLineEdit::Default</enum>
</property>
<property name="alarmHandling">
<enum>caLineEdit::onBackground</enum>
</property>
<property name="precisionMode">
<enum>caLineEdit::Channel</enum>
</property>
</widget>
<widget class="caLabel" name="calabel_7">
<property name="geometry">
<rect>
<x>10</x>
<y>115</y>
<width>206</width>
<height>26</height>
</rect>
</property>
<property name="text">
<string>Power off delay [ms]:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</widget>
<widget class="caLabel" name="calabel">
<property name="geometry">
<rect>
<x>50</x>
<y>5</y>
<width>221</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>SS1 group: $(SAFETY_GRP=)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caMultiLineString" name="camultilinestring">
<property name="geometry">
<rect>
<x>10</x>
<y>195</y>
<width>291</width>
<height>61</height>
</rect>
</property>
<property name="font">
<font>
<family>Lucida Sans Typewriter</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="plainText">
<string>NOTE:
ecmc_plugin_safety has NO safety rated
features. It only acts as an interface to a
dedicated safety system.</string>
</property>
<property name="fontScaleMode" stdset="0">
<enum>caMultiLineString::None</enum>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>caLabel</class>
<extends>QLabel</extends>
<header>caLabel</header>
</customwidget>
<customwidget>
<class>caLed</class>
<extends>QWidget</extends>
<header>caLed</header>
</customwidget>
<customwidget>
<class>caLineEdit</class>
<extends>QLineEdit</extends>
<header>caLineEdit</header>
</customwidget>
<customwidget>
<class>caMultiLineString</class>
<extends>QPlainTextEdit</extends>
<header>caMultiLineString</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,458 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>146</width>
<height>315</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="caLabel" name="calabel">
<property name="geometry">
<rect>
<x>5</x>
<y>0</y>
<width>136</width>
<height>36</height>
</rect>
</property>
<property name="text">
<string> Safety plugin</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QGroupBox" name="groupBox_6">
<property name="geometry">
<rect>
<x>5</x>
<y>35</y>
<width>136</width>
<height>241</height>
</rect>
</property>
<property name="title">
<string>Group:</string>
</property>
<widget class="caFrame" name="caframe_11">
<property name="geometry">
<rect>
<x>5</x>
<y>30</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=01,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=1</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
<widget class="caFrame" name="caframe_13">
<property name="geometry">
<rect>
<x>5</x>
<y>80</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=03,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=3</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand_4">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
<widget class="caFrame" name="caframe_14">
<property name="geometry">
<rect>
<x>5</x>
<y>105</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=04,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=4</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand_6">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
<widget class="caFrame" name="caframe_15">
<property name="geometry">
<rect>
<x>5</x>
<y>130</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=05,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=5</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand_7">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
<widget class="caFrame" name="caframe_16">
<property name="geometry">
<rect>
<x>5</x>
<y>155</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=06,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=6</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand_9">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
<widget class="caFrame" name="caframe_17">
<property name="geometry">
<rect>
<x>5</x>
<y>180</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=07,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=7</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand_12">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
<widget class="caFrame" name="caframe_18">
<property name="geometry">
<rect>
<x>5</x>
<y>205</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=08,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=8</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand_13">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
<widget class="caFrame" name="caframe_12">
<property name="geometry">
<rect>
<x>5</x>
<y>55</y>
<width>120</width>
<height>30</height>
</rect>
</property>
<property name="macro">
<string notr="true">GRP_ID=02,IOC=$(IOC)</string>
</property>
<property name="visibility">
<enum>caFrame::Calc</enum>
</property>
<property name="visibilityCalc">
<string notr="true">A&gt;=2</string>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
<widget class="caShellCommand" name="cashellcommand_3">
<property name="geometry">
<rect>
<x>15</x>
<y>5</y>
<width>100</width>
<height>21</height>
</rect>
</property>
<property name="label">
<string notr="true">$(GRP_ID)</string>
</property>
<property name="labels">
<string>$(GRP_ID)</string>
</property>
<property name="files">
<string>bash /ioc/modules/qt/ecmcOpenObject.sh</string>
</property>
<property name="args">
<string>PLG_SAFETY_GRP $(IOC) $(GRP_ID);</string>
</property>
</widget>
</widget>
</widget>
<widget class="caLineEdit" name="calineedit">
<property name="geometry">
<rect>
<x>95</x>
<y>285</y>
<width>41</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):SS1-GrpCnt</string>
</property>
</widget>
<widget class="caLabel" name="calabel_2">
<property name="geometry">
<rect>
<x>10</x>
<y>285</y>
<width>91</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Group cnt:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>caFrame</class>
<extends>QFrame</extends>
<header>caFrame</header>
<container>1</container>
</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>caShellCommand</class>
<extends>QWidget</extends>
<header>caShellCommand</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

10
qt/readme.md Normal file
View File

@@ -0,0 +1,10 @@
# Panel for plugin
```
caqtdm -macro "IOC=c6015a-02,SAFETY_GRP=first" ecmc_plugin_safety_main.ui
```
# Panel to simulate motion safety box
To be used together with the test scripts in the iocsh dir
```
caqtdm -macro "IOC=c6015a-02,BI_S_ID=014,BO_S_ID=014" sim_motion_safety_box.ui
```

247
qt/sim_motion_safety_box.ui Normal file
View File

@@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>341</width>
<height>312</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="caByteController" name="cabytecontroller">
<property name="geometry">
<rect>
<x>55</x>
<y>40</y>
<width>40</width>
<height>70</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):m$(M_ID=0)s$(BI_S_ID)-One</string>
</property>
<property name="endBit">
<number>0</number>
</property>
<property name="foreground" stdset="0">
<color>
<red>78</red>
<green>154</green>
<blue>6</blue>
</color>
</property>
<property name="background" stdset="0">
<color>
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
<property name="fontScaleMode" stdset="0">
<enum>EPushButton::None</enum>
</property>
</widget>
<widget class="caByte" name="cabyte">
<property name="geometry">
<rect>
<x>55</x>
<y>200</y>
<width>40</width>
<height>70</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):m$(M_ID=0)s$(BO_S_ID)-Zero</string>
</property>
<property name="endBit">
<number>0</number>
</property>
<property name="foreground" stdset="0">
<color>
<red>78</red>
<green>154</green>
<blue>6</blue>
</color>
</property>
</widget>
<widget class="caLabel" name="calabel">
<property name="geometry">
<rect>
<x>125</x>
<y>65</y>
<width>171</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>E-Stop command</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caLabel" name="calabel_2">
<property name="geometry">
<rect>
<x>125</x>
<y>140</y>
<width>186</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Reduce velo command</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caLabel" name="calabel_3">
<property name="geometry">
<rect>
<x>125</x>
<y>225</y>
<width>161</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Axes at rest status</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caTextEntry" name="catextentry">
<property name="geometry">
<rect>
<x>54</x>
<y>280</y>
<width>41</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):m$(M_ID=0)s$(BI_S_ID)-One</string>
</property>
</widget>
<widget class="caLabel" name="calabel_4">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>301</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Simulation of motion safety box</string>
</property>
</widget>
<widget class="caByteController" name="cabytecontroller_2">
<property name="geometry">
<rect>
<x>55</x>
<y>120</y>
<width>40</width>
<height>70</height>
</rect>
</property>
<property name="channel" stdset="0">
<string notr="true">$(IOC):m$(M_ID=0)s$(BI_S_ID)-One</string>
</property>
<property name="startBit">
<number>1</number>
</property>
<property name="endBit">
<number>1</number>
</property>
<property name="foreground" stdset="0">
<color>
<red>78</red>
<green>154</green>
<blue>6</blue>
</color>
</property>
<property name="background" stdset="0">
<color>
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
<property name="fontScaleMode" stdset="0">
<enum>EPushButton::None</enum>
</property>
</widget>
<widget class="caLabel" name="calabel_5">
<property name="geometry">
<rect>
<x>135</x>
<y>85</y>
<width>131</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>(Ramp down command)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="caLabel" name="calabel_6">
<property name="geometry">
<rect>
<x>120</x>
<y>275</y>
<width>171</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Command PV (ONE)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>caTextEntry</class>
<extends>caLineEdit</extends>
<header>caTextEntry</header>
</customwidget>
<customwidget>
<class>caByteController</class>
<extends>QWidget</extends>
<header>caByteController</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>caByte</class>
<extends>QWidget</extends>
<header>caByte</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -1,6 +1,6 @@
#==============================================================================
# addAxisToGroup.cmd
# addAxisToSafetyGroup.cmd
#-
#- !!!!!!!!!!!!! IMPORTANT !!!!!!!!!
#- This plugin has _NO_ safety rated functionalities.
@@ -17,14 +17,19 @@
#- Arguments:
#- NAME : Name of safety group
#- AX_ID : Axis ID
#- VELO_LIM : Velocity standstill limit [unit same as EGU of axis]
#- VELO_REST_LIM : Velocity at rest limit [unit same as EGU of axis]
#- VELO_MAX_LIM : Velocity maximum limit when EC_RED_VEL_CMD, set to -1 to disable [unit same as EGU of axis]
#-
#################################################################################
#- ecmcAddAxisToSafetyGroup(<group_name>, <axis_index>, <velo_limit>, <filter_time>)
#- <name> : Name of safety group to add axis to.
#- <Axis id> : Axis index to add (ecmc axis index).
#- <velo limit> : Axis standstill velo limit [unit of axis].
#- <velo_rest_limit> : Axis at rest velo limit [unit of axis].
#- <velo_max_limit> : Velocity maximum limit when EC_RED_VEL_CMD, set to -1 to disable [unit same as EGU of axis]
#- <filter_time> : NOT USED (for future implemenation). Time for axis to be below velo limit [ms].
ecmcAddAxisToSafetyGroup("${NAME}",${AX_ID},${VELO_LIM=0},0)
ecmcAddAxisToSafetyGroup("${NAME}",${AX_ID},${VELO_REST_LIM=0},0,${VELO_MAX_LIM=0.0})
#- Load SS1 axis records
dbLoadRecords("ecmcSS1Axis.template","AXIS_PREFIX=${ECMC_MOTOR_${AX_ID}_FULL_NAME=},NAME=${NAME},VEL_MAX_LIM=${VELO_MAX_LIM=0.0},VEL_REST_LIM=${VELO_REST_LIM=0.0}")

View File

@@ -15,19 +15,26 @@
#-###############################################################################
#-
#- Arguments:
#- NAME : Name of safety group
#- EC_RAMP_DOWN : Ethercat entry for rampd down command, input to ecmc (command from safety PLC/system)
#- EC_AXES_STANDSTILL : Ethercat entry for all axes in group at standstill, output from ecmc (feedback to safety PLC/system)
#- DELAY_MS : Time between rampdown command and STO
#- NAME : Name of safety group
#- EC_RAMP_DOWN_CMD : Ethercat entry for ramp down command, input to ecmc (command from safety PLC/system)
#- EC_AXES_REST_STAT : Ethercat entry for signaling that all axes in group are at rest, output from ecmc (feedback to safety PLC/system)
#- EC_AXES_LIM_VELO_CMD : Ethercat entry for reducing velocity, input to ecmc (command from safety PLC/system)
#- DELAY_MS : Time between rampdown command and STO
#-
#################################################################################
#- ecmcAddSS1SafetyGroup(<name>, <ec_rampdown_cmd>, <ec_standstill_status>,<time_delay_ms>)
#- <name> : Name of group.
#- <ec_rampdown> : Ethercat entry input for rampdown cmd.
#- <ec_standstill> : Ethercat entry output for group standstill status.
#- <time_delay_ms> : Time delay of STO [ms].
ecmcAddSS1SafetyGroup("${NAME}","${EC_RAMP_DOWN}","${EC_AXES_STANDSTILL}",${DELAY_MS=0})
#-Use ecmcAddSS1SafetyGroup(<name>, <ec_rampdown_cmd>, <ec_standstill_status>,<time_delay_ms>)
#- <name> : Name of group
#- <ec_rampdown_cmd> : Ethercat entry input for rampdown cmd
#- <ec_standstill_status> : Ethercat entry output for group standstill status
#- <ec_red_velo_cmd> : Ethercat entry input for activation of maximum velo limitation (set to "empty" to disable)
#- <time_delay_ms> : Time delay of STO [ms]
ecmcAddSS1SafetyGroup("${NAME}","${EC_RAMP_DOWN_CMD}","${EC_AXES_AT_REST_STAT}","${EC_AXES_LIM_VELO_CMD=empty}",${DELAY_MS=0})
ecmcEpicsEnvSetCalc(ECMC_PLG_SAFETY_GRP_CNT, "${ECMC_PLG_SAFETY_GRP_CNT=0}+1", "%02d")
#- Load SS1 group records
dbLoadRecords("ss1.template","P=${ECMC_PREFIX},NAME=${NAME}")
dbLoadRecords("ecmcSS1Group.template","P=${ECMC_PREFIX},NAME=${NAME},ID=${ECMC_PLG_SAFETY_GRP_CNT},COUNT=${ECMC_PLG_SAFETY_GRP_CNT},DELAY=${DELAY_MS=0}")

View File

@@ -8,11 +8,14 @@
* Created on: jan 29, 2024
* 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 0
#define ECMC_PLUGIN_VERSION 1
#ifdef __cplusplus
extern "C" {
@@ -31,11 +34,11 @@ static int alreadyLoaded = 0;
static int destructs_ = 0;
/** Optional.
* Will be called once after successfull load into ecmc.
* Will be called once after successful load into ecmc.
* Return value other than 0 will be considered error.
* configStr can be used for configuration parameters.
**/
int safetyConstruct(char *configStr)
static int construct(char *configStr)
{
if(alreadyLoaded) {
@@ -50,19 +53,19 @@ int safetyConstruct(char *configStr)
/** Optional function.
* Will be called once at unload.
**/
void safetyDestruct(void)
static void safetyDestruct(void)
{
destructs_ = 1;
deleteAllSafetyGroups();
}
/** Optional function.
* Will be called each realtime cycle if definded
* ecmcError: Error code of ecmc. Makes it posible for
* Will be called each realtime cycle if defined
* ecmcError: Error code of ecmc. Makes it possible for
* this plugin to react on ecmc errors
* Return value other than 0 will be considered to be an error code in ecmc.
**/
int safetyRealtime(int ecmcError)
static int safetyRealtime(int ecmcError)
{
if(destructs_) return 0;
@@ -71,10 +74,10 @@ int safetyRealtime(int ecmcError)
return 0;
}
/** Link to data source here since all sources should be availabe at this stage
/** Link to data source here since all sources should be available at this stage
* (for example ecmc PLC variables are defined only at enter of realtime)
**/
int safetyEnterRT(){
static int safetyEnterRT(){
return validate();
}
@@ -82,37 +85,12 @@ int safetyEnterRT(){
* Will be called once just before leaving realtime mode
* Return value other than 0 will be considered error.
**/
int safetyExitRT(void){
static int safetyExitRT(void){
return 0;
}
//// Plc function for clear of buffers
//double fft_clear(double index) {
// return (double)clearFFT((int)index);
//}
//
//// Plc function for enable
//double fft_enable(double index, double enable) {
// return (double)enableFFT((int)index, (int)enable);
//}
//
//// Plc function for trigg new measurement (will clear buffers)
//double fft_trigg(double index) {
// return (double)triggFFT((int)index);
//}
//
//// Plc function for enable
//double fft_mode(double index, double mode) {
// return (double)modeFFT((int)index, (FFT_MODE)((int)mode));
//}
//
//// Plc function for enable
//double fft_stat(double index) {
// return (double)statFFT((int)index);
//}
// Register data for plugin so ecmc know what to use
struct ecmcPluginData pluginDataDef = {
static struct ecmcPluginData pluginDataDef = {
// Allways use ECMC_PLUG_VERSION_MAGIC
.ifVersion = ECMC_PLUG_VERSION_MAGIC,
// Name
@@ -124,170 +102,19 @@ struct ecmcPluginData pluginDataDef = {
,
// Plugin version
.version = ECMC_PLUGIN_VERSION,
// Optional construct func, called once at load. NULL if not definded.
.constructFnc = safetyConstruct,
// Optional destruct func, called once at unload. NULL if not definded.
// 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 = safetyDestruct,
// 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 = safetyRealtime,
// Optional func that will be called once just before enter realtime mode
.realtimeEnterFnc = safetyEnterRT,
// Optional func that will be called once just before exit realtime mode
.realtimeExitFnc = safetyExitRT,
// PLC funcs
// .funcs[0] =
// { /*----fft_clear----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_clear",
// // Function description
// .funcDesc = "double fft_clear(index) : Clear/reset fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = fft_clear,
// .funcArg2 = NULL,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[1] =
// { /*----fft_enable----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_enable",
// // Function description
// .funcDesc = "double fft_enable(index, enable) : Set enable for fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = NULL,
// .funcArg2 = fft_enable,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[2] =
// { /*----fft_trigg----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_trigg",
// // Function description
// .funcDesc = "double fft_trigg(index) : Trigg new measurement for fft[index]. Will clear buffers.",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = fft_trigg,
// .funcArg2 = NULL,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[3] =
// { /*----fft_mode----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_mode",
// // Function description
// .funcDesc = "double fft_mode(index, mode) : Set mode Cont(1)/Trigg(2) for fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = NULL,
// .funcArg2 = fft_mode,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
// .funcs[4] =
// { /*----fft_stat----*/
// // Function name (this is the name you use in ecmc plc-code)
// .funcName = "fft_stat",
// // Function description
// .funcDesc = "double fft_stat(index) : Get status of fft (NO_STAT, IDLE, ACQ, CALC) for fft[index].",
// /**
// * 7 different prototypes allowed (only doubles since reg in plc).
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
// **/
// .funcArg0 = NULL,
// .funcArg1 = fft_stat,
// .funcArg2 = NULL,
// .funcArg3 = NULL,
// .funcArg4 = NULL,
// .funcArg5 = NULL,
// .funcArg6 = NULL,
// .funcArg7 = NULL,
// .funcArg8 = NULL,
// .funcArg9 = NULL,
// .funcArg10 = NULL,
// .funcGenericObj = NULL,
// },
.funcs[0] = {0}, // last element set all to zero..
// PLC consts
/* CONTINIOUS MODE = 1 */
// .consts[0] = {
// .constName = "fft_CONT",
// .constDesc = "FFT Mode: Continious",
// .constValue = CONT
// },
// /* TRIGGERED MODE = 2 */
// .consts[1] = {
// .constName = "fft_TRIGG",
// .constDesc = "FFT Mode :Triggered",
// .constValue = TRIGG
// },
// /* TRIGGERED MODE = 2 */
// .consts[2] = {
// .constName = "fft_NO_STAT",
// .constDesc = "FFT Status: Invalid state",
// .constValue = NO_STAT,
// },
// /* TRIGGERED MODE = 2 */
// .consts[3] = {
// .constName = "fft_IDLE",
// .constDesc = "FFT Status: Idle state (waiting for trigger)",
// .constValue = IDLE
// },
// /* TRIGGERED MODE = 2 */
// .consts[4] = {
// .constName = "fft_ACQ",
// .constDesc = "FFT Status: Acquiring data",
// .constValue = ACQ
// },
// /* TRIGGERED MODE = 2 */
// .consts[5] = {
// .constName = "fft_CALC",
// .constDesc = "FFT Status: Calculating result",
// .constValue = CALC
// },
.consts[0] = {0}, // last element set all to zero..
};

View File

@@ -35,11 +35,12 @@ extern DBBASE *pdbbase;
* - runtime_error
*/
ecmcSS1SafetyGroup::ecmcSS1SafetyGroup(const char *name,
const char *ec_rampdown_cmd,
const char *ec_standstill_status,
int time_delay_ms,
const char *cfg_string,
char* portName)
const char *ec_rampdown_cmd,
const char *ec_standstill_status,
const char *ec_limit_velo,
int time_delay_ms,
const char *cfg_string,
char* portName)
: asynPortDriver(portName,
1, /* maxAddr */
asynInt32Mask | asynFloat64Mask | asynFloat32ArrayMask |
@@ -55,49 +56,62 @@ ecmcSS1SafetyGroup::ecmcSS1SafetyGroup(const char *name,
0, /* Default priority */
0) /* Default stack size */
{
sName_ = strdup(name);
sEcRampDownCmdNameOrg_ = strdup(ec_rampdown_cmd);
sEcAxesStandStillStatOrg_= strdup(ec_standstill_status);
sEcRampDownCmdNameStrip_ = strdup(ec_rampdown_cmd);
sEcAxesStandStillStatStrip_ = strdup(ec_standstill_status);
sConfig_ = strdup(cfg_string);
delayMs_ = time_delay_ms;
sName_ = strdup(name);
sEcRampDownCmdNameOrg_ = strdup(ec_rampdown_cmd);
sEcAxesStandStillStatOrg_ = strdup(ec_standstill_status);
sEcLimitVeloOrg_ = strdup(ec_limit_velo);
limitMaxVeloEnable_ = 1;
if(strcmp(sEcLimitVeloOrg_, "empty") == 0) {
limitMaxVeloEnable_ = 0;
}
sConfig_ = strdup(cfg_string);
delayMs_ = time_delay_ms;
ptrStatus_ = (int*)&status_;
asynStatusId_ = -1;
axesCounter_ = 0;
ecmcSampleRateHz_ = getEcmcSampleRate();
dataSourcesLinked_ = 0;
ecMaster_ = NULL;
ecEntryRampDown_ = NULL;
ecEntryStandstill_ = NULL;
ecEntryLimitVelo_ = NULL;
masterId_ = 0;
slaveIdRampDown_ = 0;
bitRampDown_ = 0;
slaveIdStandStill_ = 0;
bitStandStill_ = 0;
aliasRampDown_[0] = 0;
aliasStandStill_[0] = 0;
aliasLimitVelo_[0] = 0;
rampDownCmd_ = 0;
axesAreStandstill_ = 0;
rampDownCmdOld_ = 0;
axesAreStandstillOld_ = 0;
printEnableStatus_ = 1;
limitVeloCmdOld_ = 0;
limitVeloCmd_ = 0;
axesDisabled_ = 0;
cfgDbgMode_ = 0;
oldStop_ = 0;
memset(&status_,0,sizeof(status_));
ptrStatus_ = (int*)&status_;
asynStatusId_ = -1;
axesCounter_ = 0;
ecmcSampleRateHz_ = getEcmcSampleRate();
dataSourcesLinked_ = 0;
ecMaster_ = NULL;
ecEntryRampDown_ = NULL;
ecEntryStandstill_ = NULL;
masterId_ = 0;
slaveIdRampDown_ = 0;
bitRampDown_ = 0;
slaveIdStandStill_ = 0;
bitStandStill_ = 0;
aliasRampDown_[0] = 0;
aliasStandStill_[0] = 0;
rampDownCmd_ = 0;
axesAreStandstill_ = 0;
rampDownCmdOld_ = 0;
axesAreStandstillOld_ = 0;
printEnableStatus_ = 1;
// Config defaults
cfgDbgMode_ = 0;
parseConfigStr(cfg_string);
initAsyn();
if(cfgDbgMode_) {
printf("Safety %s: Safety group created:\n"
" Type: SS1\n"
" Name: %s\n"
" I/O for rampdown command from saftey PLC: %s\n"
" I/O for axes standstill status: %s\n"
" STO delay [ms]: %d\n"
" Configuration string: %s\n",
printf("Safety %s: Group created:\n"
" Type: SS1-t\n"
" Name: %s\n"
" I/O for rampdown command from saftey PLC: %s\n"
" I/O for axes standstill status: %s\n"
" I/O for velo limit command from safety PLC: %s (%s)\n"
" STO delay [ms]: %d\n"
" Configuration string: %s\n",
sName_,sName_,sEcRampDownCmdNameOrg_,
sEcAxesStandStillStatOrg_,delayMs_,sConfig_);
sEcAxesStandStillStatOrg_,sEcLimitVeloOrg_,
limitMaxVeloEnable_ ? "enabled" : "disabled",
delayMs_,sConfig_);
}
}
@@ -109,9 +123,8 @@ ecmcSS1SafetyGroup::~ecmcSS1SafetyGroup() {
free(sName_);
free(sEcRampDownCmdNameOrg_);
free(sEcAxesStandStillStatOrg_);
free(sEcRampDownCmdNameStrip_);
free(sEcAxesStandStillStatStrip_);
free(sConfig_);
free(sEcLimitVeloOrg_);
}
void ecmcSS1SafetyGroup::parseConfigStr(const char *configStr) {
@@ -167,8 +180,20 @@ void ecmcSS1SafetyGroup::validateCfgs() {
&bitStandStill_)) {
throw std::runtime_error( "Safety: Parse error: Data source for standstill status.");
}
// init to masterIdRampDown if case !limitMaxVeloEnable_
int masterIdLimitVelo = masterIdStandStill;
if(limitMaxVeloEnable_) {
if(parseEcPath(sEcLimitVeloOrg_,
&masterIdLimitVelo,
&slaveIdLimitVelo_,
aliasLimitVelo_,
&bitLimitVelo_)) {
throw std::runtime_error( "Safety: Parse error: Data source for limit velo.");
}
}
if(masterIdStandStill != masterIdRampDown ) {
if(masterIdStandStill != masterIdRampDown || masterIdLimitVelo != masterIdRampDown) {
throw std::runtime_error( "Safety: Parse error: Master id for datasources different.");
}
masterId_ = masterIdStandStill;
@@ -180,6 +205,10 @@ void ecmcSS1SafetyGroup::validateCfgs() {
if(bitStandStill_ < 0) {
throw std::runtime_error( "Safety: Parse error: Standstill status, bit invalid.");
}
if(bitLimitVelo_ < 0) {
throw std::runtime_error( "Safety: Parse error: Limit velo, bit invalid.");
}
}
void ecmcSS1SafetyGroup::validateAxes() {
@@ -226,6 +255,22 @@ void ecmcSS1SafetyGroup::validateAxes() {
printf("Safety %s: Error, group empty (axis count zero)\n",sName_);
throw std::runtime_error( "Safety: Error, empty group not allowed.");
}
// Check if max velo enabled in axis
int axesMaxVeloEnabled = 0;
for(std::vector<safetyAxis*>::iterator saxis = axes_.begin(); saxis != axes_.end(); ++saxis) {
axesMaxVeloEnabled = (*saxis)->veloMaxLimitEnabled_ || axesMaxVeloEnabled;
}
if(limitMaxVeloEnable_ && !axesMaxVeloEnabled) {
printf("Safety %s: Error, Limit max velo enabled but no axis configured with max velo\n",sName_);
throw std::runtime_error( "Safety: Error, Limit max velo enabled but no axis configured with max velo");
}
if(!limitMaxVeloEnable_ && axesMaxVeloEnabled) {
printf("Safety %s: Error, Limit max velo disabled but axis configured with a max velo\n",sName_);
throw std::runtime_error( "Safety: Error, Limit max velo disabled but axis configured with a max velo");
}
}
void ecmcSS1SafetyGroup::connectToDataSources() {
@@ -247,6 +292,10 @@ void ecmcSS1SafetyGroup::connectToDataSources() {
throw std::runtime_error( "Safety: EtherCAT entry for rampdown I/O NULL.");
}
if(bitRampDown_ >= ecEntryRampDown_->getBits()) {
throw std::runtime_error( "Safety: Bit out of range for rampdown ethercat entry.");
}
// standstill
slave = ecMaster_->findSlave(slaveIdStandStill_);
if(!slave) {
@@ -255,30 +304,32 @@ void ecmcSS1SafetyGroup::connectToDataSources() {
ecEntryStandstill_ = slave->findEntry(aliasStandStill_);
if(!ecEntryStandstill_) {
throw std::runtime_error( "Safety: EtherCAT entry for rampdown I/O NULL.");
throw std::runtime_error( "Safety: EtherCAT entry for standstill I/O NULL.");
};
if(bitStandStill_ >= ecEntryStandstill_->getBits()) {
throw std::runtime_error( "Safety: Bit out of range for standstill ethercat entry.");
}
// Limit velo
if( limitMaxVeloEnable_ ) {
slave = ecMaster_->findSlave(slaveIdLimitVelo_);
if(!slave) {
throw std::runtime_error( "Safety: EtherCAT slave limit velo I/O NULL.");
}
ecEntryLimitVelo_ = slave->findEntry(aliasLimitVelo_);
if(!ecEntryLimitVelo_) {
throw std::runtime_error( "Safety: EtherCAT entry for limit velo I/O NULL.");
};
if(bitLimitVelo_ >= ecEntryLimitVelo_->getBits()) {
throw std::runtime_error( "Safety: Bit out of range for limit velo ethercat entry.");
}
}
dataSourcesLinked_ = 1;
return;
//// Get dataItem for rampdown command
//dataItemRampDownCmd_ = (ecmcDataItem*) getEcmcDataItem(sEcRampDownCmdNameStrip_);
//if(!dataItemRampDownCmd_) {
// throw std::runtime_error( "Safety: Data item for ramp down command NULL.");
//}
//
//// Get dataItem for axes standstill status
//dataItemStandStillStat_ = (ecmcDataItem*) getEcmcDataItem(sEcAxesStandStillStatStrip_);
//if(!dataItemStandStillStat_) {
// throw std::runtime_error( "Safety: Data item for axes standstill status NULL.");
//}
//
//if(cfgDbgMode_) {
// printf("Safety: Safety group \"%s\"\": Data sources linked.\n",sName_);
//}
//
//dataSourcesLinked_ = 1;
}
void ecmcSS1SafetyGroup::refreshAsyn() {
@@ -318,9 +369,8 @@ std::string ecmcSS1SafetyGroup::to_string(int value) {
return os.str();
}
// Executed by ecmc rt thread.
void ecmcSS1SafetyGroup::execute() {
// Ramp down and disable if safety interlock
void ecmcSS1SafetyGroup::exeRampDown() {
uint64_t data = 0;
// Read ramp down command from safety plc
if(ecEntryRampDown_->readBit(bitRampDown_,
@@ -333,7 +383,7 @@ void ecmcSS1SafetyGroup::execute() {
}
rampDownCmdOld_ = rampDownCmd_;
rampDownCmd_ = data == 0;
rampDownCmd_ = data == 0;
if(rampDownCmdOld_ != rampDownCmd_) {
@@ -353,8 +403,12 @@ void ecmcSS1SafetyGroup::execute() {
// set safety interlock in ecmc
setAxesSafetyInterlocks(rampDownCmd_);
axesDisabled_ = checkAxesDisabled();
// check if axes are standstill to safety PLC
axesAreStandstill_ = checkAxesStandstillAndDisableIfNeeded();
setAxesStandstillStatus(axesAreStandstill_);
// Disable
@@ -365,6 +419,56 @@ void ecmcSS1SafetyGroup::execute() {
}
}
// Limit velo if needed
void ecmcSS1SafetyGroup::exeLimitVelo() {
if(!limitMaxVeloEnable_) {
return;
}
uint64_t data = 0;
// Read ramp down command from safety plc
if(ecEntryLimitVelo_->readBit(bitLimitVelo_,
&data)) {
// Disable all axes
setAxesDisable(); // disable
setAxesSafetyInterlocks(0); // stop
setAxesStandstillStatus(0); // set output
throw std::out_of_range("Safety: Read limit velo cmd failed");
}
limitVeloCmdOld_ = limitVeloCmd_;
limitVeloCmd_ = data == 0;
if(limitVeloCmdOld_ != limitVeloCmd_) {
// Update asyn status wd
status_.limitVeloCmdActive = limitVeloCmd_;
refreshAsyn();
resetPrintoutStatus();
if(cfgDbgMode_) {
if(limitVeloCmd_) {
printf("Safety %s: Limit velo cmd active\n",sName_);
} else {
printf("Safety %s: Limit velo cmd not active\n",sName_);
}
}
}
if(limitVeloCmd_) {
checkAxesMaxVeloAndDisableIfNeeded();
}
// Write velo limit and activation to ecmc axis object
setAxesMaxVelo();
}
// Executed by ecmc rt thread.
void ecmcSS1SafetyGroup::execute() {
exeRampDown();
exeLimitVelo();
}
void ecmcSS1SafetyGroup::resetPrintoutStatus() {
for(std::vector<safetyAxis*>::iterator saxis = axes_.begin(); saxis != axes_.end(); ++saxis) {
(*saxis)->printEnableStat_ = 1;
@@ -384,9 +488,10 @@ void ecmcSS1SafetyGroup::setAxesStandstillStatus(int standstill) {
status_.axesAtStandstill = standstill;
refreshAsyn();
}
// Only write axis standstill bit if all axes are disabled
if(ecEntryStandstill_->writeBit(bitStandStill_,
standstill > 0)) {
((standstill > 0) && axesDisabled_) )) {
throw std::out_of_range("Safety: Read rampdown cmd failed");
}
axesAreStandstillOld_ = standstill;
@@ -396,11 +501,66 @@ void ecmcSS1SafetyGroup::setAxesStandstillStatus(int standstill) {
bool ecmcSS1SafetyGroup::checkAxesStandstill() {
bool standstill = 1;
for(std::vector<safetyAxis*>::iterator saxis = axes_.begin(); saxis != axes_.end(); ++saxis) {
standstill= standstill && checkAxisStandstill((*saxis));
standstill= standstill && checkAxisStandstill((*saxis));
}
return standstill;
}
// Check axes disabled
bool ecmcSS1SafetyGroup::checkAxesDisabled() {
bool enabledsum = 1;
int enabled = 0;
for(std::vector<safetyAxis*>::iterator saxis = axes_.begin(); saxis != axes_.end(); ++saxis) {
getAxisEnabled((*saxis)->axisId_,&enabled);
enabledsum = enabledsum && enabled;
}
return !enabledsum;
}
// Check max velo violation
void ecmcSS1SafetyGroup::checkAxesMaxVeloAndDisableIfNeeded() {
if(!limitVeloCmd_) {
return;
}
for(std::vector<safetyAxis*>::iterator saxis = axes_.begin(); saxis != axes_.end(); ++saxis) {
if(!(*saxis)->veloMaxLimitEnabled_) {
break;
}
if(checkAxisMaxVelo((*saxis))) {
printf("Safety %s: Axis %d, velo too high, disabling axis.\n", sName_, (*saxis)->axisId_);
setAxisEnable((*saxis)->axisId_,0);
}
}
return;
}
// Set max velo in axis object
void ecmcSS1SafetyGroup::setAxesMaxVelo() {
for(std::vector<safetyAxis*>::iterator saxis = axes_.begin(); saxis != axes_.end(); ++saxis) {
if( (*saxis)->veloMaxLimitEnabled_ ) {
setAxisExtMaxVelo((*saxis)->axisId_,0.95*(*saxis)->veloMaxLimit_,limitVeloCmd_);
}
}
}
bool ecmcSS1SafetyGroup::checkAxisMaxVelo(safetyAxis* axis) {
double traj = 1;
int err = getAxisTrajVelo(axis->axisId_, &traj);
if(err) {
return 0;
}
double enc = 1;
err = getAxisEncVelo(axis->axisId_, &enc);
if(err) {
return 0;
}
return std::abs(traj) >= axis->veloMaxLimit_ || std::abs(enc) >= axis->veloMaxLimit_;
}
// Check standstill axis
bool ecmcSS1SafetyGroup::checkAxisStandstill(safetyAxis* axis) {
double traj = 1;
@@ -416,7 +576,7 @@ bool ecmcSS1SafetyGroup::checkAxisStandstill(safetyAxis* axis) {
return 0;
}
return std::abs(traj) <= axis->veloLimit_ && std::abs(enc) <= axis->veloLimit_;
return std::abs(traj) <= axis->veloStandstillLimit_ && std::abs(enc) <= axis->veloStandstillLimit_;
}
// Check standstill and disable
@@ -447,7 +607,7 @@ void ecmcSS1SafetyGroup::setAxesDisable() {
if(!*saxis) {
throw std::runtime_error("Safety: Axis object NULL.");
}
setAxisEnable((*saxis)->axisId_,0);
setAxisEnable((*saxis)->axisId_,0);
}
if(printEnableStatus_ && cfgDbgMode_) {
@@ -462,23 +622,46 @@ void ecmcSS1SafetyGroup::setAxesSafetyInterlocks(int stop) {
if(!*saxis) {
throw std::runtime_error( "Safety: Axis object NULL.");
}
setAxisEmergencyStopInterlock((*saxis)->axisId_,stop);
setAxisEmergencyStopInterlock((*saxis)->axisId_,stop);
if(!oldStop_ && stop) {
//Calcualte new deceleration if delay is defined and abs(velo) > 0
if(delayMs_ > 0) {
double velo = 0;
getAxisTrajVelo((*saxis)->axisId_,&velo);
velo = std::abs(velo);
if(velo > 0) {
double newEmergDec = velo / (ECMC_PLUGIN_RAMP_DOWN_TIME_RATIO * delayMs_ / 1000.0);
setAxisEmergDeceleration((*saxis)->axisId_,newEmergDec);
printf("Safety %s: Set new emergency deceleration %lf \n",sName_,newEmergDec);
}
}
}
}
oldStop_ = stop;
}
void ecmcSS1SafetyGroup::addAxis(int axisId, double veloLimit,int standStillTimeMs) {
void ecmcSS1SafetyGroup::addAxis(int axisId,
double veloStandstillLimit,
int standStillTimeMs,
double veloMaxLimit) {
if(!getAxisValid(axisId)) {
throw std::out_of_range("Safety: Invalid axis id");
}
axes_.push_back(new safetyAxis(axisId, veloLimit, standStillTimeMs));
axes_.push_back(new safetyAxis(axisId, veloStandstillLimit,
standStillTimeMs, veloMaxLimit));
axesCounter_++;
if(cfgDbgMode_) {
printf("Safety %s: Added axis %d to safety group (velo limit = %lf, standstill filter : %d)\n"
,sName_,axisId,veloLimit,standStillTimeMs);
printf("Safety %s: Added axis %d to safety group.\n"
" Velo stand still limit: %lf\n"
" velo max limit: %lf (%s)\n"
" standstill filter time: %d\n"
,sName_,axisId,veloStandstillLimit,veloMaxLimit,
veloMaxLimit>0 ? "enabled" : "disabled", standStillTimeMs);
}
return;

View File

@@ -25,26 +25,45 @@ typedef struct {
bool error : 1;
bool rampDownCmdActive : 1;
bool axesAtStandstill : 1;
int dummy : 29;
bool limitVeloCmdActive : 1;
int dummy : 28;
} ecmcSafetyStatusWd;
class safetyAxis {
public:
safetyAxis(int axisId,
double veloLimit,
int standStillTimeMs) {
veloLimit_ = veloLimit;
axisId_ = axisId;
standStillTimeMs_ = standStillTimeMs;
printEnableStat_ = 1;
double velostandstillLimit,
int standStillTimeMs,
double veloMaxLimit) {
veloStandstillLimit_ = velostandstillLimit;
axisId_ = axisId;
standStillTimeMs_ = standStillTimeMs;
veloMaxLimit_ = veloMaxLimit;
veloMaxLimitEnabled_ = veloMaxLimit > 0;
printEnableStat_ = 1;
}
double veloLimit_;
safetyAxis(int axisId,
double velostandstillLimit,
int standStillTimeMs) {
veloStandstillLimit_ = velostandstillLimit;
axisId_ = axisId;
standStillTimeMs_ = standStillTimeMs;
veloMaxLimit_ = -1;
veloMaxLimitEnabled_ = 0;
printEnableStat_ = 1;
}
double veloStandstillLimit_;
double veloMaxLimit_; // disable with -1
int axisId_;
int standStillTimeMs_;
int printEnableStat_;
int veloMaxLimitEnabled_;
};
class ecmcSS1SafetyGroup : public asynPortDriver {
public:
@@ -54,17 +73,21 @@ class ecmcSS1SafetyGroup : public asynPortDriver {
* - out_of_range
*/
ecmcSS1SafetyGroup(const char *name,
const char *ec_rampdown_cmd,
const char *ec_standstill_status,
int time_delay_ms,
const char *cfg_string,
char* portName);
const char *ec_rampdown_cmd,
const char *ec_standstill_status,
const char *ec_limit_velo,
int time_delay_ms,
const char *cfg_string,
char* portName);
~ecmcSS1SafetyGroup();
// Call just before realtime because then all data sources should be available
void validate();
void addAxis(int axisId, double veloLimit,int standStillTimeMs);
void addAxis(int axisId,
double veloLimit,
int standStillTimeMs,
double veloMaxLimit);
void execute();
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
std::string getName();
@@ -77,19 +100,27 @@ class ecmcSS1SafetyGroup : public asynPortDriver {
void setAxesDisable();
void setAxesStandstillStatus(int standstill);
bool checkAxesStandstill();
bool checkAxesDisabled();
bool checkAxisStandstill(safetyAxis* axis);
bool checkAxisStandstillAndDisableIfNeeded(safetyAxis* axis);
bool checkAxesStandstillAndDisableIfNeeded();
void checkAxesMaxVeloAndDisableIfNeeded();
void setAxesMaxVelo();
bool checkAxisMaxVelo(safetyAxis* axis);
void resetPrintoutStatus();
void parseConfigStr(const char *configStr);
void initAsyn();
void refreshAsyn();
void exeRampDown();
void exeLimitVelo();
double ecmcSampleRateHz_;
int dataSourcesLinked_; // To avoid link several times
int objectId_; // Unique object id
int cycleCounter_;
int rampDownCmd_;
int rampDownCmdOld_;
int limitVeloCmdOld_;
int limitVeloCmd_;
// Config options
int cfgDbgMode_; // Config: allow dbg printouts
@@ -105,8 +136,7 @@ class ecmcSS1SafetyGroup : public asynPortDriver {
char* sName_;
char* sEcRampDownCmdNameOrg_;
char* sEcAxesStandStillStatOrg_;
char* sEcRampDownCmdNameStrip_;
char* sEcAxesStandStillStatStrip_;
char* sEcLimitVeloOrg_;
char* sConfig_;
int delayMs_;
@@ -115,18 +145,26 @@ class ecmcSS1SafetyGroup : public asynPortDriver {
int bitRampDown_;
int slaveIdStandStill_;
int bitStandStill_;
int slaveIdLimitVelo_;
int bitLimitVelo_;
int limitMaxVeloEnable_;
int axesDisabled_;
int axesAreStandstill_;
int axesAreStandstillOld_;
int printEnableStatus_;
char aliasRampDown_[EC_MAX_OBJECT_PATH_CHAR_LENGTH];
char aliasStandStill_[EC_MAX_OBJECT_PATH_CHAR_LENGTH];
char aliasLimitVelo_[EC_MAX_OBJECT_PATH_CHAR_LENGTH];
ecmcEc *ecMaster_;
ecmcEcEntry *ecEntryRampDown_;
ecmcEcEntry *ecEntryStandstill_;
ecmcEcEntry *ecEntryLimitVelo_;
bool oldStop_;
static std::string to_string(int value);
};
#endif /* ECMC_SAFETY_GROUP_PLG_H_ */

View File

@@ -25,4 +25,7 @@
#define ECMC_PLUGIN_SAFETY_ERROR_CODE 1
#define ECMC_PLUGIN_ALREADY_LOADED_ERROR_CODE 2
// How big part of delay is used for rampdown
#define ECMC_PLUGIN_RAMP_DOWN_TIME_RATIO 0.9
#endif /* ECMC_MOTION_PLG_DEFS_H_ */

View File

@@ -51,6 +51,7 @@ ecmcSS1SafetyGroup* getGroupFromName(const char *name) {
int createSafetyGroup(const char *name,
const char *ec_rampdown_cmd,
const char *ec_standstill_status,
const char *ec_max_velo_cmd,
int time_delay_ms) {
// ensure group does not already exist
@@ -71,6 +72,7 @@ int createSafetyGroup(const char *name,
safetyGroup = new ecmcSS1SafetyGroup(name,
ec_rampdown_cmd,
ec_standstill_status,
ec_max_velo_cmd,
time_delay_ms,
configString,
portNameBuffer);
@@ -90,7 +92,8 @@ int createSafetyGroup(const char *name,
int addAxisToSafetyGroup(const char *groupName,
int axisId,
double veloLimit,
int standStillTimeMs) {
int standStillTimeMs,
double maxVeloLimit) {
ecmcSS1SafetyGroup* grp = getGroupFromName(groupName);
@@ -99,7 +102,7 @@ int addAxisToSafetyGroup(const char *groupName,
throw std::runtime_error( "Safety: Error, group not found.");
}
grp->addAxis(axisId,veloLimit,standStillTimeMs);
grp->addAxis(axisId,veloLimit,standStillTimeMs,maxVeloLimit);
return asynSuccess;
}
@@ -160,15 +163,20 @@ int executeSafetyGroups() {
*/
void ecmcAddSS1SafetyGroupPrintHelp() {
printf("\n");
printf(" Use ecmcAddSS1SafetyGroup(<name>, <ec_rampdown_cmd>, <ec_standstill_status>,<time_delay_ms>)\n");
printf(" Use ecmcAddSS1SafetyGroup(<name>, <ec_rampdown_cmd>, <ec_standstill_status>,<ec_max_velo_cmd>,<time_delay_ms>)\n");
printf(" <name> : Name of group.\n");
printf(" <ec_rampdown_cmd> : Ethercat entry input for rampdown cmd.\n");
printf(" <ec_standstill_status> : Ethercat entry output for group standstill status.\n");
printf(" <ec_max_velo_cmd> : Ethercat entry input for activation of maximum velo limitation (set to \"empty\" to disable).\n");
printf(" <time_delay_ms> : Time delay of STO [ms].\n");
printf("\n");
}
int ecmcAddSS1SafetyGroup(const char* name, const char* ec_rampdown_cmd,const char* ec_standstill_status,int time_delay_ms) {
int ecmcAddSS1SafetyGroup(const char* name,
const char* ec_rampdown_cmd,
const char* ec_standstill_status,
const char* ec_max_velo_cmd,
int time_delay_ms) {
if(!name) {
ecmcAddSS1SafetyGroupPrintHelp();
return asynError;
@@ -190,13 +198,20 @@ int ecmcAddSS1SafetyGroup(const char* name, const char* ec_rampdown_cmd,const ch
ecmcAddSS1SafetyGroupPrintHelp();
return asynError;
}
if(!ec_max_velo_cmd) {
printf("Error: ec_max_velo_cmd ethercat entry not defined.\n");
ecmcAddSS1SafetyGroupPrintHelp();
return asynError;
}
if(time_delay_ms <= 0) {
printf("Error: time_delay invalid.\n");
exit (EXIT_FAILURE);
}
try {
createSafetyGroup(name,ec_rampdown_cmd,ec_standstill_status, time_delay_ms);
createSafetyGroup(name,ec_rampdown_cmd,ec_standstill_status,ec_max_velo_cmd,time_delay_ms);
}
catch(std::exception& e) {
printf("Exception: %s. Add safety group failed.\n",e.what());
@@ -213,16 +228,19 @@ static const iocshArg initArg1_1 =
static const iocshArg initArg2_1 =
{ "ec entry output axes standstill status", iocshArgString };
static const iocshArg initArg3_1 =
{ "ec entry input activate max velo", iocshArgString };
static const iocshArg initArg4_1 =
{ "STO delay [ms]", iocshArgInt };
static const iocshArg *const initArgs_1[] = { &initArg0_1,
&initArg1_1,
&initArg2_1,
&initArg3_1};
&initArg3_1,
&initArg4_1,};
static const iocshFuncDef initFuncDef_1 = { "ecmcAddSS1SafetyGroup", 4, initArgs_1 };
static const iocshFuncDef initFuncDef_1 = { "ecmcAddSS1SafetyGroup", 5, initArgs_1 };
static void initCallFunc_1(const iocshArgBuf *args) {
ecmcAddSS1SafetyGroup(args[0].sval, args[1].sval, args[2].sval, args[3].ival);
ecmcAddSS1SafetyGroup(args[0].sval, args[1].sval, args[2].sval, args[3].sval, args[4].ival);
}
/**
@@ -231,14 +249,19 @@ static void initCallFunc_1(const iocshArgBuf *args) {
void ecmcAddAxisToSafetyGroupPrintHelp() {
printf("\n");
printf(" Use ecmcAddAxisToSafetyGroup(<group_name>, <axis_index>)\n");
printf(" <name> : Name of safety group.\n");
printf(" <Axis id> : Axis index to add.\n");
printf(" <velo limit> : Axis standstill velo limit [unit of axis].\n");
printf(" <time> : Time for axis to be below velo limit [ms].\n");
printf(" <name> : Name of safety group.\n");
printf(" <Axis id> : Axis index to add.\n");
printf(" <standstill_velo_limit> : Axis standstill velo limit [unit of axis].\n");
printf(" <standstill_time> : Time for axis to be below standstill_velo_limit [ms].\n");
printf(" <max_velo_limit> : Axis max velo limit [unit of axis] (0 to disable).\n");
printf("\n");
}
int ecmcAddAxisToSafetyGroup(const char* name, int axis_id, double velo_lim, int stand_still_time) {
int ecmcAddAxisToSafetyGroup(const char* name,
int axis_id,
double standstill_velo_limit,
int stand_still_time,
double max_velo_limit) {
if(!name) {
ecmcAddAxisToSafetyGroupPrintHelp();
return asynError;
@@ -254,17 +277,26 @@ int ecmcAddAxisToSafetyGroup(const char* name, int axis_id, double velo_lim, int
exit(EXIT_FAILURE);
}
if(velo_lim < 0) {
printf("Error: Invalid velocity limit.\n");
if(standstill_velo_limit < 0) {
printf("Error: Invalid standstill velocity limit.\n");
exit(EXIT_FAILURE);
}
if(stand_still_time < 0) {
printf("Error: Invalid stand still filter time.\n");
printf("Error: Invalid standstill filter time.\n");
exit(EXIT_FAILURE);
}
if(max_velo_limit < 0) {
printf("Error: Invalid maximum velocity limit.\n");
exit(EXIT_FAILURE);
}
try {
return addAxisToSafetyGroup(name,axis_id, velo_lim, stand_still_time);
return addAxisToSafetyGroup(name,axis_id,
standstill_velo_limit,
stand_still_time,
max_velo_limit);
}
catch(std::exception& e) {
printf("Exception: %s. Add axis to safety group failed.\n",e.what());
@@ -279,18 +311,21 @@ static const iocshArg initArg0_2 =
static const iocshArg initArg1_2 =
{ "Axis id []", iocshArgInt };
static const iocshArg initArg2_2 =
{ "Velo limit [unit same as axis cfg]", iocshArgDouble };
{ "Velo stand still limit [unit same as axis cfg]", iocshArgDouble };
static const iocshArg initArg3_2 =
{ "Velo stand still filter time [ms]", iocshArgInt };
static const iocshArg initArg4_2 =
{ "Velo max limit [unit same as axis cfg]", iocshArgDouble };
static const iocshArg *const initArgs_2[] = { &initArg0_2,
&initArg1_2,
&initArg2_2,
&initArg3_2};
&initArg3_2,
&initArg4_2};
static const iocshFuncDef initFuncDef_2 = { "ecmcAddAxisToSafetyGroup", 4, initArgs_2};
static const iocshFuncDef initFuncDef_2 = { "ecmcAddAxisToSafetyGroup", 5, initArgs_2};
static void initCallFunc_2(const iocshArgBuf *args) {
ecmcAddAxisToSafetyGroup(args[0].sval, args[1].ival, args[2].dval, args[3].ival);
ecmcAddAxisToSafetyGroup(args[0].sval, args[1].ival, args[2].dval, args[3].ival, args[4].dval);
}
void ecmcSafetyPlgRegister(void) {

View File

@@ -25,11 +25,11 @@ int setCfgString(const char* cfgString);
* \param[in] name Name of safety group.\n
* \param[in] ec_rampdown_cmd Name of ethercat entry for ramp down command\n
* \param[in] ec_standstill_status Name of ethercat entry all axis standstill status\n
* \param[in] time_delay_ms Timedelay between ec_rampdown_cmd going high untill STO is triggered by safety relay.\n
* \param[in] time_delay_ms Timedelay between ec_ramp-down_cmd going high until STO is triggered by safety relay.\n
*
* \return 0 if success or otherwise an error code.\n
*/
//int createSafetyGroup(name,ec_rampdown_cmd,ec_standstill_status, time_delay_ms);
//int createSafetyGroup(name,ec_ramp-down_cmd,ec_standstill_status, time_delay_ms);
/** \brief Deletes all created objects\n
*
@@ -41,8 +41,8 @@ void deleteAllSafetyGroups();
*
* This tells the safety lib to connect to ecmc to find it's data sources.\n
* This function should be called just before entering realtime since then all\n
* data sources in ecmc will be definded (plc sources are compiled just before runtime\n
* so are only fist accesible now).\n
* data sources in ecmc will be defined (plc sources are compiled just before runtime\n
* so are only fist accessible now).\n
* \return 0 if success or otherwise an error code.\n
*/
int validate();

View File

@@ -13,7 +13,7 @@
#-
#################################################################################
#- Print discalimer
#- Print disclaimer
#
# !!!!!!!!!!!!! IMPORTANT !!!!!!!!!
# This plugin has _NO_ safety rated functionalities.
@@ -24,3 +24,6 @@
epicsEnvSet(ECMC_PLUGIN_FILNAME,"$(ecmc_plugin_safety_DIR)/lib/${EPICS_HOST_ARCH=linux-x86_64}/libecmc_plugin_safety.so")
epicsEnvSet(ECMC_PLUGIN_CONFIG,"DBG_PRINT=1;")
ecmcConfigOrDie "Cfg.LoadSafetyPlugin(${ECMC_PLUGIN_FILNAME},${ECMC_PLUGIN_CONFIG=""})"
#- Load SS1 group records
dbLoadRecords("ecmcSS1Main.template","P=${ECMC_PREFIX}")