forked from epics_driver_modules/motorBase
Added the ability to move all hexapod motors to new target positions (not using deferred moves).
This commit is contained in:
@@ -220,6 +220,7 @@ Modification Log for R6-8
|
||||
motorApp/NewportSrc/HXPDriver.{cpp,h}
|
||||
motorApp/NewportSrc/hxp_drivers.{cpp,h}
|
||||
motorApp/NewportSrc/hxp_error.h
|
||||
motorApp/op/adl/HXP_{extra,motors,moveAll}.adl
|
||||
|
||||
|
||||
Modification Log for R6-7
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
dbLoadTemplate("motor.substitutions.hxp")
|
||||
|
||||
HXPCreateController("HXP1", "192.168.1.42", 5001, 200, 1000)
|
||||
# A shorter, idle-poll period is desirable if the motors
|
||||
# are moved using HXP_moveAll.adl, since this period determines
|
||||
# how long it takes for the motor records to see that an
|
||||
# external move has been initiated.
|
||||
#!HXPCreateController("HXP1", "192.168.1.42", 5001, 200, 200)
|
||||
|
||||
#asynSetTraceIOMask("HXP1", 0, 2)
|
||||
#asynSetTraceMask("HXP1", 0, 255)
|
||||
|
||||
+77
-14
@@ -1,35 +1,98 @@
|
||||
record(mbbo,"$(P)$(R)CS") {
|
||||
field(DESC,"Coordinate System")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT,"@asynMask($(PORT) 0 0xFFFF)HXP_MOVE_COORD_SYS")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asynMask($(PORT) 0 0xFFFF)HXP_MOVE_COORD_SYS")
|
||||
field(ZRVL,"0")
|
||||
field(ZRST,"Work")
|
||||
field(ONVL,"1")
|
||||
field(ONST,"Tool")
|
||||
field(VAL, "0")
|
||||
field(PINI, "YES")
|
||||
field(PINI,"YES")
|
||||
}
|
||||
|
||||
record(ai,"$(P)$(R)STATUS") {
|
||||
field(DESC,"HXP Group Status")
|
||||
field(DTYP, "asynInt32")
|
||||
field(PINI, "1")
|
||||
field(DTYP,"asynInt32")
|
||||
field(PINI,"1")
|
||||
field(PREC,"0")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(INP,"@asyn($(PORT),0)HXP_STATUS")
|
||||
field(SCAN,"I/O Intr")
|
||||
field(INP, "@asyn($(PORT),0)HXP_STATUS")
|
||||
}
|
||||
|
||||
record(ai,"$(P)$(R)ERROR") {
|
||||
field(DESC,"HXP Group Error")
|
||||
field(DTYP, "asynInt32")
|
||||
field(DTYP,"asynInt32")
|
||||
field(PREC,"0")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(INP,"@asyn($(PORT),0)HXP_ERROR")
|
||||
field(SCAN,"I/O Intr")
|
||||
field(INP, "@asyn($(PORT),0)HXP_ERROR")
|
||||
}
|
||||
|
||||
record(stringin, "$(P)$(R)ERR_DESC") {
|
||||
field(DESC, "Error Description")
|
||||
field(DTYP, "asynOctetRead")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(INP, "@asyn($(PORT),0)HXP_ERROR_DESC")
|
||||
field(DESC,"Error Description")
|
||||
field(DTYP,"asynOctetRead")
|
||||
field(SCAN,"I/O Intr")
|
||||
field(INP, "@asyn($(PORT),0)HXP_ERROR_DESC")
|
||||
}
|
||||
|
||||
record(bo,"$(P)$(R)MOVE_ALL") {
|
||||
field(DESC,"Move all motors")
|
||||
field(DTYP,"asynInt32")
|
||||
field(ZNAM,"Off")
|
||||
field(ONAM,"On")
|
||||
field(OUT, "@asyn($(PORT),0)HXP_MOVE_ALL")
|
||||
}
|
||||
|
||||
record(ao,"$(P)$(R)T1") {
|
||||
field(DESC,"X target pos")
|
||||
field(DTYP,"asynFloat64")
|
||||
field(OUT, "@asyn($(PORT),0)HXP_MOVE_ALL_TARGET_X")
|
||||
field(PREC,"5")
|
||||
field(VAL, "0.0")
|
||||
field(PINI,"YES")
|
||||
}
|
||||
|
||||
record(ao,"$(P)$(R)T2") {
|
||||
field(DESC,"Y target pos")
|
||||
field(DTYP,"asynFloat64")
|
||||
field(OUT, "@asyn($(PORT),0)HXP_MOVE_ALL_TARGET_Y")
|
||||
field(PREC,"5")
|
||||
field(VAL, "0.0")
|
||||
field(PINI,"YES")
|
||||
}
|
||||
|
||||
record(ao,"$(P)$(R)T3") {
|
||||
field(DESC,"Z target pos")
|
||||
field(DTYP,"asynFloat64")
|
||||
field(OUT, "@asyn($(PORT),0)HXP_MOVE_ALL_TARGET_Z")
|
||||
field(PREC,"5")
|
||||
field(VAL, "12.0")
|
||||
field(PINI,"YES")
|
||||
}
|
||||
|
||||
record(ao,"$(P)$(R)T4") {
|
||||
field(DESC,"U target pos")
|
||||
field(DTYP,"asynFloat64")
|
||||
field(OUT, "@asyn($(PORT),0)HXP_MOVE_ALL_TARGET_U")
|
||||
field(PREC,"5")
|
||||
field(VAL, "0.0")
|
||||
field(PINI,"YES")
|
||||
}
|
||||
|
||||
record(ao,"$(P)$(R)T5") {
|
||||
field(DESC,"V target pos")
|
||||
field(DTYP,"asynFloat64")
|
||||
field(OUT, "@asyn($(PORT),0)HXP_MOVE_ALL_TARGET_V")
|
||||
field(PREC,"5")
|
||||
field(VAL, "0.0")
|
||||
field(PINI,"YES")
|
||||
}
|
||||
|
||||
record(ao,"$(P)$(R)T6") {
|
||||
field(DESC,"W target pos")
|
||||
field(DTYP,"asynFloat64")
|
||||
field(OUT, "@asyn($(PORT),0)HXP_MOVE_ALL_TARGET_W")
|
||||
field(PREC,"5")
|
||||
field(VAL, "0.0")
|
||||
field(PINI,"YES")
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,17 @@ HXPController::HXPController(const char *portName, const char *IPAddress, int IP
|
||||
IPAddress_ = epicsStrDup(IPAddress);
|
||||
IPPort_ = IPPort;
|
||||
|
||||
createParam(HXPMoveCoordSysString, asynParamInt32, &HXPMoveCoordSys_);
|
||||
createParam(HXPStatusString, asynParamInt32, &HXPStatus_);
|
||||
createParam(HXPErrorString, asynParamInt32, &HXPError_);
|
||||
createParam(HXPErrorDescString, asynParamOctet, &HXPErrorDesc_);
|
||||
createParam(HXPMoveCoordSysString, asynParamInt32, &HXPMoveCoordSys_);
|
||||
createParam(HXPStatusString, asynParamInt32, &HXPStatus_);
|
||||
createParam(HXPErrorString, asynParamInt32, &HXPError_);
|
||||
createParam(HXPErrorDescString, asynParamOctet, &HXPErrorDesc_);
|
||||
createParam(HXPMoveAllString, asynParamInt32, &HXPMoveAll_);
|
||||
createParam(HXPMoveAllTargetXString, asynParamFloat64, &HXPMoveAllTargetX_);
|
||||
createParam(HXPMoveAllTargetYString, asynParamFloat64, &HXPMoveAllTargetY_);
|
||||
createParam(HXPMoveAllTargetZString, asynParamFloat64, &HXPMoveAllTargetZ_);
|
||||
createParam(HXPMoveAllTargetUString, asynParamFloat64, &HXPMoveAllTargetU_);
|
||||
createParam(HXPMoveAllTargetVString, asynParamFloat64, &HXPMoveAllTargetV_);
|
||||
createParam(HXPMoveAllTargetWString, asynParamFloat64, &HXPMoveAllTargetW_);
|
||||
|
||||
// This socket is used for polling by the controller and all axes
|
||||
pollSocket_ = HXPTCP_ConnectToServer((char *)IPAddress, IPPort, HXP_POLL_TIMEOUT);
|
||||
@@ -131,6 +138,103 @@ HXPAxis* HXPController::getAxis(int axisNo)
|
||||
}
|
||||
|
||||
|
||||
/** Called when asyn clients call pasynInt32->write().
|
||||
* Extracts the function and axis number from pasynUser.
|
||||
* Sets the value in the parameter library.
|
||||
* If the function is HXPMoveAll_ then it calls moves all motors with a single command
|
||||
* For all other functions it calls asynMotorController::writeInt32.
|
||||
* Calls any registered callbacks for this pasynUser->reason and address.
|
||||
* \param[in] pasynUser asynUser structure that encodes the reason and address.
|
||||
* \param[in] value Value to write. */
|
||||
asynStatus HXPController::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
||||
{
|
||||
int function = pasynUser->reason;
|
||||
asynStatus status = asynSuccess;
|
||||
HXPAxis *pAxis = getAxis(pasynUser);
|
||||
static const char *functionName = "writeInt32";
|
||||
|
||||
/* 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 = setIntegerParam(pAxis->axisNo_, function, value);
|
||||
|
||||
if (function == HXPMoveAll_)
|
||||
{
|
||||
/* if value == 1: motors are moved
|
||||
if value == 0: nothing is done and parameter is simply reset */
|
||||
if (value == 1)
|
||||
{
|
||||
moveAll(pAxis);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call base class method */
|
||||
status = asynMotorController::writeInt32(pasynUser, value);
|
||||
}
|
||||
|
||||
/* Do callbacks so higher layers see any changes */
|
||||
callParamCallbacks(pAxis->axisNo_);
|
||||
if (status)
|
||||
asynPrint(pasynUser, ASYN_TRACE_ERROR,
|
||||
"%s:%s: error, status=%d function=%d, value=%d\n",
|
||||
driverName, functionName, status, function, value);
|
||||
else
|
||||
asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
|
||||
"%s:%s: function=%d, value=%d\n",
|
||||
driverName, functionName, function, value);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves all hexpod axes to new target positions
|
||||
*/
|
||||
int HXPController::moveAll(HXPAxis *pAxis)
|
||||
{
|
||||
int status;
|
||||
double x, y, z, u, v, w;
|
||||
|
||||
getDoubleParam(0, HXPMoveAllTargetX_, &x);
|
||||
getDoubleParam(0, HXPMoveAllTargetY_, &y);
|
||||
getDoubleParam(0, HXPMoveAllTargetZ_, &z);
|
||||
getDoubleParam(0, HXPMoveAllTargetU_, &u);
|
||||
getDoubleParam(0, HXPMoveAllTargetV_, &v);
|
||||
getDoubleParam(0, HXPMoveAllTargetW_, &w);
|
||||
|
||||
status = HXPHexapodMoveAbsolute(pAxis->moveSocket_, GROUP, "Work", x, y, z, u, v, w);
|
||||
|
||||
/* This is similar to what is done in HXPAxis::move() */
|
||||
if (status < 0)
|
||||
{
|
||||
/* Set the error */
|
||||
setIntegerParam(HXPError_, status);
|
||||
|
||||
/* Get the error string */
|
||||
HXPErrorStringGet(pAxis->moveSocket_, status, pAxis->errorDescFull_);
|
||||
|
||||
/* Trim the error string */
|
||||
strncpy(pAxis->errorDesc_, pAxis->errorDescFull_, 39);
|
||||
pAxis->errorDesc_[39] = 0;
|
||||
|
||||
/* Set the error description */
|
||||
setStringParam(HXPErrorDesc_, pAxis->errorDesc_);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the error */
|
||||
setIntegerParam(HXPError_, 0);
|
||||
setStringParam(HXPErrorDesc_, "");
|
||||
|
||||
/* If there was a way to force the motor record to switch to the move poll rate,
|
||||
this would be the place to do it. */
|
||||
}
|
||||
callParamCallbacks();
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// These are the HXPAxis methods
|
||||
|
||||
/** Creates a new HXPAxis object.
|
||||
@@ -263,7 +367,7 @@ asynStatus HXPAxis::move(double position, int relative, double baseVelocity, dou
|
||||
strncpy(errorDesc_, errorDescFull_, 39);
|
||||
errorDesc_[39] = 0;
|
||||
|
||||
/* */
|
||||
/* Set the error description */
|
||||
pC_->setStringParam(pC_->HXPErrorDesc_, errorDesc_);
|
||||
|
||||
}
|
||||
@@ -374,7 +478,6 @@ asynStatus HXPAxis::poll(bool *moving)
|
||||
|
||||
/* Set the axis done parameter */
|
||||
*moving = moving_;
|
||||
//if (deferredMove_) *moving = true;
|
||||
setIntegerParam(pC_->motorStatusDone_, *moving?0:1);
|
||||
|
||||
/*Test for states that mean we cannot move an axis (disabled, uninitialised, etc.)
|
||||
|
||||
@@ -16,6 +16,13 @@ USAGE... Motor driver support for the Newport Hexapod controller.
|
||||
#define HXPStatusString "HXP_STATUS"
|
||||
#define HXPErrorString "HXP_ERROR"
|
||||
#define HXPErrorDescString "HXP_ERROR_DESC"
|
||||
#define HXPMoveAllString "HXP_MOVE_ALL"
|
||||
#define HXPMoveAllTargetXString "HXP_MOVE_ALL_TARGET_X"
|
||||
#define HXPMoveAllTargetYString "HXP_MOVE_ALL_TARGET_Y"
|
||||
#define HXPMoveAllTargetZString "HXP_MOVE_ALL_TARGET_Z"
|
||||
#define HXPMoveAllTargetUString "HXP_MOVE_ALL_TARGET_U"
|
||||
#define HXPMoveAllTargetVString "HXP_MOVE_ALL_TARGET_V"
|
||||
#define HXPMoveAllTargetWString "HXP_MOVE_ALL_TARGET_W"
|
||||
|
||||
class HXPAxis : public asynMotorAxis
|
||||
{
|
||||
@@ -50,17 +57,30 @@ friend class HXPController;
|
||||
class HXPController : public asynMotorController {
|
||||
public:
|
||||
HXPController(const char *portName, const char *HXPPortName, int numAxes, double movingPollPeriod, double idlePollPeriod);
|
||||
|
||||
/* These are the methods that we override from asynMotorDriver */
|
||||
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); /* needed for implementation of moveAll */
|
||||
void report(FILE *fp, int level);
|
||||
HXPAxis* getAxis(asynUser *pasynUser);
|
||||
HXPAxis* getAxis(int axisNo);
|
||||
|
||||
/* These are the methods that are new to this class */
|
||||
int moveAll(HXPAxis* pAxis);
|
||||
|
||||
protected:
|
||||
#define FIRST_HXP_PARAM HXPMoveCoordSys_
|
||||
int HXPMoveCoordSys_;
|
||||
int HXPStatus_;
|
||||
int HXPError_;
|
||||
int HXPErrorDesc_;
|
||||
#define LAST_HXP_PARAM HXPErrorDesc_
|
||||
int HXPMoveAll_;
|
||||
int HXPMoveAllTargetX_;
|
||||
int HXPMoveAllTargetY_;
|
||||
int HXPMoveAllTargetZ_;
|
||||
int HXPMoveAllTargetU_;
|
||||
int HXPMoveAllTargetV_;
|
||||
int HXPMoveAllTargetW_;
|
||||
#define LAST_HXP_PARAM HXPMoveAllTargetW_
|
||||
|
||||
#define NUM_HXP_PARAMS ((int) (&LAST_HXP_PARAM - &FIRST_HXP_PARAM + 1))
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user