moved disconnect handling to sinqMotor
This commit is contained in:
Submodule sinqMotor updated: 2578081814...97c3ed4556
@@ -179,22 +179,52 @@ asynStatus turboPmacAxis::init() {
|
|||||||
"Q%2.2d10 Q%2.2d03 Q%2.2d04 Q%2.2d06 P%2.2d22 Q%2.2d00 I%2.2d65",
|
"Q%2.2d10 Q%2.2d03 Q%2.2d04 Q%2.2d06 P%2.2d22 Q%2.2d00 I%2.2d65",
|
||||||
axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_);
|
axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_, axisNo_);
|
||||||
status = pC_->writeRead(axisNo_, command, response, 7);
|
status = pC_->writeRead(axisNo_, command, response, 7);
|
||||||
|
|
||||||
|
msgPrintControlKey keyDisconnected = msgPrintControlKey(
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, 1);
|
||||||
|
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
|
if (pC_->getMsgPrintControl().shouldBePrinted(keyDisconnected, true,
|
||||||
|
pC_->pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nCould not communicate "
|
"Controller \"%s\", axis %d => %s, line %d\nCould not "
|
||||||
"with controller during IOC initialization. Check if you used "
|
"communicate with controller during IOC initialization (error "
|
||||||
"\"pmacAsynIPPortConfigure\" instead of the standard "
|
"%s). Did you use \"drvAsynIPPortConfigure\" instead of "
|
||||||
"\"drvAsynIPPortConfigure\" function in the .cmd file in order to "
|
"\"pmacAsynIPPortConfigure\" in the .cmd file to create the "
|
||||||
"create the port driver.\n",
|
"port driver?\n",
|
||||||
pC_->portName, axisNo(), __PRETTY_FUNCTION__, __LINE__);
|
pC_->portName, axisNo(), __PRETTY_FUNCTION__, __LINE__,
|
||||||
pTurboPmacA_->needInit = true;
|
pC_->stringifyAsynStatus(status));
|
||||||
}
|
}
|
||||||
|
pTurboPmacA_->needInit = true;
|
||||||
|
|
||||||
|
status = callParamCallbacks();
|
||||||
|
if (status != asynSuccess) {
|
||||||
|
// If we can't communicate with the parameter library, it
|
||||||
|
// doesn't make sense to try and upstream this to the user ->
|
||||||
|
// Just log the error
|
||||||
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line "
|
||||||
|
"%d\ncallParamCallbacks failed with %s.\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->stringifyAsynStatus(status));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error has been detected -> Reset the error count
|
||||||
|
if (status == asynSuccess) {
|
||||||
|
pC_->getMsgPrintControl().resetCount(keyDisconnected, pC_->pasynUser());
|
||||||
|
}
|
||||||
|
|
||||||
nvals = sscanf(response, "%lf %lf %lf %lf %d %lf %lf", &motorPos,
|
nvals = sscanf(response, "%lf %lf %lf %lf %d %lf %lf", &motorPos,
|
||||||
&motorVmax, &motorVelocity, &motorAccel, &acoDelay,
|
&motorVmax, &motorVelocity, &motorAccel, &acoDelay,
|
||||||
&counts_to_eu, &deadband_counts);
|
&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));
|
||||||
|
|
||||||
// The PMAC electronic specifies the acceleration in m/s^2. Since we
|
// The PMAC electronic specifies the acceleration in m/s^2. Since we
|
||||||
@@ -227,18 +257,18 @@ asynStatus turboPmacAxis::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if the new target position is within the range current position +/-
|
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
|
+/- deadband. If that is the case, no movement command should be sent.
|
||||||
functionality is implemented within the motor record itself, we just need to
|
This functionality is implemented within the motor record itself, we
|
||||||
populate the field SPDP (see record PushSPDB2Field in db/turboPmac.db)
|
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.
|
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
|
160). This value then needs to be converted into counts (by dividing it
|
||||||
16). After words, the deadband in counts then need to be converted into
|
by 16). After words, the deadband in counts then need to be converted
|
||||||
engineering units. For this, the scaling factor Qxx10 needs to be applied
|
into engineering units. For this, the scaling factor Qxx10 needs to be
|
||||||
(see SINQ_2G_MCU_SW_manual_rev7, p. 17):
|
applied (see SINQ_2G_MCU_SW_manual_rev7, p. 17): [Qxx10] = engineering
|
||||||
[Qxx10] = engineering units (eu) / counts
|
units (eu) / counts deadband_eu = Qxx10 * Ixx65 / 16
|
||||||
deadband_eu = Qxx10 * Ixx65 / 16
|
|
||||||
|
|
||||||
The values of Qxx10 and Ixx65 are read out during initialization and are
|
The values of Qxx10 and Ixx65 are read out during initialization and are
|
||||||
assumed to not change during operation.
|
assumed to not change during operation.
|
||||||
@@ -249,11 +279,12 @@ asynStatus turboPmacAxis::init() {
|
|||||||
// Update the parameter library immediately
|
// Update the parameter library immediately
|
||||||
status = callParamCallbacks();
|
status = callParamCallbacks();
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
// If we can't communicate with the parameter library, it doesn't make
|
// If we can't communicate with the parameter library, it doesn't
|
||||||
// sense to try and upstream this to the user -> Just log the error
|
// make sense to try and upstream this to the user -> Just log the
|
||||||
asynPrint(
|
// error
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\ncallParamCallbacks "
|
"Controller \"%s\", axis %d => %s, line "
|
||||||
|
"%d\ncallParamCallbacks "
|
||||||
"failed with %s.\n",
|
"failed with %s.\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
pC_->stringifyAsynStatus(status));
|
pC_->stringifyAsynStatus(status));
|
||||||
@@ -341,13 +372,13 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
// If an error occurred while waiting for the handshake, abort the
|
// If an error occurred while waiting for the handshake, abort
|
||||||
// waiting procedure and continue with the poll in order to handle
|
// the waiting procedure and continue with the poll in order to
|
||||||
// the error.
|
// handle the error.
|
||||||
pTurboPmacA_->waitForHandshake = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
} else if (handshakePerformed == 1) {
|
} else if (handshakePerformed == 1) {
|
||||||
// Handshake has been performed successfully -> Continue with the
|
// Handshake has been performed successfully -> Continue with
|
||||||
// poll
|
// the poll
|
||||||
pTurboPmacA_->waitForHandshake = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
} else {
|
} else {
|
||||||
// Still waiting for the handshake - try again in the next busy
|
// Still waiting for the handshake - try again in the next busy
|
||||||
@@ -387,15 +418,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
The axis limits are set as: ({[]})
|
The axis limits are set as: ({[]})
|
||||||
where [] are the positive and negative limits set in EPICS/NICOS, {} are the
|
where [] are the positive and negative limits set in EPICS/NICOS, {} are
|
||||||
software limits set on the MCU and () are the hardware limit switches. In
|
the software limits set on the MCU and () are the hardware limit
|
||||||
other words, the EPICS/NICOS limits should be stricter than the software
|
switches. In other words, the EPICS/NICOS limits should be stricter than
|
||||||
limits on the MCU which in turn should be stricter than the hardware limit
|
the software limits on the MCU which in turn should be stricter than the
|
||||||
switches. For example, if the hardware limit switches are at [-10, 10], the
|
hardware limit switches. For example, if the hardware limit switches are
|
||||||
software limits could be at [-9, 9] and the EPICS / NICOS limits could be at
|
at [-10, 10], the software limits could be at [-9, 9] and the EPICS /
|
||||||
|
NICOS limits could be at
|
||||||
[-8, 8]. Therefore, we cannot use the software limits read from the MCU
|
[-8, 8]. Therefore, we cannot use the software limits read from the MCU
|
||||||
directly, but need to shrink them a bit. In this case, we're shrinking them
|
directly, but need to shrink them a bit. In this case, we're shrinking
|
||||||
by limitsOffset on both sides.
|
them by limitsOffset on both sides.
|
||||||
*/
|
*/
|
||||||
getAxisParamChecked(this, motorLimitsOffset, &limitsOffset);
|
getAxisParamChecked(this, motorLimitsOffset, &limitsOffset);
|
||||||
highLimit = highLimit - limitsOffset;
|
highLimit = highLimit - limitsOffset;
|
||||||
@@ -411,8 +443,8 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
(axStatus != -3 && axStatus != -5));
|
(axStatus != -3 && axStatus != -5));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the unique callsite identifier manually so it can be used later in
|
// Create the unique callsite identifier manually so it can be used
|
||||||
// the shouldBePrinted calls.
|
// later in the shouldBePrinted calls.
|
||||||
msgPrintControlKey keyStatus = msgPrintControlKey(
|
msgPrintControlKey keyStatus = msgPrintControlKey(
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||||
bool resetCountStatus = true;
|
bool resetCountStatus = true;
|
||||||
@@ -433,9 +465,9 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
if (pC_->getMsgPrintControl().shouldBePrinted(keyStatus, true,
|
if (pC_->getMsgPrintControl().shouldBePrinted(keyStatus, true,
|
||||||
pC_->pasynUser())) {
|
pC_->pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
"Controller \"%s\", axis %d => %s, line "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nEmergency stop "
|
"%d\nEmergency stop "
|
||||||
"activated.%s\n",
|
"activated.%s\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
pC_->getMsgPrintControl().getSuffix());
|
pC_->getMsgPrintControl().getSuffix());
|
||||||
@@ -508,8 +540,8 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
*moving = false;
|
*moving = false;
|
||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
// Move is interrupted, but the motor is not ready to receive another
|
// Move is interrupted, but the motor is not ready to receive
|
||||||
// move command. Therefore it is treated as still moving.
|
// another move command. Therefore it is treated as still moving.
|
||||||
*moving = true;
|
*moving = true;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
@@ -604,11 +636,11 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
if (pC_->getMsgPrintControl().shouldBePrinted(
|
if (pC_->getMsgPrintControl().shouldBePrinted(
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, true,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, true,
|
||||||
pC_->pasynUser())) {
|
pC_->pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
|
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
|
||||||
"still moving, but received another move command. EPICS "
|
"still moving, but received another move command. EPICS "
|
||||||
"should prevent this, check if *moving is set correctly.%s\n",
|
"should prevent this, check if *moving is set "
|
||||||
|
"correctly.%s\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
pC_->getMsgPrintControl().getSuffix());
|
pC_->getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
@@ -623,13 +655,14 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
asynPrint(
|
asynPrint(
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nLost feedback "
|
"Controller \"%s\", axis %d => %s, line %d\nLost feedback "
|
||||||
"from auxiliary device during movement (P%2.2d01 = %d).%s\n",
|
"from auxiliary device during movement (P%2.2d01 = "
|
||||||
|
"%d).%s\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
||||||
error, pC_->getMsgPrintControl().getSuffix());
|
error, pC_->getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
snprintf(
|
snprintf(userMessage, sizeUserMessage,
|
||||||
userMessage, sizeUserMessage,
|
"Lost feedback from auxiliary device during movement "
|
||||||
"Lost feedback from auxiliary device during movement (P%2.2d01 = "
|
"(P%2.2d01 = "
|
||||||
"%d). Please call the support.",
|
"%d). Please call the support.",
|
||||||
axisNo_, error);
|
axisNo_, error);
|
||||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||||
@@ -638,12 +671,12 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
if (pC_->getMsgPrintControl().shouldBePrinted(
|
if (pC_->getMsgPrintControl().shouldBePrinted(
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, true,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, true,
|
||||||
pC_->pasynUser())) {
|
pC_->pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
"Controller \"%s\", axis %d => %s, line %d\nNo feedback "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nNo feedback from "
|
"from "
|
||||||
"auxiliary device before movement (P%2.2d01 = %d).%s\n",
|
"auxiliary device before movement (P%2.2d01 = %d).%s\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
error, pC_->getMsgPrintControl().getSuffix());
|
axisNo_, error, pC_->getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(
|
snprintf(
|
||||||
@@ -655,10 +688,10 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
/*
|
/*
|
||||||
Software limits of the controller have been hit. Since the EPICS limits
|
Software limits of the controller have been hit. Since the EPICS
|
||||||
are derived from the software limits and are a little bit smaller, this
|
limits are derived from the software limits and are a little bit
|
||||||
error case can only happen if either the axis has an incremental encoder
|
smaller, this error case can only happen if either the axis has an
|
||||||
which is not properly homed or if a bug occured.
|
incremental encoder which is not properly homed or if a bug occured.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pC_->getMsgPrintControl().shouldBePrinted(
|
if (pC_->getMsgPrintControl().shouldBePrinted(
|
||||||
@@ -685,9 +718,9 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
if (pC_->getMsgPrintControl().shouldBePrinted(
|
if (pC_->getMsgPrintControl().shouldBePrinted(
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, true,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, true,
|
||||||
pC_->pasynUser())) {
|
pC_->pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
"Controller \"%s\", axis %d => %s, line %d\nMaximum "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nMaximum allowed "
|
"allowed "
|
||||||
"following error exceeded.%s\n",
|
"following error exceeded.%s\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
pC_->getMsgPrintControl().getSuffix());
|
pC_->getMsgPrintControl().getSuffix());
|
||||||
@@ -730,9 +763,9 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
pC_->getMsgPrintControl().getSuffix());
|
pC_->getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
snprintf(
|
snprintf(userMessage, sizeUserMessage,
|
||||||
userMessage, sizeUserMessage,
|
"Driver hardware error (P%2.2d01 = 13). Please call the "
|
||||||
"Driver hardware error (P%2.2d01 = 13). Please call the support.",
|
"support.",
|
||||||
axisNo_);
|
axisNo_);
|
||||||
setAxisParamChecked(this, motorMessageText, userMessage);
|
setAxisParamChecked(this, motorMessageText, userMessage);
|
||||||
break;
|
break;
|
||||||
@@ -798,9 +831,9 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
|||||||
getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
|
getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
|
||||||
|
|
||||||
if (enabled == 0) {
|
if (enabled == 0) {
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is disabled.\n",
|
"disabled.\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
@@ -819,8 +852,8 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
|||||||
getAxisParamChecked(this, motorCanSetSpeed, &motorCanSetSpeed);
|
getAxisParamChecked(this, motorCanSetSpeed, &motorCanSetSpeed);
|
||||||
|
|
||||||
// Prepend the new motor speed, if the user is allowed to set the speed.
|
// Prepend the new motor speed, if the user is allowed to set the speed.
|
||||||
// Mind the " " (space) before the closing "", as the command created here
|
// Mind the " " (space) before the closing "", as the command created
|
||||||
// is prepended to the one down below.
|
// here is prepended to the one down below.
|
||||||
if (motorCanSetSpeed != 0) {
|
if (motorCanSetSpeed != 0) {
|
||||||
snprintf(command, sizeof(command), "Q%2.2d04=%lf ", axisNo_,
|
snprintf(command, sizeof(command), "Q%2.2d04=%lf ", axisNo_,
|
||||||
motorVelocity);
|
motorVelocity);
|
||||||
@@ -833,8 +866,8 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
|||||||
motorVelocity);
|
motorVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform handshake, Set target position (and speed, if allowed) and start
|
// Perform handshake, Set target position (and speed, if allowed) and
|
||||||
// the move command
|
// start the move command
|
||||||
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_,
|
||||||
@@ -849,9 +882,9 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
|||||||
status = pC_->writeRead(axisNo_, command, response, 0);
|
status = pC_->writeRead(axisNo_, command, response, 0);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
|
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
"Controller \"%s\", axis %d => %s, line %d\nStarting "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nStarting movement to "
|
"movement to "
|
||||||
"target position %lf failed.\n",
|
"target position %lf failed.\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
motorTargetPosition);
|
motorTargetPosition);
|
||||||
@@ -859,8 +892,8 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the next poll, we will check if the handshake has been performed in a
|
// In the next poll, we will check if the handshake has been performed
|
||||||
// reasonable time
|
// in a reasonable time
|
||||||
pTurboPmacA_->waitForHandshake = true;
|
pTurboPmacA_->waitForHandshake = true;
|
||||||
pTurboPmacA_->timeAtHandshake = time(NULL);
|
pTurboPmacA_->timeAtHandshake = time(NULL);
|
||||||
|
|
||||||
@@ -889,25 +922,25 @@ asynStatus turboPmacAxis::stop(double acceleration) {
|
|||||||
status = pC_->writeRead(axisNo_, command, response, 0);
|
status = pC_->writeRead(axisNo_, command, response, 0);
|
||||||
|
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
"Controller \"%s\", axis %d => %s, line %d\nStopping "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nStopping the movement "
|
"the movement "
|
||||||
"failed.\n",
|
"failed.\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
||||||
setAxisParamChecked(this, motorStatusProblem, true);
|
setAxisParamChecked(this, motorStatusProblem, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the driver to idle state and move out of the handshake wait loop,
|
// Reset the driver to idle state and move out of the handshake wait
|
||||||
// if we're currently inside it.
|
// loop, if we're currently inside it.
|
||||||
pTurboPmacA_->waitForHandshake = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Stopping the motor results in a movement and further move commands have to
|
Stopping the motor results in a movement and further move commands have
|
||||||
wait until the stopping movement is done. Therefore, we need to wait until
|
to wait until the stopping movement is done. Therefore, we need to wait
|
||||||
the poller "sees" the changed state (otherwise, we risk issuing move
|
until the poller "sees" the changed state (otherwise, we risk issuing
|
||||||
commands while the motor is stopping). To ensure that at least one poll is
|
move commands while the motor is stopping). To ensure that at least one
|
||||||
done, this thread (which also runs move commands) is paused for twice the
|
poll is done, this thread (which also runs move commands) is paused for
|
||||||
idle poll period.
|
twice the idle poll period.
|
||||||
*/
|
*/
|
||||||
unsigned int idlePollMicros =
|
unsigned int idlePollMicros =
|
||||||
(unsigned int)ceil(pC_->idlePollPeriod() * 1e6);
|
(unsigned int)ceil(pC_->idlePollPeriod() * 1e6);
|
||||||
@@ -938,8 +971,8 @@ asynStatus turboPmacAxis::doReset() {
|
|||||||
setAxisParamChecked(this, motorStatusProblem, true);
|
setAxisParamChecked(this, motorStatusProblem, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the driver to idle state and move out of the handshake wait loop,
|
// Reset the driver to idle state and move out of the handshake wait
|
||||||
// if we're currently inside it.
|
// loop, if we're currently inside it.
|
||||||
pTurboPmacA_->waitForHandshake = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
|
|
||||||
// Disable the axis
|
// Disable the axis
|
||||||
@@ -1037,13 +1070,14 @@ asynStatus turboPmacAxis::readEncoderType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is not a command that can always be run when enabling a motor as it also
|
This is not a command that can always be run when enabling a motor as it
|
||||||
causes relative encoders to reread a position necessitating recalibration. We
|
also causes relative encoders to reread a position necessitating
|
||||||
only want it to run on absolute encoders. We also want it to be clear to
|
recalibration. We only want it to run on absolute encoders. We also want it
|
||||||
instrument scientists, that power has to be cut to the motor, in order to reread
|
to be clear to instrument scientists, that power has to be cut to the motor,
|
||||||
the encoder as not all motors have breaks and they may start to move when
|
in order to reread the encoder as not all motors have breaks and they may
|
||||||
disabled. For that reason, we don't automatically disable the motors to run the
|
start to move when disabled. For that reason, we don't automatically disable
|
||||||
command and instead require that the scientists first disable the motor.
|
the motors to run the command and instead require that the scientists first
|
||||||
|
disable the motor.
|
||||||
*/
|
*/
|
||||||
asynStatus turboPmacAxis::rereadEncoder() {
|
asynStatus turboPmacAxis::rereadEncoder() {
|
||||||
char command[pC_->MAXBUF_] = {0};
|
char command[pC_->MAXBUF_] = {0};
|
||||||
@@ -1087,11 +1121,12 @@ asynStatus turboPmacAxis::rereadEncoder() {
|
|||||||
return asynError;
|
return asynError;
|
||||||
} else {
|
} else {
|
||||||
snprintf(command, sizeof(command), "M%2.2d=15", axisNo_);
|
snprintf(command, sizeof(command), "M%2.2d=15", axisNo_);
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW,
|
||||||
pC_->pasynUser(), ASYN_TRACE_FLOW,
|
"Controller \"%s\", axis %d => %s, line %d\nRereading "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nRereading absolute "
|
"absolute "
|
||||||
"encoder via command %s.\n",
|
"encoder via command %s.\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, command);
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
command);
|
||||||
pC_->writeRead(axisNo_, command, response, 0);
|
pC_->writeRead(axisNo_, command, response, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1100,8 +1135,8 @@ asynStatus turboPmacAxis::rereadEncoder() {
|
|||||||
// it is actually finished, so we instead wait for 0.5 seconds.
|
// it is actually finished, so we instead wait for 0.5 seconds.
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
|
|
||||||
// Turn off parameter as finished rereading, this will only be immediately
|
// Turn off parameter as finished rereading, this will only be
|
||||||
// noticed in the read back variable though
|
// immediately noticed in the read back variable though
|
||||||
setAxisParamChecked(this, rereadEncoderPosition, false);
|
setAxisParamChecked(this, rereadEncoderPosition, false);
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
@@ -1121,27 +1156,28 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
/*
|
/*
|
||||||
Continue regardless of the status returned by the poll; we just want to
|
Continue regardless of the status returned by the poll; we just want to
|
||||||
find out whether the motor is currently moving or not. If the poll
|
find out whether the motor is currently moving or not. If the poll
|
||||||
function fails before it can determine that, it is assumed that the motor
|
function fails before it can determine that, it is assumed that the
|
||||||
is not moving.
|
motor is not moving.
|
||||||
*/
|
*/
|
||||||
bool moving = false;
|
bool moving = false;
|
||||||
doPoll(&moving);
|
doPoll(&moving);
|
||||||
|
|
||||||
// If the axis is currently moving, it cannot be disabled. Ignore the
|
// If the axis is currently moving, it cannot be disabled. Ignore the
|
||||||
// command and inform the user. We check the last known status of the axis
|
// command and inform the user. We check the last known status of the
|
||||||
// instead of "moving", since status -6 is also moving, but the motor can
|
// axis instead of "moving", since status -6 is also moving, but the
|
||||||
// actually be disabled in this state!
|
// motor can actually be disabled in this state!
|
||||||
int axStatus = pTurboPmacA_->axisStatus;
|
int axStatus = pTurboPmacA_->axisStatus;
|
||||||
if (axStatus == 1 || axStatus == 2 || axStatus == 3 || axStatus == 4 ||
|
if (axStatus == 1 || axStatus == 2 || axStatus == 3 || axStatus == 4 ||
|
||||||
axStatus == 5 || axStatus == 6 || axStatus == 7 || axStatus == 8 ||
|
axStatus == 5 || axStatus == 6 || axStatus == 7 || axStatus == 8 ||
|
||||||
axStatus == 9 || axStatus == 10 || axStatus == 11 || axStatus == 12 ||
|
axStatus == 9 || axStatus == 10 || axStatus == 11 || axStatus == 12 ||
|
||||||
axStatus == 13 || axStatus == 15 || axStatus == 16) {
|
axStatus == 13 || axStatus == 15 || axStatus == 16) {
|
||||||
|
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
pC_->pasynUser(), ASYN_TRACE_ERROR,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
||||||
"idle (status %d) and can therefore not be enabled / disabled.\n",
|
"idle (status %d) and can therefore not be enabled / "
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axStatus);
|
"disabled.\n",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
axStatus);
|
||||||
|
|
||||||
setAxisParamChecked(this, motorMessageText,
|
setAxisParamChecked(this, motorMessageText,
|
||||||
"Axis cannot be disabled while it is moving.");
|
"Axis cannot be disabled while it is moving.");
|
||||||
@@ -1152,9 +1188,9 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
// Axis is already enabled / disabled and a new enable / disable command
|
// Axis is already enabled / disabled and a new enable / disable command
|
||||||
// was sent => Do nothing
|
// was sent => Do nothing
|
||||||
if ((axStatus != -3) == on) {
|
if ((axStatus != -3) == on) {
|
||||||
asynPrint(
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_WARNING,
|
||||||
pC_->pasynUser(), ASYN_TRACE_WARNING,
|
"Controller \"%s\", axis %d => %s, line %d\nAxis is "
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is already %s.\n",
|
"already %s.\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
on ? "enabled" : "disabled");
|
on ? "enabled" : "disabled");
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
@@ -1305,8 +1341,8 @@ asynStatus turboPmacCreateAxis(const char *portName, int axis) {
|
|||||||
https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorController.cpp
|
https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorController.cpp
|
||||||
https://github.com/epics-modules/asyn/blob/master/asyn/asynPortDriver/asynPortDriver.cpp
|
https://github.com/epics-modules/asyn/blob/master/asyn/asynPortDriver/asynPortDriver.cpp
|
||||||
|
|
||||||
The created object is registered in EPICS in its constructor and can safely
|
The created object is registered in EPICS in its constructor and can
|
||||||
be "leaked" here.
|
safely be "leaked" here.
|
||||||
*/
|
*/
|
||||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
@@ -1329,14 +1365,15 @@ static const iocshArg *const CreateAxisArgs[] = {&CreateAxisArg0,
|
|||||||
static const iocshFuncDef configTurboPmacCreateAxis = {
|
static const iocshFuncDef configTurboPmacCreateAxis = {
|
||||||
"turboPmacAxis", 2, CreateAxisArgs,
|
"turboPmacAxis", 2, CreateAxisArgs,
|
||||||
"Create an instance of a turboPmac axis. The first argument is the "
|
"Create an instance of a turboPmac axis. The first argument is the "
|
||||||
"controller this axis should be attached to, the second argument is the "
|
"controller this axis should be attached to, the second argument is "
|
||||||
|
"the "
|
||||||
"axis number."};
|
"axis number."};
|
||||||
static void configTurboPmacCreateAxisCallFunc(const iocshArgBuf *args) {
|
static void configTurboPmacCreateAxisCallFunc(const iocshArgBuf *args) {
|
||||||
turboPmacCreateAxis(args[0].sval, args[1].ival);
|
turboPmacCreateAxis(args[0].sval, args[1].ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is made known to EPICS in turboPmac.dbd and is called by EPICS
|
// This function is made known to EPICS in turboPmac.dbd and is called by
|
||||||
// in order to register both functions in the IOC shell
|
// EPICS in order to register both functions in the IOC shell
|
||||||
static void turboPmacAxisRegister(void) {
|
static void turboPmacAxisRegister(void) {
|
||||||
iocshRegister(&configTurboPmacCreateAxis,
|
iocshRegister(&configTurboPmacCreateAxis,
|
||||||
configTurboPmacCreateAxisCallFunc);
|
configTurboPmacCreateAxisCallFunc);
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
|
|
||||||
// Definition of local variables.
|
// Definition of local variables.
|
||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
asynStatus timeoutStatus = asynSuccess;
|
|
||||||
char drvMessageText[MAXBUF_] = {0};
|
char drvMessageText[MAXBUF_] = {0};
|
||||||
char modResponse[MAXBUF_] = {0};
|
char modResponse[MAXBUF_] = {0};
|
||||||
int motorStatusProblem = 0;
|
int motorStatusProblem = 0;
|
||||||
@@ -284,8 +283,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
getMsgPrintControl().getSuffix());
|
getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
checkComTimeoutWatchdog(axisNo, drvMessageText, sizeof(drvMessageText));
|
||||||
sizeof(drvMessageText));
|
|
||||||
|
|
||||||
int timeoutCounter = 0;
|
int timeoutCounter = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -333,14 +331,10 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
axis->setNeedInit(true);
|
axis->setNeedInit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeoutStatus == asynError) {
|
|
||||||
status = asynError;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The message should only ever terminate due to reason 2
|
// The message should only ever terminate due to reason 2
|
||||||
msgPrintControlKey terminateKey =
|
msgPrintControlKey terminateKey =
|
||||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
if (eomReason != 2) {
|
if (status == asynSuccess && eomReason != 2) {
|
||||||
status = asynError;
|
status = asynError;
|
||||||
|
|
||||||
char reasonStringified[30] = {0};
|
char reasonStringified[30] = {0};
|
||||||
@@ -391,7 +385,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
}
|
}
|
||||||
msgPrintControlKey numResponsesKey =
|
msgPrintControlKey numResponsesKey =
|
||||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
if (numExpectedResponses != numReceivedResponses) {
|
if (status == asynSuccess && numExpectedResponses != numReceivedResponses) {
|
||||||
adjustResponseForPrint(modResponse, response, MAXBUF_);
|
adjustResponseForPrint(modResponse, response, MAXBUF_);
|
||||||
|
|
||||||
if (getMsgPrintControl().shouldBePrinted(numResponsesKey, true,
|
if (getMsgPrintControl().shouldBePrinted(numResponsesKey, true,
|
||||||
|
|||||||
Reference in New Issue
Block a user