forked from epics_driver_modules/motorBase
newport model 3 driver: reverted back to the old definition of moving axis in the poller in XPSAxis.cpp. I made the new method, of checking the socket return value, an option which is enabled by using a new function called XPSEnableMovingMode. Also added the ability to run a TCL script. This may become a generic function in the base classes later on. Added a Db template to set and execute a TCL script.
This commit is contained in:
@@ -26,6 +26,7 @@ DB += XPSAuxBo.db
|
||||
DB += XPSAuxLi.db
|
||||
DB += XPSAuxLo.db
|
||||
DB += XPS_extra.db
|
||||
DB += XPSTclScript.template
|
||||
DB += HXP_extra.db
|
||||
DB += HXP_coords.db
|
||||
DB += ACRAux.template
|
||||
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
####################################################
|
||||
#
|
||||
# Template for executing TCL script on an XPS.
|
||||
# Uses parameters in model 3 XPS driver (XPSController).
|
||||
#
|
||||
# Matthew Pearson
|
||||
# July 2013
|
||||
#
|
||||
# Macros:
|
||||
# $(P) - PV name prefix
|
||||
# $(R) - PV base record name
|
||||
# $(PORT) - asyn port for the controller
|
||||
# $(ADDR) - asyn address (normally 0)
|
||||
# $(TIMEOUT) - asyn timeout
|
||||
#
|
||||
####################################################
|
||||
|
||||
# ///
|
||||
# /// Name of the TCL script to execute
|
||||
# ///
|
||||
record(waveform, "$(P)$(R)TCLScript")
|
||||
{
|
||||
field(DESC, "Name of the TCL script")
|
||||
field(PINI, "YES")
|
||||
field(DTYP, "asynOctetWrite")
|
||||
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XPS_TCL_SCRIPT")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "256")
|
||||
info(autosaveFields, "VAL")
|
||||
}
|
||||
|
||||
# ///
|
||||
# /// Execute the TCL script (non blocking)
|
||||
# ///
|
||||
record(bo, "$(P)$(R)TCLScriptExecute")
|
||||
{
|
||||
field(DESC, "Execute TCL Script")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XPS_TCL_SCRIPT_EXECUTE")
|
||||
field(ZNAM, "TCL Execute")
|
||||
field(ONAM, "TCL Execute")
|
||||
}
|
||||
|
||||
|
||||
@@ -577,28 +577,37 @@ asynStatus XPSAxis::poll(bool *moving)
|
||||
* homing, jogging, etc. However, this information is about the group, not the axis, so if one
|
||||
* motor in the group was moving, then they all appeared to be moving. This is not what we want, because
|
||||
* the EPICS motor record required the first motor to stop before the second motor could be moved.
|
||||
* Instead we look for a response on the moveSocket_ to see when the motor motion was complete */
|
||||
* Instead we look for a response on the moveSocket_ to see when the motor motion was complete.
|
||||
NOTE: by default this mode is disabled. To enable it use the XPSController::enableMovingMode() function.*/
|
||||
|
||||
/* If the group is not moving then the axis is not moving */
|
||||
if ((axisStatus_ < 43) || (axisStatus_ > 48)) moving_ = false;
|
||||
if ((axisStatus_ < 43) || (axisStatus_ > 48)) {
|
||||
moving_ = false;
|
||||
} else {
|
||||
if (!pC_->enableMovingMode_) {
|
||||
moving_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the axis is moving then read from the moveSocket to see if it is done
|
||||
* We currently assume the move is complete if we get any response, we don't
|
||||
* check the actual response. */
|
||||
if (moving_) {
|
||||
status = ReadXPSSocket(moveSocket_, readResponse, sizeof(readResponse), 0);
|
||||
if (status < 0) {
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR,
|
||||
"%s:%s: [%s,%d]: error calling ReadXPSSocket status=%d\n",
|
||||
driverName, functionName, pC_->portName, axisNo_, status);
|
||||
goto done;
|
||||
}
|
||||
if (status > 0) {
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s:%s: [%s,%d]: readXPSSocket returned nRead=%d, [%s]\n",
|
||||
driverName, functionName, pC_->portName, axisNo_, status, readResponse);
|
||||
status = 0;
|
||||
moving_ = false;
|
||||
if (pC_->enableMovingMode_) {
|
||||
if (moving_) {
|
||||
status = ReadXPSSocket(moveSocket_, readResponse, sizeof(readResponse), 0);
|
||||
if (status < 0) {
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR,
|
||||
"%s:%s: [%s,%d]: error calling ReadXPSSocket status=%d\n",
|
||||
driverName, functionName, pC_->portName, axisNo_, status);
|
||||
goto done;
|
||||
}
|
||||
if (status > 0) {
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s:%s: [%s,%d]: readXPSSocket returned nRead=%d, [%s]\n",
|
||||
driverName, functionName, pC_->portName, axisNo_, status, readResponse);
|
||||
status = 0;
|
||||
moving_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,8 @@ XPSController::XPSController(const char *portName, const char *IPAddress, int IP
|
||||
createParam(XPSProfileGroupNameString, asynParamOctet, &XPSProfileGroupName_);
|
||||
createParam(XPSTrajectoryFileString, asynParamOctet, &XPSTrajectoryFile_);
|
||||
createParam(XPSStatusString, asynParamInt32, &XPSStatus_);
|
||||
createParam(XPSTclScriptString, asynParamOctet, &XPSTclScript_);
|
||||
createParam(XPSTclScriptExecuteString, asynParamInt32, &XPSTclScriptExecute_);
|
||||
|
||||
// This socket is used for polling by the controller and all axes
|
||||
pollSocket_ = TCP_ConnectToServer((char *)IPAddress, IPPort, XPS_POLL_TIMEOUT);
|
||||
@@ -209,6 +211,10 @@ XPSController::XPSController(const char *portName, const char *IPAddress, int IP
|
||||
/* Flag used to turn off setting MSTA problem bit when the axis is disabled.*/
|
||||
noDisableError_ = 0;
|
||||
|
||||
/* Flag to disable a mode to change the moving state determination for an axis.*/
|
||||
/* See function XPSController::enableMovingMode().*/
|
||||
enableMovingMode_ = false;
|
||||
|
||||
}
|
||||
|
||||
void XPSController::report(FILE *fp, int level)
|
||||
@@ -235,6 +241,51 @@ void XPSController::report(FILE *fp, int level)
|
||||
asynMotorController::report(fp, level);
|
||||
}
|
||||
|
||||
asynStatus XPSController::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
||||
{
|
||||
int function = pasynUser->reason;
|
||||
int status = asynSuccess;
|
||||
XPSAxis *pAxis;
|
||||
static const char *functionName = "writeInt32";
|
||||
|
||||
pAxis = this->getAxis(pasynUser);
|
||||
if (!pAxis) return asynError;
|
||||
|
||||
/* Set the parameter and readback in the parameter library. This may be overwritten when we read back the
|
||||
* status at the end, but that's OK */
|
||||
status = pAxis->setIntegerParam(function, value);
|
||||
|
||||
if (function == XPSTclScriptExecute_) {
|
||||
/* Execute the TCL script */
|
||||
char fileName[MAX_FILENAME_LEN];
|
||||
getStringParam(XPSTclScript_, (int)sizeof(fileName), fileName);
|
||||
if (fileName != NULL) {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
|
||||
"Executing TCL script %s on XPS: %s\n",
|
||||
fileName, this->portName);
|
||||
status = TCLScriptExecute(pAxis->moveSocket_,
|
||||
fileName,"0","0");
|
||||
if (status != 0) {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
"TCLScriptExecute returned error %d, on XPS: %s\n",
|
||||
status, this->portName);
|
||||
status = asynError;
|
||||
}
|
||||
} else {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
"TCL script name has not been set on XPS: %s\n",
|
||||
this->portName);
|
||||
status = asynError;
|
||||
}
|
||||
} else {
|
||||
/* Call base class method */
|
||||
status = asynMotorController::writeInt32(pasynUser, value);
|
||||
}
|
||||
|
||||
return (asynStatus)status;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a deferred move (a coordinated group move) on all the axes in a group.
|
||||
* @param groupName Pointer to string naming the group on which to perform the group move.
|
||||
@@ -1158,6 +1209,18 @@ asynStatus XPSController::noDisableError()
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
/* Function to enable a mode where the XPSAxis poller will check the moveSocket response
|
||||
to determine motion done. It does not rely on the axis state in this case. This prevents
|
||||
axes in multipleAxis groups being in 'moving state' when another axis in the same
|
||||
group is moving. This allows the motor record to move the axis when another axis in the
|
||||
same group is moving. However, this has the consequence that a moving state is not
|
||||
detected if the move is externally generated. So by default this mode is turned off. It
|
||||
can be enabled by calling this function. */
|
||||
asynStatus XPSController::enableMovingMode()
|
||||
{
|
||||
enableMovingMode_ = true;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1257,6 +1320,22 @@ asynStatus XPSNoDisableError(const char *XPSName)
|
||||
return pC->noDisableError();
|
||||
}
|
||||
|
||||
asynStatus XPSEnableMovingMode(const char *XPSName)
|
||||
{
|
||||
XPSController *pC;
|
||||
static const char *functionName = "XPSEnableMovingMode";
|
||||
|
||||
pC = (XPSController*) findAsynPortDriver(XPSName);
|
||||
if (!pC) {
|
||||
printf("%s:%s: Error port %s not found\n", driverName, functionName, XPSName);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
return pC->enableMovingMode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Code for iocsh registration */
|
||||
|
||||
@@ -1342,6 +1421,16 @@ static void noDisableErrorCallFunc(const iocshArgBuf *args)
|
||||
XPSNoDisableError(args[0].sval);
|
||||
}
|
||||
|
||||
/* XPSEnableMovingMode */
|
||||
static const iocshArg XPSEnableMovingModeArg0 = {"Controller port name", iocshArgString};
|
||||
static const iocshArg * const XPSEnableMovingModeArgs[] = {&XPSEnableMovingModeArg0};
|
||||
static const iocshFuncDef enableMovingMode = {"XPSEnableMovingMode", 1, XPSEnableMovingModeArgs};
|
||||
|
||||
static void enableMovingModeCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
XPSEnableMovingMode(args[0].sval);
|
||||
}
|
||||
|
||||
|
||||
static void XPSRegister3(void)
|
||||
{
|
||||
@@ -1350,6 +1439,7 @@ static void XPSRegister3(void)
|
||||
iocshRegister(&configXPSProfile, configXPSProfileCallFunc);
|
||||
iocshRegister(&disableAutoEnable, disableAutoEnableCallFunc);
|
||||
iocshRegister(&noDisableError, noDisableErrorCallFunc);
|
||||
iocshRegister(&enableMovingMode, enableMovingModeCallFunc);
|
||||
}
|
||||
epicsExportRegistrar(XPSRegister3);
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ USAGE... Newport XPS EPICS asyn motor device driver
|
||||
#define XPSProfileGroupNameString "XPS_PROFILE_GROUP_NAME"
|
||||
#define XPSTrajectoryFileString "XPS_TRAJECTORY_FILE"
|
||||
#define XPSStatusString "XPS_STATUS"
|
||||
#define XPSTclScriptString "XPS_TCL_SCRIPT"
|
||||
#define XPSTclScriptExecuteString "XPS_TCL_SCRIPT_EXECUTE"
|
||||
|
||||
class XPSController : public asynMotorController {
|
||||
|
||||
@@ -34,6 +36,7 @@ class XPSController : public asynMotorController {
|
||||
int enableSetPosition, double setPositionSettlingTime);
|
||||
|
||||
/* These are the methods that we override from asynMotorDriver */
|
||||
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
||||
void report(FILE *fp, int level);
|
||||
XPSAxis* getAxis(asynUser *pasynUser);
|
||||
XPSAxis* getAxis(int axisNo);
|
||||
@@ -60,6 +63,11 @@ class XPSController : public asynMotorController {
|
||||
/* Function to disable the MSTA problem bit in the event of an XPS Disable state 20 */
|
||||
asynStatus noDisableError();
|
||||
|
||||
/* Function to enable a mode where the XPSAxis poller will check the moveSocket response
|
||||
to determine motion done. */
|
||||
asynStatus enableMovingMode();
|
||||
|
||||
|
||||
protected:
|
||||
XPSAxis **pAxes_; /**< Array of pointers to axis objects */
|
||||
|
||||
@@ -73,7 +81,9 @@ class XPSController : public asynMotorController {
|
||||
int XPSProfileGroupName_;
|
||||
int XPSTrajectoryFile_;
|
||||
int XPSStatus_;
|
||||
#define LAST_XPS_PARAM XPSStatus_
|
||||
int XPSTclScript_;
|
||||
int XPSTclScriptExecute_;
|
||||
#define LAST_XPS_PARAM XPSTclScriptExecute_
|
||||
|
||||
private:
|
||||
bool enableSetPosition_; /**< Enable/disable setting the position from EPICS */
|
||||
@@ -89,6 +99,7 @@ class XPSController : public asynMotorController {
|
||||
epicsEventId profileExecuteEvent_;
|
||||
int autoEnable_;
|
||||
int noDisableError_;
|
||||
bool enableMovingMode_;
|
||||
|
||||
friend class XPSAxis;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user