323 lines
12 KiB
C++
323 lines
12 KiB
C++
/*
|
|
This class extends asynMotorAxis by some features used in SINQ.
|
|
|
|
Stefan Mathis, November 2024
|
|
*/
|
|
|
|
#ifndef sinqAxis_H
|
|
#define sinqAxis_H
|
|
#include "asynMotorAxis.h"
|
|
|
|
class epicsShareClass sinqAxis : public asynMotorAxis {
|
|
public:
|
|
/**
|
|
* @brief Construct a new sinqAxis object
|
|
*
|
|
* @param pC_ Pointer to the controller of the axis
|
|
* @param axis Index of the axis
|
|
*/
|
|
sinqAxis(class sinqController *pC_, int axisNo);
|
|
|
|
/**
|
|
* @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)
|
|
|
|
After calling doPoll:
|
|
|
|
- Reset motorStatusProblem_, motorStatusCommsError_ and motorMessageText_ if
|
|
doPoll returned asynSuccess
|
|
|
|
- If the movement timeout watchdog has been started, check it.
|
|
|
|
- The flags `motorStatusHome_`, `motorStatusHomed_` and
|
|
`motorStatusAtHome_` are set to their idle values (0, 1 and 1 respectively)
|
|
in the `poll()` method once the homing procedure is finished. See the
|
|
documentation of the `home()` method for more details.
|
|
|
|
- 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);
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
virtual asynStatus doPoll(bool *moving);
|
|
|
|
/**
|
|
* @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);
|
|
|
|
/**
|
|
* @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 Wrapper around doHome which handles the homing-related flags
|
|
*
|
|
* The homing procedure of the motor record is controlled by the following
|
|
* parameter library flags:
|
|
*
|
|
* - `motorMoveToHome_`: Setting this flag to `1` indicates to EPICS that a
|
|
homing procedure should start and can therefore be used to start homing from
|
|
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.
|
|
*
|
|
* This function performs the following operations in the given order:
|
|
*
|
|
* - Call `doHome()` and forward the parameters
|
|
*
|
|
* - If `doHome()` returned asynSuccess: Set `motorStatusHome_` to `1`,
|
|
`motorStatusHomed_` to `0` and `motorStatusAtHome_` to `0`.
|
|
*
|
|
* - If `doHome()` returned asynError: This means that the motor cannot be
|
|
homed because the encoder is absolute. Set a corresponding error message,
|
|
but return asynSuccess in order to avoid any automatic retries by asyn.
|
|
|
|
* - 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 `poll()` method once the homing procedure is finished.
|
|
*
|
|
* @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. If the motor
|
|
cannot be homed because it has an absolute encoder, this function should
|
|
return asynError.
|
|
*
|
|
* @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 This function is called when the PV "$(INSTR)$(M):Reset" is set to
|
|
* any value. This method should be implemented by a child class of
|
|
* sinqAxis.
|
|
*
|
|
* @return asynStatus
|
|
*/
|
|
virtual asynStatus reset();
|
|
|
|
/**
|
|
* @brief This function enables / disables an axis. It should be implemented
|
|
* by a child class of sinqAxis.
|
|
*
|
|
* The concrete implementation should (but doesn't need to) follow the
|
|
* convetion that a value of 0 disables the axis and any other value enables
|
|
* it.
|
|
*
|
|
* @param on
|
|
* @return asynStatus
|
|
*/
|
|
virtual asynStatus enable(bool on);
|
|
|
|
/**
|
|
* @brief Populate the motor record fields VELO, VBAS and VMAX
|
|
*
|
|
* Populates the speed fields of the motor record. If the param lib
|
|
* entry motorCanSetSpeed_ (connected to the PV x:VariableSpeed) is set to
|
|
* 1, VBAS and VMAX are set to min and max respectively. Otherwise, they are
|
|
* set to val. Additionally, the speed itself is set to velo.
|
|
*
|
|
* The units of the inputs are engineering units (EGU) per second (e.g. mm/s
|
|
* if the EGU is mm).
|
|
*
|
|
* If the given configuration is invalid (min > max, velo < min, velo > max)
|
|
* and the motor is configured as a variable speed motor (param lib entry
|
|
* motorCanSetSpeed_ is 1), this function returns an asynError.
|
|
*
|
|
* @param velo Actual velocity (EGU / s)
|
|
* @param vbas Minimum allowed velocity (EGU / s)
|
|
* @param velo Maximum allowed velocity (EGU / s)
|
|
*
|
|
* @return asynStatus
|
|
*/
|
|
virtual asynStatus setVeloFields(double velo, double vbas, double vmax);
|
|
|
|
/**
|
|
* @brief Populate the ACCL field of the motor record
|
|
*
|
|
* Populates the acceleration field of the motor record with the given
|
|
* value. If accl is not positive, this function does not set the value and
|
|
* returns an asynError.
|
|
*
|
|
* The unit of the input is engineering units (EGU) per second squared (e.g.
|
|
* mm/s^2 if the EGU is mm).
|
|
*
|
|
* @param accl Actual acceleration (EGU / s^2)
|
|
* @return asynStatus
|
|
*/
|
|
virtual asynStatus setAcclField(double accl);
|
|
|
|
/**
|
|
* @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 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]
|
|
|
|
with
|
|
|
|
timeContSpeed = abs(motorTargetPosition - motorPosition) / motorVelBase
|
|
timeAcc = motorVelBase / motorAccel
|
|
|
|
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 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 checkMovTimeoutWatchdog(bool moving);
|
|
|
|
/**
|
|
* @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;
|
|
}
|
|
|
|
/**
|
|
* @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;
|
|
}
|
|
|
|
friend class sinqController;
|
|
|
|
protected:
|
|
// Internal variables used in the movement timeout watchdog
|
|
time_t expectedArrivalTime_;
|
|
time_t offsetMovTimeout_;
|
|
double scaleMovTimeout_;
|
|
bool watchdogMovActive_;
|
|
// Store the motor target position for the movement time calculation
|
|
double targetPosition_;
|
|
|
|
private:
|
|
sinqController *pC_;
|
|
};
|
|
|
|
#endif
|