Improved homing doc, fixed wrong setting of motorStatusHomed and added check to move
This commit is contained in:
@@ -109,11 +109,11 @@ 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 motorErrorMessage -> MOTOR_MESSAGE_TEXT.
|
||||
# This record is coupled to the parameter library via motorErrorMessage -> MOTOR_ERROR_MESSAGE.
|
||||
record(waveform, "$(INSTR)$(M):ErrorMessage") {
|
||||
alias("$(INSTR)$(M)-MsgTxt") # Old PV name, aliased for backwards compatibility
|
||||
field(DTYP, "asynOctetRead")
|
||||
field(INP, "@asyn($(CONTROLLER),$(AXIS),1) MOTOR_MESSAGE_TEXT")
|
||||
field(INP, "@asyn($(CONTROLLER),$(AXIS),1) MOTOR_ERROR_MESSAGE")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(ERRORMSGSIZE=200)") # Should be the same as MAXBUF in the driver code
|
||||
field(SCAN, "I/O Intr")
|
||||
|
||||
@@ -35,6 +35,11 @@ struct sinqAxisImpl {
|
||||
Store the time since the last poll
|
||||
*/
|
||||
epicsTimeStamp lastPollTime;
|
||||
|
||||
// For this time in seconds, any error message will be kept alive in the
|
||||
// parameter library.
|
||||
time_t errorDisplayDuration;
|
||||
epicsTimeStamp errorInitialAppearance;
|
||||
};
|
||||
|
||||
sinqAxis::sinqAxis(class sinqController *pC, int axisNo)
|
||||
@@ -49,6 +54,8 @@ sinqAxis::sinqAxis(class sinqController *pC, int axisNo)
|
||||
.targetPosition = 0.0,
|
||||
.wasMoving = false,
|
||||
.lastPollTime = lastPollTime,
|
||||
.errorDisplayDuration = 2,
|
||||
.errorInitialAppearance = lastPollTime,
|
||||
});
|
||||
}()) {
|
||||
|
||||
@@ -281,6 +288,14 @@ asynStatus sinqAxis::forcedPoll(bool *moving) {
|
||||
setAxisParamChecked(this, motorErrorMessage,
|
||||
static_cast<char *>(waitingMessage));
|
||||
}
|
||||
|
||||
bool statProblem = false;
|
||||
getAxisParamChecked(this, motorStatusProblem, &statProblem);
|
||||
if (!statProblem) {
|
||||
// The error initially appeared at this point in time
|
||||
pSinqA_->errorInitialAppearance = ts;
|
||||
}
|
||||
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
} else {
|
||||
// No errors are waiting -> Clear everything.
|
||||
@@ -330,11 +345,12 @@ asynStatus sinqAxis::forcedPoll(bool *moving) {
|
||||
poll_status = pl_status;
|
||||
}
|
||||
|
||||
/*
|
||||
Delete the error message AFTER updating the PVs so it is not there anymore
|
||||
during the next poll.
|
||||
*/
|
||||
setAxisParamChecked(this, motorErrorMessage, "");
|
||||
// Delete the error message after the display duration has been exceeded.
|
||||
epicsTimeStamp errorRemovalTime = pSinqA_->errorInitialAppearance;
|
||||
epicsTimeAddSeconds(&errorRemovalTime, pSinqA_->errorDisplayDuration);
|
||||
if (epicsTimeLessThanEqual(&ts, &errorRemovalTime) == 0) {
|
||||
setAxisParamChecked(this, motorErrorMessage, "");
|
||||
}
|
||||
|
||||
return poll_status;
|
||||
}
|
||||
@@ -370,6 +386,10 @@ asynStatus sinqAxis::move(double position, int relative, double minVelocity,
|
||||
pC_->portName, axisNo(), __PRETTY_FUNCTION__, __LINE__);
|
||||
setAxisParamChecked(this, motorErrorMessage,
|
||||
"Motor needs to be homed / referenced first.");
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
epicsTimeStamp ts;
|
||||
epicsTimeGetCurrent(&ts);
|
||||
pSinqA_->errorInitialAppearance = ts;
|
||||
return pC_->callParamCallbacks();
|
||||
}
|
||||
|
||||
@@ -746,6 +766,11 @@ asynStatus sinqAxis::setScaleMovTimeout(time_t scaleMovTimeout) {
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus sinqAxis::setErrorDisplayDuration(time_t errorDisplayDuration) {
|
||||
pSinqA_->errorDisplayDuration = errorDisplayDuration;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
bool sinqAxis::wasMoving() { return pSinqA_->wasMoving; }
|
||||
|
||||
void sinqAxis::setWasMoving(bool wasMoving) { pSinqA_->wasMoving = wasMoving; }
|
||||
@@ -903,12 +928,63 @@ static void setScaleMovTimeoutCallFunc(const iocshArgBuf *args) {
|
||||
|
||||
// =============================================================================
|
||||
|
||||
// This function is made known to EPICS in sinqMotor.dbd and is called by EPICS
|
||||
// in order to register all functions in the IOC shell
|
||||
/**
|
||||
* @brief Set the (minimum) error display duration (FFI implementation)
|
||||
*
|
||||
* @param portName Name of the controller
|
||||
* @param axisNo Axis number
|
||||
* @param errorDisplayDuration Minimum display duration
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus setErrorDisplayDuration(const char *portName, int axisNo,
|
||||
double errorDisplayDuration) {
|
||||
|
||||
sinqController *pC;
|
||||
pC = (sinqController *)findAsynPortDriver(portName);
|
||||
if (pC == nullptr) {
|
||||
errlogPrintf("Controller \"%s\" => %s, line %d:\nPort %s not found.",
|
||||
portName, __PRETTY_FUNCTION__, __LINE__, portName);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
asynMotorAxis *asynAxis = pC->getAxis(axisNo);
|
||||
sinqAxis *axis = dynamic_cast<sinqAxis *>(asynAxis);
|
||||
if (axis == nullptr) {
|
||||
errlogPrintf("Controller \"%s\" => %s, line %d:\nAxis %d does not "
|
||||
"exist or is not an instance of sinqAxis.",
|
||||
portName, __PRETTY_FUNCTION__, __LINE__, axisNo);
|
||||
}
|
||||
|
||||
return axis->setErrorDisplayDuration(errorDisplayDuration);
|
||||
}
|
||||
|
||||
static const iocshArg setErrorDisplayDurationArg0 = {"Controller port name",
|
||||
iocshArgString};
|
||||
static const iocshArg setErrorDisplayDurationArg1 = {"Axis number",
|
||||
iocshArgInt};
|
||||
static const iocshArg setErrorDisplayDurationArg2 = {
|
||||
"(Minimum) error display duration", iocshArgDouble};
|
||||
static const iocshArg *const setErrorDisplayDurationArgs[] = {
|
||||
&setErrorDisplayDurationArg0, &setErrorDisplayDurationArg1,
|
||||
&setErrorDisplayDurationArg2};
|
||||
static const iocshFuncDef setErrorDisplayDurationDef = {
|
||||
"setErrorDisplayDuration", 3, setErrorDisplayDurationArgs,
|
||||
"Specify an offset (in seconds) for the movement timeout watchdog"};
|
||||
|
||||
static void settErrorDisplayDurationCallFunc(const iocshArgBuf *args) {
|
||||
setErrorDisplayDuration(args[0].sval, args[1].ival, args[2].dval);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
// This function is made known to EPICS in sinqMotor.dbd and is called by
|
||||
// EPICS in order to register all functions in the IOC shell
|
||||
static void sinqAxisRegister(void) {
|
||||
iocshRegister(&setOffsetMovTimeoutDef, setOffsetMovTimeoutCallFunc);
|
||||
iocshRegister(&setScaleMovTimeoutDef, setScaleMovTimeoutCallFunc);
|
||||
iocshRegister(&setWatchdogEnabledDef, setWatchdogEnabledCallFunc);
|
||||
iocshRegister(&setErrorDisplayDurationDef,
|
||||
settErrorDisplayDurationCallFunc);
|
||||
}
|
||||
epicsExportRegistrar(sinqAxisRegister);
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ class HIDDEN sinqAxis : public asynMotorAxis {
|
||||
|
||||
/**
|
||||
* @brief Enable / disable the watchdog. Also available in the IOC shell
|
||||
* (see "extern C" section in sinqController.cpp).
|
||||
* (see "extern C" section in sinqAxis.cpp).
|
||||
*
|
||||
* If enable is set to false and the watchdog is currently running, this
|
||||
* function stops it immediately.
|
||||
@@ -349,7 +349,7 @@ class HIDDEN sinqAxis : public asynMotorAxis {
|
||||
|
||||
/**
|
||||
* @brief Set the offsetMovTimeout. Also available in the IOC shell
|
||||
* (see "extern C" section in sinqController.cpp).
|
||||
* (see "extern C" section in sinqAxis.cpp).
|
||||
*
|
||||
* See documentation of `checkMovTimeoutWatchdog` for details.
|
||||
*
|
||||
@@ -360,7 +360,7 @@ class HIDDEN sinqAxis : public asynMotorAxis {
|
||||
|
||||
/**
|
||||
* @brief Set the scaleMovTimeout. Also available in the IOC shell
|
||||
* (see "extern C" section in sinqController.cpp).
|
||||
* (see "extern C" section in sinqAxis.cpp).
|
||||
*
|
||||
See documentation of `checkMovTimeoutWatchdog` for details.
|
||||
*
|
||||
@@ -369,6 +369,18 @@ class HIDDEN sinqAxis : public asynMotorAxis {
|
||||
*/
|
||||
virtual asynStatus setScaleMovTimeout(time_t scaleMovTimeout);
|
||||
|
||||
/**
|
||||
* @brief Set the errorDisplayDuration. Also available in the IOC shell
|
||||
* (see "extern C" section in sinqAxis.cpp).
|
||||
*
|
||||
This time in seconds define for which time an error will be displayed after
|
||||
its root cause has been resolved.
|
||||
*
|
||||
* @param errorDisplayDuration Error display time (in seconds)
|
||||
* @return asynStatus
|
||||
*/
|
||||
virtual asynStatus setErrorDisplayDuration(time_t errorDisplayDuration);
|
||||
|
||||
/**
|
||||
* @brief Return the axis number of this axis
|
||||
*
|
||||
|
||||
@@ -176,10 +176,10 @@ sinqController::sinqController(const char *portName,
|
||||
|
||||
// =========================================================================;
|
||||
|
||||
// MOTOR_MESSAGE_TEXT corresponds to the PV definition inside sinqMotor.db.
|
||||
// MOTOR_ERROR_MESSAGE corresponds to the PV definition inside sinqMotor.db.
|
||||
// This text is used to forward status messages to NICOS and in turn to the
|
||||
// user.
|
||||
status = createParam("MOTOR_MESSAGE_TEXT", asynParamOctet,
|
||||
status = createParam("MOTOR_ERROR_MESSAGE", asynParamOctet,
|
||||
&pSinqC_->motorErrorMessage);
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
|
||||
@@ -24,7 +24,7 @@ Stefan Mathis, November 2024
|
||||
#include <memory>
|
||||
|
||||
#define motorMessageIsFromDriverString "MOTOR_MESSAGE_DRIVER"
|
||||
#define motorMessageTextString "MOTOR_MESSAGE_TEXT"
|
||||
#define motorMessageTextString "MOTOR_ERROR_MESSAGE"
|
||||
#define IncrementalEncoder "incremental"
|
||||
#define AbsoluteEncoder "absolute"
|
||||
#define NoEncoder "none"
|
||||
|
||||
Reference in New Issue
Block a user