Merge branch 'master' of git.psi.ch:epics_ioc_modules/ecmc_plugin_safety
This commit is contained in:
@@ -1,258 +0,0 @@
|
||||
# Act pos
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-PosAct-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Pos Act")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.actpos_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "${RAW_EGU= }")
|
||||
}
|
||||
|
||||
# Set pos
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-PosSet-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Pos Set")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.setpos_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "${RAW_EGU= }")
|
||||
}
|
||||
|
||||
# Position Error
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-PosErr-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Pos Error (diff)")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.diffpos_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "${RAW_EGU= }")
|
||||
}
|
||||
|
||||
# X axis time (reltive within buffer)
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Time-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Rel. time within buffer")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.x_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Enable
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Ena-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Enable")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enable_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Enabled
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-EnaAct-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Enabled")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enabled_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Busy
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Bsy-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Busy")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.busy_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Execute
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Exe-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Execute")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.execute_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Traj source
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-TrjSrc-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Traj source")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.trajsrc_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Enc source
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-EncSrc-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Enc source")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.encsrc_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis At target
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-AtTrg-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "At target")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.attarget_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Error Id
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-ErrId-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Error Id")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt32ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.error_arr")
|
||||
field(FTVL, "LONG")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
# Axis Error Id
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Stat-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Status wd")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt32ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.statuswd_arr")
|
||||
field(FTVL, "LONG")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
}
|
||||
|
||||
record(bo,"$(P)Plg-Mtn${INDEX}-EnaCmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Plg Enable")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enable")
|
||||
field(ZNAM,"FALSE")
|
||||
field(ONAM,"TRUE")
|
||||
field(DOL, "0")
|
||||
field(VAL, "0")
|
||||
}
|
||||
|
||||
record(ao,"$(P)Plg-Mtn${INDEX}-AxCmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Axis")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.axis_id")
|
||||
field(DOL, "0")
|
||||
field(VAL, "1")
|
||||
}
|
||||
|
||||
record(ai,"$(P)Plg-Mtn${INDEX}-SmpHz-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Sample rate")
|
||||
field(DTYP,"asynFloat64")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.samplerate")
|
||||
field(VAL, "1")
|
||||
field(EGU, "Hz")
|
||||
field(SCAN, "I/O Intr")
|
||||
}
|
||||
|
||||
record(ai,"$(P)Plg-Mtn${INDEX}-BuffSze"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Buffer Size")
|
||||
field(DTYP,"asynInt32")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.buff_size")
|
||||
field(VAL, "1")
|
||||
}
|
||||
|
||||
record(ai,"$(P)Plg-Mtn${INDEX}-ElmCnt"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Elements in buffer count")
|
||||
field(DTYP,"asynInt32")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.elem_count")
|
||||
field(VAL, "1")
|
||||
}
|
||||
|
||||
record(bo,"$(P)Plg-Mtn${INDEX}-TrgCmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Trigg command")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.trigg")
|
||||
field(ZNAM,"IDLE")
|
||||
field(ONAM,"TRIGG")
|
||||
field(VAL, "0")
|
||||
field(HIGH, 0.001)
|
||||
}
|
||||
|
||||
record(longout,"$(P)Plg-Mtn${INDEX}-Mde-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Mode selection")
|
||||
field(PINI, "1")
|
||||
field(TSE, "0")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.mode")
|
||||
field(SCAN, "Passive")
|
||||
}
|
||||
|
||||
record(longout,"$(P)Plg-Mtn${INDEX}-Cmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Command")
|
||||
field(PINI, "1")
|
||||
field(TSE, "0")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.cmd")
|
||||
field(SCAN, "Passive")
|
||||
}
|
||||
|
||||
record(longin,"$(P)Plg-Mtn${INDEX}-Stat"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Status")
|
||||
field(PINI, "1")
|
||||
field(TSE, "0")
|
||||
field(DTYP, "asynInt32")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.status")
|
||||
field(SCAN, "I/O Intr")
|
||||
}
|
||||
54
Db/ss1.template
Normal file
54
Db/ss1.template
Normal file
@@ -0,0 +1,54 @@
|
||||
#- Status word:
|
||||
#- bool error : 1;
|
||||
#- bool rampDownCmdActive : 1;
|
||||
#- bool axesAtStandstill : 1;
|
||||
|
||||
record(longin,"${P}SS1-${NAME}-Stat"){
|
||||
field(DESC, "SS1-${NAME}: Status Word")
|
||||
field(PINI, "$(PINI=1)")
|
||||
field(DTYP, "asynInt32")
|
||||
field(INP, "@asyn(PLUGIN.SAFETY.GROUP.$(NAME),$(ADDR=0),$(TIMEOUT=1))plugin.safety.ss1.$(NAME).status")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(FLNK, "${P}SS1-${NAME}-Stat_.PROC")
|
||||
field(TSE, "$(TSE=-2)")
|
||||
}
|
||||
|
||||
record(mbbiDirect,"${P}SS1-${NAME}-Stat_"){
|
||||
field(DESC, "SS1-${NAME}: Status Word mbbiD")
|
||||
field(PINI, "$(PINI=1)")
|
||||
field(INP, "${P}SS1-${NAME}-Stat.VAL")
|
||||
field(FLNK, "${P}SS1-${NAME}-Err.PROC")
|
||||
field(TSE, "$(TSE=-2)")
|
||||
}
|
||||
|
||||
# // bit 0 error
|
||||
record(bi,"${P}SS1-${NAME}-Err"){
|
||||
field(DESC, "SS1-${NAME}: Error")
|
||||
field(INP, "${P}SS1-${NAME}-Stat_.B0")
|
||||
field(ZNAM, "OK")
|
||||
field(ONAM, "Error")
|
||||
field(ZSV, "NO_ALARM")
|
||||
field(OSV, "MAJOR")
|
||||
field(FLNK, "${P}SS1-${NAME}-RmpDwnCmdAct.PROC")
|
||||
}
|
||||
|
||||
# // bit 1 rampDownCmdActive
|
||||
record(bi,"${P}SS1-${NAME}-RmpDwnCmdAct"){
|
||||
field(DESC, "SS1-${NAME}: Ramp down cmd from safty PLC")
|
||||
field(INP, "${P}SS1-${NAME}-Stat_.B1")
|
||||
field(ZNAM, "Not Active")
|
||||
field(ONAM, "Active")
|
||||
field(ZSV, "NO_ALARM")
|
||||
field(OSV, "NO_ALARM")
|
||||
field(FLNK, "${P}SS1-${NAME}-AxsStndStllAct.PROC")
|
||||
}
|
||||
|
||||
# // bit 2 axesAtStandstill
|
||||
record(bi,"${P}SS1-${NAME}-AxsStndStllAct"){
|
||||
field(DESC, "SS1-${NAME}: Axes at standstill")
|
||||
field(INP, "${P}SS1-${NAME}-Stat_.B2")
|
||||
field(ZNAM, "Moving")
|
||||
field(ONAM, "Standstill")
|
||||
field(ZSV, "NO_ALARM")
|
||||
field(OSV, "NO_ALARM")
|
||||
}
|
||||
@@ -42,4 +42,6 @@ SOURCES += $(SRC_DIR)/ecmcSS1SafetyGroup.cpp
|
||||
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
|
||||
TEMPLATES += $(wildcard $(DB_DIR)/*.template)
|
||||
|
||||
30
scripts/addAxisToGroup.cmd
Normal file
30
scripts/addAxisToGroup.cmd
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
#==============================================================================
|
||||
# addAxisToGroup.cmd
|
||||
#-
|
||||
#- !!!!!!!!!!!!! IMPORTANT !!!!!!!!!
|
||||
#- This plugin has _NO_ safety rated functionalities.
|
||||
#- The intended use of this plugin is only to handle interfacing with a safety PLC.
|
||||
#-
|
||||
#-------------- Information:
|
||||
#- Description: add axis to group
|
||||
#-
|
||||
#- by Anders Sandström, Paul Scherrer Institute, 2023
|
||||
#- email: anders.sandstroem@psi.ch
|
||||
#-
|
||||
#-###############################################################################
|
||||
#-
|
||||
#- Arguments:
|
||||
#- NAME : Name of safety group
|
||||
#- AX_ID : Axis ID
|
||||
#- VELO_LIM : Velocity standstill limit [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].
|
||||
#- <filter_time> : NOT USED (for future implemenation). Time for axis to be below velo limit [ms].
|
||||
|
||||
ecmcAddAxisToSafetyGroup("${NAME}",${AX_ID},${VELO_LIM=0},0)
|
||||
33
scripts/addSS1Group.cmd
Normal file
33
scripts/addSS1Group.cmd
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
#==============================================================================
|
||||
# addSS1Group.cmd
|
||||
#-
|
||||
#- !!!!!!!!!!!!! IMPORTANT !!!!!!!!!
|
||||
#- This plugin has _NO_ safety rated functionalities.
|
||||
#- The intended use of this plugin is only to handle interfacing with a safety PLC.
|
||||
#-
|
||||
#-------------- Information:
|
||||
#- Description: Create a SS1 motion group
|
||||
#-
|
||||
#- by Anders Sandström, Paul Scherrer Institute, 2023
|
||||
#- email: anders.sandstroem@psi.ch
|
||||
#-
|
||||
#-###############################################################################
|
||||
#-
|
||||
#- Arguments:
|
||||
#- NAME : Name of safety group
|
||||
#- EC_RAMP_DOWN_CMD : Ethercat entry for rampd down command (cmd from safety PLC/system)
|
||||
#- EC_STANDSTILL_STAT : Ethercat entry for axes at standstill status (feedback to 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_cmd> : Ethercat entry input for rampdown cmd.
|
||||
#- <ec_standstill_status> : Ethercat entry output for group standstill status.
|
||||
#- <time_delay_ms> : Time delay of STO [ms].
|
||||
ecmcAddSS1SafetyGroup("${NAME}","${EC_RAMP_DOWN_CMD}","${EC_STANDSTILL_STAT}",${DELAY_MS=0})
|
||||
|
||||
#- Load SS1 group records
|
||||
dbLoadRecords("ss1.template","P=${ECMC_PREFIX},NAME=${NAME}")
|
||||
@@ -62,7 +62,8 @@ ecmcSS1SafetyGroup::ecmcSS1SafetyGroup(const char *name,
|
||||
sEcAxesStandStillStatStrip_ = strdup(ec_standstill_status);
|
||||
sConfig_ = strdup(cfg_string);
|
||||
delayMs_ = time_delay_ms;
|
||||
status_ = 0;
|
||||
memset(&status_,0,sizeof(status_));
|
||||
ptrStatus_ = (int*)&status_;
|
||||
asynStatusId_ = -1;
|
||||
axesCounter_ = 0;
|
||||
ecmcSampleRateHz_ = getEcmcSampleRate();
|
||||
@@ -273,16 +274,31 @@ void ecmcSS1SafetyGroup::connectToDataSources() {
|
||||
//dataSourcesLinked_ = 1;
|
||||
}
|
||||
|
||||
void ecmcSS1SafetyGroup::refreshAsyn() {
|
||||
setIntegerParam(asynStatusId_, (epicsInt32)*ptrStatus_);
|
||||
callParamCallbacks();
|
||||
}
|
||||
|
||||
asynStatus ecmcSS1SafetyGroup::readInt32(asynUser *pasynUser, epicsInt32 *value) {
|
||||
int function = pasynUser->reason;
|
||||
if( function == asynStatusId_ ) {
|
||||
*value = (epicsInt32)*ptrStatus_;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
return asynError;
|
||||
}
|
||||
|
||||
void ecmcSS1SafetyGroup::initAsyn() {
|
||||
|
||||
// Add motion "plugin.motion%d.status"
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "_" + to_string(objectId_) +
|
||||
// Add motion "plugin.safety.ss1.<grp_name>.status"
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "." ECMC_PLUGIN_ASYN_SS1 "." + std::string(sName_) +
|
||||
"." + ECMC_PLUGIN_ASYN_SAFETY_STAT;
|
||||
int *paramId = &asynStatusId_;
|
||||
if( createParam(0, paramName.c_str(), asynParamInt32, paramId ) != asynSuccess ) {
|
||||
throw std::runtime_error("Safety: Failed create asyn parameter mode");
|
||||
}
|
||||
setIntegerParam(*paramId, (epicsInt32)status_);
|
||||
setIntegerParam(asynStatusId_, (epicsInt32)*ptrStatus_);
|
||||
|
||||
// Update integers
|
||||
callParamCallbacks();
|
||||
@@ -313,6 +329,11 @@ void ecmcSS1SafetyGroup::execute() {
|
||||
rampDownCmd_ = data == 0;
|
||||
|
||||
if(rampDownCmdOld_ != rampDownCmd_) {
|
||||
|
||||
// Update asyn status wd
|
||||
status_.rampDownCmdActive = rampDownCmd_;
|
||||
refreshAsyn();
|
||||
|
||||
resetPrintoutStatus();
|
||||
if(cfgDbgMode_) {
|
||||
if(rampDownCmd_) {
|
||||
@@ -351,6 +372,10 @@ void ecmcSS1SafetyGroup::setAxesStandstillStatus(int standstill) {
|
||||
} else {
|
||||
printf("Safety %s: Axes are moving\n",sName_);
|
||||
}
|
||||
|
||||
// Update asyn status wd
|
||||
status_.axesAtStandstill = standstill;
|
||||
refreshAsyn();
|
||||
}
|
||||
|
||||
if(ecEntryStandstill_->writeBit(bitStandStill_,
|
||||
@@ -426,16 +451,6 @@ void ecmcSS1SafetyGroup::setAxesSafetyInterlocks(int stop) {
|
||||
}
|
||||
}
|
||||
|
||||
asynStatus ecmcSS1SafetyGroup::readInt32(asynUser *pasynUser, epicsInt32 *value) {
|
||||
int function = pasynUser->reason;
|
||||
if( function == asynStatusId_ ){
|
||||
*value = (epicsInt32)status_;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
return asynError;
|
||||
}
|
||||
|
||||
void ecmcSS1SafetyGroup::addAxis(int axisId, double veloLimit,int standStillTimeMs) {
|
||||
|
||||
if(!getAxisValid(axisId)) {
|
||||
@@ -456,122 +471,3 @@ void ecmcSS1SafetyGroup::addAxis(int axisId, double veloLimit,int standStillTime
|
||||
std::string ecmcSS1SafetyGroup::getName() {
|
||||
return sName_;
|
||||
}
|
||||
|
||||
uint8_t ecmcSS1SafetyGroup::getUint8(uint8_t* data) {
|
||||
return *data;
|
||||
}
|
||||
|
||||
int8_t ecmcSS1SafetyGroup::getInt8(uint8_t* data) {
|
||||
int8_t* p=(int8_t*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
uint16_t ecmcSS1SafetyGroup::getUint16(uint8_t* data) {
|
||||
uint16_t* p=(uint16_t*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
int16_t ecmcSS1SafetyGroup::getInt16(uint8_t* data) {
|
||||
int16_t* p=(int16_t*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
uint32_t ecmcSS1SafetyGroup::getUint32(uint8_t* data) {
|
||||
uint32_t* p=(uint32_t*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
int32_t ecmcSS1SafetyGroup::getInt32(uint8_t* data) {
|
||||
int32_t* p=(int32_t*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
uint64_t ecmcSS1SafetyGroup::getUint64(uint8_t* data) {
|
||||
uint64_t* p=(uint64_t*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
int64_t ecmcSS1SafetyGroup::getInt64(uint8_t* data) {
|
||||
int64_t* p=(int64_t*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
float ecmcSS1SafetyGroup::getFloat32(uint8_t* data) {
|
||||
float* p=(float*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
double ecmcSS1SafetyGroup::getFloat64(uint8_t* data) {
|
||||
double* p=(double*)data;
|
||||
return *p;
|
||||
}
|
||||
|
||||
size_t ecmcSS1SafetyGroup::getEcDataTypeByteSize(ecmcEcDataType dt){
|
||||
switch(dt) {
|
||||
case ECMC_EC_NONE:
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case ECMC_EC_B1:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ECMC_EC_B2:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ECMC_EC_B3:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ECMC_EC_B4:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ECMC_EC_U8:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ECMC_EC_S8:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ECMC_EC_U16:
|
||||
return 2;
|
||||
break;
|
||||
|
||||
case ECMC_EC_S16:
|
||||
return 2;
|
||||
break;
|
||||
|
||||
case ECMC_EC_U32:
|
||||
return 4;
|
||||
break;
|
||||
|
||||
case ECMC_EC_S32:
|
||||
return 4;
|
||||
break;
|
||||
|
||||
case ECMC_EC_U64:
|
||||
return 8;
|
||||
break;
|
||||
|
||||
case ECMC_EC_S64:
|
||||
return 8;
|
||||
break;
|
||||
|
||||
case ECMC_EC_F32:
|
||||
return 4;
|
||||
break;
|
||||
|
||||
case ECMC_EC_F64:
|
||||
return 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,13 @@
|
||||
#include "ecmcEc.h"
|
||||
#include <vector>
|
||||
|
||||
typedef struct {
|
||||
bool error : 1;
|
||||
bool rampDownCmdActive : 1;
|
||||
bool axesAtStandstill : 1;
|
||||
int dummy : 29;
|
||||
} ecmcSafetyStatusWd;
|
||||
|
||||
class safetyAxis {
|
||||
public:
|
||||
safetyAxis(int axisId,
|
||||
@@ -76,6 +83,7 @@ class ecmcSS1SafetyGroup : public asynPortDriver {
|
||||
void resetPrintoutStatus();
|
||||
void parseConfigStr(const char *configStr);
|
||||
void initAsyn();
|
||||
void refreshAsyn();
|
||||
double ecmcSampleRateHz_;
|
||||
int dataSourcesLinked_; // To avoid link several times
|
||||
int objectId_; // Unique object id
|
||||
@@ -88,7 +96,9 @@ class ecmcSS1SafetyGroup : public asynPortDriver {
|
||||
|
||||
// Asyn
|
||||
int asynStatusId_;
|
||||
int status_;
|
||||
ecmcSafetyStatusWd status_;
|
||||
int* ptrStatus_;
|
||||
|
||||
int axesCounter_;
|
||||
std::vector<safetyAxis*> axes_;
|
||||
|
||||
@@ -116,18 +126,6 @@ class ecmcSS1SafetyGroup : public asynPortDriver {
|
||||
ecmcEcEntry *ecEntryRampDown_;
|
||||
ecmcEcEntry *ecEntryStandstill_;
|
||||
|
||||
// Some generic utility functions
|
||||
static uint8_t getUint8(uint8_t* data);
|
||||
static int8_t getInt8(uint8_t* data);
|
||||
static uint16_t getUint16(uint8_t* data);
|
||||
static int16_t getInt16(uint8_t* data);
|
||||
static uint32_t getUint32(uint8_t* data);
|
||||
static int32_t getInt32(uint8_t* data);
|
||||
static uint64_t getUint64(uint8_t* data);
|
||||
static int64_t getInt64(uint8_t* data);
|
||||
static float getFloat32(uint8_t* data);
|
||||
static double getFloat64(uint8_t* data);
|
||||
static size_t getEcDataTypeByteSize(ecmcEcDataType dt);
|
||||
static std::string to_string(int value);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define ECMC_MOTION_PLG_DEFS_H_
|
||||
|
||||
#define ECMC_PLUGIN_ASYN_PREFIX "plugin.safety"
|
||||
#define ECMC_PLUGIN_ASYN_SS1 "ss1"
|
||||
|
||||
// Options
|
||||
#define ECMC_PLUGIN_DBG_PRINT_OPTION_CMD "DBG_PRINT="
|
||||
|
||||
@@ -48,7 +48,7 @@ int createSafetyGroup(const char *name,
|
||||
// create asynport name for new object ()
|
||||
memset(portNameBuffer, 0, ECMC_PLUGIN_MAX_PORTNAME_CHARS);
|
||||
snprintf (portNameBuffer, ECMC_PLUGIN_MAX_PORTNAME_CHARS,
|
||||
ECMC_PLUGIN_PORTNAME_PREFIX "_%d", safetyGroupsCounter);
|
||||
ECMC_PLUGIN_PORTNAME_PREFIX ".GROUP.%s",name );
|
||||
try {
|
||||
safetyGroup = new ecmcSS1SafetyGroup(name,
|
||||
ec_rampdown_cmd,
|
||||
|
||||
Reference in New Issue
Block a user