Compare commits

..

3 Commits
1.4.0 ... 1.5.0

Author SHA1 Message Date
cff64f5ecf Added new feature to set deadband
All checks were successful
Test And Build / Lint (push) Successful in 6s
Test And Build / Build (push) Successful in 12s
The field SPDB can now be populated via either the substitutions file or
from inside the driver (using the motorPositionDeadband paramLib entry).
2025-09-09 16:50:26 +02:00
7a0de4e9d9 Perform callParamCallbacks even if movement watchdog timed out
All checks were successful
Test And Build / Lint (push) Successful in 6s
Test And Build / Build (push) Successful in 5s
2025-08-14 17:15:21 +02:00
566728c57c Fixed error in README.md
All checks were successful
Test And Build / Lint (push) Successful in 5s
Test And Build / Build (push) Successful in 5s
2025-08-12 09:15:55 +02:00
5 changed files with 45 additions and 4 deletions

View File

@@ -257,7 +257,7 @@ This method should not be called in the driver code itself if a poll is needed -
- `startMovTimeoutWatchdog`: Starts a watchdog for the movement time. This watchdog compares the actual time spent in a movement operation with an expected time, which is calculated based on the distance of the current and the target position.
- `checkMovTimeoutWatchdog`: Check if the watchdog timed out.
- `setWatchdogEnabled`: Enables / disables the watchdog. This function is also available in the IOC shell.
- `setOffsetMovTimeout`: Set a linear offset for the expected movement time. This function is also available in the IOC shell.
- `setOffsetMovTimeout`: Set a constant offset for the expected movement time. This function is also available in the IOC shell.
- `setScaleMovTimeout`: Set a scaling factor for the expected movement time. This function is also available in the IOC shell.
#### msgPrintControl.h

View File

@@ -41,6 +41,7 @@ record(motor,"$(INSTR)$(M)")
field(PINI,"NO")
field(DHLM, "$(DHLM=0)")
field(DLLM, "$(DLLM=0)")
field(SPDB, "$(SPDB=0)")
field(TWV,"1")
field(RTRY,"0")
field(RDBD, "$(RDBD=10e300)") # Suppress retries and overshoot stop commands
@@ -238,6 +239,27 @@ record(ao, "$(INSTR)$(M):PushDLLM2Field") {
field(PINI, "NO")
}
# This record pair reads the parameter library value for "motorPositionDeadband"
# and pushes it to the motor record field "SPDP". This can be used to the position
# deadband from the hardware
# The implementation strategy is taken from https://epics.anl.gov/tech-talk/2022/msg00464.php.
# This record is coupled to the parameter library via motorPositionDeadband -> MOTOR_POSITION_DEADBAND.
record(ai, "$(INSTR)$(M):SPDB_RBV")
{
field(DTYP, "asynFloat64")
field(VAL, "$(SPDP=0)")
field(INP, "@asyn($(CONTROLLER),$(AXIS)) MOTOR_POSITION_DEADBAND")
field(SCAN, "I/O Intr")
field(FLNK, "$(INSTR)$(M):PushSPDB2Field")
field(PINI, "NO")
}
record(ao, "$(INSTR)$(M):PushSPDB2Field") {
field(DOL, "$(INSTR)$(M):SPDB_RBV NPP")
field(OUT, "$(INSTR)$(M).SPDB")
field(OMSL, "closed_loop")
field(PINI, "NO")
}
# This record pair reads the parameter library value for "motorVeloFromDriver_"
# and pushes it to the motor record field "VELO". This can be used to read the speed value
# from the hardware and correspondingly update the motor record from the driver.

View File

@@ -283,9 +283,12 @@ asynStatus sinqAxis::forcedPoll(bool *moving) {
pSinqA_->wasMoving = *moving;
}
// Check and update the watchdog
if (checkMovTimeoutWatchdog(*moving) != asynSuccess) {
return asynError;
// Check and update the watchdog as well as the general poll status IF the
// poll did not fail already.
if (poll_status == asynSuccess) {
if (checkMovTimeoutWatchdog(*moving) != asynSuccess) {
poll_status = asynError;
}
}
// According to the function documentation of asynMotorAxis::poll, this

View File

@@ -92,6 +92,7 @@ struct sinqControllerImpl {
int motorAcclFromDriver;
int motorHighLimitFromDriver;
int motorLowLimitFromDriver;
int motorPositionDeadband;
int adaptivePolling;
int encoderType;
};
@@ -267,6 +268,17 @@ sinqController::sinqController(const char *portName,
exit(-1);
}
status = createParam("MOTOR_POSITION_DEADBAND", asynParamFloat64,
&pSinqC_->motorPositionDeadband);
if (status != asynSuccess) {
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
"parameter failed with %s).\nTerminating IOC",
portName, __PRETTY_FUNCTION__, __LINE__,
stringifyAsynStatus(status));
exit(-1);
}
status = createParam("MOTOR_ENABLE_MOV_WATCHDOG", asynParamInt32,
&pSinqC_->motorEnableMovWatchdog);
if (status != asynSuccess) {
@@ -699,6 +711,9 @@ int sinqController::motorHighLimitFromDriver() {
int sinqController::motorLowLimitFromDriver() {
return pSinqC_->motorLowLimitFromDriver;
}
int sinqController::motorPositionDeadband() {
return pSinqC_->motorPositionDeadband;
}
int sinqController::adaptivePolling() { return pSinqC_->adaptivePolling; }
int sinqController::encoderType() { return pSinqC_->encoderType; }

View File

@@ -315,6 +315,7 @@ class HIDDEN sinqController : public asynMotorController {
int motorAcclFromDriver();
int motorHighLimitFromDriver();
int motorLowLimitFromDriver();
int motorPositionDeadband();
int adaptivePolling();
int encoderType();