After reimplementing the pmacV3 driver using the sinqMotor parent class,

quite some changes have accumulated. Besides various code changes, especially the documentation has
been improved.
This commit is contained in:
2024-11-20 11:29:20 +01:00
parent 89bbbedaee
commit 5502c39219
9 changed files with 603 additions and 108 deletions

View File

@@ -3,23 +3,39 @@ This class extends asynMotorAxis by some features used in SINQ.
Stefan Mathis, November 2024
*/
#ifndef __SINQDRIVER
#define __SINQDRIVER
#include "asynMotorAxis.h"
class epicsShareClass sinqAxis : public asynMotorAxis {
public:
sinqAxis(class sinqController *pC_, int axis);
/**
This function is executed at the very first poll after the IOC startup. If
it returns anything else than 'asynSuccess', the function is evaluated again
after 100 ms until it succeeds. Every 10 trials a warning is emitted.
* @brief Construct a new sinqAxis object
*
* @param pC_ Pointer to the controller of the axis
* @param axis Index of the axis
*/
asynStatus atFirstPoll();
sinqAxis(class sinqController *pC_, int axisNo);
/**
Wrapper around doPoll which performs the following operations;
* @brief This function is executed once during the very first poll.
*
* This function is executed at the very first poll after the IOC startup.
If it returns anything else than 'asynSuccess', the function is evaluated
again after 100 ms until it succeeds. Every 10 trials a warning is emitted.
The default implementation just returns asynSuccess and is meant to be
overwritten by concrete driver implementations.
*
* @return asynStatus
*/
virtual asynStatus atFirstPoll();
/**
* @brief Perform some standardized operation before and after the concrete
`doPoll` implementation.
*
* Wrapper around doPoll which performs the following operations:
Before calling doPoll:
- Try to execute atFirstPoll once (and retry, if that failed)
@@ -28,35 +44,121 @@ class epicsShareClass sinqAxis : public asynMotorAxis {
doPoll returned asynSuccess
- Run `callParamCallbacks`
- Return the status of `doPoll`
*
* @param moving Forwarded to `doPoll`.
* @return asynStatus Forward the status of `doPoll`, unless one of
the parameter library operation fails (in that case, returns the failed
operation status).
*/
asynStatus poll(bool *moving);
/**
Implementation of the "proper", device-specific poll method. This method
should be implemented by a child class of sinqAxis.
* @brief Implementation of the "proper", device-specific poll method. This
method should be implemented by a child class of sinqAxis.
*
* @param moving Should be set to true, if the axis is moving,
* and false otherwise.
* @return asynStatus
*/
asynStatus doPoll(bool *moving);
virtual asynStatus doPoll(bool *moving);
/**
Wrapper around move which calculates the (absolute) target position and
stores it in the parameter library. After that, it calls and returns doMove
* @brief Perform some standardized operation before and after the concrete
`doMove` implementation.
* Wrapper around `doMove` which calculates the (absolute) target position
and stores it in the parameter library. After that, it calls and returns
`doMove`.
*
* @param position Forwarded to `doMove`.
* @param relative Forwarded to `doMove`.
* @param minVelocity Forwarded to `doMove`.
* @param maxVelocity Forwarded to `doMove`.
* @param acceleration Forwarded to `doMove`.
* @return asynStatus Forward the status of `doMove`, unless one of
the parameter library operation fails (in that case, returns the failed
operation status).
*/
asynStatus move(double position, int relative, double minVelocity,
double maxVelocity, double acceleration);
/**
Implementation of the "proper", device-specific poll method. This method
should be implemented by a child class of sinqAxis.
*/
asynStatus doMove(double position, int relative, double minVelocity,
double maxVelocity, double acceleration);
* @brief Implementation of the "proper", device-specific move method. This
method should be implemented by a child class of sinqAxis.
*
* @param position Target position `VAL` from the motor record
* @param relative Specifies, whether the target position is
relative or absolute.
* @param minVelocity Minimum velocity VMIN from the motor record
* @param maxVelocity Maximum velocity VMAX from the motor record
* @param acceleration Acceleration ACCEL from the motor record
* @return asynStatus
*/
virtual asynStatus doMove(double position, int relative, double minVelocity,
double maxVelocity, double acceleration);
/**
* @brief Perform some standardized operation before and after the concrete
`doHome` implementation.
*
* Wrapper around move which calculates the (absolute) target position and
stores it in the parameter library. The target position in a homing maneuver
is calculated as follows:
if abs(current position - high limit) > abs(current position - low limit)
{
high limit
}
else
{
low limit
}
After that, it calls and returns doHome.
*
* @param minVelocity Forwarded to `doHome`.
* @param maxVelocity Forwarded to `doHome`.
* @param acceleration Forwarded to `doHome`.
* @param forwards Forwarded to `doHome`.
* @return asynStatus Forward the status of `doHome`, unless one of
the parameter library operation fails (in that case, returns the failed
operation status).
*/
asynStatus home(double minVelocity, double maxVelocity, double acceleration,
int forwards);
/**
* @brief Implementation of the "proper", device-specific home method. This
method should be implemented by a child class of sinqAxis.
*
* @param minVelocity Minimum velocity VMIN from the motor record
* @param maxVelocity Maximum velocity VMAX from the motor record
* @param acceleration Acceleration ACCEL from the motor record
* @param forwards Is 1, if the motor record field HOMF was used
to trigger the homing, and 0, if HOMR was used.
* @return asynStatus
*/
virtual asynStatus doHome(double minVelocity, double maxVelocity,
double acceleration, int forwards);
/**
* @brief Start the watchdog for the movement, if the watchdog is not
disabled. See the documentation of checkMovTimeoutWatchdog for more details.
*
* @return asynStatus If one of the parameter library operations
used to get the values for the timeout calculation failed, return that
status, otherwise return asynSuccess.
*/
asynStatus startMovTimeoutWatchdog();
/**
* @brief Check if the watchdog timed out
*
Manages a timeout mechanism for the movement:
If the movement takes too long, create an error message and return
asynError. The watchdog is started when moving switches from "false" to
"true" and stopped when moving switches from "true" to "false". At the
watchdog start, the estimated movement time is calculated as
If the axis is moving and the movement takes too long, create an error
message and return asynError. The watchdog is started when moving switches
from "false" to "true" and stopped when moving switches from "true" to
"false". At the watchdog start, the estimated movement time is calculated as
t = offsetMovTimeout_ + scaleMovTime_ * [timeContSpeed + 2*timeAccel]
@@ -68,24 +170,57 @@ class epicsShareClass sinqAxis : public asynMotorAxis {
The values motorTargetPosition, motorVelBase, motorAccel and
positionAtMovementStart are taken from the parameter library. Therefore it
is necessary to populate them before using this function. If they are not
given, both speed and velocity are assumed to be infinity. This means that
given, both speed and velocity are assumed to be infinite. This means that
timeContSpeed and/or timeAcc are set to zero. motorTargetPosition is
populated automatically when using the doMove function.
The values offsetMovTimeout_ and scaleMovTimeout_ can be set directly from
the IOC shell with the functions setScaleMovTimeout and setOffsetMovTimeout,
if sinqMotor is loaded via the "require" mechanism.
*
* @param moving Should be the "moving" status from `poll` /
`doPoll`.
* @return asynStatus Return asynError, if the watchdog timed out,
and asynSuccess otherwise.
*/
asynStatus movementTimeoutWatchdog(bool moving);
asynStatus checkMovTimeoutWatchdog(bool moving);
// Setter for offsetMovTimeout
asynStatus setOffsetMovTimeout(time_t offsetMovTimeout) {
/**
* @brief Enable / disable the watchdog. Also available in the IOC shell
* (see "extern C" section in sinqController.cpp).
*
* If enable is set to false and the watchdog is currently running, this
* function stops it immediately.
*
* @param enabled
* @return asynStatus
*/
virtual asynStatus setWatchdogEnabled(bool enable);
/**
* @brief Set the offsetMovTimeout. Also available in the IOC shell
* (see "extern C" section in sinqController.cpp).
*
See documentation of `checkMovTimeoutWatchdog` for details.
*
* @param offsetMovTimeout Offset (in seconds)
* @return asynStatus
*/
virtual asynStatus setOffsetMovTimeout(time_t offsetMovTimeout) {
offsetMovTimeout_ = offsetMovTimeout;
return asynSuccess;
}
// Setter for scaleMovTimeout
asynStatus setScaleMovTimeout(time_t scaleMovTimeout) {
/**
* @brief Set the scaleMovTimeout. Also available in the IOC shell
* (see "extern C" section in sinqController.cpp).
*
See documentation of `checkMovTimeoutWatchdog` for details.
*
* @param scaleMovTimeout Scaling factor (in seconds)
* @return asynStatus
*/
virtual asynStatus setScaleMovTimeout(time_t scaleMovTimeout) {
scaleMovTimeout_ = scaleMovTimeout;
return asynSuccess;
}
@@ -100,6 +235,7 @@ class epicsShareClass sinqAxis : public asynMotorAxis {
time_t expectedArrivalTime_;
time_t offsetMovTimeout_;
double scaleMovTimeout_;
bool watchdogEnabled_;
bool watchdogMovActive_;
private: