Prototype for version 0.3

This commit is contained in:
2024-12-04 13:38:13 +01:00
parent 6656841a01
commit 86006e408a
5 changed files with 196 additions and 147 deletions

View File

@ -393,54 +393,6 @@ asynStatus sinqAxis::startMovTimeoutWatchdog() {
watchdogMovActive_ = true;
/*
The motor record resolution (index motorRecResolution_ in the parameter
library, MRES in the motor record) is NOT a conversion factor between
user units (e.g. mm) and motor units (e.g. encoder steps), but a scaling
factor defining the resolution of the position readback field RRBV. This
is due to an implementation detail inside EPICS described here:
https://epics.anl.gov/tech-talk/2018/msg00089.php
https://github.com/epics-modules/motor/issues/8
Basically, the position value in the parameter library is a double which
is then truncated to an integer in devMotorAsyn.c (because it was
originally meant for converting from engineering units to encoder steps,
which are by definition integer values). Therefore, if we want a
precision of 1 millimeter, we need to set MRES to 1. If we want one of
1 micrometer, we need to set MRES to 0.001. The readback value needs to
be multiplied with MRES to get the actual value.
In the driver, we use user units. Therefore, when we interact with the
parameter library, we need to account for MRES. This means:
- When writing position or speed to the parameter library, we divide the
value by the motor record resolution.
- When reading position or speed from the parameter library, we multiply
the value with the motor record resolution.
Index and motor record field are coupled as follows:
The parameter motorRecResolution_ is coupled to the field MRES of the
motor record in the following manner:
- In sinqMotor.db, the PV (motor_record_pv_name) MOTOR_REC_RESOLUTION
is defined as a copy of the field (motor_record_pv_name).MRES:
record(ao,"$(P)$(M):Resolution") {
field(DESC, "$(M) resolution")
field(DOL, "$(P)$(M).MRES CP MS")
field(OMSL, "closed_loop")
field(DTYP, "asynFloat64")
field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_REC_RESOLUTION")
field(PREC, "$(PREC)")
}
- The PV name MOTOR_REC_RESOLUTION is coupled in asynMotorController.h
to the constant motorRecResolutionString
- ... which in turn is assigned to motorRecResolution_ in
asynMotorController.cpp This way of making the field visible to the
driver is described here:
https://epics.anl.gov/tech-talk/2020/msg00378.php This is a one-way
coupling, changes to the parameter library via setDoubleParam are NOT
transferred to (motor_record_pv_name).MRES or to
(motor_record_pv_name):Resolution.
NOTE: This function must not be called in the constructor (e.g. in order
to save the read result to the member variable earlier), since the
parameter library is updated at a later stage!

View File

@ -251,7 +251,7 @@ asynStatus sinqController::readInt32(asynUser *pasynUser, epicsInt32 *value) {
return asynSuccess;
} else if (pasynUser->reason == motorCanDisable_) {
// By default, motors cannot be disabled
*value = 0;
*value = 1;
return asynSuccess;
} else {
return asynMotorController::readInt32(pasynUser, value);

View File

@ -67,7 +67,7 @@ class epicsShareClass sinqController : public asynMotorController {
* @param value Read-out value
* @return asynStatus
*/
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
/**
* @brief Error handling in case accessing the parameter library failed.