Safety commit
This commit is contained in:
12
README.md
12
README.md
@ -1,5 +1,9 @@
|
|||||||
# detectorTower
|
# detectorTower
|
||||||
|
|
||||||
|
## <span style="color:red">Please read the documentation of sinqMotor first: https://git.psi.ch/sinq-epics-modules/sinqmotor</span>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
This is a driver for the detector tower which is based on the Turbo PMAC driver (https://git.psi.ch/sinq-epics-modules/turboPmac). It consists of the following three objects:
|
This is a driver for the detector tower which is based on the Turbo PMAC driver (https://git.psi.ch/sinq-epics-modules/turboPmac). It consists of the following three objects:
|
||||||
- `detectorTowerAxis`: This is a virtual axis which controls multiple physical motors in order to provide a synchronized movement.
|
- `detectorTowerAxis`: This is a virtual axis which controls multiple physical motors in order to provide a synchronized movement.
|
||||||
- `detectorTowerController`: This is an expanded variant of `turboPmacController` provided by the Turbo PMAC library linked above.It is needed to operate a `detectorTowerAxis`, but it can also be used to operate a "normal" `turboPmacAxis`.
|
- `detectorTowerController`: This is an expanded variant of `turboPmacController` provided by the Turbo PMAC library linked above.It is needed to operate a `detectorTowerAxis`, but it can also be used to operate a "normal" `turboPmacAxis`.
|
||||||
@ -68,12 +72,12 @@ dbLoadRecords("$(sinqMotor_DB)/asynRecord.db","P=$(INSTR)$(NAME),PORT=$(ASYN_POR
|
|||||||
|
|
||||||
### Substitution file
|
### Substitution file
|
||||||
|
|
||||||
From the perspective of EPICS, the main detector flight tube axis and the auxiliary axes are independent axes and therefore each axis needs its own parametrizatioin in the substitution file. If additional axes are used in the axis, they are parametrized as usual:
|
From the perspective of EPICS, the main detector flight tube axis and the auxiliary axes are independent axes and therefore each axis needs its own parametrization in the substitution file. If additional axes are used in the axis, they are parametrized as usual:
|
||||||
|
```
|
||||||
detectorTowerAxis("$(NAME)",1, 2, 3);
|
detectorTowerAxis("$(NAME)",1, 2, 3);
|
||||||
turboPmacAxis("$(NAME)",4);
|
turboPmacAxis("$(NAME)",4);
|
||||||
turboPmacAxis("$(NAME)",5);
|
turboPmacAxis("$(NAME)",5);
|
||||||
|
```
|
||||||
```
|
```
|
||||||
file "$(SINQDBPATH)"
|
file "$(SINQDBPATH)"
|
||||||
{
|
{
|
||||||
@ -91,6 +95,8 @@ Note that the speed of the detector tower axes 1, 2 and 3 cannot be set. Setting
|
|||||||
|
|
||||||
## Developer guide
|
## Developer guide
|
||||||
|
|
||||||
|
### Code architecture
|
||||||
|
|
||||||
The code is designed around the `detectorTowerAxis`, which controls the angle of the beam guide and acts as a "master" axis. Other movements are realized as auxiliary axes (e.g. for the vertical lift offset and the tilt offset). The `detectorTowerAxis` has pointers to all associated auxiliary axes and (as described above) its IOC shell constructor also builds the associated auxiliary axes.
|
The code is designed around the `detectorTowerAxis`, which controls the angle of the beam guide and acts as a "master" axis. Other movements are realized as auxiliary axes (e.g. for the vertical lift offset and the tilt offset). The `detectorTowerAxis` has pointers to all associated auxiliary axes and (as described above) its IOC shell constructor also builds the associated auxiliary axes.
|
||||||
|
|
||||||
The `doPoll` implementation for `detectorTowerAxis` queries the status of both the `detectorTowerAxis` itself and all associated auxiliary axes. If any of the axes is moving, the `detectorTowerAxis` is set to "moving" as well. In turn, the `doPoll` implementation of a `auxiliaryAxis` checks if its associated `detectorTowerAxis` is moving and sets its own movement status accordingly.
|
The `doPoll` implementation for `detectorTowerAxis` queries the status of both the `detectorTowerAxis` itself and all associated auxiliary axes. If any of the axes is moving, the `detectorTowerAxis` is set to "moving" as well. In turn, the `doPoll` implementation of a `auxiliaryAxis` checks if its associated `detectorTowerAxis` is moving and sets its own movement status accordingly.
|
||||||
|
@ -55,10 +55,6 @@ auxiliaryAxis::auxiliaryAxis(detectorTowerController *pC, int axisNo)
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize all member variables
|
|
||||||
// Assumed to be not ready by default, this is overwritten in the next poll
|
|
||||||
targetPosition_ = 0.0;
|
|
||||||
|
|
||||||
// Register the hook function during construction of the first axis object
|
// Register the hook function during construction of the first axis object
|
||||||
if (axes.empty()) {
|
if (axes.empty()) {
|
||||||
initHookRegister(&epicsInithookFunction);
|
initHookRegister(&epicsInithookFunction);
|
||||||
@ -241,3 +237,5 @@ asynStatus auxiliaryAxis::stop(double acceleration) {
|
|||||||
|
|
||||||
return rw_status;
|
return rw_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asynStatus auxiliaryAxis::reset() { return dTA_->reset(); };
|
||||||
|
@ -63,10 +63,16 @@ class auxiliaryAxis : public turboPmacAxis {
|
|||||||
asynStatus doMove(double position, int relative, double min_velocity,
|
asynStatus doMove(double position, int relative, double min_velocity,
|
||||||
double max_velocity, double acceleration);
|
double max_velocity, double acceleration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Call the reset function of the associated `detectorTowerAxis`.
|
||||||
|
*
|
||||||
|
* @return asynStatus
|
||||||
|
*/
|
||||||
|
asynStatus reset();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
detectorTowerController *pC_;
|
detectorTowerController *pC_;
|
||||||
detectorTowerAxis *dTA_;
|
detectorTowerAxis *dTA_;
|
||||||
double targetPosition_;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class detectorTowerAxis;
|
friend class detectorTowerAxis;
|
||||||
|
@ -78,7 +78,6 @@ detectorTowerAxis::detectorTowerAxis(detectorTowerController *pC, int axisNo,
|
|||||||
// Initialize all member variables
|
// Initialize all member variables
|
||||||
// Assumed to be not ready by default, this is overwritten in the next poll
|
// Assumed to be not ready by default, this is overwritten in the next poll
|
||||||
error_ = 0;
|
error_ = 0;
|
||||||
targetPosition_ = 0.0;
|
|
||||||
receivedTarget_ = false;
|
receivedTarget_ = false;
|
||||||
startingDeferredMovement_ = false;
|
startingDeferredMovement_ = false;
|
||||||
deferredMovementWait_ = 0.1; // seconds
|
deferredMovementWait_ = 0.1; // seconds
|
||||||
@ -191,17 +190,11 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the previous motor position
|
// Read the previous motor position
|
||||||
pl_status = pC_->getDoubleParam(axisNo_, pC_->motorPosition(),
|
pl_status = motorPosition(&previousBeamTiltAngle);
|
||||||
&previousBeamTiltAngle);
|
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorPosition_", axisNo_,
|
return pl_status;
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform from EPICS to motor coordinates (see comment in
|
|
||||||
// turboPmacAxis::atFirstPoll)
|
|
||||||
previousBeamTiltAngle = previousBeamTiltAngle * motorRecResolution;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Query the following information:
|
Query the following information:
|
||||||
- In-position flag
|
- In-position flag
|
||||||
@ -224,7 +217,7 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
|||||||
&liftOffsetHighLimit, &liftOffsetLowLimit, &tiltOffsetHighLimit,
|
&liftOffsetHighLimit, &liftOffsetLowLimit, &tiltOffsetHighLimit,
|
||||||
&tiltOffsetLowLimit);
|
&tiltOffsetLowLimit);
|
||||||
if (nvals != 10) {
|
if (nvals != 10) {
|
||||||
return pC_->errMsgCouldNotParseResponse(command, response, axisNo_,
|
return pC_->couldNotParseResponse(command, response, axisNo_,
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,12 +705,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
|||||||
double liftOffsetPosition =
|
double liftOffsetPosition =
|
||||||
detectorHeight + detectorRadius * sin(beamTiltAngle);
|
detectorHeight + detectorRadius * sin(beamTiltAngle);
|
||||||
|
|
||||||
pl_status = pC_->setDoubleParam(liftAxisNo, pC_->motorPosition(),
|
pl_status = setMotorPosition(liftOffsetPosition);
|
||||||
liftOffsetPosition / motorRecResolution);
|
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorPosition_",
|
return pl_status;
|
||||||
liftAxisNo, __PRETTY_FUNCTION__,
|
|
||||||
__LINE__);
|
|
||||||
}
|
}
|
||||||
pl_status = pC_->setDoubleParam(liftAxisNo, pC_->motorHighLimitFromDriver(),
|
pl_status = pC_->setDoubleParam(liftAxisNo, pC_->motorHighLimitFromDriver(),
|
||||||
liftOffsetHighLimit);
|
liftOffsetHighLimit);
|
||||||
@ -738,14 +728,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
// There exists no readback value for tiltOffsetAxis_, hence we just set the
|
// There exists no readback value for tiltOffsetAxis_, hence we just set the
|
||||||
// current position to the target position.
|
// current position to the target position.
|
||||||
pl_status = tiltOffsetAxis_->setDoubleParam(
|
tiltOffsetAxis_->setMotorPosition(tiltOffsetAxis_->targetPosition_);
|
||||||
pC_->motorPosition(),
|
|
||||||
tiltOffsetAxis_->targetPosition_ / motorRecResolution);
|
|
||||||
|
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorPosition_",
|
return pl_status;
|
||||||
tiltAxisNo, __PRETTY_FUNCTION__,
|
|
||||||
__LINE__);
|
|
||||||
}
|
}
|
||||||
pl_status = pC_->setDoubleParam(tiltAxisNo, pC_->motorHighLimitFromDriver(),
|
pl_status = pC_->setDoubleParam(tiltAxisNo, pC_->motorHighLimitFromDriver(),
|
||||||
tiltOffsetHighLimit);
|
tiltOffsetHighLimit);
|
||||||
@ -764,11 +749,9 @@ asynStatus detectorTowerAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
// Transform from motor to EPICS coordinates (see comment in
|
// Transform from motor to EPICS coordinates (see comment in
|
||||||
// turboPmacAxis::init())
|
// turboPmacAxis::init())
|
||||||
pl_status = setDoubleParam(pC_->motorPosition(),
|
pl_status = setMotorPosition(beamTiltAngle);
|
||||||
beamTiltAngle / motorRecResolution);
|
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorPosition_", axisNo_,
|
return pl_status;
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pl_status = setIntegerParam(pC_->positionStateRBV(), positionState);
|
pl_status = setIntegerParam(pC_->positionStateRBV(), positionState);
|
||||||
@ -988,7 +971,7 @@ detectorTowerAxis::toggleWorkingChangerState(bool toChangingPosition) {
|
|||||||
return rw_status;
|
return rw_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
asynStatus detectorTowerAxis::reset() {
|
asynStatus detectorTowerAxis::doReset() {
|
||||||
|
|
||||||
char response[pC_->MAXBUF_];
|
char response[pC_->MAXBUF_];
|
||||||
asynStatus pl_status = asynSuccess;
|
asynStatus pl_status = asynSuccess;
|
||||||
@ -1106,10 +1089,6 @@ asynStatus detectorTowerCreateAxis(const char *portName, int axisDetectorTower,
|
|||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Same procedure as for the CreateController function, but for the axis
|
|
||||||
itself.
|
|
||||||
*/
|
|
||||||
static const iocshArg CreateAxisArg0 = {"Controller name (e.g. mcu1)",
|
static const iocshArg CreateAxisArg0 = {"Controller name (e.g. mcu1)",
|
||||||
iocshArgString};
|
iocshArgString};
|
||||||
static const iocshArg CreateAxisArg1 = {"Number of the detector angle axis",
|
static const iocshArg CreateAxisArg1 = {"Number of the detector angle axis",
|
||||||
|
@ -8,10 +8,6 @@
|
|||||||
// https://en.cppreference.com/w/cpp/language/class.
|
// https://en.cppreference.com/w/cpp/language/class.
|
||||||
class detectorTowerController;
|
class detectorTowerController;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class detectorTowerAxis : public turboPmacAxis {
|
class detectorTowerAxis : public turboPmacAxis {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -97,12 +93,12 @@ class detectorTowerAxis : public turboPmacAxis {
|
|||||||
asynStatus toggleWorkingChangerState(bool toChangingPosition);
|
asynStatus toggleWorkingChangerState(bool toChangingPosition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset the axis error
|
* @brief Implementation of the `doReset` method of sinqAxis
|
||||||
*
|
*
|
||||||
* @param on
|
* @param on
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus reset();
|
asynStatus doReset();
|
||||||
|
|
||||||
// If true, either this axis or one of the auxiliaryAxis attached to it
|
// If true, either this axis or one of the auxiliaryAxis attached to it
|
||||||
// received a movement command.
|
// received a movement command.
|
||||||
@ -121,7 +117,6 @@ class detectorTowerAxis : public turboPmacAxis {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
detectorTowerController *pC_;
|
detectorTowerController *pC_;
|
||||||
double targetPosition_;
|
|
||||||
int error_;
|
int error_;
|
||||||
auxiliaryAxis *tiltOffsetAxis_;
|
auxiliaryAxis *tiltOffsetAxis_;
|
||||||
auxiliaryAxis *liftOffsetAxis_;
|
auxiliaryAxis *liftOffsetAxis_;
|
||||||
|
Reference in New Issue
Block a user