Improved homing doc, fixed wrong setting of motorStatusHomed and added check to move
This commit is contained in:
@@ -280,9 +280,9 @@ bookkeeping tasks before and after calling `doPoll`:
|
||||
message is waiting in the temporary buffer, set `motorStatusProblem` to true,
|
||||
otherwise to false. If an old error message is waiting in the temporary
|
||||
buffer, but `doPoll` returned `asynSuccess`, overwrite the paramLib entry for
|
||||
`motorMessageText` with the old error message.
|
||||
`motorErrorMessage` with the old error message.
|
||||
- Run `callParamCallbacks`
|
||||
- Reset `motorMessageText` AFTER updating the PVs. This makes sure that the
|
||||
- Reset `motorErrorMessage` AFTER updating the PVs. This makes sure that the
|
||||
error message is shown for at least one poll cycle.
|
||||
- Return the status of `doPoll`
|
||||
- `motorPosition`: Returns the parameter library value of the motor position,
|
||||
|
||||
@@ -109,7 +109,7 @@ record(ao,"$(INSTR)$(M):RecResolution") {
|
||||
# This record contains messages from the driver (usually error messages).
|
||||
# The macro ERRORMSGSIZE can be used to set the maximum length of the message.
|
||||
# if not provided, a default value of 200 is used.
|
||||
# This record is coupled to the parameter library via motorMessageText -> MOTOR_MESSAGE_TEXT.
|
||||
# This record is coupled to the parameter library via motorErrorMessage -> MOTOR_MESSAGE_TEXT.
|
||||
record(waveform, "$(INSTR)$(M):ErrorMessage") {
|
||||
alias("$(INSTR)$(M)-MsgTxt") # Old PV name, aliased for backwards compatibility
|
||||
field(DTYP, "asynOctetRead")
|
||||
|
||||
@@ -72,7 +72,7 @@ sinqAxis::sinqAxis(class sinqController *pC, int axisNo)
|
||||
Initialize the parameter library entry for the motor message text, because
|
||||
it is read during the first poll before it has been written to.
|
||||
*/
|
||||
status = setStringParam(pC_->motorMessageText(), "");
|
||||
status = setStringParam(pC_->motorErrorMessage(), "");
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d:\nFATAL ERROR "
|
||||
@@ -143,7 +143,7 @@ sinqAxis::sinqAxis(class sinqController *pC, int axisNo)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Set the homing-related flags
|
||||
// Motor is assumed to not being in a homing run at IOC startup.
|
||||
status = setIntegerParam(pC_->motorStatusHome(), 0);
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
@@ -154,7 +154,9 @@ sinqAxis::sinqAxis(class sinqController *pC, int axisNo)
|
||||
pC_->stringifyAsynStatus(status));
|
||||
exit(-1);
|
||||
}
|
||||
status = setIntegerParam(pC_->motorStatusHomed(), 0);
|
||||
|
||||
// Motor is assumed to not be at the home position at IOC startup.
|
||||
status = setIntegerParam(pC_->motorStatusAtHome(), 0);
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d:\nFATAL ERROR "
|
||||
@@ -164,7 +166,9 @@ sinqAxis::sinqAxis(class sinqController *pC, int axisNo)
|
||||
pC_->stringifyAsynStatus(status));
|
||||
exit(-1);
|
||||
}
|
||||
status = setIntegerParam(pC_->motorStatusAtHome(), 0);
|
||||
|
||||
// Motor is assumed to not have been homed in the past.
|
||||
status = setIntegerParam(pC_->motorStatusHomed(), 0);
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d:\nFATAL ERROR "
|
||||
@@ -232,14 +236,14 @@ asynStatus sinqAxis::forcedPoll(bool *moving) {
|
||||
pSinqA_->lastPollTime = ts;
|
||||
|
||||
/*
|
||||
If the "motorMessageText" record currently contains an error message, it
|
||||
If the "motorErrorMessage" record currently contains an error message, it
|
||||
should be shown for at least one poll period. To assure this, it is read out
|
||||
here from the paramLib into "waitingMessage". If no new error message was
|
||||
added to the parameter library at the end of the poll cycle, the
|
||||
"waitingMessage" is briefly put into the paramLib again, then the PVs are
|
||||
updated and then the message text is cleared again.
|
||||
*/
|
||||
getAxisParamChecked(this, motorMessageText,
|
||||
getAxisParamChecked(this, motorErrorMessage,
|
||||
static_cast<char *>(waitingMessage));
|
||||
|
||||
// Clear the communication
|
||||
@@ -271,16 +275,16 @@ asynStatus sinqAxis::forcedPoll(bool *moving) {
|
||||
If doPoll cleared the error message paramLib entry, but an old message
|
||||
is still waiting, set the old message.
|
||||
*/
|
||||
getAxisParamChecked(this, motorMessageText,
|
||||
getAxisParamChecked(this, motorErrorMessage,
|
||||
static_cast<char *>(newMessage));
|
||||
if (newMessage[0] == '\0') {
|
||||
setAxisParamChecked(this, motorMessageText,
|
||||
setAxisParamChecked(this, motorErrorMessage,
|
||||
static_cast<char *>(waitingMessage));
|
||||
}
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
} else {
|
||||
// No errors are waiting -> Clear everything.
|
||||
setAxisParamChecked(this, motorMessageText, "");
|
||||
setAxisParamChecked(this, motorErrorMessage, "");
|
||||
setAxisParamChecked(this, motorStatusProblem, false);
|
||||
}
|
||||
|
||||
@@ -330,7 +334,7 @@ asynStatus sinqAxis::forcedPoll(bool *moving) {
|
||||
Delete the error message AFTER updating the PVs so it is not there anymore
|
||||
during the next poll.
|
||||
*/
|
||||
setAxisParamChecked(this, motorMessageText, "");
|
||||
setAxisParamChecked(this, motorErrorMessage, "");
|
||||
|
||||
return poll_status;
|
||||
}
|
||||
@@ -348,9 +352,23 @@ asynStatus sinqAxis::move(double position, int relative, double minVelocity,
|
||||
// Status of parameter library operations
|
||||
asynStatus status = asynSuccess;
|
||||
double motorRecRes = 0.0;
|
||||
char encType[pC_->MAXBUF_] = {0};
|
||||
int motorStatHomed = 0;
|
||||
|
||||
// =========================================================================
|
||||
|
||||
/*
|
||||
Check if the motor is allowed to move: If the motor hasn't been homed in the
|
||||
past and has an incremental encoder, it needs to be homed first!
|
||||
*/
|
||||
getAxisParamChecked(this, encoderType, &encType);
|
||||
getAxisParamChecked(this, motorStatusHomed, &motorStatHomed);
|
||||
if (strcmp(encType, IncrementalEncoder) == 0 && motorStatHomed == 0) {
|
||||
setAxisParamChecked(this, motorErrorMessage,
|
||||
"Motor needs to be homed first.");
|
||||
return asynError;
|
||||
}
|
||||
|
||||
// Store the target position internally
|
||||
getAxisParamChecked(this, motorRecResolution, &motorRecRes);
|
||||
pSinqA_->targetPosition = position * motorRecRes;
|
||||
@@ -367,7 +385,6 @@ asynStatus sinqAxis::move(double position, int relative, double minVelocity,
|
||||
|
||||
// Since the move command was successfull, we assume that the motor has
|
||||
// started its movement.
|
||||
setAxisParamChecked(this, motorStatusHomed, false);
|
||||
setAxisParamChecked(this, motorStatusAtHome, false);
|
||||
|
||||
// Needed for adaptive polling
|
||||
@@ -410,7 +427,7 @@ asynStatus sinqAxis::home(double minVelocity, double maxVelocity,
|
||||
|
||||
} else if (status == asynError) {
|
||||
// asynError means that we tried to home an absolute encoder
|
||||
setAxisParamChecked(this, motorMessageText,
|
||||
setAxisParamChecked(this, motorErrorMessage,
|
||||
"Can't home a motor with absolute encoder");
|
||||
|
||||
status = assertConnected();
|
||||
@@ -547,7 +564,7 @@ asynStatus sinqAxis::setVeloFields(double velo, double vbas, double vmax) {
|
||||
"vmax=%lf.\n",
|
||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||
vbas, vmax);
|
||||
setAxisParamChecked(this, motorMessageText,
|
||||
setAxisParamChecked(this, motorErrorMessage,
|
||||
"Lower speed limit must not be smaller than "
|
||||
"upper speed limit. Please call the support.");
|
||||
return asynError;
|
||||
@@ -561,7 +578,7 @@ asynStatus sinqAxis::setVeloFields(double velo, double vbas, double vmax) {
|
||||
velo, vbas, vmax);
|
||||
|
||||
setAxisParamChecked(
|
||||
this, motorMessageText,
|
||||
this, motorErrorMessage,
|
||||
"Speed is not inside limits. Set a new valid speed and try "
|
||||
"to move the motor. Otherwise, please call the support.");
|
||||
return asynError;
|
||||
@@ -704,7 +721,7 @@ asynStatus sinqAxis::checkMovTimeoutWatchdog(bool moving) {
|
||||
}
|
||||
|
||||
setAxisParamChecked(
|
||||
this, motorMessageText,
|
||||
this, motorErrorMessage,
|
||||
"Exceeded expected arrival time. Check if the axis is blocked.");
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
} else {
|
||||
|
||||
@@ -111,10 +111,15 @@ class HIDDEN sinqAxis : public asynMotorAxis {
|
||||
* @brief Perform some standardized operations before and after the concrete
|
||||
`doMove` implementation.
|
||||
|
||||
* Wrapper around `doMove` which calculates the (absolute) target position
|
||||
and stores it in the member variable `targetPosition_`. This member variable
|
||||
is e.g. used for the movement watchdog. Afterwards, it calls and returns
|
||||
`doMove`.
|
||||
Wrapper around `doMove` which performs the following operations:
|
||||
- If the motor has an incremental encoder and the paramLib entry for
|
||||
motorStatusHomed returns 0, the move command is not forwarded if the motor
|
||||
has an incremental encoder.
|
||||
- It calculates the (absolute) target position and stores it in the member
|
||||
variable `targetPosition_`. This member variable is e.g. used for the
|
||||
movement watchdog.
|
||||
|
||||
Afterwards, it calls and returns `doMove`.
|
||||
*
|
||||
* @param position Forwarded to `doMove`.
|
||||
* @param relative Forwarded to `doMove`.
|
||||
@@ -154,16 +159,24 @@ class HIDDEN sinqAxis : public asynMotorAxis {
|
||||
within the driver.
|
||||
|
||||
* - `motorStatusHome_`: This flag should be set to `1` while the motor is
|
||||
actively moving toward its home position and to `0` when the home position
|
||||
is reached.
|
||||
*
|
||||
* - `motorStatusHomed_`: This flag should be set to `0` at the start of a
|
||||
homing command and to 1 once the home position is reached.
|
||||
*
|
||||
* - `motorStatusAtHome_`: This flag is similar to `motorStatusHomed_`, but
|
||||
in addition it should also be `1` when the motor is at its home position,
|
||||
but wasn't actively homed in order to get there.
|
||||
*
|
||||
actively moving toward its home position and to `0` otherwise.
|
||||
|
||||
* - `motorStatusAtHome_`: This flag should be set to `0` at the start of a
|
||||
homing command and to 1 once the home position is reached. This is obviously
|
||||
the case right after a homing run. Corresponds to bit 7 of the MSTA field of
|
||||
the motor record.
|
||||
|
||||
* - `motorStatusHomed_`: This flag should be set to `1` if it is known that
|
||||
that the motor has been homed since the last power cycle of the controller.
|
||||
|
||||
There are two ways the motor record can get this information:
|
||||
1) If a home run has been performed by the driver itself via
|
||||
`sinqAxis::home` (this function).
|
||||
2) If the controller reports that the motor has been homed in the past
|
||||
(possibly before the IOC startup). This information needs to be provided by
|
||||
the controller (e.g. in an "init" function). Likewise, if the driver detects
|
||||
a power cycle of the controller, the driver must set this field back to `0`.
|
||||
|
||||
* This function performs the following operations in the given order:
|
||||
*
|
||||
* - Call `doHome()` and forward the parameters
|
||||
@@ -178,8 +191,8 @@ class HIDDEN sinqAxis : public asynMotorAxis {
|
||||
* - If `doHome()` returned anything else: Forward the status.
|
||||
*
|
||||
* The flags `motorStatusHome_`, `motorStatusHomed_` and
|
||||
`motorStatusAtHome_` are set to their idle values (0, 1 and 1 respectively)
|
||||
in the `forcedPoll())` method once the homing procedure is finished.
|
||||
`motorStatusAtHome_` are set to 0, 1 and 1 respectively in the
|
||||
`forcedPoll())` method once the homing procedure is finished.
|
||||
*
|
||||
* @param minVelocity Forwarded to `doHome`.
|
||||
* @param maxVelocity Forwarded to `doHome`.
|
||||
|
||||
@@ -76,7 +76,7 @@ struct sinqControllerImpl {
|
||||
These integers are indices to paramLib entries and are populated when the
|
||||
parameters are created. See the documentation in db/sinqMotor.db.
|
||||
*/
|
||||
int motorMessageText;
|
||||
int motorErrorMessage;
|
||||
int motorReset;
|
||||
int motorEnable;
|
||||
int motorEnableRBV;
|
||||
@@ -130,7 +130,7 @@ sinqController::sinqController(const char *portName,
|
||||
.timeoutEvents = {},
|
||||
.maxSubsequentTimeouts = 10,
|
||||
.maxSubsequentTimeoutsExceeded = false,
|
||||
.motorMessageText = 0,
|
||||
.motorErrorMessage = 0,
|
||||
.motorReset = 0,
|
||||
.motorEnable = 0,
|
||||
.motorEnableRBV = 0,
|
||||
@@ -180,7 +180,7 @@ sinqController::sinqController(const char *portName,
|
||||
// This text is used to forward status messages to NICOS and in turn to the
|
||||
// user.
|
||||
status = createParam("MOTOR_MESSAGE_TEXT", asynParamOctet,
|
||||
&pSinqC_->motorMessageText);
|
||||
&pSinqC_->motorErrorMessage);
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\" => %s, line %d:\nFATAL ERROR (creating a "
|
||||
@@ -504,7 +504,7 @@ asynStatus sinqController::couldNotParseResponse(const char *command,
|
||||
}
|
||||
|
||||
setAxisParamChecked(
|
||||
axis, motorMessageText,
|
||||
axis, motorErrorMessage,
|
||||
"Could not interpret controller response. Please call the support");
|
||||
setAxisParamChecked(axis, motorStatusCommsError, true);
|
||||
|
||||
@@ -526,7 +526,7 @@ asynStatus sinqController::paramLibAccessFailed(asynStatus status,
|
||||
|
||||
// Log the error message and try to propagate it. If propagating fails,
|
||||
// there is nothing we can do here anyway.
|
||||
setStringParam(motorMessageText(),
|
||||
setStringParam(motorErrorMessage(),
|
||||
"Accessing paramLib failed. Please call the support.");
|
||||
}
|
||||
|
||||
@@ -597,7 +597,7 @@ asynStatus sinqController::checkComTimeoutWatchdog(sinqAxis *axis) {
|
||||
asynStatus status =
|
||||
checkComTimeoutWatchdog(axis->axisNo(), errorMessage, MAXBUF_);
|
||||
if (status == asynError) {
|
||||
setAxisParamChecked(axis, motorMessageText, errorMessage);
|
||||
setAxisParamChecked(axis, motorErrorMessage, errorMessage);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -645,7 +645,7 @@ asynStatus sinqController::checkMaxSubsequentTimeouts(int timeoutNo,
|
||||
asynStatus status = checkMaxSubsequentTimeouts(timeoutNo, axis->axisNo(),
|
||||
motorMessage, MAXBUF_);
|
||||
if (status == asynError) {
|
||||
setAxisParamChecked(axis, motorMessageText, motorMessage);
|
||||
setAxisParamChecked(axis, motorErrorMessage, motorMessage);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -709,7 +709,7 @@ asynStatus sinqController::setThresholdComTimeout(time_t comTimeoutWindow,
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
int sinqController::motorMessageText() { return pSinqC_->motorMessageText; }
|
||||
int sinqController::motorErrorMessage() { return pSinqC_->motorErrorMessage; }
|
||||
int sinqController::motorReset() { return pSinqC_->motorReset; }
|
||||
int sinqController::motorEnable() { return pSinqC_->motorEnable; }
|
||||
int sinqController::motorEnableRBV() { return pSinqC_->motorEnableRBV; }
|
||||
|
||||
@@ -101,7 +101,7 @@ class HIDDEN sinqController : public asynMotorController {
|
||||
*
|
||||
* If accessing the parameter library failed (return status !=
|
||||
asynSuccess), calling this function writes a standardized message to both
|
||||
the IOC shell and the motorMessageText PV. It then returns the input
|
||||
the IOC shell and the motorErrorMessage PV. It then returns the input
|
||||
status.
|
||||
*
|
||||
* @param status Status of the failed parameter library access
|
||||
@@ -278,7 +278,7 @@ class HIDDEN sinqController : public asynMotorController {
|
||||
* the readback velocity instead of that written into the VELO / JVEL
|
||||
* fields.
|
||||
*
|
||||
* @return int
|
||||
* @return Index of the paramLib entry
|
||||
*/
|
||||
int motorVelocity() { return motorVelocity_; }
|
||||
int motorVelBase() { return motorVelBase_; }
|
||||
@@ -307,10 +307,24 @@ class HIDDEN sinqController : public asynMotorController {
|
||||
int motorStatusDirection() { return motorStatusDirection_; }
|
||||
int motorStatusDone() { return motorStatusDone_; }
|
||||
int motorStatusHighLimit() { return motorStatusHighLimit_; }
|
||||
/**
|
||||
* @brief Set to 1 if the motor is currently homing and 0 otherwise.
|
||||
*
|
||||
* See docstring of the sinqAxis::home function.
|
||||
*
|
||||
* @return Index of the paramLib entry
|
||||
*/
|
||||
int motorStatusAtHome() { return motorStatusAtHome_; }
|
||||
int motorStatusSlip() { return motorStatusSlip_; }
|
||||
int motorStatusPowerOn() { return motorStatusPowerOn_; }
|
||||
int motorStatusFollowingError() { return motorStatusFollowingError_; }
|
||||
/**
|
||||
* @brief Set to 1 if the motor is currently at its home position.
|
||||
*
|
||||
* See docstring of the sinqAxis::home function.
|
||||
*
|
||||
* @return Index of the paramLib entry
|
||||
*/
|
||||
int motorStatusHome() { return motorStatusHome_; }
|
||||
int motorStatusHasEncoder() { return motorStatusHasEncoder_; }
|
||||
int motorStatusProblem() { return motorStatusProblem_; }
|
||||
@@ -318,6 +332,13 @@ class HIDDEN sinqController : public asynMotorController {
|
||||
int motorStatusGainSupport() { return motorStatusGainSupport_; }
|
||||
int motorStatusCommsError() { return motorStatusCommsError_; }
|
||||
int motorStatusLowLimit() { return motorStatusLowLimit_; }
|
||||
/**
|
||||
* @brief Set to 1 if the motor has been homed in the past and 0 otherwise
|
||||
*
|
||||
* See docstring of the sinqAxis::home function.
|
||||
*
|
||||
* @return Index of the paramLib entry
|
||||
*/
|
||||
int motorStatusHomed() { return motorStatusHomed_; }
|
||||
|
||||
// Parameters for passing additional motor record information to the driver
|
||||
@@ -327,7 +348,7 @@ class HIDDEN sinqController : public asynMotorController {
|
||||
|
||||
// Accessors for additional PVs defined in sinqController (which are hidden
|
||||
// in pSinqC_)
|
||||
int motorMessageText();
|
||||
int motorErrorMessage();
|
||||
int motorReset();
|
||||
int motorEnable();
|
||||
int motorEnableRBV();
|
||||
|
||||
Reference in New Issue
Block a user