Compare commits

...

3 Commits

Author SHA1 Message Date
7a96ed2b71 Fixed bug: Wrong scale used before
Some checks failed
Test And Build / Lint (push) Failing after 3s
Test And Build / Build (push) Successful in 8s
The correct scale from counts to engeering units is Qxx00.
2025-09-10 11:52:51 +02:00
cf43a1c57a Updated to sinqMotor 1.5 to get deadband feature
Some checks failed
Test And Build / Lint (push) Failing after 3s
Test And Build / Build (push) Successful in 7s
2025-09-09 16:52:19 +02:00
85317e24cd Deadband check in driver code 2025-09-09 13:43:11 +02:00
3 changed files with 58 additions and 23 deletions

View File

@@ -70,12 +70,13 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
axes.push_back(this); axes.push_back(this);
} }
pTurboPmacA_ = std::make_unique<turboPmacAxisImpl>( pTurboPmacA_ = std::make_unique<turboPmacAxisImpl>((turboPmacAxisImpl){
(turboPmacAxisImpl){.waitForHandshake = false, .waitForHandshake = false,
.enableDisable = false, .enableDisable = false,
.timeAtHandshake = 0, .timeAtHandshake = 0,
.axisStatus = 0, .axisStatus = 0,
.needInit = false}); .needInit = false,
});
// Provide initial values for some parameter library entries // Provide initial values for some parameter library entries
status = pC_->setIntegerParam(axisNo_, pC_->rereadEncoderPosition(), 0); status = pC_->setIntegerParam(axisNo_, pC_->rereadEncoderPosition(), 0);
@@ -132,8 +133,16 @@ asynStatus turboPmacAxis::init() {
double motorVelocity = 0.0; double motorVelocity = 0.0;
double motorVmax = 0.0; double motorVmax = 0.0;
double motorAccel = 0.0; double motorAccel = 0.0;
int acoDelay = 0.0; // Offset time for the movement watchdog caused by
// the air cushions in milliseconds. // Conversion factor between engineering units (EU) and encoder counts
double counts_to_eu = 0.0;
// Deadband in counts. Can be a fraction of a count, hence double.
double deadband_counts = 0.0;
// Offset time for the movement watchdog caused by the air cushions in
// milliseconds.
int acoDelay = 0.0;
int axStatus = 0; int axStatus = 0;
// The parameter library takes some time to be initialized. Therefore we // The parameter library takes some time to be initialized. Therefore we
@@ -163,12 +172,16 @@ asynStatus turboPmacAxis::init() {
/* /*
Read out the axis status, the current position, current and maximum speed, Read out the axis status, the current position, current and maximum speed,
acceleration and the air cushion delay. acceleration, the air cushion delay, the scaling factor between counts and
engineering units ([Qxx00] = engineering units / counts) and the deadband
Ixx65.
*/ */
snprintf(command, sizeof(command), snprintf(command, sizeof(command),
"P%2.2d00 Q%2.2d10 Q%2.2d03 Q%2.2d04 Q%2.2d06 P%2.2d22", axisNo_, "P%2.2d00 Q%2.2d10 Q%2.2d03 Q%2.2d04 Q%2.2d06 P%2.2d22 Q%2.2d00 "
axisNo_, axisNo_, axisNo_, axisNo_, axisNo_); "I%2.2d65",
status = pC_->writeRead(axisNo_, command, response, 6); axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_,
axisNo_);
status = pC_->writeRead(axisNo_, command, response, 8);
if (status != asynSuccess) { if (status != asynSuccess) {
asynPrint( asynPrint(
pC_->pasynUser(), ASYN_TRACE_ERROR, pC_->pasynUser(), ASYN_TRACE_ERROR,
@@ -180,8 +193,9 @@ asynStatus turboPmacAxis::init() {
pC_->portName, axisNo(), __PRETTY_FUNCTION__, __LINE__); pC_->portName, axisNo(), __PRETTY_FUNCTION__, __LINE__);
pTurboPmacA_->needInit = true; pTurboPmacA_->needInit = true;
} }
nvals = sscanf(response, "%d %lf %lf %lf %lf %d", &axStatus, &motorPos, nvals = sscanf(response, "%d %lf %lf %lf %lf %d %lf %lf", &axStatus,
&motorVmax, &motorVelocity, &motorAccel, &acoDelay); &motorPos, &motorVmax, &motorVelocity, &motorAccel,
&acoDelay, &counts_to_eu, &deadband_counts);
// The acoDelay is given in milliseconds -> Convert to seconds, rounded up // The acoDelay is given in milliseconds -> Convert to seconds, rounded up
setOffsetMovTimeout(std::ceil(acoDelay / 1000.0)); setOffsetMovTimeout(std::ceil(acoDelay / 1000.0));
@@ -191,7 +205,7 @@ asynStatus turboPmacAxis::init() {
// here to mm/s^2. // here to mm/s^2.
motorAccel = motorAccel * 1000; motorAccel = motorAccel * 1000;
if (nvals != 6) { if (nvals != 8) {
return pC_->couldNotParseResponse(command, response, axisNo_, return pC_->couldNotParseResponse(command, response, axisNo_,
__PRETTY_FUNCTION__, __LINE__); __PRETTY_FUNCTION__, __LINE__);
} }
@@ -215,6 +229,26 @@ asynStatus turboPmacAxis::init() {
return status; return status;
} }
/*
Check if the new target position is within the range current position +/-
deadband. If that is the case, no movement command should be sent. This
functionality is implemented within the motor record itself, we just need to
populate the field SPDP (see record PushSPDB2Field in db/turboPmac.db)
First, the deadband is read out (Ixx65, see Turbo PMAC User Manual, p.
160). This value then needs to be converted into counts (by dividing it by
16). After words, the deadband in counts then need to be converted into
engineering units. For this, the scaling factor Qxx10 needs to be applied
(see SINQ_2G_MCU_SW_manual_rev7, p. 17):
[Qxx10] = engineering units (eu) / counts
deadband_eu = Qxx10 * Ixx65 / 16
The values of Qxx10 and Ixx65 are read out during initialization and are
assumed to not change during operation.
*/
setAxisParamChecked(this, motorPositionDeadband,
counts_to_eu * deadband_counts / 16.0);
// Update the parameter library immediately // Update the parameter library immediately
status = callParamCallbacks(); status = callParamCallbacks();
if (status != asynSuccess) { if (status != asynSuccess) {
@@ -752,7 +786,7 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
char command[pC_->MAXBUF_] = {0}; char command[pC_->MAXBUF_] = {0};
char response[pC_->MAXBUF_] = {0}; char response[pC_->MAXBUF_] = {0};
double motorCoordinatesPosition = 0.0; double motorTargetPosition = 0.0;
double motorRecResolution = 0.0; double motorRecResolution = 0.0;
double motorVelocity = 0.0; double motorVelocity = 0.0;
int enabled = 0; int enabled = 0;
@@ -773,13 +807,14 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
} }
// Convert from EPICS to user / motor units // Convert from EPICS to user / motor units
motorCoordinatesPosition = position * motorRecResolution; motorTargetPosition = position * motorRecResolution;
motorVelocity = maxVelocity * motorRecResolution; motorVelocity = maxVelocity * motorRecResolution;
asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW, asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW,
"Controller \"%s\", axis %d => %s, line %d\nStart of axis to " "Controller \"%s\", axis %d => %s, line %d\nStart of axis to "
"position %lf.\n", "position %lf.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, position); pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
motorTargetPosition);
// Check if the speed is allowed to be changed // Check if the speed is allowed to be changed
getAxisParamChecked(this, motorCanSetSpeed, &motorCanSetSpeed); getAxisParamChecked(this, motorCanSetSpeed, &motorCanSetSpeed);
@@ -804,11 +839,11 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
if (relative) { if (relative) {
snprintf(&command[writeOffset], sizeof(command) - writeOffset, snprintf(&command[writeOffset], sizeof(command) - writeOffset,
"P%2.2d23=0 Q%2.2d02=%lf M%2.2d=2", axisNo_, axisNo_, "P%2.2d23=0 Q%2.2d02=%lf M%2.2d=2", axisNo_, axisNo_,
motorCoordinatesPosition, axisNo_); motorTargetPosition, axisNo_);
} else { } else {
snprintf(&command[writeOffset], sizeof(command) - writeOffset, snprintf(&command[writeOffset], sizeof(command) - writeOffset,
"P%2.2d23=0 Q%2.2d01=%lf M%2.2d=1", axisNo_, axisNo_, "P%2.2d23=0 Q%2.2d01=%lf M%2.2d=1", axisNo_, axisNo_,
motorCoordinatesPosition, axisNo_); motorTargetPosition, axisNo_);
} }
// We don't expect an answer // We don't expect an answer
@@ -820,7 +855,7 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
"Controller \"%s\", axis %d => %s, line %d\nStarting movement to " "Controller \"%s\", axis %d => %s, line %d\nStarting movement to "
"target position %lf failed.\n", "target position %lf failed.\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
motorCoordinatesPosition); motorTargetPosition);
setAxisParamChecked(this, motorStatusProblem, true); setAxisParamChecked(this, motorStatusProblem, true);
return status; return status;
} }

View File

@@ -47,7 +47,7 @@ struct turboPmacControllerImpl {
int flushHardware; int flushHardware;
int limFromHardware; int limFromHardware;
}; };
#define NUM_turboPmac_DRIVER_PARAMS 3 #define NUM_turboPmac_DRIVER_PARAMS 5
turboPmacController::turboPmacController(const char *portName, turboPmacController::turboPmacController(const char *portName,
const char *ipPortConfigName, const char *ipPortConfigName,